We often use a pipe. As says Amardeep, the child process inherits the parent's descriptor, including pipe.
Here is an example for 2 commands. I'm not sure of my algorithm for n commands :-)
void do__pipe(char** cmd1, char** cmd2)
{
int fd[2]; /* fd[0] for reading fd[1] for writting */
if (pipe(fd) == -1)
{
perror("pipe");
}
switch (fork())
{
case -1:
perror("fork"); exit (1);
case 0:
close (fd[0]);
dup2 (fd[1], STDOUT_FILENO);
close (fd[1]);
execvp (cmd1[0], cmd1);
exit (1);
}
dup2(STDIN_FILENO, STDIN_FILENO);
switch (fork())
{
case -1:
perror("fork (2)"); exit (1);
case 0:
close (fd[1]);
dup2 (fd[0], STDIN_FILENO);
close (fd[0]);
execvp (cmd2[0], cmd2);
exit (1);
}u
wait((int*)NULL);
}
this code has been taken from a small shell I had to write for my studies, so char** cmd1 would be something like ["cat", "/etc/passwd"] and cmd2 could be ["wc", "-l"]