Search code examples
coperating-systempipeexecvpdup2

C Programming 2 pipes


I want to set up 2 pipes in my program. I have 1 pipe working fine, but I don't know where to place the second pipe.

The pseudo code of my setup is shown below,

Here is it with curly braces sorry about that

//the first pipe:   
pipe(pipe1) 

//the second pipe:  
pipe(pipe2) 

pid = fork()

if(pid == 0) {

  dup2(pipe1[1], 1)
  close(pipe1[0])
  execvp(beforepipe)
  }  

if(pid > 0) { //everything below is in here

  pid2 = fork()

  if(pid2 == 0){

    //pipe1
    dup2(pipe1[0],0)
    dup2(out,1)
    close(pipe1[1])
    execvp(afterpipe)

    //pipe2 does not work might need to be placed in different area
    dup2(pipe1[1],1)
    close(pipe1[0])
    execvp(beforepipe1)
    }

  if(pid2 > 0){
    close(pipe[0])
    close(pipe[1])
    wait() //this is an infinite for loop

    pid3 = fork()

    if(pid3 == 0){
      dup2(pipe2[0],0)
      dup2(out,1)
      close(pipe2[1])
      execvp(afterpipe2)
      }

    if(pid3 > 0) {
      close(pipe2[0])
      close(pipe2[1])
      wait()
      }
    }

The position of the second pipe is in the wrong place or the code is altogether wrong.

Any suggestions?


Solution

  • Your main problem is that you are not closing anywhere near enough file descriptors. Given a file input1 in the current directory containing your string "eschew obfuscation\", this code works for me (but note how many file descriptors have to be closed!).

    • Rule of thumb: if a pipe is dup2()d or dup()d to standard input or output, close both file pipe file descriptors.

    Example code (with debug tracing in place):

    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    /* command pipeline: cat input1 | tr a-z A-Z | tr \\ q */
    
    int main(void)
    {
        int pipe1[2];
        int pipe2[2];
        pid_t pid1;
        char *cmd1[] = { "cat", "input1",        0 };
        char *cmd2[] = { "tr",  "a-z",    "A-Z", 0 };
        char *cmd3[] = { "tr",  "\\",     "q",   0 };
    
        if (pipe(pipe1) != 0 || pipe(pipe2) != 0)
        {
            perror("pipe failed");
            return 1;
        }
    
        pid1 = fork();
    
        if (pid1 < 0)
        {
            perror("fork 1 failed");
            return 1;
        }
    
        if (pid1 == 0)
        {
            /* Child 1 - cat */
            dup2(pipe1[1], 1);
            close(pipe1[0]);
            close(pipe1[1]);
            close(pipe2[0]);
            close(pipe2[1]);
            execvp(cmd1[0], cmd1);
            perror("failed to execute cmd1");
            return 1;
        }
    
        printf("pid 1 = %d\n", pid1);
        fflush(stdout);
    
        pid_t pid2 = fork();
        if (pid2 < 0)
        {
            perror("fork 2 failed");
            return 1;
        }
    
        if (pid2 == 0)
        {
            /* Child 2 - tr a-z A-Z */
            dup2(pipe1[0], 0);
            dup2(pipe2[1], 1);
            close(pipe1[0]);
            close(pipe1[1]);
            close(pipe2[0]);
            close(pipe2[1]);
            execvp(cmd2[0], cmd2);
            perror("failed to execute cmd2");
            return 1;
        }
    
        printf("pid 2 = %d\n", pid2);
        fflush(stdout);
    
        pid_t pid3 = fork();
        if (pid3 < 0)
        {
            perror("fork 3 failed");
            return 1;
        }
    
        if (pid3 == 0)
        {
            /* Child 3 - tr \\ q */
            dup2(pipe2[0], 0);
            close(pipe1[0]);
            close(pipe1[1]);
            close(pipe2[0]);
            close(pipe2[1]);
            execvp(cmd3[0], cmd3);
            perror("failed to execute cmd3");
            return 1;
        }
    
        printf("pid 3 = %d\n", pid3);
        fflush(stdout);
    
        /* Parent - wait for the kids to all die */
        close(pipe1[0]);
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
    
        pid_t corpse;
        int   status;
        while ((corpse = wait(&status)) > 0)
            printf("Child %d died status 0x%.4X\n", corpse, status);
    
        return 0;
    }