Question

Good morning, I've been "fighting" with this method for a long time and finally I decided to ask for help because I don't get what am I doing wrong. I am trying to create multiple children from the same parent and make the STDOUT of "child 1" the STDIN of "child 2" that way until there are no more children like a pipeline.

My actual code

void filter(void) {

 if(Number_cmd != 0) {

 int p,i;
 int fd[2];

 for(i=0;i<Number_cmd;i++)
     pipe(fd);

 for(p=(Number_cmd-1); p>=0; p--){
     switch(fork()) {
     case -1:
           perror("fork");
           exit(1);
     case  0:  
        /* Child */
           close(fd[1]);
           close(0);
           dup(fd[0]);
           close(fd[0]); 

           execlp(filter[p], filter[p], NULL);
           perror("exec");
           exit(1);
     default:            
         /* Father */
           close(fd[0]);          
           close(1);
           dup(fd[1]);                
           close(fd[1]);
           break;
         }
      }
   } 
}

void directory(char* directory_name) {

   DIR* dir = NULL;
   struct dirent* ent;
   char fich[1024];
   char buff[4096];
   int fd, reading;
   struct stat sdata;

   dir = opendir(directory_name);

   while((ent=readdir(dir))!=NULL) {
        if(ent->d_name[0]=='.')
          continue;

        fich[0]='\0'; 
        strcat(fich, directory_name); 
        strcat(fich, "/");          
        strcat(fich, ent->d_name); 
        stat(fich,&sdata);

        if(S_ISDIR(sdata.st_mode))
          continue;

        fd = open(fich, O_RDONLY);

        while((reading= read(fd, buff, 4096)) > 0){
           (write(1, buff, reading) < reading);
           continue;
       }
        close(fd);  
   }
   closedir(dir);
}

The problem is when im trying to call the method with more than one command, it looks like ii doesnt do anything, but when i run it with one command is working ok. Thank everyone in advance. (Sorry for my English; it's not my native language)

EDIT

This is the main method:

char** cmd;
int Number_cmd;

int main(int argc, char* argv[]){ 

    cmd = &(argv[2]);            /*list of the commands*/
    Number_cmd = argc-2;         /* number of commands*/

      filter();
      directory(argv[1]);
      return 0;
}
Was it helpful?

Solution

Problem 1:

  for(i=0;i<Number_cmd;i++)
      pipe(fd);

Unless the variable Number_cmd is 1 (or smaller), you leak pipe descriptors like crazy. You need some sort of array of file descriptors:

int fds[Number_cmd][2];

for (int i = 0; i < Number_cmd; i++)
    if (pipe(fd[i]) != 0)
        …report error and abandon ship (remembering to close any opened pipes)…

Problem 2:

This is mainly a consequence of Problem 1 — but you don't close enough file descriptors. Essentially, if you have N pipes open, your child will end up closing 2*N file descriptors, after duplicating two to standard input and standard output. The first and last children will be different; they don't override standard input and standard output respectively.

There are probably other issues, but these two spring to mind at once from a fairly quick look at the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top