CS162 : Machine Problem 6 - pcpipe.c Second Edition: Monday, January 18, 2010 First Edition: January 22, 2009 (One day after Obama's inauguration as 44th U.S. President) References: man pipe man 7 pipe man dup2 man fork man execve man waitpid Write a program pcpipe.c (producer-consumer-pipe) that will be invoked as follows: pcpipe -producer producerprog producer_args ... \ -consumer consumerprog consumer_args ... that has the same effect as the bash command: producerprog producer_args ... \ | consumerprog consumer_args ... For example ./pcpipe -producer ls -l /etc/init.d -consumer grep "mount" should produce the same results as the command ls -l /etc/init.d | grep "mount" The program pcpipe should work as follows: 1. Create a pipe (man 2 pipe). int filedes[2], p; // filedes[0] is the read end, // filedes[1] is the write end. p = pipe(filedes); 2a. Fork a child "prod" 2b. In the parent process, fork a second child "cons" 3. Redirect the stdout of "prod" as input for the pipe, how? In the parent "prod" try: if( dup2(filedes[1], STDOUT_FILENO) != STDOUT_FILENO ) errorExit(); else { /* output of prod will now go to pipe */ } 4. Redirect the output of the pipe as stdin for "cons". How? In the child "cons" try: if( dup2(filedes[0], STDIN_FILENO) != STDIN_FILENO ) errorExit(); else { /* output of pipe will now go to "cons" */ } 5. In "prod", execve() the "producerprog" program, ensuring that arguments are included 6. In "cons", execve() the "consumerprog" program, arguments included 7. Can parent program pcpipe exit without waiting for any of its children? Should you use waitpid() instead? Notes: 1. You can handle command line arguments as follows: int main(int argc, char *argv[], char *envv[]) { int j; for(j = 0; j < argc; ++j) { if( strcmp(argv[j], "-producer") == 0 ) { /* argv[j+1] is the producerprog followed by arguments until -consumer */ } if( strcmp(argv[j], "-consumer") == 0 ) { /* argv[j+1] is the consumerprog followed by arguments until end of array */ } } } 2. You should be careful with fork()ing. After each fork, check whether we are in the child or in the parent. For example your code should be: prod = fork(); if( prod == 0 ) { /* put producer code here */ dup2( ); close(unneeded filedes[] ) execve( ); } if( prod > 0 ) { /* parent */ cons = fork(); if(cons == 0) { /* put consumer code here */ /* similar to above */ execve( ); } } /* This is parent */ close(unneeded filedes[] ); waitpid( ... ); waitpid( ... ); } 3. the standard input of pcpipe should be made standard input of producerprog, and the standard output of pcpipe should be made standard output of consumerprog Submissions: Deadline of submission: Jan 18, 2010, 23:59 Midnight, by email to pmanalastas@gmail.com. Email enclosure should be named familynameFirstName_mp6.zip. As usual put all programs in a directory with your name, before doing zip on the directory. Include a Makefile if the build requires a library other than "libc", or if the manner of building is not the normal one. Include a README file if you want to tell the teacher any unusual features of your program, like failing to compile, or compiling but failing to run, or running but giving wrong answers, or any features that you failed to implement, or extra features that you successfully implemented. |