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 | |
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')
-rw-r--r-- | usr.bin/mail/aux.c | 14 | ||||
-rw-r--r-- | usr.bin/mail/cmd1.c | 52 | ||||
-rw-r--r-- | usr.bin/mail/cmd3.c | 21 | ||||
-rw-r--r-- | usr.bin/mail/collect.c | 234 | ||||
-rw-r--r-- | usr.bin/mail/def.h | 11 | ||||
-rw-r--r-- | usr.bin/mail/edit.c | 13 | ||||
-rw-r--r-- | usr.bin/mail/extern.h | 22 | ||||
-rw-r--r-- | usr.bin/mail/fio.c | 107 | ||||
-rw-r--r-- | usr.bin/mail/glob.h | 7 | ||||
-rw-r--r-- | usr.bin/mail/lex.c | 79 | ||||
-rw-r--r-- | usr.bin/mail/main.c | 77 | ||||
-rw-r--r-- | usr.bin/mail/quit.c | 63 | ||||
-rw-r--r-- | usr.bin/mail/tty.c | 152 |
13 files changed, 458 insertions, 394 deletions
diff --git a/usr.bin/mail/aux.c b/usr.bin/mail/aux.c index 17beb8e6174..043fcea28e6 100644 --- a/usr.bin/mail/aux.c +++ b/usr.bin/mail/aux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aux.c,v 1.18 2001/09/16 16:12:56 millert Exp $ */ +/* $OpenBSD: aux.c,v 1.19 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: aux.c,v 1.5 1997/05/13 06:15:52 mikel Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)aux.c 8.1 (Berkeley) 6/6/93"; #else -static char rcsid[] = "$OpenBSD: aux.c,v 1.18 2001/09/16 16:12:56 millert Exp $"; +static char rcsid[] = "$OpenBSD: aux.c,v 1.19 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -150,7 +150,7 @@ hfield(field, mp) ibuf = setinput(mp); if ((lc = mp->m_lines - 1) < 0) return(NULL); - if (readline(ibuf, linebuf, LINESIZE) < 0) + if (readline(ibuf, linebuf, LINESIZE, NULL) < 0) return(NULL); while (lc > 0) { if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0) @@ -181,7 +181,7 @@ gethfield(f, linebuf, rem, colon) for (;;) { if (--rem < 0) return(-1); - if ((c = readline(f, linebuf, LINESIZE)) <= 0) + if ((c = readline(f, linebuf, LINESIZE, NULL)) <= 0) return(-1); for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':'; cp++) @@ -203,7 +203,7 @@ gethfield(f, linebuf, rem, colon) ungetc(c = getc(f), f); if (c != ' ' && c != '\t') break; - if ((c = readline(f, line2, LINESIZE)) < 0) + if ((c = readline(f, line2, LINESIZE, NULL)) < 0) break; rem--; for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++) @@ -559,7 +559,7 @@ name1(mp, reptype) return(cp); ibuf = setinput(mp); namebuf[0] = '\0'; - if (readline(ibuf, linebuf, LINESIZE) < 0) + if (readline(ibuf, linebuf, LINESIZE, NULL) < 0) return(savestr(namebuf)); newname: for (cp = linebuf; *cp && *cp != ' '; cp++) @@ -570,7 +570,7 @@ newname: *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;) *cp2++ = *cp++; *cp2 = '\0'; - if (readline(ibuf, linebuf, LINESIZE) < 0) + if (readline(ibuf, linebuf, LINESIZE, NULL) < 0) return(savestr(namebuf)); if ((cp = strchr(linebuf, 'F')) == NULL) return(savestr(namebuf)); diff --git a/usr.bin/mail/cmd1.c b/usr.bin/mail/cmd1.c index fd2315be97b..4d4c98fafb8 100644 --- a/usr.bin/mail/cmd1.c +++ b/usr.bin/mail/cmd1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd1.c,v 1.19 2001/11/16 17:10:06 millert Exp $ */ +/* $OpenBSD: cmd1.c,v 1.20 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: cmd1.c,v 1.9 1997/07/09 05:29:48 mikel Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)cmd1.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: cmd1.c,v 1.19 2001/11/16 17:10:06 millert Exp $"; +static char rcsid[] = "$OpenBSD: cmd1.c,v 1.20 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -57,6 +57,7 @@ static char rcsid[] = "$OpenBSD: cmd1.c,v 1.19 2001/11/16 17:10:06 millert Exp $ */ static int screen; +static volatile sig_atomic_t gothdrint; int headers(v) @@ -65,6 +66,8 @@ headers(v) int *msgvec = v; int n, mesg, flag, size; struct message *mp; + struct sigaction act, oact; + sigset_t oset; size = screensize(); n = msgvec[0]; @@ -81,7 +84,15 @@ headers(v) mesg = mp - &message[0]; if (dot != &message[n-1]) dot = mp; - for (; mp < &message[msgCount]; mp++) { + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = hdrint; + if (sigaction(SIGINT, NULL, &oact) == 0 && + oact.sa_handler != SIG_IGN) { + (void)sigaction(SIGINT, &act, &oact); + (void)sigprocmask(SIG_UNBLOCK, &intset, &oset); + } + for (gothdrint = 0; !gothdrint && mp < &message[msgCount]; mp++) { mesg++; if (mp->m_flag & MDELETED) continue; @@ -89,6 +100,14 @@ headers(v) break; printhead(mesg); } + if (gothdrint) { + fflush(stdout); + fputs("\nInterrupt\n", stderr); + } + if (oact.sa_handler != SIG_IGN) { + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); + } if (flag == 0) { puts("No more mail."); return(1); @@ -186,7 +205,7 @@ printhead(mesg) char **ap; mp = &message[mesg-1]; - (void)readline(setinput(mp), headline, LINESIZE); + (void)readline(setinput(mp), headline, LINESIZE, NULL); if ((subjline = hfield("subject", mp)) == NULL) subjline = hfield("subj", mp); /* @@ -344,8 +363,8 @@ type1(msgvec, cmd, doign, page) int nlines, *ip, restoreterm; struct message *mp; struct termios tbuf; - char * volatile cp; - FILE * volatile obuf; + char *cp; + FILE *obuf; obuf = stdout; restoreterm = 0; @@ -357,10 +376,8 @@ type1(msgvec, cmd, doign, page) restoreterm = (tcgetattr(fileno(stdin), &tbuf) == 0); obuf = Popen(cmd, "w"); if (obuf == NULL) { - warn("%s", cp); + warn("%s", cmd); obuf = stdout; - } else { - (void)signal(SIGPIPE, SIG_IGN); } } else if (value("interactive") != NULL && (page || (cp = value("crt")) != NULL)) { @@ -375,8 +392,7 @@ type1(msgvec, cmd, doign, page) if (obuf == NULL) { warn("%s", cp); obuf = stdout; - } else - (void)signal(SIGPIPE, SIG_IGN); + } } } @@ -395,7 +411,6 @@ type1(msgvec, cmd, doign, page) if (obuf != stdout) { (void)Pclose(obuf); - (void)signal(SIGPIPE, SIG_DFL); if (restoreterm) (void)tcsetattr(fileno(stdin), TCSADRAIN, &tbuf); } @@ -437,7 +452,7 @@ top(v) if (!lineb) putchar('\n'); for (lines = 0; lines < c && lines <= topl; lines++) { - if (readline(ibuf, linebuf, sizeof(linebuf)) < 0) + if (readline(ibuf, linebuf, sizeof(linebuf), NULL) < 0) break; puts(linebuf); lineb = blankline(linebuf); @@ -528,3 +543,14 @@ inc(v) return(0); } + +/* + * User hit ^C while printing the headers. + */ +void +hdrint(s) + int s; +{ + + gothdrint = 1; +} diff --git a/usr.bin/mail/cmd3.c b/usr.bin/mail/cmd3.c index 7b9d878c6f6..845350a765f 100644 --- a/usr.bin/mail/cmd3.c +++ b/usr.bin/mail/cmd3.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd3.c,v 1.15 2001/01/19 04:11:28 millert Exp $ */ +/* $OpenBSD: cmd3.c,v 1.16 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: cmd3.c,v 1.8 1997/07/09 05:29:49 mikel Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: cmd3.c,v 1.15 2001/01/19 04:11:28 millert Exp $"; +static char rcsid[] = "$OpenBSD: cmd3.c,v 1.16 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -61,17 +61,19 @@ shell(v) void *v; { char *str = v; - sig_t sigint = signal(SIGINT, SIG_IGN); char *shell; char cmd[BUFSIZ]; + struct sigaction oact; + sigset_t oset; - (void)strncpy(cmd, str, sizeof(cmd) - 1); - cmd[sizeof(cmd) - 1] = '\0'; + (void)ignoresig(SIGINT, &oact, &oset); + (void)strlcpy(cmd, str, sizeof(cmd)); if (bangexp(cmd, sizeof(cmd)) < 0) return(1); shell = value("SHELL"); (void)run_command(shell, 0, 0, -1, "-c", cmd, NULL); - (void)signal(SIGINT, sigint); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); puts("!"); return(0); } @@ -84,12 +86,15 @@ int dosh(v) void *v; { - sig_t sigint = signal(SIGINT, SIG_IGN); char *shell; + struct sigaction oact; + sigset_t oset; shell = value("SHELL"); + (void)ignoresig(SIGINT, &oact, &oset); (void)run_command(shell, 0, 0, -1, NULL, NULL, NULL); - (void)signal(SIGINT, sigint); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); putchar('\n'); return(0); } diff --git a/usr.bin/mail/collect.c b/usr.bin/mail/collect.c index 0274b3115c7..60d14da6a70 100644 --- a/usr.bin/mail/collect.c +++ b/usr.bin/mail/collect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: collect.c,v 1.21 2001/06/23 23:04:21 millert Exp $ */ +/* $OpenBSD: collect.c,v 1.22 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: collect.c,v 1.9 1997/07/09 05:25:45 mikel Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)collect.c 8.2 (Berkeley) 4/19/94"; #else -static char rcsid[] = "$OpenBSD: collect.c,v 1.21 2001/06/23 23:04:21 millert Exp $"; +static char rcsid[] = "$OpenBSD: collect.c,v 1.22 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -63,55 +63,31 @@ static char rcsid[] = "$OpenBSD: collect.c,v 1.21 2001/06/23 23:04:21 millert Ex * away on dead.letter. */ -static sig_t saveint; /* Previous SIGINT value */ -static sig_t savehup; /* Previous SIGHUP value */ -static sig_t savetstp; /* Previous SIGTSTP value */ -static sig_t savettou; /* Previous SIGTTOU value */ -static sig_t savettin; /* Previous SIGTTIN value */ static FILE *collf; /* File for saving away */ static int hadintr; /* Have seen one SIGINT so far */ -static sigjmp_buf colljmp; /* To get back to work */ -static int colljmp_p; /* whether to long jump */ -static sigjmp_buf collabort; /* To end collection with error */ - FILE * collect(hp, printheaders) struct header *hp; int printheaders; { FILE *fbuf; - int lc, cc, fd, c, t, lastlong, rc; - volatile int escape, eofcount, longline; - volatile char getsub; + int lc, cc, fd, c, t, lastlong, rc, sig; + int escape, eofcount, longline; + char getsub; char linebuf[LINESIZE], tempname[PATHSIZE], *cp; - sigset_t oset, nset; collf = NULL; - /* - * Start catching signals from here, but we're still die on interrupts - * until we're in the main loop. - */ - sigemptyset(&nset); - sigaddset(&nset, SIGINT); - sigaddset(&nset, SIGHUP); - sigprocmask(SIG_BLOCK, &nset, &oset); - if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) - (void)signal(SIGINT, collint); - if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) - (void)signal(SIGHUP, collhup); - savetstp = signal(SIGTSTP, collstop); - savettou = signal(SIGTTOU, collstop); - savettin = signal(SIGTTIN, collstop); - if (sigsetjmp(collabort, 1) || sigsetjmp(colljmp, 1)) { - (void)rm(tempname); - goto err; - } - sigdelset(&oset, SIGINT); - sigdelset(&oset, SIGHUP); - sigprocmask(SIG_SETMASK, &oset, NULL); - + eofcount = 0; + hadintr = 0; + lastlong = 0; + longline = 0; + if ((cp = value("escape")) != NULL) + escape = *cp; + else + escape = ESCAPE; noreset++; + (void)snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir); if ((fd = mkstemp(tempname)) == -1 || @@ -135,40 +111,43 @@ collect(hp, printheaders) puthead(hp, stdout, t); fflush(stdout); } - if ((cp = value("escape")) != NULL) - escape = *cp; - else - escape = ESCAPE; - eofcount = 0; - hadintr = 0; - lastlong = 0; - longline = 0; + if (getsub && gethfromtty(hp, GSUBJECT) == -1) + goto err; - if (!sigsetjmp(colljmp, 1)) { - if (getsub) - gethfromtty(hp, GSUBJECT); - } else { - /* - * Come here for printing the after-signal message. - * Duplicate messages won't be printed because - * the write is aborted if we get a SIGTTOU. - */ + if (0) { cont: - if (hadintr) { + /* Come here for printing the after-suspend message. */ + if (isatty(0)) { + puts("(continue)"); fflush(stdout); - fputs("\n(Interrupt -- one more to kill letter)\n", - stderr); - } else { - if (isatty(0)) { - puts("(continue)"); - fflush(stdout); - } } } for (;;) { - colljmp_p = 1; - c = readline(stdin, linebuf, LINESIZE); - colljmp_p = 0; + c = readline(stdin, linebuf, LINESIZE, &sig); + + /* Act on any signal caught during readline() ignoring 'c' */ + switch (sig) { + case 0: + break; + case SIGINT: + if (collabort()) + goto err; + continue; + case SIGHUP: + rewind(collf); + savedeadletter(collf); + /* + * Let's pretend nobody else wants to clean up, + * a true statement at this time. + */ + exit(1); + default: + /* Stopped due to job control */ + (void)kill(0, sig); + goto cont; + } + + /* No signal, check for error */ if (c < 0) { if (value("interactive") != NULL && value("ignoreeof") != NULL && ++eofcount < 25) { @@ -236,8 +215,9 @@ cont: * Act like an interrupt happened. */ hadintr++; - collint(SIGINT); - exit(1); + collabort(); + fputs("Interrupt\n", stderr); + goto err; case 'h': /* * Grab a bunch of headers. @@ -304,7 +284,7 @@ cont: fflush(stdout); lc = 0; cc = 0; - while ((rc = readline(fbuf, linebuf, LINESIZE)) >= 0) { + while ((rc = readline(fbuf, linebuf, LINESIZE, NULL)) >= 0) { if (rc != LINESIZE - 1) lc++; if ((t = putline(collf, linebuf, @@ -389,10 +369,14 @@ cont: if (value("interactive") != NULL) { if (value("askcc") != NULL || value("askbcc") != NULL) { - if (value("askcc") != NULL) - gethfromtty(hp, GCC); - if (value("askbcc") != NULL) - gethfromtty(hp, GBCC); + if (value("askcc") != NULL) { + if (gethfromtty(hp, GCC) == -1) + goto err; + } + if (value("askbcc") != NULL) { + if (gethfromtty(hp, GBCC) == -1) + goto err; + } } else { puts("EOT"); (void)fflush(stdout); @@ -408,16 +392,6 @@ out: if (collf != NULL) rewind(collf); noreset--; - (void)sigemptyset(&nset); - (void)sigaddset(&nset, SIGINT); - (void)sigaddset(&nset, SIGHUP); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - (void)signal(SIGINT, saveint); - (void)signal(SIGHUP, savehup); - (void)signal(SIGTSTP, savetstp); - (void)signal(SIGTTOU, savettou); - (void)signal(SIGTTIN, savettin); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); return(collf); } @@ -477,15 +451,19 @@ mesedit(fp, c) FILE *fp; int c; { - sig_t sigint = signal(SIGINT, SIG_IGN); - FILE *nf = run_editor(fp, (off_t)-1, c, 0); + FILE *nf; + struct sigaction oact; + sigset_t oset; + (void)ignoresig(SIGINT, &oact, &oset); + nf = run_editor(fp, (off_t)-1, c, 0); if (nf != NULL) { fseek(nf, 0L, 2); collf = nf; (void)Fclose(fp); } - (void)signal(SIGINT, sigint); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); } /* @@ -501,9 +479,11 @@ mespipe(fp, cmd) { FILE *nf; int fd; - sig_t sigint = signal(SIGINT, SIG_IGN); char *shell, tempname[PATHSIZE]; + struct sigaction oact; + sigset_t oset; + (void)ignoresig(SIGINT, &oact, &oset); (void)snprintf(tempname, sizeof(tempname), "%s/mail.ReXXXXXXXXXX", tmpdir); if ((fd = mkstemp(tempname)) == -1 || @@ -534,7 +514,8 @@ mespipe(fp, cmd) collf = nf; (void)Fclose(fp); out: - (void)signal(SIGINT, sigint); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); } /* @@ -590,37 +571,11 @@ forward(ms, fp, fn, f) } /* - * Print (continue) when continued after ^Z. + * User aborted during message composition. + * Save the partial message in ~/dead.letter. */ -/*ARGSUSED*/ -void -collstop(s) - int s; -{ - sig_t old_action = signal(s, SIG_DFL); - sigset_t nset; - - (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); - if (colljmp_p) { - colljmp_p = 0; - hadintr = 0; - siglongjmp(colljmp, 1); - } -} - -/* - * On interrupt, come here to save the partial message in ~/dead.letter. - * Then jump out of the collection loop. - */ -/*ARGSUSED*/ -void -collint(s) - int s; +int +collabort() { /* * the control flow is subtle, because we can be called from ~q. @@ -630,29 +585,19 @@ collint(s) puts("@"); fflush(stdout); clearerr(stdin); - return; + } else { + fflush(stdout); + fputs("\n(Interrupt -- one more to kill letter)\n", + stderr); + hadintr++; } - hadintr = 1; - siglongjmp(colljmp, 1); + return(0); } + fflush(stdout); rewind(collf); if (value("nosave") == NULL) savedeadletter(collf); - siglongjmp(collabort, 1); -} - -/*ARGSUSED*/ -void -collhup(s) - int s; -{ - rewind(collf); - savedeadletter(collf); - /* - * Let's pretend nobody else wants to clean up, - * a true statement at this time. - */ - exit(1); + return(1); } void @@ -677,19 +622,16 @@ savedeadletter(fp) rewind(fp); } -void +int gethfromtty(hp, gflags) struct header *hp; int gflags; { - if (grabh(hp, gflags) == SIGINT) { - fflush(stdout); - fputs("\n(Interrupt -- one more to kill letter)\n", - stderr); - if (grabh(hp, gflags) == SIGINT) { - hadintr++; - collint(SIGINT); - exit(1); - } + + hadintr = 0; + while (grabh(hp, gflags) != 0) { + if (collabort()) + return(-1); } + return(0); } diff --git a/usr.bin/mail/def.h b/usr.bin/mail/def.h index 533a2932998..2403d47607d 100644 --- a/usr.bin/mail/def.h +++ b/usr.bin/mail/def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: def.h,v 1.7 2001/01/16 05:36:08 millert Exp $ */ +/* $OpenBSD: def.h,v 1.8 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: def.h,v 1.9 1996/12/28 07:11:00 tls Exp $ */ /* * Copyright (c) 1980, 1993 @@ -33,7 +33,7 @@ * SUCH DAMAGE. * * @(#)def.h 8.4 (Berkeley) 4/20/95 - * $OpenBSD: def.h,v 1.7 2001/01/16 05:36:08 millert Exp $ + * $OpenBSD: def.h,v 1.8 2001/11/20 20:50:00 millert Exp $ */ /* @@ -271,13 +271,6 @@ struct ignoretab { #define CSEND 2 /* Execute in send mode only */ /* - * Kludges to handle the change from setexit / reset to sigsetjmp / siglongjmp - */ - -#define setexit() sigsetjmp(srbuf, 1) -#define reset(x) siglongjmp(srbuf, x) - -/* * Truncate a file to the last character written. This is * useful just before closing an old file that was opened * for read/write. diff --git a/usr.bin/mail/edit.c b/usr.bin/mail/edit.c index 90cf18607fc..86cbda720fb 100644 --- a/usr.bin/mail/edit.c +++ b/usr.bin/mail/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.9 2001/01/19 04:11:28 millert Exp $ */ +/* $OpenBSD: edit.c,v 1.10 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: edit.c,v 1.5 1996/06/08 19:48:20 christos Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93"; #else -static char rcsid[] = "$OpenBSD: edit.c,v 1.9 2001/01/19 04:11:28 millert Exp $"; +static char rcsid[] = "$OpenBSD: edit.c,v 1.10 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -88,6 +88,8 @@ edit1(msgvec, type) { int c, i; FILE *fp; + struct sigaction oact; + sigset_t oset; struct message *mp; off_t size; @@ -95,8 +97,6 @@ edit1(msgvec, type) * Deal with each message to be edited . . . */ for (i = 0; msgvec[i] && i < msgCount; i++) { - sig_t sigint; - if (i > 0) { char buf[100]; char *p; @@ -113,7 +113,7 @@ edit1(msgvec, type) } dot = mp = &message[msgvec[i] - 1]; touch(mp); - sigint = signal(SIGINT, SIG_IGN); + (void)ignoresig(SIGINT, &oact, &oset); fp = run_editor(setinput(mp), mp->m_size, type, readonly); if (fp != NULL) { (void)fseek(otf, 0L, 2); @@ -134,7 +134,8 @@ edit1(msgvec, type) warn("/tmp"); (void)Fclose(fp); } - (void)signal(SIGINT, sigint); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &oact, NULL); } return(0); } diff --git a/usr.bin/mail/extern.h b/usr.bin/mail/extern.h index fd7ad6453c1..16024b82f3d 100644 --- a/usr.bin/mail/extern.h +++ b/usr.bin/mail/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.17 2001/11/16 17:10:06 millert Exp $ */ +/* $OpenBSD: extern.h,v 1.18 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: extern.h,v 1.7 1997/07/09 05:22:00 mikel Exp $ */ /*- @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)extern.h 8.2 (Berkeley) 4/20/95 - * $OpenBSD: extern.h,v 1.17 2001/11/16 17:10:06 millert Exp $ + * $OpenBSD: extern.h,v 1.18 2001/11/20 20:50:00 millert Exp $ */ struct name; @@ -103,9 +103,7 @@ void clob1 __P((int)); int clobber __P((void *)); void close_all_files __P((void)); int cmatch __P((char *, char *)); -void collhup __P((int)); -void collint __P((int)); -void collstop __P((int)); +int collabort __P((void)); void commands __P((void)); int copycmd __P((void *)); int core __P((void *)); @@ -114,13 +112,14 @@ int delete __P((void *)); int delm __P((int [])); int deltype __P((void *)); void demail __P((void)); +void dointr __P((void)); int dosh __P((void *)); int dot_lock __P((const char *, int, FILE *, const char *)); void dot_unlock __P((const char *)); int echo __P((void *)); int edit1 __P((int *, int)); int editor __P((void *)); -void edstop __P((void)); +int edstop __P((void)); int elsecmd __P((void *)); int endifcmd __P((void *)); int evalcol __P((int)); @@ -131,6 +130,7 @@ int file __P((void *)); struct grouphead * findgroup __P((char [])); void findmail __P((char *, char *, int)); +void fioint __P((int)); int first __P((int, int)); void fixhead __P((struct header *, struct name *)); void fmt __P((char *, struct name *, FILE *, int)); @@ -141,15 +141,14 @@ int from __P((void *)); off_t fsize __P((FILE *)); int getfold __P((char *, int)); int gethfield __P((FILE *, char [], int, char **)); -void gethfromtty __P((struct header *, int)); +int gethfromtty __P((struct header *, int)); int getmsglist __P((char *, int *, int)); int getrawlist __P((char [], char **, int)); int getuserid __P((char [])); int grabh __P((struct header *, int)); int group __P((void *)); -void hangup __P((int)); int hash __P((char *)); -void hdrstop __P((int)); +void hdrint __P((int)); int headers __P((void *)); int help __P((void *)); void holdsigs __P((void)); @@ -157,6 +156,7 @@ int ifcmd __P((void *)); int igfield __P((void *)); struct ignoretab; int ignore1 __P((char *[], struct ignoretab *, char *)); +int ignoresig __P((int, struct sigaction *, sigset_t *)); int igshow __P((struct ignoretab *, char *)); void intr __P((int)); int inc __P((void *)); @@ -205,10 +205,10 @@ void printhead __P((int)); int puthead __P((struct header *, FILE *, int)); int putline __P((FILE *, char *, int)); int pversion __P((void *)); -void quit __P((void)); +int quit __P((void)); int quitcmd __P((void *)); int raise __P((int)); -int readline __P((FILE *, char *, int)); +int readline __P((FILE *, char *, int, int *)); void register_file __P((FILE *, int, int)); void regret __P((int)); void relsesigs __P((void)); diff --git a/usr.bin/mail/fio.c b/usr.bin/mail/fio.c index 3589a49c3f9..3fef0ff1b8a 100644 --- a/usr.bin/mail/fio.c +++ b/usr.bin/mail/fio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $ */ +/* $OpenBSD: fio.c,v 1.19 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: fio.c,v 1.8 1997/07/07 22:57:55 phil Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)fio.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $"; +static char rcsid[] = "$OpenBSD: fio.c,v 1.19 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -57,6 +57,8 @@ static char rcsid[] = "$OpenBSD: fio.c,v 1.18 2001/01/16 05:36:08 millert Exp $" * File I/O. */ +static volatile sig_atomic_t fiosignal; + /* * Wrapper for read() to catch EINTR. */ @@ -206,22 +208,67 @@ putline(obuf, linebuf, outlf) * include the newline (or carriage return) at the end. */ int -readline(ibuf, linebuf, linesize) +readline(ibuf, linebuf, linesize, signo) FILE *ibuf; char *linebuf; int linesize; + int *signo; { + struct sigaction act; + struct sigaction savetstp; + struct sigaction savettou; + struct sigaction savettin; + struct sigaction saveint; + struct sigaction savehup; + sigset_t oset; int n; + /* + * Setup signal handlers if the caller asked us to catch signals. + * Note that we do not restart system calls since we need the + * read to be interuptible. + */ + if (signo) { + fiosignal = 0; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = fioint; + if (sigaction(SIGINT, NULL, &saveint) == 0 && + saveint.sa_handler != SIG_IGN) { + (void)sigaction(SIGINT, &act, &saveint); + (void)sigprocmask(SIG_UNBLOCK, &intset, &oset); + } + if (sigaction(SIGHUP, NULL, &savehup) == 0 && + savehup.sa_handler != SIG_IGN) + (void)sigaction(SIGHUP, &act, &savehup); + (void)sigaction(SIGTSTP, &act, &savetstp); + (void)sigaction(SIGTTOU, &act, &savettou); + (void)sigaction(SIGTTIN, &act, &savettin); + } + clearerr(ibuf); - if (fgets(linebuf, linesize, ibuf) == NULL) - return(-1); + if (fgets(linebuf, linesize, ibuf) == NULL) { + if (ferror(ibuf)) + clearerr(ibuf); + n = -1; + } else { + n = strlen(linebuf); + if (n > 0 && linebuf[n - 1] == '\n') + linebuf[--n] = '\0'; + if (n > 0 && linebuf[n - 1] == '\r') + linebuf[--n] = '\0'; + } + + if (signo) { + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + *signo = fiosignal; + } - n = strlen(linebuf); - if (n > 0 && linebuf[n - 1] == '\n') - linebuf[--n] = '\0'; - if (n > 0 && linebuf[n - 1] == '\r') - linebuf[--n] = '\0'; return(n); } @@ -340,6 +387,34 @@ relsesigs() } /* + * Unblock and ignore a signal + */ +int +ignoresig(sig, oact, oset) + int sig; + struct sigaction *oact; + sigset_t *oset; +{ + struct sigaction act; + sigset_t nset; + int error; + + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = SIG_IGN; + error = sigaction(sig, &act, oact); + + if (error == 0) { + sigemptyset(&nset); + sigaddset(&nset, sig); + (void)sigprocmask(SIG_UNBLOCK, &nset, oset); + } else if (oset != NULL) + (void)sigprocmask(SIG_BLOCK, NULL, oset); + + return(error); +} + +/* * Determine the size of the file possessed by * the passed buffer. */ @@ -493,3 +568,15 @@ getdeadletter() } return(cp); } + +/* + * Signal handler used by readline() to catch SIGINT, SIGHUP, SIGTSTP, + * SIGTTOU, SIGTTIN. + */ +void +fioint(s) + int s; +{ + + fiosignal = s; +} diff --git a/usr.bin/mail/glob.h b/usr.bin/mail/glob.h index 4a43011bc1a..d82df7d78a0 100644 --- a/usr.bin/mail/glob.h +++ b/usr.bin/mail/glob.h @@ -1,4 +1,4 @@ -/* $OpenBSD: glob.h,v 1.4 1998/09/27 21:16:42 millert Exp $ */ +/* $OpenBSD: glob.h,v 1.5 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: glob.h,v 1.4 1996/06/08 19:48:25 christos Exp $ */ /* @@ -84,10 +84,7 @@ int screenheight; /* Screen height, or best guess, for "header" command */ int realscreenheight; /* the real screen height */ int uflag; /* Are we in -u mode? */ - -#include <setjmp.h> - -sigjmp_buf srbuf; +sigset_t intset; /* Signal set that is just SIGINT */ /* diff --git a/usr.bin/mail/lex.c b/usr.bin/mail/lex.c index ff068f48529..a17a2d89b4a 100644 --- a/usr.bin/mail/lex.c +++ b/usr.bin/mail/lex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.c,v 1.24 2001/11/17 19:10:25 deraadt Exp $ */ +/* $OpenBSD: lex.c,v 1.25 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: lex.c,v 1.10 1997/05/17 19:55:13 pk Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)lex.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: lex.c,v 1.24 2001/11/17 19:10:25 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: lex.c,v 1.25 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -209,7 +209,7 @@ incfile() int *msgvec; -int reset_on_stop; /* do a reset() if stopped */ +int reset_on_stop; /* reset prompt if stopped */ /* * Interpret user commands one by one. If standard input is not a tty, @@ -218,20 +218,11 @@ int reset_on_stop; /* do a reset() if stopped */ void commands() { - int n; - volatile int eofloop = 0; + int n, sig, *sigp; + int eofloop = 0; char linebuf[LINESIZE]; - if (!sourcing) { - if (signal(SIGINT, SIG_IGN) != SIG_IGN) - (void)signal(SIGINT, intr); - if (signal(SIGHUP, SIG_IGN) != SIG_IGN) - (void)signal(SIGHUP, hangup); - (void)signal(SIGTSTP, stop); - (void)signal(SIGTTOU, stop); - (void)signal(SIGTTIN, stop); - } - setexit(); + prompt: for (;;) { /* * Print the prompt, if needed. Clear out @@ -250,8 +241,24 @@ commands() * and handle end of file specially. */ n = 0; + sig = 0; + sigp = sourcing ? NULL : &sig; for (;;) { - if (readline(input, &linebuf[n], LINESIZE - n) < 0) { + if (readline(input, &linebuf[n], LINESIZE - n, sigp) < 0) { + if (sig) { + if (sig == SIGINT) + dointr(); + else if (sig == SIGHUP) + /* nothing to do? */ + exit(1); + else { + /* Stopped by job control */ + (void)kill(0, sig); + if (reset_on_stop) + reset_on_stop = 0; + } + goto prompt; + } if (n == 0) n = -1; break; @@ -597,10 +604,8 @@ isprefix(as1, as2) int inithdr; /* am printing startup headers */ -/*ARGSUSED*/ void -intr(s) - int s; +dointr() { noreset = 0; @@ -617,42 +622,6 @@ intr(s) image = -1; } fputs("Interrupt\n", stderr); - reset(0); -} - -/* - * When we wake up after ^Z, reprint the prompt. - */ -void -stop(s) - int s; -{ - sig_t old_action = signal(s, SIG_DFL); - sigset_t nset; - - (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); - if (reset_on_stop) { - reset_on_stop = 0; - reset(0); - } -} - -/* - * Branch here on hangup signal and simulate "exit". - */ -/*ARGSUSED*/ -void -hangup(s) - int s; -{ - - /* nothing to do? */ - exit(1); } /* diff --git a/usr.bin/mail/main.c b/usr.bin/mail/main.c index e8ffac609eb..e08b15135fd 100644 --- a/usr.bin/mail/main.c +++ b/usr.bin/mail/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.14 2001/10/11 20:59:46 millert Exp $ */ +/* $OpenBSD: main.c,v 1.15 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: main.c,v 1.7 1997/05/13 06:15:57 mikel Exp $ */ /* @@ -44,7 +44,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95"; #else -static char rcsid[] = "$OpenBSD: main.c,v 1.14 2001/10/11 20:59:46 millert Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.15 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -54,6 +54,7 @@ static char rcsid[] = "$OpenBSD: main.c,v 1.14 2001/10/11 20:59:46 millert Exp $ #include "extern.h" int main __P((int, char **)); +__dead void usage __P((void)); /* * Mail -- a mail program @@ -61,8 +62,6 @@ int main __P((int, char **)); * Startup -- interface with user. */ -sigjmp_buf hdrjmp; - int main(argc, argv) int argc; @@ -73,8 +72,8 @@ main(argc, argv) char *subject; char *ef; char nosrc = 0; - sig_t prevint; char *rc; + extern char *version; /* * Set up a reasonable environment. @@ -82,6 +81,7 @@ main(argc, argv) * start the SIGCHLD catcher, and so forth. */ (void)signal(SIGCHLD, sigchild); + (void)signal(SIGPIPE, SIG_IGN); if (isatty(0)) assign("interactive", ""); image = -1; @@ -188,13 +188,9 @@ main(argc, argv) */ bcc = cat(bcc, nalloc(optarg, GBCC)); break; - case '?': - fprintf(stderr, "\ -Usage: %s [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\ - [- sendmail-options ...]\n\ - %s [-iInNv] -f [name]\n\ - %s [-iInNv] [-u user]\n", __progname, __progname, __progname); - exit(1); + default: + usage(); + /*NOTREACHED*/ } } for (i = optind; (argv[i]) && (*argv[i] != '-'); i++) @@ -208,6 +204,15 @@ Usage: %s [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\ errx(1, "You must specify direct recipients with -s, -c, or -b"); if (ef != NULL && to != NIL) errx(1, "Cannot give -f and people to send to"); + /* + * Block SIGINT except where we install an explicit handler for it. + */ + sigemptyset(&intset); + sigaddset(&intset, SIGINT); + (void)sigprocmask(SIG_BLOCK, &intset, NULL); + /* + * Initialization. + */ tinit(); setscreensize(); input = stdin; @@ -238,40 +243,21 @@ Usage: %s [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\ ef = "%"; if (setfile(ef) < 0) exit(1); /* error already reported */ - if (sigsetjmp(hdrjmp, 1) == 0) { - extern char *version; - if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) - (void)signal(SIGINT, hdrstop); - if (value("quiet") == NULL) - (void)printf("Mail version %s. Type ? for help.\n", - version); - announce(); - (void)fflush(stdout); - (void)signal(SIGINT, prevint); - } + if (value("quiet") == NULL) + (void)printf("Mail version %s. Type ? for help.\n", + version); + announce(); + (void)fflush(stdout); commands(); - (void)signal(SIGHUP, SIG_IGN); - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); + (void)ignoresig(SIGHUP, NULL, NULL); + (void)ignoresig(SIGINT, NULL, NULL); + (void)ignoresig(SIGQUIT, NULL, NULL); quit(); exit(0); } /* - * Interrupt printing of the headers. - */ -void -hdrstop(signo) - int signo; -{ - - fflush(stdout); - fputs("\nInterrupt\n", stderr); - siglongjmp(hdrjmp, 1); -} - -/* * Compute what the screen size for printing headers should be. * We use the following algorithm for the height: * If baud rate < 1200, use 9 @@ -305,3 +291,16 @@ setscreensize() if ((screenwidth = ws.ws_col) == 0) screenwidth = 80; } + +__dead void +usage() +{ + + fprintf(stderr, "usage: %s [-iInv] [-s subject] [-c cc-addr] " + "[-b bcc-addr] to-addr ...\n", __progname); + fprintf(stderr, " %*s [- sendmail-options ...]\n", + (int)strlen(__progname), ""); + fprintf(stderr, " %s [-iInNv] -f [name]\n", __progname); + fprintf(stderr, " %s [-iInNv] [-u user]\n", __progname); + exit(1); +} diff --git a/usr.bin/mail/quit.c b/usr.bin/mail/quit.c index 1fe4b088a27..2f2ba2987e6 100644 --- a/usr.bin/mail/quit.c +++ b/usr.bin/mail/quit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: quit.c,v 1.14 2001/01/16 05:36:09 millert Exp $ */ +/* $OpenBSD: quit.c,v 1.15 2001/11/20 20:50:00 millert Exp $ */ /* $NetBSD: quit.c,v 1.6 1996/12/28 07:11:07 tls Exp $ */ /* @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)quit.c 8.2 (Berkeley) 4/28/95"; #else -static char rcsid[] = "$OpenBSD: quit.c,v 1.14 2001/01/16 05:36:09 millert Exp $"; +static char rcsid[] = "$OpenBSD: quit.c,v 1.15 2001/11/20 20:50:00 millert Exp $"; #endif #endif /* not lint */ @@ -73,7 +73,7 @@ quitcmd(v) * Save all untouched messages back in the system mailbox. * Remove the system mailbox, if none saved there. */ -void +int quit() { int mcount, p, modify, autohold, anystat, holdbit, nohold; @@ -88,15 +88,13 @@ quit() * so just return quickly. */ if (readonly) - return; + return(0); /* * If editing (not reading system mail box), then do the work * in edstop() */ - if (edit) { - edstop(); - return; - } + if (edit) + return(edstop()); /* * See if there any messages to save in mbox. If no, we @@ -114,11 +112,11 @@ quit() if (flock(fileno(fbuf), LOCK_EX) == -1) { warn("Unable to lock mailbox"); (void)Fclose(fbuf); - return; + return(-1); } if (!spool_lock()) { (void)Fclose(fbuf); - return; /* lockspool printed error for us */ + return(-1); /* lockspool printed error for us */ } rbuf = NULL; if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) { @@ -195,14 +193,14 @@ quit() p, p == 1 ? "" : "s", mailname); (void)Fclose(fbuf); spool_unlock(); - return; + return(0); } if (c == 0) { if (p != 0) { writeback(rbuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(0); } goto cream; } @@ -224,7 +222,7 @@ quit() warn("%s", tempname); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } if ((ibuf = Fopen(tempname, "r")) == NULL) { warn("%s", tempname); @@ -232,7 +230,7 @@ quit() (void)Fclose(obuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } (void)rm(tempname); if ((abuf = Fopen(mbox, "r")) != NULL) { @@ -246,7 +244,7 @@ quit() (void)Fclose(obuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } (void)Fclose(obuf); (void)close(creat(mbox, 0600)); @@ -255,15 +253,14 @@ quit() (void)Fclose(ibuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } - } - else { + } else { if ((obuf = Fopen(mbox, "a")) == NULL) { warn("%s", mbox); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } fchmod(fileno(obuf), 0600); } @@ -275,7 +272,7 @@ quit() (void)Fclose(obuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } /* @@ -302,7 +299,7 @@ quit() (void)Fclose(obuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(-1); } (void)Fclose(obuf); if (mcount == 1) @@ -319,7 +316,7 @@ quit() writeback(rbuf); (void)Fclose(fbuf); spool_unlock(); - return; + return(0); } /* @@ -340,12 +337,12 @@ cream: alter(mailname); (void)Fclose(fbuf); spool_unlock(); - return; + return(0); } demail(); (void)Fclose(fbuf); spool_unlock(); - return; + return(0);; newmail: puts("Thou hast new mail."); @@ -353,6 +350,7 @@ newmail: (void)Fclose(fbuf); spool_unlock(); } + return(0); } /* @@ -415,7 +413,7 @@ writeback(res) * Terminate an editing session by attempting to write out the user's * file from the temporary. Save any new stuff appended to the file. */ -void +int edstop() { int gotcha, c; @@ -425,7 +423,7 @@ edstop() char tempname[PATHSIZE]; if (readonly) - return; + return(0); holdsigs(); if (Tflag != NULL) { if ((readstat = Fopen(Tflag, "w")) == NULL) @@ -459,14 +457,14 @@ edstop() (obuf = Fdopen(fd, "w")) == NULL) { warn("%s", tempname); relsesigs(); - reset(0); + return(-1); } if ((ibuf = Fopen(mailname, "r")) == NULL) { warn("%s", mailname); (void)Fclose(obuf); (void)rm(tempname); relsesigs(); - reset(0); + return(-1); } fseek(ibuf, (long)mailsize, 0); while ((c = getc(ibuf)) != EOF) @@ -477,7 +475,7 @@ edstop() warn("%s", tempname); (void)rm(tempname); relsesigs(); - reset(0); + return(-1); } (void)rm(tempname); } @@ -486,7 +484,7 @@ edstop() if ((obuf = Fopen(mailname, "r+")) == NULL) { warn("%s", mailname); relsesigs(); - reset(0); + return(-1); } trunc(obuf); c = 0; @@ -497,7 +495,7 @@ edstop() if (sendmessage(mp, obuf, NULL, NULL) < 0) { warn("%s", mailname); relsesigs(); - reset(0); + return(-1); } } gotcha = (c == 0 && ibuf == NULL); @@ -510,7 +508,7 @@ edstop() if (ferror(obuf)) { warn("%s", mailname); relsesigs(); - reset(0); + return(-1); } (void)Fclose(obuf); if (gotcha) { @@ -522,4 +520,5 @@ edstop() done: relsesigs(); + return(0); } 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; } |