X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/470c33f3448aad96e77401f41b39bd0b4c648a55..a0d23834212281b6e06fb9727d035a6a225d4aff:/usr/src/usr.bin/mail/collect.c diff --git a/usr/src/usr.bin/mail/collect.c b/usr/src/usr.bin/mail/collect.c index 2d847c7f64..e1c716075c 100644 --- a/usr/src/usr.bin/mail/collect.c +++ b/usr/src/usr.bin/mail/collect.c @@ -2,21 +2,11 @@ * Copyright (c) 1980 Regents of the University of California. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.redist.c% */ #ifndef lint -static char sccsid[] = "@(#)collect.c 5.14 (Berkeley) %G%"; +static char sccsid[] = "@(#)collect.c 5.25 (Berkeley) %G%"; #endif /* not lint */ /* @@ -27,7 +17,7 @@ static char sccsid[] = "@(#)collect.c 5.14 (Berkeley) %G%"; */ #include "rcv.h" -#include +#include "extern.h" /* * Read a message from standard output and return a read file to it @@ -40,47 +30,53 @@ static char sccsid[] = "@(#)collect.c 5.14 (Berkeley) %G%"; * away on dead.letter. */ -static int (*saveint)(); /* Previous SIGINT value */ -static int (*savehup)(); /* Previous SIGHUP value */ -static int (*savecont)(); /* Previous SIGCONT value */ +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 jmp_buf coljmp; /* To get back to work */ +static jmp_buf colljmp; /* To get back to work */ +static int colljmp_p; /* whether to long jump */ +static jmp_buf collabort; /* To end collection with error */ FILE * collect(hp, printheaders) struct header *hp; + int printheaders; { FILE *fbuf; - int lc, cc, escape, eof; - int collrub(), intack(), collcont(); + int lc, cc, escape, eofcount; register int c, t; char linebuf[LINESIZE], *cp; extern char tempMail[]; char getsub; int omask; + void collint(), collhup(), collstop(); - noreset++; collf = NULL; - /* * Start catching signals from here, but we're still die on interrupts * until we're in the main loop. */ omask = sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) - signal(SIGINT, value("ignore") != NOSTR ? intack : collrub); + signal(SIGINT, collint); if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) - signal(SIGHUP, collrub); - savecont = signal(SIGCONT, SIG_DFL); - if (setjmp(coljmp)) { - remove(tempMail); + signal(SIGHUP, collhup); + savetstp = signal(SIGTSTP, collstop); + savettou = signal(SIGTTOU, collstop); + savettin = signal(SIGTTIN, collstop); + if (setjmp(collabort) || setjmp(colljmp)) { + rm(tempMail); goto err; } sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP))); - if ((collf = fopen(tempMail, "w+")) == NULL) { + noreset++; + if ((collf = Fopen(tempMail, "w+")) == NULL) { perror(tempMail); goto err; } @@ -94,7 +90,7 @@ collect(hp, printheaders) t = GTO|GSUBJECT|GCC|GNL; getsub = 0; if (hp->h_subject == NOSTR && value("interactive") != NOSTR && - value("ask")) + (value("ask") != NOSTR || value("asksub") != NOSTR)) t &= ~GNL, getsub++; if (printheaders) { puthead(hp, stdout, t); @@ -104,11 +100,10 @@ collect(hp, printheaders) escape = *cp; else escape = ESCAPE; - eof = 0; + eofcount = 0; hadintr = 0; - if (!setjmp(coljmp)) { - signal(SIGCONT, collcont); + if (!setjmp(colljmp)) { if (getsub) grabh(hp, GSUBJECT); } else { @@ -128,17 +123,18 @@ cont: } } for (;;) { - if (readline(stdin, linebuf) < 0) { + colljmp_p = 1; + c = readline(stdin, linebuf, LINESIZE); + colljmp_p = 0; + if (c < 0) { if (value("interactive") != NOSTR && - value("ignoreeof") != NOSTR) { - if (++eof > 35) - break; + value("ignoreeof") != NOSTR && ++eofcount < 25) { printf("Use \".\" to terminate letter\n"); continue; } break; } - eof = 0; + eofcount = 0; hadintr = 0; if (linebuf[0] == '.' && linebuf[1] == '\0' && value("interactive") != NOSTR && @@ -194,7 +190,7 @@ cont: * Act like an interrupt happened. */ hadintr++; - collrub(SIGINT); + collint(SIGINT); exit(1); case 'h': /* @@ -230,7 +226,7 @@ cont: hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); break; case 'd': - strcpy(linebuf + 2, deadletter); + strcpy(linebuf + 2, getdeadletter()); /* fall into . . . */ case 'r': /* @@ -252,7 +248,7 @@ cont: printf("%s: Directory\n", cp); break; } - if ((fbuf = fopen(cp, "r")) == NULL) { + if ((fbuf = Fopen(cp, "r")) == NULL) { perror(cp); break; } @@ -260,15 +256,15 @@ cont: fflush(stdout); lc = 0; cc = 0; - while (readline(fbuf, linebuf) >= 0) { + while (readline(fbuf, linebuf, LINESIZE) >= 0) { lc++; if ((t = putline(collf, linebuf)) < 0) { - fclose(fbuf); + Fclose(fbuf); goto err; } cc += t; } - fclose(fbuf); + Fclose(fbuf); printf("%d/%d\n", lc, cc); break; case 'w': @@ -297,21 +293,17 @@ cont: * standard list processing garbage. * If ~f is given, we don't shift over. */ - if (!rcvmode) { - printf("No messages to send from!?!\n"); - break; - } if (forward(linebuf + 2, collf, c) < 0) goto err; goto cont; case '?': - if ((fbuf = fopen(THELPFILE, "r")) == NULL) { - perror(THELPFILE); + if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) { + perror(_PATH_TILDE); break; } while ((t = getc(fbuf)) != EOF) - putchar(t); - fclose(fbuf); + (void) putchar(t); + Fclose(fbuf); break; case 'p': /* @@ -322,7 +314,7 @@ cont: printf("-------\nMessage contains:\n"); puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); while ((t = getc(collf)) != EOF) - putchar(t); + (void) putchar(t); goto cont; case '|': /* @@ -347,27 +339,31 @@ cont: goto out; err: if (collf != NULL) { - fclose(collf); + Fclose(collf); collf = NULL; } out: if (collf != NULL) rewind(collf); + noreset--; + sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); signal(SIGINT, saveint); signal(SIGHUP, savehup); - signal(SIGCONT, savecont); + signal(SIGTSTP, savetstp); + signal(SIGTTOU, savettou); + signal(SIGTTIN, savettin); sigsetmask(omask); - noreset--; return collf; } /* * Write a file, ex-like if f set. */ - +int exwrite(name, fp, f) char name[]; FILE *fp; + int f; { register FILE *of; register int c; @@ -385,7 +381,7 @@ exwrite(name, fp, f) fprintf(stderr, "File exists\n"); return(-1); } - if ((of = fopen(name, "w")) == NULL) { + if ((of = Fopen(name, "w")) == NULL) { perror(NOSTR); return(-1); } @@ -395,14 +391,14 @@ exwrite(name, fp, f) cc++; if (c == '\n') lc++; - putc(c, of); + (void) putc(c, of); if (ferror(of)) { perror(name); - fclose(of); + Fclose(of); return(-1); } } - fclose(of); + Fclose(of); printf("%d/%ld\n", lc, cc); fflush(stdout); return(0); @@ -412,20 +408,20 @@ exwrite(name, fp, f) * Edit the message being collected on fp. * On return, make the edit file the new temp file. */ +void mesedit(fp, c) FILE *fp; + int c; { - int (*sigint)() = signal(SIGINT, SIG_IGN); - int (*sigcont)() = signal(SIGCONT, SIG_DFL); + sig_t sigint = signal(SIGINT, SIG_IGN); FILE *nf = run_editor(fp, (off_t)-1, c, 0); if (nf != NULL) { - fseek(nf, (off_t)0, 2); + fseek(nf, 0L, 2); collf = nf; - fclose(fp); + Fclose(fp); } (void) signal(SIGINT, sigint); - (void) signal(SIGCONT, sigcont); } /* @@ -434,16 +430,16 @@ mesedit(fp, c) * New message collected from stdout. * Sh -c must return 0 to accept the new message. */ +void mespipe(fp, cmd) FILE *fp; char cmd[]; { FILE *nf; - int (*sigint)() = signal(SIGINT, SIG_IGN); - int (*sigcont)() = signal(SIGCONT, SIG_DFL); + sig_t sigint = signal(SIGINT, SIG_IGN); extern char tempEdit[]; - if ((nf = fopen(tempEdit, "w+")) == NULL) { + if ((nf = Fopen(tempEdit, "w+")) == NULL) { perror(tempEdit); goto out; } @@ -452,13 +448,14 @@ mespipe(fp, cmd) * stdin = current message. * stdout = new message. */ - if (run_command(cmd, 0, fileno(fp), fileno(nf), NOSTR) < 0) { - (void) fclose(nf); + if (run_command(cmd, + 0, fileno(fp), fileno(nf), NOSTR, NOSTR, NOSTR) < 0) { + (void) Fclose(nf); goto out; } if (fsize(nf) == 0) { fprintf(stderr, "No bytes from \"%s\" !?\n", cmd); - (void) fclose(nf); + (void) Fclose(nf); goto out; } /* @@ -466,10 +463,9 @@ mespipe(fp, cmd) */ (void) fseek(nf, 0L, 2); collf = nf; - (void) fclose(fp); + (void) Fclose(fp); out: (void) signal(SIGINT, sigint); - (void) signal(SIGCONT, sigcont); } /* @@ -480,9 +476,11 @@ out: * the message temporary. The flag argument is 'm' if we * should shift over and 'f' if not. */ +int forward(ms, fp, f) char ms[]; FILE *fp; + int f; { register int *msgvec; extern char tempMail[]; @@ -504,7 +502,7 @@ forward(ms, fp, f) } if (f == 'f' || f == 'F') tabst = NOSTR; - else if ((tabst = value("tabstr")) == NOSTR) + else if ((tabst = value("indentprefix")) == NOSTR) tabst = "\t"; ig = isupper(f) ? NULL : ignore; printf("Interpolating:"); @@ -526,60 +524,83 @@ forward(ms, fp, f) * Print (continue) when continued after ^Z. */ /*ARGSUSED*/ -collcont(s) +void +collstop(s) + int s; { + sig_t old_action = signal(s, SIG_DFL); - hadintr = 0; - longjmp(coljmp, 1); + sigsetmask(sigblock(0) & ~sigmask(s)); + kill(0, s); + sigblock(sigmask(s)); + signal(s, old_action); + if (colljmp_p) { + colljmp_p = 0; + hadintr = 0; + longjmp(colljmp, 1); + } } /* - * On interrupt, go here to save the partial - * message on ~/dead.letter. - * Then restore signals and execute the normal - * signal routine. We only come here if signals - * were previously set anyway. + * On interrupt, come here to save the partial message in ~/dead.letter. + * Then jump out of the collection loop. */ -collrub(s) +/*ARGSUSED*/ +void +collint(s) + int s; { - register FILE *dbuf; - register int c; - - if (s == SIGINT && hadintr == 0) { + /* + * the control flow is subtle, because we can be called from ~q. + */ + if (!hadintr) { + if (value("ignore") != NOSTR) { + puts("@"); + fflush(stdout); + clearerr(stdin); + return; + } hadintr = 1; - longjmp(coljmp, 1); + longjmp(colljmp, 1); } rewind(collf); - if (s == SIGINT && value("nosave") != NOSTR || fsize(collf) == 0) - goto done; - if ((dbuf = fopen(deadletter, "w")) == NULL) - goto done; - chmod(deadletter, 0600); - while ((c = getc(collf)) != EOF) - putc(c, dbuf); - fclose(dbuf); -done: - fclose(collf); - signal(SIGINT, saveint); - signal(SIGHUP, savehup); - signal(SIGCONT, savecont); - if (rcvmode) { - if (s == SIGHUP) - hangup(SIGHUP); - else - stop(s); - } else - exit(1); + if (value("nosave") == NOSTR) + savedeadletter(collf); + longjmp(collabort, 1); } -/* - * Acknowledge an interrupt signal from the tty by typing an @ - */ /*ARGSUSED*/ -intack(s) +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); +} + +void +savedeadletter(fp) + register FILE *fp; { + register FILE *dbuf; + register int c; + char *cp; - puts("@"); - fflush(stdout); - clearerr(stdin); + if (fsize(fp) == 0) + return; + cp = getdeadletter(); + c = umask(077); + dbuf = Fopen(cp, "a"); + (void) umask(c); + if (dbuf == NULL) + return; + while ((c = getc(fp)) != EOF) + (void) putc(c, dbuf); + Fclose(dbuf); + rewind(fp); }