views:

112

answers:

1

Hello

I have tried to do fork() and piping in main and it works perfectly fine but when I try to implement it in a function for some reason I don't get any output, this is my code:

void cmd(int **pipefd,int count,int type, int last);    

int main(int argc, char *argv[]) {
int pipefd[3][2];
int i, total_cmds = 3,count = 0;
int in = 1;

for(i = 0; i < total_cmds;i++){
 pipe(pipefd[count++]);
 cmd(pipefd,count,i,0);    
}

 /*Last Command*/
 cmd(pipefd,count,i,1);    

exit(EXIT_SUCCESS);
}

void cmd(int **pipefd,int count,int type, int last){    
    int child_pid,i,i2;

     if ((child_pid = fork()) == 0) {

            if(count == 1){
               dup2(pipefd[count-1][1],1); /*first command*/
            }
            else if(last!=1){
               dup2(pipefd[count - 2][0],0); /*middle commands*/
               dup2(pipefd[count - 1][1],1);
            }
            else if(last == 1){
               dup2(pipefd[count - 1][0],0); /*last command*/
            }


            for(i = 0; i < count;i++){/*close pipes*/
            for(i2 = 0; i2 < 2;i2++){
               close(pipefd[i][i2]);
            }}



            if(type == 0){
                execlp("ls","ls","-al",NULL);
            }
            else if(type == 1){
                execlp("grep","grep",".bak",NULL);
            }
            else if(type==2){
                               execl("/usr/bin/wc","wc",NULL);
            }
            else if(type ==3){
                         execl("/usr/bin/wc","wc","-l",NULL);
           }
            perror("exec");
            exit(EXIT_FAILURE);
    }
    else if (child_pid < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
    }
}

I checked the file descriptors and it is opening the right ones, not sure what the problem could be..

Edit: I Fixed the problem but I'm having child processes, which way would be the best to wait for the child , while(wait(NULL)!=-1); but that hangs

+2  A: 

The problem is that pipefd is not an int**, it's an int[3][2], so when you pass it to cmd, you get garbage. Your compiler should be giving you a warning on each call to cmd(), such as something like this:

warning: passing argument 1 of 'cmd' from incompatible pointer type

If not, turn up your warning level.

It's true that arrays decay into pointers to their first elements, so you can pass a 1-D array to a function expecting a pointer, but that's only true for the first dimension of arrays. In particular, a 2D array does not decay into a pointer to a pointer. It decays at the first level only, so pipefd can decay into the type int (*)[2], which is read as "pointer to array 2 of int"

So, the correct way to write cmd is this:

void cmd(int (*pipefd)[2],int count,int type, int last)
Adam Rosenfield
Ahh Okay That solved some of the problem but in thhis method would be the best way to kill the child processes
Luke
It seems to work now but my program hangs
Luke