0

I am writing code that creates a tiny shell. I am having trouble trying to get my code to read multiple commands. Each command is seperated by a ";" character. For example if I run my code and type "ls -l; ls" both of the commands work properly. However if I do something like "ls; ls -l" it doesn't execute ls -l. I believe my error is how I read the commands but I am unsure. Below is my code.

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>

 #define MAX_CHARACTERS 512

int commandSplit(char *c, char *a[], int t[]) {

int count = 0;
int total = 0;
char *temp[MAX_CHARACTERS];
char *readCommands = strtok(c, ";");
while(readCommands != NULL) {
    printf("Reading full command: %s\n", readCommands);
    temp[count] = readCommands;
    count++;
    readCommands = strtok(NULL, ";");
}
for(int i = 0; i  < count; i++) {
    char *read = strtok(temp[i], " ");
    int track = 0;
    while(read != NULL) {
        printf("Individual command w/ %i chars: %s\n", (int)strlen(read), read);
        a[total] = read;
        printf("a[%i] = %s\n", total, a[total]);
        track++;
        total++;
        read = strtok(NULL, " ");
    }
    t[i] = track;
}

return count;
}

int main() {

int exitProgram = 0;
char *args[MAX_CHARACTERS];

while(!exitProgram) {

char *commands = (char *)(malloc(MAX_CHARACTERS*sizeof(char)));
int tracker[MAX_CHARACTERS];
int numOfCommands = 0;
printf("tinyshell>");
fgets(commands, MAX_CHARACTERS, stdin);
int len;
len = strlen(commands);
if (len > 0 && commands[len-1] == '\n') {
    commands[len-1] = '\0';
}
if(len > MAX_CHARACTERS) {
    printf("TOO MANY CHARACTERS - MAX: 512\n");
    continue;
}

if(strlen(commands) == 0) continue;

numOfCommands = commandSplit(commands, args, tracker);

if(strcmp(args[0], "quit") == 0) {
    printf("Reached an exit1\n");
    exitProgram = 1;
    continue;
}

printf("Tracker is: ");
for(int i = 0; i < numOfCommands; i++) printf("%i, ", tracker[i]);
printf("\n");

int l = 0;
for(int i = 0; i < numOfCommands; i++) {
    int status;
    if((tracker[i] == 1) && (strcmp(args[l], "exit") == 0)) {
        printf("Reached an exit2\n");
        exitProgram = 1;
        continue;
    }
    char *holder[tracker[i]+1];
    for(int j = 0; j < tracker[i]; j++) {
        holder[j] = args[l];
        l++;
    }
    holder[tracker[i]] = NULL;
    for(int o = 0; o < tracker[i]; o++) {
        printf("Holder is: %s\n", holder[o]);
    }
    pid_t p = fork();
    pid_t waiting;
    if(p == 0) {
    printf("I am in child process\n");
    execvp(holder[0], holder);

    fprintf(stderr, "Child process could not execvp!\n");
    exit(1);
    }
    else {
        if(p < 0) {
            fprintf(stderr, "Fork FAILED!\n");
        }
        else {
            waiting = wait(&status);
            printf("Child %d, status %d\n", waiting, status);
        }
    }
    for(int i = 0; i < numOfCommands; i++) {
        args[i] = NULL;
    }
}

}   

return 0;

}
David
  • 217
  • 4
  • 14
  • why don't you use `system` in that case? – Jean-François Fabre Sep 17 '16 at 16:42
  • This is an assignment I am working on and there are guidelines I must follow. – David Sep 17 '16 at 16:47
  • What are the printfs telling you? (That's a rhetorical question.) Just add more printfs or use a debugger. The only thing that matters is what's in the `holder` array when you call `execvp`. It's either right or it's wrong, and if it's wrong, it's up to you to figure out why. – user3386109 Sep 17 '16 at 17:06
  • Don't cast the return of `malloc`. All you need is `char *commands = malloc (MAX_CHARACTERS * sizeof *commands);` See: [**Do I cast the result of malloc?**](http://stackoverflow.com/q/605845/995714) for thorough explanation. – David C. Rankin Sep 17 '16 at 18:15

1 Answers1

0

I figured out the answer. I have a nested for loop that uses the same iteration variable name so that was causing my iterations to jump to undesired places.

David
  • 217
  • 4
  • 14