Search code examples
cunixposixfile-descriptordup

Piping the stdout of a command to the stdin of another other using shared file and dup2()


I am writing a porgram with takes two arguments - the name of commands. The program should redirect the output of the first to a file 'tmp' than execute it, than redirect the stdin of the second command to 'tmp' and execute the second command.


#include<unistd.h>
#include<fcntl.h>
#include<wait.h>
#include<stdio.h>

int main(int argc, char** argv){
    int fd = open("tmp", O_RDWR |O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
    int cpid = fork();
    
    if(cpid == 0){  
        dup2(fd, 1);
        execlp(argv[1], "", NULL);          
    }
    
    wait(NULL); 
    //If we uncoment this line the program gives correct output
    //fd = open("tmp", O_RDWR, S_IRUSR | S_IWUSR);
 
    dup2(fd, 0);
    
    execlp(argv[2], "", NULL);  
}

However when i run the program like ./main ls wc instead of 5 5 50 i get output 0 0 0 which means the wc command reads 0 bytes from stdin. But if I instead create the file descriptor anew on the same file 'tmp' the program gives the correct output. How can this behaviour be explained?


Solution

  • This question is basically a duplicate of Can anyone explain a simple description regarding 'file descriptor' after fork()? but since this is a bit subtle I'll explain this specific case.

    1. The process opens a file. This creates a file description. File descriptions are an intermediate concept between files and file descriptors. They are not directly exposed in the Unix API, but they have an important property in addition to the file that they point to, which we'll see in a minute.
    2. The child writes to this file description. The parent waits.
    3. The parent reads from the file description.

    At the end of step 2, the file position on this file description is the end of the file. So at step 3, the parent starts reading at the end of the file.

    If you add a call to rewind(fd) after wait(NULL), the child will read from the beginning of the file.

    If you open the same file with a new open call, this creates a new file description. open puts the position on the new file description at the beginning of the file unless you set append mode.

    The same file descriptions can be accessed through any number of file descriptors, potentially in different processes. The file position is a property of the file description, so anything that moves it (reading, writing, seeking) through one file descriptor also moves it for the other file descriptors, even in different processes.