Classic C. Using pipes in execvp function, redirecting stdin and stdout

I want to simulate bash in my Linux C program using pipes and the execvp function. eg

ls -l | wc -l 

There is my program:

 if(pipe(des_p) == -1) {perror("Failed to create pipe");} if(fork() == 0) { //first fork close(1); //closing stdout dup(des_p[1]); //replacing stdout with pipe write close(des_p[0]); //closing pipe read close(des_p[1]); //closing pipe write if(execvp(bash_args[0], bash_args)) // contains ls -l /* error checking */ } else { if(fork() == 0) { //creating 2nd child close(0); //closing stdin dup(des_p[0]); //replacing stdin with pipe read close(des_p[1]); //closing pipe write close(des_p[0]); //closing pipe read if(execvp(bash_args[another_place], bash_args)) //contains wc -l /* error checking */ } close(des_p[0]); close(des_p[1]); wait(0); wait(0); } 

This code really works, but does not do the right thing. What is wrong with this code? This does not work, and I do not know why.

+6
source share
2 answers

You need to close the fds in the parent, or the child will not receive EOF because the channel is still open for writing in the parent. This will cause the second wait() to hang. Works for me:

 #include <unistd.h> #include <stdlib.h> int main(int argc, char** argv) { int des_p[2]; if(pipe(des_p) == -1) { perror("Pipe failed"); exit(1); } if(fork() == 0) //first fork { close(STDOUT_FILENO); //closing stdout dup(des_p[1]); //replacing stdout with pipe write close(des_p[0]); //closing pipe read close(des_p[1]); const char* prog1[] = { "ls", "-l", 0}; execvp(prog1[0], prog1); perror("execvp of ls failed"); exit(1); } if(fork() == 0) //creating 2nd child { close(STDIN_FILENO); //closing stdin dup(des_p[0]); //replacing stdin with pipe read close(des_p[1]); //closing pipe write close(des_p[0]); const char* prog2[] = { "wc", "-l", 0}; execvp(prog2[0], prog2); perror("execvp of wc failed"); exit(1); } close(des_p[0]); close(des_p[1]); wait(0); wait(0); return 0; } 
+22
source

Read what the wait function does. It will wait until one child process occurs. You expect the first child to come out before you start the second child. The first child will probably not come out until there is some process that is being read from the other end of the channel.

+1
source

All Articles