如何使 cat 和 grep 在 c 中的第一个和第二个管道中工作,就像 bash 中的 heredoc <<

how make cat and grep work in the first and the second pipe in c writing like heredoc in bash <<

我正在努力使 shell 像 bash,但我无法解决 heredoc << 所以我为这个问题制作了一个尽可能简单的测试代码。

        void pipeline()
    {
        int i = 0;
        int fd[2];
        pid_t pid;
        int fdd = 0;
    
        while (i < 2)
        {
            pipe(fd);
            pid = fork();
            if (pid == 0)
            {   
                //dup2(fd[1],1); if i dup in the first pipe cat dont finalize
                if (i == 0)
                    dup2(fd[0],0);
                write(fd[1], "hello\nhow\nare\nyou\n", 17);
                close(fd[0]);
                close(fd[1]);
                dup2(fdd, 0);
                if (i == 0)
                    execlp("cat", "cat", NULL);
                else
                    execlp("grep", "grep", "you" , NULL);
                perror("error");
                exit(1);
            }
            else 
            {   
                close(fd[1]);
                fdd = fd[0];
                wait(NULL);
                i++;
            }
        }
    }
    
    int main(int *argc, char **argv, char **env)
    {
        pipeline();
}

我知道 cat 和 grep 需要 EOF 到 运行;我正在做的是在 stdin 和 运行ning cat 中编写,但我的问题是:如何在不在第一个管道上复制 stdout 的情况下为 grep 保存 stdout?

如果我在 dup2(fd[1],1) cat 上 dup 在第一个管道中不起作用,有人可以帮我让这段代码工作吗?并尽可能使其与 bash heredoc 相似。

how do I save stdout for grep without duping stdout on the first pipe?

我将从最右边到最左边重新排列子进程的创建 - 然后 grep 首先创建并可以输出到初始输出描述符。一个必要的改变是 运行 所有子进程在等待之前和写入之前,这样即使管道缓冲区不能满足 heredoc 也不会出现死锁.

void pipeline()
{
    int i = 2;  // create children from last to first
    int fd[2];
    pid_t pid;
    int fdd = 1;    // output of last child is STDOUT
    while (i--)
    {
        pipe(fd);
        pid = fork();
        if (pid == 0)
        {
            dup2(fdd, 1);   // child's output
            dup2(fd[0], 0);
            close(fd[0]);
            close(fd[1]);
            if (i == 0)
                execlp("cat", "cat", "-A", NULL);
            else
                execlp("grep", "grep", "you" , NULL);
            perror("error");
            exit(1);
        }
        if (fdd != 1) close(fdd);   // close if a pipe write end
        fdd = fd[1];    // preceding child's output is pipe write end
        close(fd[0]);
    }
    write(fd[1], "hello\nhow\nare\nyou\n", 17);
    close(fd[1]);   // signal EOF to child
    while (wait(NULL) > 0) ;    // wait for all children
}