diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-11-20 20:50:01 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-11-20 20:50:01 +0000 |
commit | a773d207e5326979dbae610af9f727ba9d9aab9a (patch) | |
tree | 25eae41092ce63d11c23e2bde172d49858a6b094 /usr.bin/mail/tty.c | |
parent | 65d78d4142675bd4f69ddc0d983e59907c358f64 (diff) |
Major signal overhaul. We no longer longjmp all over the place.
Instead, routines responsible to gathering user input (or in some
cases outputting data) catch the signals and set flags as needed.
Because of this some handlers are install without the SA_RESTART
flag so syscalls are not restarted and we can check the flag. All
signal handlers are now safe.
This should make the flow of control a bit more grokable but the
code is still ugly.
Diffstat (limited to 'usr.bin/mail/tty.c')
-rw-r--r-- | usr.bin/mail/tty.c | 152 |
1 files changed, 99 insertions, 53 deletions
diff --git a/usr.bin/mail/tty.c b/usr.bin/mail/tty.c index 0bfb6006ebc..0acd5bf1861 100644 --- a/usr.bin/mail/tty.c +++ b/usr.bin/mail/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.12 2001/06/23 23:04:23 millert Exp $ */ +/* $OpenBSD: tty.c,v 1.13 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: tty.c,v 1.7 1997/07/09 05:25:46 mikel Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: tty.c,v 1.12 2001/06/23 23:04:23 millert Exp $"; +static char rcsid[] = "$OpenBSD: tty.c,v 1.13 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -51,14 +51,14 @@ static char rcsid[] = "$OpenBSD: tty.c,v 1.12 2001/06/23 23:04:23 millert Exp $" #include "rcv.h" #include "extern.h" #include <sys/ioctl.h> +#include <errno.h> static cc_t c_erase; /* Current erase char */ static cc_t c_kill; /* Current kill char */ -static sigjmp_buf rewrite; /* Place to go when continued */ -static sigjmp_buf intjmp; /* Place to go when interrupted */ #ifndef TIOCSTI static int ttyset; /* We must now do erase/kill */ #endif +static volatile sig_atomic_t ttysignal; /* Interrupted by a signal? */ /* * Read all relevant header fields. @@ -70,24 +70,28 @@ grabh(hp, gflags) int gflags; { struct termios ttybuf; - volatile sig_t saveint; #ifndef TIOCSTI - sig_t savequit; + struct sigaction savequit; #else # ifdef TIOCEXT - volatile int extproc; + int extproc; int flag; # endif /* TIOCEXT */ #endif - sig_t savetstp; - sig_t savettou; - sig_t savettin; - volatile int errs = 0; + struct sigaction savetstp; + struct sigaction savettou; + struct sigaction savettin; + struct sigaction act; + char *s; + int error; - savetstp = signal(SIGTSTP, SIG_DFL); - savettou = signal(SIGTTOU, SIG_DFL); - savettin = signal(SIGTTIN, SIG_DFL); - errs = 0; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = SIG_DFL; + (void)sigaction(SIGTSTP, &act, &savetstp); + (void)sigaction(SIGTTOU, &act, &savettou); + (void)sigaction(SIGTTIN, &act, &savettin); + error = 1; #ifndef TIOCSTI ttyset = 0; #endif @@ -100,10 +104,10 @@ grabh(hp, gflags) #ifndef TIOCSTI ttybuf.c_cc[VERASE] = 0; ttybuf.c_cc[VKILL] = 0; - if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL) - (void)signal(SIGINT, SIG_DFL); - if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL) - (void)signal(SIGQUIT, SIG_DFL); + act.sa_handler = SIG_IGN; + if (sigaction(SIGQUIT, &act, &savequit) == 0 && + savequit.sa_handler == SIG_DFL) + (void)sigaction(SIGQUIT, &savequit, NULL); #else # ifdef TIOCEXT extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0); @@ -113,53 +117,58 @@ grabh(hp, gflags) warn("TIOCEXT: off"); } # endif /* TIOCEXT */ - if (sigsetjmp(intjmp, 1)) { - errs = SIGINT; - goto out; - } - saveint = signal(SIGINT, ttyint); #endif if (gflags & GTO) { #ifndef TIOCSTI if (!ttyset && hp->h_to != NIL) ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf); #endif - hp->h_to = - extract(readtty("To: ", detract(hp->h_to, 0)), GTO); + s = readtty("To: ", detract(hp->h_to, 0)); + if (s == NULL) + goto out; + hp->h_to = extract(s, GTO); } if (gflags & GSUBJECT) { #ifndef TIOCSTI if (!ttyset && hp->h_subject != NULL) ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf); #endif - hp->h_subject = readtty("Subject: ", hp->h_subject); + s = readtty("Subject: ", hp->h_subject); + if (s == NULL) + goto out; + hp->h_subject = s; } if (gflags & GCC) { #ifndef TIOCSTI if (!ttyset && hp->h_cc != NIL) ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf); #endif - hp->h_cc = - extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC); + s = readtty("Cc: ", detract(hp->h_cc, 0)); + if (s == NULL) + goto out; + hp->h_cc = extract(s, GCC); } if (gflags & GBCC) { #ifndef TIOCSTI if (!ttyset && hp->h_bcc != NIL) ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf); #endif - hp->h_bcc = - extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC); + s = readtty("Bcc: ", detract(hp->h_bcc, 0)); + if (s == NULL) + goto out; + hp->h_bcc = extract(s, GBCC); } + error = 0; out: - (void)signal(SIGTSTP, savetstp); - (void)signal(SIGTTOU, savettou); - (void)signal(SIGTTIN, savettin); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); #ifndef TIOCSTI ttybuf.c_cc[VERASE] = c_erase; ttybuf.c_cc[VKILL] = c_kill; if (ttyset) tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf); - (void)signal(SIGQUIT, savequit); + (void)sigaction(SIGQUIT, &savequit, NULL); #else # ifdef TIOCEXT if (extproc) { @@ -169,8 +178,7 @@ out: } # endif /* TIOCEXT */ #endif - (void)signal(SIGINT, saveint); - return(errs); + return(error); } /* @@ -184,9 +192,11 @@ char * readtty(pr, src) char pr[], src[]; { + struct sigaction act, oact; + sigset_t oset; char ch, canonb[BUFSIZ]; - volatile int c; - char *cp, * volatile cp2; + char *cp, *cp2; + int c; fputs(pr, stdout); fflush(stdout); @@ -219,26 +229,50 @@ readtty(pr, src) while (cp2 < canonb + BUFSIZ) *cp2++ = 0; cp2 = cp; - if (sigsetjmp(rewrite, 1)) - goto redo; - (void)signal(SIGTSTP, ttystop); - (void)signal(SIGTTOU, ttystop); - (void)signal(SIGTTIN, ttystop); + sigemptyset(&act.sa_mask); + act.sa_flags = 0; /* Note: will not restart syscalls */ + act.sa_handler = ttyint; + (void)sigaction(SIGINT, &act, &oact); + act.sa_handler = ttystop; + (void)sigaction(SIGTSTP, &act, NULL); + (void)sigaction(SIGTTOU, &act, NULL); + (void)sigaction(SIGTTIN, &act, NULL); + (void)sigprocmask(SIG_UNBLOCK, &intset, &oset); clearerr(stdin); while (cp2 < canonb + BUFSIZ) { c = getc(stdin); + switch (ttysignal) { + case SIGINT: + ttysignal = 0; + cp2 = NULL; + c = EOF; + /* FALLTHROUGH */ + case 0: + break; + default: + ttysignal = 0; + goto redo; + } if (c == EOF || c == '\n') break; *cp2++ = c; } - *cp2 = 0; - (void)signal(SIGTSTP, SIG_DFL); - (void)signal(SIGTTOU, SIG_DFL); - (void)signal(SIGTTIN, SIG_DFL); + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGTSTP, &act, NULL); + (void)sigaction(SIGTTOU, &act, NULL); + (void)sigaction(SIGTTIN, &act, NULL); + (void)sigaction(SIGTTIN, &oact, NULL); + if (cp2 == NULL) + return(NULL); /* user hit ^C */ + *cp2 = '\0'; if (c == EOF && ferror(stdin)) { redo: cp = strlen(canonb) > 0 ? canonb : NULL; clearerr(stdin); + /* XXX - make iterative, not recursive */ return(readtty(pr, cp)); } #ifndef TIOCSTI @@ -274,7 +308,7 @@ redo: *cp2 = '\0'; #endif if (equal("", canonb)) - return(NULL); + return(""); return(savestr(canonb)); } @@ -285,16 +319,27 @@ void ttystop(s) int s; { - sig_t old_action = signal(s, SIG_DFL); + struct sigaction act, oact; sigset_t nset; + int save_errno; + /* + * Save old handler and set to default. + * Unblock receipt of 's' and then resend it. + */ + save_errno = errno; + (void)sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = SIG_DFL; + (void)sigaction(s, &act, &oact); (void)sigemptyset(&nset); (void)sigaddset(&nset, s); (void)sigprocmask(SIG_UNBLOCK, &nset, NULL); (void)kill(0, s); (void)sigprocmask(SIG_BLOCK, &nset, NULL); - (void)signal(s, old_action); - siglongjmp(rewrite, 1); + (void)sigaction(s, &oact, NULL); + ttysignal = s; + errno = save_errno; } /*ARGSUSED*/ @@ -302,5 +347,6 @@ void ttyint(s) int s; { - siglongjmp(intjmp, 1); + + ttysignal = s; } |