0

I am working on an assignment to create an extremely simple Linux shell in C, and it works almost exactly how I want it to.

If the user enters a simple Linux command, the program will run it and loop to allow another command. If the user enters "quit", the program exits.

My problem is that the commands only work the first time. Afterward, they seem to somehow become formatted improperly. Is there a way I can reinitialize my args array so that it will receive the new input properly?

int main() {
    char* args[50];          // Argument array.
    char userInput[200];     // User input.
    char* userQuit = "quit"; // String to be compared to user input to quit program.
    int pid;                 // Process ID for fork().
    int i = 0;               // Counter.

    while(1) {
        // Promt and get input from user.
        printf("minor5> ");
        fgets(userInput, sizeof(userInput), stdin);

        // Pass userInput into args array.
        args[0] = strtok(userInput, " \n\0");

        // Loop to separate args into individual arguments, delimited by either space, newline, or NULL.
        while(args[i] != NULL) {
            i++;
            args[i] = strtok(NULL, " \n\0");
        }

        // If the first argument is "quit", exit the program.
        if(strcmp(args[0], userQuit) == 0) {
            printf("Exiting Minor5 Shell...\n");
            exit(EXIT_SUCCESS);
        }

        // Create child process.
        pid = fork();

        // Parent process will wait for child to execute.
        // Child process will execute the command given in userInput.
        if(pid > 0) {
            // Parent //
            wait( (int *) 0 );
        } else {
            // Child //
            int errChk;
            errChk = execvp(args[0], args);

            if(errChk == -1) {
                printf("%s: Command not found\n", userInput);
            }
        }
    }

    return 0;
}
0

1 Answer 1

1

You need to ensure that args has a NULL last value. It probably had one on the first command, by chance, but no guarantee

Here's a reworked snippet of your parsing loop [please pardon the gratuitous style cleanup]:

// Pass userInput into args array.
char *uptr = userInput;

i = 0;
while (1) {
    char *token = strtok(uptr, " \n");
    uptr = NULL;

    if (token == NULL)
        break;

    args[i++] = token;
}

// NOTE: this is the key missing ingredient from your code
args[i] = NULL;
Sign up to request clarification or add additional context in comments.

4 Comments

sorry but why do you think that the args in his code is not guaranteed to have NULL last value? this condition while(args[i] != NULL) guarantees that, doesn't it? the other thing is that he doesn't reset his i back to 0
This code caused a segmentation fault on attempting to enter a command the second time.
@mangusta Thanks man. I didn't notice I forgot to reset my counter. That was the whole problem. It works perfectly now! Thank you.
@mangusta No, it doesn't. Pull OP's code and run it. Do: ls /etc/passwd. Then do: vi [without any args]. You'll see it was passed: vi "" instead of no args. Try a manual vi for reference

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.