Search code examples
c++cfilepipefile-descriptor

How do I pass pipe to a C app as a file?


I would like to do something like this:

nc localhost 1234 | myapp

But I would like myapp to be able to see the pipe passed from the first part of the command as a file.

For example:

int main() {
    File *fp;
    fp = /* get pointer file which is the pipe passed as "nc localhost 1234" */
}

Is this possible?

Thanks.


Solution

  • Have you considered using a named pipe? They are like pipes, one directional, but they have names. If you wanted two directions you could just make two pipes. You make the pipes like this:

    mkfifo /dir/to_prog
    mkfifo /dir/from_prog
    

    Then the output of one program can be separately piped to the second and the name of the pipe can be used like a normal filename:

    nc localhost 1234 > /dir/to_prog
    myapp -i /dir/to_prog -o /dir/from_prog
    cat < /dir/from_prog
    

    Except that those three commands could even be issued in three separate shells. myapp.c could look like this:

    #include <stdio.h>
    
    int
    main(int argc, char *argv[])
    {
        int iFd, oFd, opt;
    
        while (opt = getopt(argc, argv, "i:o:")) != -1) {
    
            switch (opt) {
    
            ...
    
            case 'i':  iFd = open(optarg, O_RDONLY); break;
            case 'o':  oFd = open(optarg, O_WRONLY); break;
    
            ...
            }
        }
    
        ...
    
        read(iFd, inBuf);
    
        ...
    
        write(oFd, outBuf);
    
        ...
    }
    

    I've used this method a few times when I've needed to be able to handle a stream of data in a program that also needed to keep it's own STDIN or STDOUT for some reason. The only tricky part comes if you wish myprog to be able to read data from the pipe that was written by two programs, as in:

    cat afile > /dir/to_prog
    cat anotherFile > /dir/to_prog
    

    and have myprog be able to read both files. The issue is that when the first cat exits it closes /dir/to_prog, and myprog will read this as an EOF. A lot of programs interpret EOF as "no more data time to quit!" but in this case once the second cat starts myprog will be able to read more data from /dir/to_prog, it just has to know not to give up reading when it sees EOF. And of course, if two programs write to a named pipe (or read from it) at the same time their data will be randomly interleaved.