Public feed
#529378
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <errno.h>#include <string.h>#define MAXLENGTH 255/* Like read, but hide EINTR and EAGAIN. */static ssize_tn_read (int fd, void *buffer, size_t count){ size_t n = 0; char *buf = buffer; int i; while (n < count) { i = read (fd, buf + n, count - n); switch (i) { case 0: return n; break; case -1: switch (errno) { case EINTR: case EAGAIN:#ifdef ERESTART case ERESTART:#endif break; default: return -1; } break; default: n += i; break; } } return n;}/* Like write, but hide EINTR and EAGAIN. */static ssize_tn_write (int fd, const void *buffer, size_t count){ size_t n = 0; const char *buf = buffer; int i; while (n < count) { i = write(fd, buf + n, count - n); switch (i) { case 0: return n; break; case -1: switch (errno) { case EINTR: case EAGAIN:#ifdef ERESTART case ERESTART:#endif break; default: return -1; } break; default: n += i; break; } } return n;}static voidbe_child (int in, int out, int err){ char buffer[MAXLENGTH]; FILE *outs; FILE *ins; outs = fdopen (out, "w"); ins = fdopen (in, "r"); memset (buffer, 0, sizeof (buffer)); while (fgets (buffer, MAXLENGTH, ins) != NULL) { //int i, len, max; char reverse[MAXLENGTH +1]; char *p = buffer; int i; memset (reverse, 0, sizeof (reverse)); p += strlen(buffer); p -= 2; for(i = 0; i < strlen(buffer); i++, p--) { reverse[i] = *p; }#if 0 if ((len = strlen (buffer)) == 0) { exit (0); } max = len; if (max % 2) { max --; } len -=1; max /= 2; for (i = 0; i < max; i++) { char c = buffer[i]; buffer[i] = buffer[len - i]; buffer[len -i] = c; }#endif fprintf (outs, "%s\n", reverse); fflush (outs); memset (buffer, 0, sizeof (buffer)); }}static voidbe_parent (int in, int out, int err){ char buffer[MAXLENGTH]; FILE *outs; FILE *ins; outs = fdopen (out, "r"); ins = fdopen (in, "w"); memset (buffer, 0, sizeof (buffer)); while (fgets (buffer, MAXLENGTH, stdin) != NULL) { fprintf (ins, "%s", buffer); fflush (ins); memset (buffer, 0, sizeof (buffer)); fgets (buffer, MAXLENGTH, outs); fprintf (stdout, "%s", buffer); memset (buffer, 0, sizeof (buffer)); }}enum { PIPE_READ = 0, PIPE_WRITE = 1};intmain (int argc, char **argv){ pid_t c_pid; pid_t gc_pid; int ready_a[2]; int ready_b[2]; int stdin_pipe[2]; int stdout_pipe[2]; int stderr_pipe[2]; int stdin_fd, stdout_fd, stderr_fd; int c; /* setup the pipes */ if (pipe (ready_a) || pipe (ready_b)) { goto bail_ready; } if (pipe (stdin_pipe)) { goto bail_stdin; } if (pipe (stdout_pipe)) { goto bail_stdout; } if (pipe (stderr_pipe)) { goto bail_stderr; } /* I wanna have children! */ c_pid = fork (); switch (c_pid) { case -1: /* Ewk error */ perror ("Error during fork"); exit (-1); break; /* not reached */ case 0: /* The child: lets get mommy & daddy some * grandchildren */ /* we only need our ends of the pipes */ close (ready_a[0]); close (ready_b[1]); close (stdin_pipe[PIPE_WRITE]); close (stdout_pipe[PIPE_READ]); close (stderr_pipe[PIPE_READ]); gc_pid = fork (); if (gc_pid < 0) { /* Ewk error during fork */ } else if (gc_pid > 0) { /* The intermidiate child must DIE! */ exit (0); } setsid (); setpgid (0, 0);#if 0 close (STDIN_FILENO); close (STDOUT_FILENO); close (STDERR_FILENO); /* Set up stdin/out/err */ dup2 (stdin_pipe[PIPE_READ], STDIN_FILENO); close (stdin_pipe[PIPE_READ]); dup2 (stdout_pipe[PIPE_WRITE], STDOUT_FILENO); close (stdout_pipe[PIPE_WRITE]); dup2 (stderr_pipe[PIPE_WRITE], STDERR_FILENO); close (stderr_pipe[PIPE_WRITE]);#endif c = 0; n_write (ready_a[1], &c, 1); fsync (ready_a[1]); n_read (ready_b[0], &c, 1); be_child (stdin_pipe[PIPE_READ], stdout_pipe[PIPE_WRITE], stderr_pipe[PIPE_WRITE]); break; default: /* The parent! */wait_again: /* Don't call me horned, just reaper */ if (waitpid (c_pid, NULL, 0) < 0) { if (errno == EINTR) { goto wait_again; } else if (errno == ECHILD) { ; /* NOOP! Child already reaped. */ } else { perror ("Uhm, ewkk, whatever"); } } printf ("child reaped\n"); close (ready_b[0]); close (ready_a[1]); close (stdin_pipe[PIPE_READ]); close (stdout_pipe[PIPE_WRITE]); close (stderr_pipe[PIPE_WRITE]); /* wait for the child to become read */ n_read (ready_a[0], &c, 1); /* Ok got child ready signal (hopefully) * signal the child back and close the ready * descriptors */ n_write (ready_b[1], &c, 1); close (ready_a[0]); close (ready_b[1]); stdin_fd = stdin_pipe[PIPE_WRITE]; stdout_fd = stdout_pipe[PIPE_READ]; stderr_fd = stderr_pipe[PIPE_READ]; printf ("everything ready, entering parent routine\n"); /* now lets be the parent */ be_parent (stdin_fd, stdout_fd, stderr_fd); break; } close (stderr_pipe[0]); close (stderr_pipe[1]); bail_stderr: close (stdout_pipe[0]); close (stdout_pipe[1]); bail_stdout: close (stdin_pipe[0]); close (stdin_pipe[1]); bail_stdin: close (ready_a[0]); close (ready_a[1]); close (ready_b[0]); close (ready_b[1]);bail_ready: return 0;}