#include "apue.h" #define BUFFSIZE 512 static void sig_term(int); static volatile sig_atomic_t sigcaught; /* set by signal handler */ void loop(int ptym, int ignoreeof) { pid_t child; int nread; char buf[BUFFSIZE]; if ((child = fork()) < 0) { err_sys("fork error"); } else if (child == 0) { /* child copies stdin to ptym */ for ( ; ; ) { if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) err_sys("read error from stdin"); else if (nread == 0) break; /* EOF on stdin means we're done */ if (writen(ptym, buf, nread) != nread) err_sys("writen error to master pty"); } /* * We always terminate when we encounter an EOF on stdin, * but we notify the parent only if ignoreeof is 0. */ if (ignoreeof == 0) kill(getppid(), SIGTERM); /* notify parent */ exit(0); /* and terminate; child can't return */ } /* * Parent copies ptym to stdout. */ if (signal_intr(SIGTERM, sig_term) == SIG_ERR) err_sys("signal_intr error for SIGTERM"); for ( ; ; ) { if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) break; /* signal caught, error, or EOF */ if (writen(STDOUT_FILENO, buf, nread) != nread) err_sys("writen error to stdout"); } /* * There are three ways to get here: sig_term() below caught the * SIGTERM from the child, we read an EOF on the pty master (which * means we have to signal the child to stop), or an error. */ if (sigcaught == 0) /* tell child if it didn't send us the signal */ kill(child, SIGTERM); /* * Parent returns to caller. */ } /* * The child sends us SIGTERM when it gets EOF on the pty slave or * when read() fails. We probably interrupted the read() of ptym. */ static void sig_term(int signo) { sigcaught = 1; /* just set flag and return */ }