diff options
-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; } |