The following is a multi-piping program that connect any number of commands.
Steps:
- Calculate the number of needed pipes.
- Create the pipes and note that all coming childs will inherit it (remember to close all the pipes in the parent).
- Fork a new child and redirect STDIN & STDOUT and note that first command should not redirect STDIN and last command should not redirect STDOUT.
- Close all the pipes after redirection in child and repeat 3 until all commands are done.
- Close all pipes in the parent.
- Parent wait for the last child.
Usage: pipe cmd1 cmd2 cmd3 ...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc,char* *argv,char* *envp)
{
int i, j;
int nProcess = argc - 1;
int nPipes = nProcess - 1;
int fd[nPipes][2]; // Pipe file descriptors
pid_t pid;
char cmd[20] = "/bin/";
#ifdef DEBUG
printf("Pipes: [%d] Process [%d]\n", nPipes, nProcess);
#endif
/********************/
/* Create the pipes */
/********************/
for(i=0;i < nPipes;i++)
{
pipe(fd[i]);
}
/************************************/
/* Spawn child(s) for all processes */
/************************************/
for(j = 1;j <= nProcess;j++)
{
#ifdef DEBUG
printf("Child [%d] spawned.\n", j);
#endif
pid = fork();
if (pid == 0)
{
/***********************************************/
/* ----------- ----------- */
/* fd[j-2] --> process --> fd[j-1] */
/* ----------- ----------- */
/***********************************************/
if ( j != 1 ) // First cmd should NOT redirect STDIN
dup2(fd[j-2][1], STDIN_FILENO);
if ( j != nProcess ) // Last cmd should NOT redirect STDOUT
dup2(fd[j-1][0], STDOUT_FILENO);
/*************************************************************/
/* Close unuseful file descriptors: */
/* the pipe's writing and reading ends */
/* (the latter is not needed anymore, after the duplication) */
/*************************************************************/
for(i=0; i < nPipes;i++)
{
close(fd[i][0]);
close(fd[i][1]);
}
/**********************************************************/
/* Append command to /bin/ */
/* Child will have a separate (copy-on-write) copy of cmd */
/**********************************************************/
strcat(cmd, argv[j]);
execlp(cmd, argv[j], (char *)0);
perror("execlp");
exit( EXIT_FAILURE );
} /* end Child section */
}
/*****************************/
/* Parent code will follow */
/* If everything goes right! */
/*****************************/
for(i=0; i < nPipes;i++)
{
close(fd[i][0]);
close(fd[i][1]);
}
/****************************/
/* Wait for the last child! */
/****************************/
waitpid(pid, 0, 0);
return 0;
}
I have tested this code on Solaris and it worked properly!
0 comments:
Post a Comment