maart@cs.vu.nl (Maarten Litmaath) (11/05/88)
\In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu>, pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: \I have two processes that I want to communicate. I want the parent to \be able to fprintf to the child's stdin and to fscanf from the child's \stdout. I know that I need to fork and then in the child do an execlp, \but I can't figure out how to set up the file descriptors so I can do \what I want. Other people already solved Lorien's problem, but the next is a related one. I know why the following program doesn't work. The quiz is: can YOU figure out why it fails? (Prizes to /dev/null.) ---------------------------------------------------------------------- #include <stdio.h> #include <signal.h> #define my_dup2(a, b) (dup2(a, b) != -1 || panic("Dup failed")) char Text[] = "This is the text"; int down[2], up[2]; main() { char *whoami; int catch(), chpid; signal(SIGPIPE, catch); if (pipe(down) != 0) panic("error creating pipe down"); if (pipe(up) != 0) panic("error creating pipe up"); switch (chpid = fork()) { case -1: panic("Fork failed"); case 0: whoami = "Child"; do_child(); break; default: whoami = "Parent"; fprintf(stderr, "Child pid is %d\n", chpid); do_parent(); break; } fprintf(stderr, "%s exits\n", whoami); } do_parent() { FILE *fp; char buf[100]; int nr_read; fprintf(stderr, "Parent pipe\n"); /* Connect write end of down to std output */ close(1); my_dup2(down[1], 1); close(down[1]); /* Connect read end of up to std input */ close(0); my_dup2(up[0], 0); close(up[0]); /* Convert output file descriptor to stream */ if ((fp = fdopen(1, "w")) == NULL) panic("Can't convert descriptor to stream"); fprintf(fp, "%s", Text); if (fclose(fp) == EOF) panic("Fclose failed"); /* Child now sees EOF --> terminates */ fprintf(stderr, "Just before read\n"); /* Read results back from child */ while ((nr_read = read(0, buf, sizeof buf)) > 0) fprintf(stderr, "received '%.*s'\n", nr_read, buf); } do_child() { /* Connect read end of down to std input */ close(0); my_dup2(down[0], 0); close(down[0]); /* Connect write end of up to std output */ close(1); my_dup2(up[1], 1); close(up[1]); /* Exec the actual child program */ fprintf(stderr, "Just before exec\n"); execl("/bin/cat", "cat", (char *) 0); panic("Exec failed"); } panic(msg) char *msg; { fprintf(stderr, "Panic: %s\n", msg); exit(1); } catch(signo) int signo; { if (signo == SIGPIPE) fprintf(stderr, "Pipe broken\n"); else fprintf(stderr, "Signal %d\n", signo); exit(2); } -- George Bush: |Maarten Litmaath @ VU Amsterdam: Capt. Slip of the Tongue |maart@cs.vu.nl, mcvax!botter!maart