Using a fork process on C failed while loop

Viewed 72

I'm trying to create a simple shell interface program that takes shell commands as user input from the parent process and send the simple shell command to the child process via a pip IPC which actually executes the shell command. The child while loop keeps repeating even after typing "quit"

int main() {
    char userInput[BUFFER_SIZE];

    int fpipe[2];
    pid_t pid;

    // INTRODUCTION TO PROGRAM
    printf("------- WELCOME TO THE FORKED PARENT -------\n");
    printf("------- YOU MAY QUIT AT ANY TIME BY TYPING 'quit' or 'q' -------\n");

    if (pipe(fpipe)== -1){
        printf("------- PIPE HAS FAILED -------\n");
        return 1;
    }

    pid = fork();

    if (pid < 0){
        printf("------- FORK HAS FAILED -------\n");
        return 1;
    }

    if (pid > 0){
        close(fpipe[0]);
        printf("\nosh> ");
        scanf("%s", userInput);

        while ((strcmp(userInput,"quit") != 0 && strcmp(userInput,"q") != 0)){
            printf("\nosh> ");
            write(fpipe[1], userInput, strlen(userInput)+1);
            scanf("%s", userInput);
        }
        close(fpipe[1]);
    }

    else{
        close(fpipe[1]);

        while(1){
            if (read(fpipe[0], userInput, BUFFER_SIZE) == -1){
                return 1;

            }
            if ((strcmp(userInput,"quit") != 0 && strcmp(userInput,"q") != 0)){
                system(userInput);
                printf("osh> ");
            }
            else{
                break;
            }
        }
        close(fpipe[0]);
    }
    return 0;
}
1 Answers

The problem is that the loop in the parent stops when the user enters quit, it doesn't send it to the child. So the child's condition for stopping the loop is never matched. It keeps reading from the pipe, which returns nothing because it's at EOF, so it keeps executing the last command that was sent.

The simplest solution is for the child to break out of the loop when it gets EOF from the pipe, rather than looking for quit.

        while(1){
            int n;
            n = read(fpipe[0], userInput, BUFFER_SIZE);
            if (n == -1) {
                return 1;
            }
            if (n == 0) {
                break;
            }
            system(userInput);
        }
Related