Here is my whole code, I have an idea on what needs to be replaced by I'm not sure on how to go about it. The goal of the program is to read files within Linux using a simple shell, I have done this using forks but now I need to translate it to be multithreaded.
// Header files
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <pthread.h>
///////////////////////////////////////////////////////////////////////////////////////////////////
#define LINE_LEN 80 //length of each command line.
#define MAX_ARGS 64 //maximum amounts of arguments of each command.
#define MAX_ARG_LEN 16 //length of each argument.
#define MAX_PATHS 64 //maximum amounts of paths.
#define MAX_PATH_LEN 96 //maximum length of each path.
#define WHITESPACE " .,''\t\n" //delimeters for command line.
#define TRUE 1 //1 for TRUE
#ifndef NULL //if NULL is not defined, then define NULL as 0
#define NULL 0
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
// each command line has a name,
// amount of arguments --> argcount
//arguments is in an array --> argvalue[MAX_ARGS]
typedef struct {
char *name; //command name
int argcount; //number of arguments
char *argvalue[MAX_ARGS]; //argument values (array of values) AKA Strings
} command_t;
// function prototypes
char *lookupPath(char **, char **);
int parseCommand(char *, command_t *);
int parsePath(char **);
void printPrompt();
void readCommand(char *);
/***************************************************************
* Function main. This function performs the bulk of the
* program's purpose: calling each of the seperate functions
* in the order of steps specified in the program description.
*
* In short, the path is first parsed, then user is prompted to
* input a command, the command is read, parsed, validated, and,
* if a valid command it is executed by a thread using
* the execv function. The program closes when the user enters
* "stop","exit", or "quit.
*
* Shorthand:
* Read/print promt > validate > execute > leave with 1 of 3 commands
**************************************************************/
int main(int argcount, char *argvalue[]) {
//initialize variables
char *pathv[MAX_PATHS]; //array of paths
command_t command; //intialize command_t struct variable command
char *commandLine = (char *)malloc(LINE_LEN); //command line
//get the directory paths from PATH
parsePath(pathv);
//print the first prompt
printPrompt();
//loop the program to allow the user to input multiple commands or until the user wishes to exit
while (TRUE) {
//read the command from the keyboard, then store it into the commandLine.
readCommand(commandLine);
//if command is 'stop','exit', or 'quit' then exit the program.
if (strcasecmp(commandLine, "stop\n") == 0 ||strcasecmp(commandLine, "exit\n") == 0 || strcasecmp(commandLine, "quit\n") == 0) {
free(commandLine);
break;
}
//parse the command
parseCommand(commandLine, &command);
//assign the path to the command name
command.name = lookupPath(command.argvalue, pathv);
//check if command is valid
if (command.name == NULL) {
printf("Command name is NULL \n");//failed response
printPrompt();//open promt again
continue;
}else {//if command is valid, fork and execute command
/*******************************************
*******************************************
*Note : PThread would replace this I think*
*******************************************
*******************************************/
// create a child process.
int childPid = fork();
//create temp and append path to command name
char temp[LINE_LEN];
strcpy(temp, "/bin/");
strcat(temp, command.name);
//if fork is successful
if (childPid == 0) {
//execute the command.
execv(temp, argvalue);
}
//wait for child to terminate
if (wait(NULL) > 0) {
printPrompt();
}
}
}
//terminate shell
printf("Exiting now...\n");
return 0;
}
/**********************************************************
* Function lookupPath: Searches for the directories identified
* by the dir argument to see if argvalue[0] (the file name)
* appears there. If so, allocate a new string, place the full
* path name in it, then return the string.
*
* Shorthand:
* Using "dir" to see if in argvalues[], if it is allocate string (char *)
*********************************************************/
char *lookupPath(char **argvalue, char **dir) {
//initialize Variables
char pName[MAX_PATH_LEN]; //path name array
int x; //loop variable
//check to see if command name is already an absolute path name
if (*argvalue[0] == '/') {
if (access(argvalue[0], 0) == 0) {
return argvalue[0];
}
return NULL;
}
//look in PATH directories
for (x = 0; a < MAX_PATHS; x++) {
//temporary absolute path
char tpath[MAX_PATH_LEN];
//if current directory is NULL, exit loop
if (dir[x] == NULL) {
break;
}
//copy dir[x] to tpath
strcpy(tpath, dir[x]);
//append '/' to tpath
strcat(tpath, "/");
strcat(tpath, argvalue[0]);
strcpy(pName, tpath);
//use access() to see if the file is in a dir
if (access(pName, 0) == 0) {
return argvalue[0];
}
}
return NULL;
}
/**********************************************************
* Function parseCommand: Determines the command name and
* constructs the parameter list. This function builds
* argvalue[] and sets the argcount value, where argcount is the
* number of "tokens" or words on the command line. argvalue[]
* is an array of strings (pointers to char *). The last
* element in argvalue[] must be NULL. As we scan the command
* line from the left, the first token goes into argvalue[0],
* the second in argvalue[1], and so on. Each time we add a
* token to argvalue[], we increment argcount.
*
* Shorthand:
* argcount = number of arguments
* argvalue - strings turned into arrays
*********************************************************/
int parseCommand(char *cLine, command_t *cmd) {
//initialize Variables
int argcount;
char **clPtr;
clPtr = &cLine;
argcount = 0;
//initialize first index of cmd's array argvalue with MAX_ARG_LEN
cmd->argvalue[argcount] = (char *)malloc(MAX_ARG_LEN);
//fill argvalue[] (we will split commands with whitespace)
while ((cmd->argvalue[argcount] = strsep(clPtr, WHITESPACE)) != NULL) {
cmd->argvalue[++argcount] = (char *)malloc(MAX_ARG_LEN);
strcat(cmd->argvalue[0], cmd->argvalue[argcount]);
}
//set the command name and argcount
cmd->argcount = argcount - 1;
cmd->name = (char *)malloc(sizeof(cmd->argvalue[0]));
strcpy(cmd->name, cmd->argvalue[0]);
return 1;
}
/**********************************************************
* Function parsePath: Reads the PATH variable for this
* environment, then builds an array, dirs[], of the
* directories in PATH.
*
* Shorthand:
* Read path > make array dirs[]
*********************************************************/
int parsePath(char *dirs[]) {
//initialize Variables
char *pathEnvVar; //path enviroment variable
char *thePath; //name of path
int x; //counter for loops
//set all current directories to NULL
for (x = 0; x < MAX_PATHS; x++) {
dirs[i] = NULL;
}
//store the value of PATH in pathEnvVar
pathEnvVar = (char *)getenv("PATH");
//store the length + 1 of pathEnvVar in thePath (reminder that space is needed bc of how arrays work)
thePath = (char *)malloc(strlen(pathEnvVar) + 1);
//store pathEnvVar in thePath
strcpy(thePath, pathEnvVar);
for (x = 0; x < MAX_PATHS; x++) {
//split the value by ':', then store them into the dirs.
dirs[x] = strsep(&thePath, ":");
if (dirs[x] == NULL)
break;
}
//loop through all path directories
for (x = 0; x < MAX_PATHS; x++) {
//if current directory is null, finish
if (dirs[x] == NULL) {
break;
}
}
return 0;
}
/**********************************************************
* Function printPrompt. Prints prompt which consists
* simply of '>>>' for the user to enter a command.
*
* Shorthand:
* Print prompt
*********************************************************/
void printPrompt() {
const char *promptString = ">>> ";
printf("%s", promptString);
}
/**********************************************************
* Function readCommand. Reads command input by the
* user into buffer using the standard input library.
*
* Shorthand:
* Reads inputs
*********************************************************/
void readCommand(char *buffer) {
fgets(buffer, sizeof(buffer), stdin);
}
So far all I have added is the "
#include <pthread.h>
" in my code as im unsure on how to to go about it further. Any help is appreciated!