diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-02-07 20:16:48 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-02-07 20:16:48 +0000 |
commit | cd5093984971948489d38c67a4c8e4e16568ca9a (patch) | |
tree | eb5143db3163e87b067388a79b481bbc22a25e61 /usr.bin | |
parent | 93b7efb0a56c62840bfe5dd6e4e8d0efac14fb89 (diff) |
Change tipout to use poll(2) instead of the ghastly setup with signals/longjmp.
Tested/briefly read by mk@, blambert@.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tip/cmds.c | 14 | ||||
-rw-r--r-- | usr.bin/tip/tipout.c | 169 |
2 files changed, 111 insertions, 72 deletions
diff --git a/usr.bin/tip/cmds.c b/usr.bin/tip/cmds.c index d17bd53682b..f5b4661e376 100644 --- a/usr.bin/tip/cmds.c +++ b/usr.bin/tip/cmds.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmds.c,v 1.31 2010/01/12 22:36:38 deraadt Exp $ */ +/* $OpenBSD: cmds.c,v 1.32 2010/02/07 20:16:47 nicm Exp $ */ /* $NetBSD: cmds.c,v 1.7 1997/02/11 09:24:03 mrg Exp $ */ /* @@ -143,7 +143,7 @@ transfer(char *buf, int fd, char *eofchars) parwrite(FD, buf, size(buf)); quit = 0; - kill(tipout_pid, SIGIOT); + write(tipout_fd, "W", 1); read(tipout_fd, (char *)&ccc, 1); /* Wait until read process stops */ /* @@ -297,7 +297,7 @@ transmit(FILE *fp, char *eofchars, char *command) time_t start_t, stop_t; sig_t f; - kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ + write(tipout_fd, "W", 1); /* put TIPOUT into a wait state */ stop = 0; f = signal(SIGINT, stopsnd); tcsetattr(0, TCSAFLUSH, &defchars); @@ -476,7 +476,7 @@ pipeout(int c) putchar(c); if (prompt("Local command? ", buf, sizeof(buf))) return; - kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ + write(tipout_fd, "W", 1); /* put TIPOUT into a wait state */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); tcsetattr(0, TCSAFLUSH, &defchars); @@ -529,7 +529,7 @@ consh(int c) putchar(c); if (prompt("Local command? ", buf, sizeof(buf))) return; - kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */ + write(tipout_fd, "W", 1); /* put TIPOUT into a wait state */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); tcsetattr(0, TCSAFLUSH, &defchars); @@ -610,7 +610,7 @@ setscript(void) /* * enable TIPOUT side for dialogue */ - kill(tipout_pid, SIGEMT); + write(tipout_fd, "S", 1); if (boolean(value(SCRIPT))) write(tipout_fd, value(RECORD), size(value(RECORD))); write(tipout_fd, "\n", 1); @@ -745,7 +745,7 @@ variable(int c) vlex(buf); if (vtable[BEAUTIFY].v_access&CHANGED) { vtable[BEAUTIFY].v_access &= ~CHANGED; - kill(tipout_pid, SIGSYS); + write(tipout_fd, "B", 1); } if (vtable[SCRIPT].v_access&CHANGED) { vtable[SCRIPT].v_access &= ~CHANGED; diff --git a/usr.bin/tip/tipout.c b/usr.bin/tip/tipout.c index 9898d76f2bf..c3b2c733bb0 100644 --- a/usr.bin/tip/tipout.c +++ b/usr.bin/tip/tipout.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tipout.c,v 1.20 2009/12/12 13:38:09 nicm Exp $ */ +/* $OpenBSD: tipout.c,v 1.21 2010/02/07 20:16:47 nicm Exp $ */ /* $NetBSD: tipout.c,v 1.5 1996/12/29 10:34:12 cgd Exp $ */ /* @@ -30,6 +30,10 @@ * SUCH DAMAGE. */ +#include <sys/types.h> + +#include <poll.h> + #include "tip.h" /* @@ -39,33 +43,30 @@ * reading from the remote host */ -static jmp_buf sigbuf; +static void tipout_wait(void); +static void tipout_script(void); +static void tipout_write(char *, size_t); +static void tipout_sighandler(int); -static void intIOT(int); -static void intEMT(int); -static void intTERM(int); -static void intSYS(int); +volatile sig_atomic_t tipout_die; /* * TIPOUT wait state routine -- - * sent by TIPIN when it wants to posses the remote host + * sent by TIPIN when it wants to possess the remote host */ -/*ARGSUSED*/ static void -intIOT(int signo) +tipout_wait(void) { write(tipin_fd, &ccc, 1); read(tipin_fd, &ccc, 1); - longjmp(sigbuf, 1); } /* * Scripting command interpreter -- * accepts script file name over the pipe and acts accordingly */ -/*ARGSUSED*/ static void -intEMT(int signo) +tipout_script(void) { char c, line[256]; char *pline = line; @@ -91,25 +92,39 @@ intEMT(int signo) } } write(tipin_fd, &reply, 1); - longjmp(sigbuf, 1); } +/* + * Write remote input out to stdout (and script file if enabled). + */ static void -intTERM(int signo) +tipout_write(char *buf, size_t len) { - if (boolean(value(SCRIPT)) && fscript != NULL) - fclose(fscript); - if (signo && tipin_pid) - kill(tipin_pid, signo); - exit(0); + char *cp; + + for (cp = buf; cp < buf + len; cp++) + *cp &= STRIP_PAR; + + write(STDOUT_FILENO, buf, len); + + if (boolean(value(SCRIPT)) && fscript != NULL) { + if (!boolean(value(BEAUTIFY))) + fwrite(buf, 1, len, fscript); + else { + for (cp = buf; cp < buf + len; cp++) { + if ((*cp >= ' ' && *cp <= '~') || + any(*cp, value(EXCEPTIONS))) + putc(*cp, fscript); + } + } + } } -/*ARGSUSED*/ +/* ARGSUSED */ static void -intSYS(int signo) +tipout_sighandler(int signo) { - setboolean(value(BEAUTIFY), !boolean(value(BEAUTIFY))); - longjmp(sigbuf, 1); + tipout_die = 1; } /* @@ -118,54 +133,78 @@ intSYS(int signo) void tipout(void) { - char buf[BUFSIZ]; - char *cp; - ssize_t scnt; - size_t cnt; - sigset_t mask, omask; + struct pollfd pfds[2]; + char buf[BUFSIZ], ch; + ssize_t len; + int flag; signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); - signal(SIGEMT, intEMT); /* attention from TIPIN */ - signal(SIGTERM, intTERM); /* time to go signal */ - signal(SIGIOT, intIOT); /* scripting going on signal */ - signal(SIGHUP, intTERM); /* for dial-ups */ - signal(SIGSYS, intSYS); /* beautify toggle */ - (void) setjmp(sigbuf); - sigprocmask(SIG_BLOCK, NULL, &omask); - for (;;) { - sigprocmask(SIG_SETMASK, &omask, NULL); - scnt = read(FD, buf, BUFSIZ); - if (scnt <= 0) { - /* lost carrier */ - if (scnt == 0 || (scnt < 0 && errno == EIO)) { - sigemptyset(&mask); - sigaddset(&mask, SIGTERM); - sigprocmask(SIG_BLOCK, &mask, NULL); - intTERM(0); - /*NOTREACHED*/ + + tipout_die = 0; + signal(SIGTERM, tipout_sighandler); + signal(SIGHUP, tipout_sighandler); + + pfds[0].fd = tipin_fd; + pfds[0].events = POLLIN; + + pfds[1].fd = FD; + pfds[1].events = POLLIN; + + while (!tipout_die) { + if (poll(pfds, 2, INFTIM) == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + goto fail; + } + + if (pfds[0].revents & (POLLHUP|POLLERR)) + goto fail; + if (pfds[0].revents & POLLIN) { + switch (read(tipin_fd, &ch, 1)) { + case 0: + goto fail; + case -1: + if (errno == EINTR || errno == EAGAIN) + break; + goto fail; + default: + switch (ch) { + case 'W': /* wait state */ + tipout_wait(); + break; + case 'S': /* script file */ + tipout_script(); + break; + case 'B': /* toggle beautify */ + flag = !boolean(value(BEAUTIFY)); + setboolean(value(BEAUTIFY), flag); + break; + } + break; } - continue; } - cnt = scnt; - sigemptyset(&mask); - sigaddset(&mask, SIGEMT); - sigaddset(&mask, SIGTERM); - sigaddset(&mask, SIGIOT); - sigaddset(&mask, SIGSYS); - sigprocmask(SIG_BLOCK, &mask, NULL); - for (cp = buf; cp < buf + cnt; cp++) - *cp &= STRIP_PAR; - write(STDOUT_FILENO, buf, cnt); - if (boolean(value(SCRIPT)) && fscript != NULL) { - if (!boolean(value(BEAUTIFY))) { - fwrite(buf, 1, cnt, fscript); - continue; + + if (pfds[1].revents & (POLLHUP|POLLERR)) + goto fail; + if (pfds[1].revents & POLLIN) { + switch (len = read(FD, buf, BUFSIZ)) { + case 0: + goto fail; + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + goto fail; + default: + tipout_write(buf, len); + break; } - for (cp = buf; cp < buf + cnt; cp++) - if ((*cp >= ' ' && *cp <= '~') || - any(*cp, value(EXCEPTIONS))) - putc(*cp, fscript); } } + +fail: + if (boolean(value(SCRIPT)) && fscript != NULL) + fclose(fscript); + kill(tipin_pid, SIGTERM); + exit(0); } |