Pipes Shell的sort命令仅在退出时打印输出

时间:2019-11-21 21:44:59

标签: c shell pipe fork

我正在用C设计自己的shell,但是有一个非常奇怪的问题,到目前为止,我只在使用sort进行管道处理时才遇到这种情况。

每当我使用sort(例如ls | sort -r)运行管道时,输出都是正确的,但仅在退出外壳程序时显示。我尝试用不同的方式进行分叉/管道传输,重定向管道的stderror输出(以防万一它被放到那里,等等)而无法解决。

奇怪的是,其他管道命令,例如grep甚至lolcat似乎都可以正常工作。如果有人可以在这里指导我,我将不胜感激。我的命令执行功能包括在下面。

int exec_command(char *command) {
    pid_t pid;

    // Split the arguments
    char *args[LENGTH];
    int i = 0;

    // Gets the first token, tokenizing on ' '
    char *token = strtok(command, " ");
    while (token != NULL && i < LENGTH - 1) { // Ensures we don't go out of bounds
        args[i] = token; // Append it to the args list
        token = strtok(NULL, " "); // Fetch next token
        i++; // Increment our index
    } 
    args[i] = NULL; // Set the element after last to NULL

    // Handles cd
    // Removed for simplicity

    int pipe_index;
    if ((pipe_index = find_pipe(args)) != -1) { // Has a pipe
        // Split the args array into two arrays - left half and right half - based on the pipe
        args[pipe_index] = NULL; // args (left_args) ends at the pipe
        char *right_args[LENGTH];
        for (i = pipe_index + 1; i < LENGTH - 1 && args[i] != NULL; i++)
            right_args[i - pipe_index - 1] = args[i];  // right_args contains everything after the pipe
        right_args[i - pipe_index - 1] = NULL; // end right_args

        int pipefd[3];
        if (pipe(pipefd) == -1) { // Create pipe
            perror("pipe");
            return -1;
        }

        if ((pid = fork()) < 0) { // Create child
            perror("fork");
            return -1;
        }

        if (pid == 0) { // In child
            if ((pid = fork()) < 0) { // Create grandchild
                perror("fork");
                return -1;
            }

            if (pid == 0) { // Grandchild reads from pipe and handles the right-half command
                close(pipefd[1]); // Close unused write end
                dup2(pipefd[0], 0); // Replaces standard input with pipe input
                if(execvp(right_args[0], right_args) == -1)
                    printf("Command failed. Check spelling and arguments\n");
                kill(getpid(), SIGTERM); // Ensure the grandchild is killed
                return 0;
            } else { // Child writes to pipe and handles the left command
                close(pipefd[0]); // Close unused read end
                dup2(pipefd[1], 1); // Replaces standard output with pipe output
                dup2(pipefd[2], 2); // Replaces standard error with pipe error
                if(execvp(args[0], args) == -1)
                    printf("Command failed. Check spelling and arguments\n");
                kill(getpid(), SIGTERM); // Ensure the child is killed
                return 0;
            }
        } else // In parent
            wait(0);

        return 0;
    } // End pipe

    // Executes normal commands, those without a pipe
    // Removed for simplicity

    return 0;
}

0 个答案:

没有答案