CS360 Final -- December 11, 1999. Question 2:
Answer and grading
15 points
You will need to create two pipes. One for prog2 and one
for prog3. Standard output will be dup'd to the first pipe,
and f1 will be fdopen'd on the second pipe. Then you
call fork()/execlp() for the two programs. Actually, the
ordering is different than the above. You need to:
- Call pipe() for one pipe.
- Call fork()
- In the child, you:
- Call dup2() so that standard input comes from the pipe.
- Close both ends of the pipe (note, the read end will still be
open as standard input.
- Call execlp() on prog2.
- Meanwhile, we're back in the parent.
- Call dup2() so that standard output goes to the pipe.
- Close both ends of the pipe (note, the write end will still be
open as standard output.
- Call pipe() again.
- Call fork() again.
- In the child, you:
- Call dup2() so that standard input comes from the pipe.
- Close both ends of the pipe (note, the read end will still be
open as standard input.
- Call execlp() on prog3.
- Back in the parent:
- Call f1 = fdopen() on the write end of the pipe.
- Close the read end of the pipe.
- At the end of the program call wait() for both children.
Here's the code with all error checking.
main(int argc, char **argv)
{
/* Declarations: */
FILE *f1;
int p1[2];
int p2[2];
int i;
if (argc != 1) { fprintf(stderr, "usage: prog1\n"); exit(1); }
if (pipe(p1) < 0) { perror("pipe"); exit(1); }
i = fork();
if (i < 0) { perror("fork"); exit(1); }
if (i == 0) { /* Child */
if (dup2(p1[0], 0) < 0) { perror("dup2"); exit(1); }
close(p1[0]);
close(p1[1]);
execlp("prog2", "prog2", NULL);
perror("execlp");
exit(1);
}
if (dup2(p1[1], 1) < 0) { perror("dup2"); exit(1); }
close(p1[0]);
close(p1[1]);
if (pipe(p2) < 0) { perror("pipe"); exit(1); }
i = fork();
if (i < 0) { perror("fork"); exit(1); }
if (i == 0) { /* Child */
if (dup2(p2[0], 0) < 0) { perror("dup2"); exit(1); }
close(p2[0]);
close(p2[1]);
execlp("prog3", "prog3", NULL);
perror("execlp");
exit(1);
}
f1 = fdopen(p2[1], "w");
if (f1 == NULL) { perror("fdopen"); exit(1); }
close(p2[0]);
.... /* Various code that writes to both standard output and f1 */
wait(&i);
wait(&i);
}
Grading
Points were allocated as follows:
- Call pipe() for one pipe: 1 point
- Call fork() for prog2: 1 point
- Call dup2() correctly in the child: 1 point
- Call close() on both ends of the pipe in the child: 2 points
- Call execlp() on prog2 in the child: 1 point
- Call exit() after execlp(): 1 point
- Call dup2() in the parent so that standard output goes to the pipe: 1 point.
- Close the read end of the pipe in the parent: 1 point
- (You should close the write end too, but since that won't kill the code
too badly, I didn't take off for it).
- Call pipe() again: 1 point
- Call fork() again: 1 point
- Have the child's code match the code for the first child: 1 point
- Call f1 = fdopen() on the write end of the pipe: 1 point
- Close the read end of the pipe: 1 point
- At the end of the program call wait() for both children: 1 point
That assumes that you got the ordering correct. I took off points
(up to 10) for when the flow of control was confused, since that is
extremely important for getting the program right.
I didn't take off for error checking, except for execlp().