I have a project due in a class that requires me to build a simple shell in C. I'm new to C and the problem I am facing right now is that of parsing the commands correctly before sending them off to be executed. I know there are a few different ways to do this, but we are required to use strtok and I am having some problems with it it seems.
Here is the entirety of my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
int parseCommands(char *command, char **args){
int pos = 0;
printf("%s\n", command);
char *readCommand = NULL;
char delims[] = {" \n"};
readCommand = strtok(command, delims);
while(readCommand != '\0'){
printf("%s\n", readCommand);
strcpy(args[pos], readCommand);
printf("%s\n", args[pos]);
readCommand = strtok(NULL, delims);
pos++;
}
return pos;
}
int executeCommand(char **args){
pid_t pID;
switch(pID = fork()){
case 0:
execvp(args[0], args);
perror("Some sort of exec error");
return -1;
case -1:
perror("Could not even fork");
return -2;
default:
wait(NULL);
return 0;
}
}
void main(){
char wd[256];
char input[256];
char *args[15];
char strDelims[] = ";";
char *readInput = NULL;
while(1){
getcwd(wd, sizeof wd);
printf("mysh: %s> ", wd);
fgets(input, sizeof input, stdin);
readInput = strtok(input, strDelims);
int numArgs;
numArgs = parseCommands(readInput, args);
if(numArgs < 1)
printf("There was a problem parsing the command\n");
if(strcmp(args[0], "cd") == 0){
printf("%d\n", numArgs);
if(numArgs > 1){
if((chdir(args[1])) < 0){
perror("I'm afraid I can't let you do that Dave\n");
}
}
else{
if((chdir(getenv("HOME"))) < 0){
perror("Can't go home\n");
}
}
}
else if(strcmp(readInput, "quit") == 0){
break;
}
else{
if((executeCommand(args)) != 0)
printf("Problem executing the command\n");
}
readInput = strtok(input, strDelims);
}
}
This is the output from a couple commands:
mysh: /path/to/stuff> cd
cd
cd
cd
1
mysh: /path/to/home> cd /bin
cd /bin
cd
cd
/bin
/bin
2
mysh: /bin> ls
ls
ls
ls
Segmentation fault
mysh: /path/to/stuff> ps aux
ps aux
ps
ps
aux
aux
Segmentation fault
I just think it's odd that cd
seems to work fairly well but it doesn't really like anything else. This makes me think that something goes wrong later (but before the printf for the numArgs?). Also just fyi, we were told that each command would not exceed 15 arguments or 256 characters.
This has been frustrating me for awhile now so any help with this specific problem would be fantastic (I realize there are other errors or poor sections of code in there, but I would like to figure out/fix those on my own). Thanks a lot! :)
some pointers
normally strtok shares a static buffer, so when you call strtok first before your parse function and then later inside the parse function you probably mess up what was in the buffer before.
you also do not allocate space for args[] you only declare an array of pointers (char *args[15])
but then in your parse function you do a strcpy to whatever the pointer points to.
you would need to allocate a buffer, assign to args[i] and then copy the string to it.
so instead of
strcpy(args[pos], readCommand);
do
args[pos] = strdup(readCommand);