views:

52

answers:

1

Hello. I have some problems trying to make a simple program using execlp, fork and pipes. The program at hand is supossed to do "last |head -5| sort" but it doesn't work. Here is the code.

#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

//last |head -5| sort
int main(int argc, char* argv[]){

 int buzon[2];
 int buzon2[2];

 if(pipe(buzon) < 0)
  error("error de pipe");

 switch(fork()){

  case -1:
   error("error de fork");

  case 0:
   if(close(1) < 0) error("error de close");
   if(dup(buzon[1]) < 0) error("error de dup");
   if(close(buzon[0]) < 0) error("error de close");
   if(close(buzon[1]) < 0) error("error de close");
   execlp("last", "last", NULL);
   error("error de execlp");

 }



 switch(fork()){

  case -1:
   error("error de fork");

  case 0:
   if(close(0) < 0) error("error de close");
   if(close(1) < 0) error("error de close");
   if(dup(buzon[0]) < 0) error("error de dup");
   if(dup(buzon[1]) < 0) error("error de dup");
   if(close(buzon[0]) < 0) error("error de close");
   if(close(buzon[1]) < 0) error("error de close");
   execlp("head", "head", "-n 5", NULL);
   error("error de execlp");


 }


 switch(fork()){
  case -1: 
   error("error de fork");
  case 0:
   if(close(0)<0) error("error de close");
   if(dup(buzon[0]) != 1) error("error de dup");
   if(close(buzon[0]) < 0) error("error de close");
   if(close(buzon[1]) < 0) error("error de close");
   execlp("sort", "sort", NULL);
   error("error de execlp");
 }


 if(close(buzon[0]) < 0) error("error de close");
 if(close(buzon[1]) < 0) error("error de close");
 while(wait(NULL) != -1);





}

Any idea of what fails. The problem is when I use 2 pipes. If I make a program which only uses 1 pipe, it works.

A: 

You need to actually create the second pipe, then use that for the stdout of the head process and the stdin of the sort process. At the point of your second fork():

 close(buzon[1]);
 pipe(buzon2);

 /* Now buzon[0], buzon2[0] and buzon2[1] are still open in this process */

 switch(fork()){

  case -1:
   error("error de fork");

  case 0:
   if(close(0) < 0) error("error de close");
   if(close(1) < 0) error("error de close");
   if(dup(buzon[0]) < 0) error("error de dup");
   if(dup(buzon2[1]) < 0) error("error de dup");
   if(close(buzon[0]) < 0) error("error de close");
   if(close(buzon2[0]) < 0) error("error de close");
   if(close(buzon2[1]) < 0) error("error de close");
   execlp("head", "head", "-n 5", NULL);
   error("error de execlp");
   exit(1);
 }

 close(buzon[0]);
 close(buzon2[1]);
 /* Now buzon2[0] is still open in this process */

 switch(fork()){
  case -1: 
   error("error de fork");
  case 0:
   if(close(0)<0) error("error de close");
   if(dup(buzon2[0]) < 0) error("error de dup");
   if(close(buzon2[0]) < 0) error("error de close");
   execlp("sort", "sort", NULL);
   error("error de execlp");
   exit(1);
 }

 close(buzon2[0]);

(You should also exit() the child process after an execlp() error)

caf
After doing that, it gives me the following error when executing:Head: writing error: invalid file descriptor.Any idea?
olbrich
@olbrich: It works fine for me - perhaps you didn't get all the changes (are you calling `dup()` on now `buzon2[1]` in the `head` path, rather than `buzon[1]`?)
caf
@caf: it works fine now, I confused buzon2[1] with buzon[1] in the dup(). Thank you very much!
olbrich