I need to write my pipestream. My program should get names of another programs and call them, first program should read from stdin second from output of the first an so on. Last program print the result in stdout. The problem is it doesn't work. When I call this program to two another simple programs (they both are to read x and print 2*x while it can read), and give it some data I suppose that I should get result immediately, but I don't. What is more when I give it end of file it doesn't react. Don't pay attention on safe_* functions, they are the same as standart, but the check for an errors. Help me, please =)
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "safe_functions.h"
void call(const char *filename, int in_descr, int out_descr, pid_t *sons, int n)
{
sons[n] = safe_fork();
if(sons[n] == 0)
{
safe_dup2(in_descr, STDIN_FILENO);
safe_dup2(out_descr, STDOUT_FILENO);
safe_execv(filename, (char **)NULL);
}
}
int find_num(pid_t * sons, int n, pid_t id)
{
for(int i=0; i<n; i++)
if(sons[i] == id)
return i;
return -1;
}
int main(int argc, const char ** argv)
{
int **descr;
descr = (int**)safe_malloc(argc*sizeof(int*));
for(int i=0; i<argc; i++)
descr[i] = (int*) safe_malloc(2*sizeof(int));
for(int i=1; i+1<argc; i++)
safe_pipe(descr[i]);
descr[0][0] = 0;
descr[argc-1][1] = 1;
pid_t *sons = safe_malloc((argc-1) * sizeof(pid_t));
for(int i=1; i<argc; i++)
call(argv[i], descr[i-1][0], descr[i][1], sons, i-1);
int status;
pid_t id;
while(1)
{
id = safe_wait(&status);
if(id == -1)
break;
if(WIFEXITED(status))
{
int num = find_num(sons, argc-1, id);
safe_close(descr[num][0]);
safe_close(descr[num+1][1]);
continue;
}
if(WIFSIGNALED(status))
{
int num = find_num(sons, argc-1, id);
fatal_error("Process was teminated by a signal", argv[num+1], WEXITSTATUS(status));
}
}
free(sons);
for(int i=0; i<argc; i++)
free(descr[i]);
free(descr);
}
An SSCCE (Short, Self-Contained, Correct Example)
This code uses my
stderr.h
andstderr.c
code in place of yourerror.h
(contact me if you want the code — see my profile). It writes out thesafe_*
functions — or, at least, my implementation of them.The
dump_fds()
function reports on which file descriptors are open in the range 0-19, which is sufficient for this and most programs; a more complex version works withsysconf()
to determine the number of file descriptors to check, but the number is usually vastly greater (eg 256 or larger) than the number in use. I use it as a simple way to check that all the file descriptors that should be closed are closed.There is considerable debug output. The call to
execv()
provides a proper argument list.Example Output