在我自己的shell中实现管道

时间:2017-04-04 15:00:48

标签: c shell fork

我一直在尝试在自己的shell中实现管道,但是有一个我无法修复的错误:

目前,我只管道两个流程。我得到两个命令参数,并将其传递给pipe_launch()。这是我的pipe_launch()函数:

int pipe_launch(char** arg1, char** arg2) {
    int fd[2], pid;

    pipe(fd);

    if( (pid = fork()) == 0 ) {
        close(1);
        dup(fd[1]);
        close(fd[0]);
        launch(arg1, STDOUT_FILENO, KHOL_FG);
        exit(EXIT_FAILURE);
    }
    else if (pid > 0){
        close(0);
        dup(fd[0]);
        close(fd[1]);
        return launch(arg2, STDOUT_FILENO, KHOL_FG);
    }
}

供参考,launch()功能:

int launch(char **args, int fd, int options) {

    int khol_bg = 1 ? options & KHOL_BG : 0;
    int khol_stdout = 1 ? options & KHOL_STDOUT : 0;
    int khol_stderr = 1 ? options & KHOL_STDERR : 0;
    int khol_stdin = 1 ? options & KHOL_STDIN : 0;

    pid_t pid, wpid;

    int status;

    if( (pid = fork()) == 0 ) {
        // child process

        if(fd > 2) {

            if(khol_stdout && dup2(fd, STDOUT_FILENO) == -1 ) {
                fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
                return 1;
            }

            if(khol_stderr && dup2(fd, STDERR_FILENO) == -1 ) {
                fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
                return 1;
            }

            if(khol_stdin && dup2(fd, STDIN_FILENO) == -1 ) {
                fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
                return 1;
            }

            close(fd);
        }


        if( execvp(args[0], args) == -1 ) {
            fprintf(stderr, RED "khol: %s\n" RESET, strerror(errno));
        }
        exit(EXIT_FAILURE);
    } else if (pid < 0) {
        fprintf(stderr, RED "khol: %s\n" RESET, strerror(errno));
    } else {
        do {
            if( !khol_bg ) {
                wpid = waitpid(pid, &status, WUNTRACED);
            }
            else {
                printf(YELLOW "[bg][%d] - %s\n" RESET, pid, args[0]);
            }
        } while ( !WIFEXITED(status) && !WIFSIGNALED(status) );
    }

    return 1;
}

现在,当我运行cat sorting | sort之类的命令时,它会成功执行并显示所需的输出,但在显示下一个提示后,它会自动退出:

/home/sanketdg/projects/khol > cat sorting | sort
12
15
46
78
89
/home/sanketdg/projects/khol > % 

%表示shell已退出。

1 个答案:

答案 0 :(得分:1)

你的shell正在关闭它自己的标准输入,并且无法读取任何将来的命令。

else if (pid > 0){
    close(0);

(它还为管道的第一部分执行了一个不必要的双叉:设置管道后一个fork(),然后fork()中的另一个launch()。)

pipe()需要在父shell中执行,但我建议将FD操作推迟到分叉的launch()子项。不要忘记之后关闭父母的pipe两个结尾。