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.
Asked
Active
Viewed 1.6k times
4
-
Related: [get command output in pipe, C for Linux](http://stackoverflow.com/questions/219138/) – ephemient Apr 17 '09 at 21:32
3 Answers
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 fork
s. In the child, it reattaches stdout (or stdin) to one end of the pipe, then exec
s 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
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