=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mail/tty.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- src/usr.bin/mail/tty.c 2001/06/23 23:04:23 1.12 +++ src/usr.bin/mail/tty.c 2001/11/20 20:50:00 1.13 @@ -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 @@ #include "rcv.h" #include "extern.h" #include +#include 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 @@ 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 @@ #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 @@ 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 @@ } # endif /* TIOCEXT */ #endif - (void)signal(SIGINT, saveint); - return(errs); + return(error); } /* @@ -184,9 +192,11 @@ 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 @@ 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 @@ *cp2 = '\0'; #endif if (equal("", canonb)) - return(NULL); + return(""); return(savestr(canonb)); } @@ -285,16 +319,27 @@ 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 @@ ttyint(s) int s; { - siglongjmp(intjmp, 1); + + ttysignal = s; }