The reply here is what I use in my code, and it works fine, but I think it needs a little improvement: we need to move the read AFTER the wait, else there could be a race between the child and the original processes and the read result may be unpredictable, i.e. you could read a previous reply, or just a part of the expected current reply.
I post the same code as here, just adjusting the wait() position and adding some comments:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);
int main() {
int link[2];
pid_t pid;
char foo[4096];
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execl("/bin/ls", "ls", "-1", (char *)0);
die("execl");
} else {
close(link[1]);
wait(NULL); // N.B.: wait until the child process completes, else we could read a partial or empty output
const int nbytes = read(link[0], foo, sizeof(foo)); // read the output once the child has completed
printf("Output: (%.*s)\n", nbytes, foo);
}
return 0;
}