简体   繁体   中英

Piping to redirect stdout of one program to stdin of another

We have to write a C program that will essentially redirect stdin of one command/program to another command/program stdout, using pipes. If the program on the command line was passed ./a.out ls -l \\; more ./a.out ls -l \\; more , it should redirect the stdout of ls -l to more , with the \\; being the delimiter. This program should work for any command/program that is in our path so: ./a.out cat filename.c \\; more ./a.out cat filename.c \\; more , should be the same as typing: cat filename.c | more cat filename.c | more .

My problem is that my program can't seem to exec properly or that the pipes are not working as expected. Basically I'm just getting no output aside from the print statement debugging I have placed. To be specific, the program prints: Exec... and then ERROR, which is all in the parent code.

  #include <fcntl.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  void pipeit(char * pro1, char * pro2, char * p1args[], char * p2args[])
  {
     pid_t pid;
     int fd[2];
     int st;
     pipe(fd);
     pid = fork();

     if(pid < 0)
     {
        printf("Error Forking...\n");
        exit(-1);
     }
     else if(pid == 0)
     {
        dup2(fd[1],1);
        close(fd[0]);
        close(1);
        printf("Exec 1...\n");
        execv(pro1, p1args);
        printf("ERROR\n");
     }
     else
     {
        waitpid(pid,&st,0);
        if(st<0)
        {
           printf("Child Error\n");   
        }
        dup2(fd[0],0);
        close(fd[1]);
        close(0);
        printf("Exec...\n");
        execv(pro2,p2args);
        printf("ERROR\n");
     }
     return;
  }
  /* THIS IS JUST COMMAND LINE PARSING */
  int main(int argc, char * argv[])
  {
     int i = 1;
     char * pro1;
     char * pro2;
     char * first[argc+1];
     char * second[argc+1];
     while(i<argc && argv[i][0] != ';')
     {
        if(i == 1)
        {
           pro1 = argv[i];
        }
        else
        {
           first[i] = argv[i];
        }
        i++; 
     }
     first[i] = NULL;
     while(i<argc)
     {
        if(argv[i][0] == ';')
        {
           i++;
           pro2 = argv[i];
        }
        else
        {
           second[i] = argv[i];
        }
        i++; 
     }
     second[i] = NULL;
     pipeit(pro1,pro2,first, second);
     return 0;
  }

In the child, you have:

    dup2(fd[1],1);
    close(fd[0]);
    close(1);

This duplicates the pipe to standard output, but then closes standard output. Fix by not closing standard output, and by closing both ends of the pipe. Rule of thumb: if you duplicate one end of a pipe to standard input, output or error, you should close both of the original pipe descriptors.

    dup2(fd[1],1);
    close(fd[0]);
    close(fd[1]);

You have the analogous problem in the parent with standard input being closed.

You also have the wait() in the wrong place. The processes must run concurrently. If the first process in the pipeline generates so much data that the pipe can't hold it all, the process will block. If the other process is waiting for the first process to die before it reads anything, it isn't going to work well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM