summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2010-02-07 20:16:48 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2010-02-07 20:16:48 +0000
commitcd5093984971948489d38c67a4c8e4e16568ca9a (patch)
treeeb5143db3163e87b067388a79b481bbc22a25e61 /usr.bin
parent93b7efb0a56c62840bfe5dd6e4e8d0efac14fb89 (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.c14
-rw-r--r--usr.bin/tip/tipout.c169
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);
}