#include #include #include #include #include #include #include #include #include static int bailout(const char *str) { perror(str); exit(EXIT_FAILURE); } static void do_child(int rd) { char buf[16384]; struct timespec ts = {2, 0}; int in = 0; !nanosleep(&ts, NULL) || bailout("child: nanosleep"); while (1) { ssize_t rdcnt = read(rd, buf, sizeof buf); if (-1 == rdcnt) bailout("child: read"); if (0 == rdcnt) break; in += rdcnt; } fprintf(stderr, "in = %d\n", in); exit(EXIT_SUCCESS); } static void do_parent(int wd) { int out; char buf[5*PIPE_BUF]; FILE *stream; int opts; memset(buf, 'a', sizeof buf -1); buf[sizeof buf -1] = 0; if (-1 == (opts = fcntl(wd, F_GETFL)) || -1 == fcntl(wd, F_SETFL, opts | O_NONBLOCK)) bailout("parent: fcntl"); NULL != (stream = fdopen(wd, "w")) || bailout("parent: fdopen"); !setvbuf(stream, NULL, _IONBF, 0) || bailout("parent: setvbbuf"); out = fprintf(stream, "%s", buf); fprintf(stderr, "out = %d (%s)\n", out, strerror(errno)); exit(EXIT_SUCCESS); } void main(void) { int pipe_ends[2]; !pipe(pipe_ends) || bailout("pipe"); switch (fork()) { case -1: bailout("fork"); case 0: close(pipe_ends[1]); do_child(pipe_ends[0]); default: close(pipe_ends[0]); do_parent(pipe_ends[1]); } }