Redirect stdout of two processes to another process's stdin in Linux C

c, linux, redirect, stdin, stdout

Solution

I'm not sure that it's a good idea, but it is perfectly feasible. The key observation is that you only need one pipe. Several processes (with a common parent) can write to a single pipe. However, only one file descriptor can be used as the standard input. In the original code, only one of the pipes was connected to C as its standard input (the others were still connected, but mainly because you hadn't closed enough descriptors).

- Rule of thumb: if you connect one end of a pipe to standard input or standard output via `dup2()` (or `dup()`), you should close both of the file descriptors returned by `pipe()`.

Try this code for size. I've reduced the bushiness of the tree, removed unused variables (nothing uses the process IDs returned by `fork()`), renamed the pipe, made sure it is closed properly in each process, and provided some writing activity in processes A and B and some reading activity in process C in lieu of running commands. I'm assuming that `usleep()` (micro-sleep, sleep time expressed in microseconds) is available; if not, try `nanosleep()`, but it has a more complex interface).

#include <unistd.h>

int main(void)
{
    int ABtoC[2];
    pipe(ABtoC);

    if (fork() > 0)
    {
        // Process A
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);     // Close this too!
        // Process A writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Hi\n", sizeof("Hi\n")-1);
            usleep(5000);
        }
    }
    else if (fork() > 0)
    {
        // Process B
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);
        // Process B writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Lo\n", sizeof("Lo\n")-1);
            usleep(5000);
        }
    }
    else
    {
        char buffer[100];
        ssize_t nbytes;
        close(ABtoC[1]);
        dup2(ABtoC[0], STDIN_FILENO);
        close(ABtoC[0]);
        // Process C reading from both A and B
        while ((nbytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
            write(STDOUT_FILENO, buffer, nbytes);
    }
    return(0);
}

The tail end of a run on my Mac (Mac OS X 10.7.5, GCC 4.7.1) produced:

Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Hi
Lo
Lo
Hi
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Lo
Hi

Problem

I'm running into problem about redirect stdout of multi process. Assuming I have process A, I use fork() in A and then I get process A and B. And I use fork() in B, finally I get process A, B and C. Both B and C are implementing other program by exec(). Now, I try to redirect the stdout of A and B to stdin of C with two pipes. ``` #include<unistd.h> #include<stdio.h> #include<sty/types.h> int main() { int AtoC [2]; pipe(AtoC); int fd1,fd2; fd1=fork(); if(fd1>0) { /***In process A, I do the following steps: ***/ close(AtoC[0]); dup2(AtoC[1], STDOUT_FILENO); /* program running in process A */ } else { int BtoC [2]; pipe(BtoC); fd2=fork(); if(fd2>0) { /***In process B, I do the following steps: ***/ close(AtoC[1]); close(BtoC[0]); dup2(BtoC[1], STDOUT_FILENO); /*** execute another program in process B using execl(); ***/ } else { /*** In process C, I do the following steps: ***/ close(AtoC[1]); close(BtoC[1]); dup2(AtoC[0],STDIN_FILENO); dup2(BtoC[0],STDIN_FILENO); /*** execute another different program in process C using execl(); ***/ } } } ``` Now, after these two statements : ``` dup2(AtoC[0],STDIN_FILENO); dup2(BtoC[0],STDIN_FILENO); ``` the stdin of process C is finally redirect to `BtoC[0]` ,which is the stdout of process B. And the stdout of process A is not passed into process C's stdin. My question is whether there is any solution can let me redirect both process A and B's stdout into process C's stdin at the same time. Another question is if I also want to print the stdout of process A in screen, what should I do? I know the command `tee` in command line. I try to use the corresponding function `tee(int fd_in, int fd_out, size_t len, unsigned int flags)`in process A, but I failed to print anything of stdout of process A. Any suggestion is appreciated, thanks.

Original source