Public feed #529378

Stuff

public c v1 · immutable
Raw Edit
·published 2007-06-01 22:01 UTC
rendered paste body
#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;}