4

I'm developing a program which executes a program using execvp. It needs to capture the results of the child process and parse them in the main process. It seems there is a way, using named pipes, and duping. I'm trying to hunt down a good example of this, but so far no luck. If anyone has any pointers, links and/or suggestions about this, I'd greatly appreciate it.

Mat
  • 202,337
  • 40
  • 393
  • 406
Jack BeNimble
  • 35,733
  • 41
  • 130
  • 213

3 Answers3

7

You don't need named pipes; unnamed pipes work just fine. Actually, often you can just use popen instead of doing the pipe/fork/dup/exec yourself. popen works like this (though your libc's implementation likely has more error checking):

FILE *popen(const char *command, const char *type) {
    int fds[2];
    const char *argv[4] = {"/bin/sh", "-c", command};
    pipe(fds);
    if (fork() == 0) {
        close(fds[0]);
        dup2(type[0] == 'r' ? 0 : 1, fds[1]);
        close(fds[1]);
        execvp(argv[0], argv);
        exit(-1);
    }
    close(fds[1]);
    return fdopen(fds[0], type);
}

This creates an unnamed pipe, and forks. In the child, it reattaches stdout (or stdin) to one end of the pipe, then execs the child. The parent can simply read (or write) from the other end of the pipe.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • Great. I've reviewed how pipes work and this ought to do the trick. – Jack BeNimble Apr 18 '09 at 01:41
  • Just for the record if someone stumbles onto this. The conditional based on type[0] is not entirely correct. One needs to close the stdout/stdin before the dup2 for it be possible. Also the pipe is unidirectional and the fds[1] is the write end so it'd need to be the fds[0] in dup2 for the read case. – Tommi Kyntola Feb 16 '15 at 16:18
  • @TommiKyntola from the `dup2` man page: "*makes `newfd` be the copy of `oldfd`, closing `newfd` first if necessary*" so this should work without manually closing stdout/stdin first. – scohe001 May 16 '18 at 19:08
2

Can't you just use popen()?

janneb
  • 36,249
  • 2
  • 81
  • 97
0

Here is a simple example that demonstrates the use of popen to achieve your goal. Just put something more interesting than "echo" as the command :)

#include <stdio.h>

int main() 
{
    char buf[100];
    int i = 0;
    FILE *p = popen("echo \"Test\"","r");
    if (p != NULL )
    {
        while (!feof(p) && (i < 99) )
        {
            fread(&buf[i++],1,1,p);
        }
        buf[i] = 0;
        printf("%s",buf);
        pclose(p);
        return 0;
    }
    else
    {
        return -1;
    }
}
David Weber
  • 1,965
  • 1
  • 22
  • 32