xref: /csrg-svn/usr.bin/mail/collect.c (revision 66999)
122448Sdist /*
262083Sbostic  * Copyright (c) 1980, 1993
362083Sbostic  *	The Regents of the University of California.  All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622448Sdist  */
722448Sdist 
834905Sbostic #ifndef lint
9*66999Sedward static char sccsid[] = "@(#)collect.c	8.2 (Berkeley) 04/19/94";
1034905Sbostic #endif /* not lint */
111227Skas 
121227Skas /*
131227Skas  * Mail -- a mail program
141227Skas  *
151227Skas  * Collect input from standard input, handling
161227Skas  * ~ escapes.
171227Skas  */
181227Skas 
191227Skas #include "rcv.h"
2054505Sbostic #include "extern.h"
211227Skas 
221227Skas /*
231227Skas  * Read a message from standard output and return a read file to it
241227Skas  * or NULL on error.
251227Skas  */
261227Skas 
271227Skas /*
281227Skas  * The following hokiness with global variables is so that on
291227Skas  * receipt of an interrupt signal, the partial message can be salted
3031142Sedward  * away on dead.letter.
311227Skas  */
321227Skas 
3339162Sbostic static	sig_t	saveint;		/* Previous SIGINT value */
3439162Sbostic static	sig_t	savehup;		/* Previous SIGHUP value */
3539162Sbostic static	sig_t	savetstp;		/* Previous SIGTSTP value */
3639162Sbostic static	sig_t	savettou;		/* Previous SIGTTOU value */
3739162Sbostic static	sig_t	savettin;		/* Previous SIGTTIN value */
3831142Sedward static	FILE	*collf;			/* File for saving away */
391227Skas static	int	hadintr;		/* Have seen one SIGINT so far */
401227Skas 
4136554Sedward static	jmp_buf	colljmp;		/* To get back to work */
4236554Sedward static	int	colljmp_p;		/* whether to long jump */
4336554Sedward static	jmp_buf	collabort;		/* To end collection with error */
441227Skas 
451227Skas FILE *
collect(hp,printheaders)4634800Sedward collect(hp, printheaders)
471227Skas 	struct header *hp;
4854505Sbostic 	int printheaders;
491227Skas {
5034963Sedward 	FILE *fbuf;
5136554Sedward 	int lc, cc, escape, eofcount;
521227Skas 	register int c, t;
531227Skas 	char linebuf[LINESIZE], *cp;
541227Skas 	extern char tempMail[];
5516732Sralph 	char getsub;
5631142Sedward 	int omask;
5747706Sbostic 	void collint(), collhup(), collstop();
581227Skas 
5931142Sedward 	collf = NULL;
6031142Sedward 	/*
6131142Sedward 	 * Start catching signals from here, but we're still die on interrupts
6231142Sedward 	 * until we're in the main loop.
6331142Sedward 	 */
6431142Sedward 	omask = sigblock(sigmask(SIGINT) | sigmask(SIGHUP));
6531142Sedward 	if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
6636554Sedward 		signal(SIGINT, collint);
6731142Sedward 	if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN)
6836554Sedward 		signal(SIGHUP, collhup);
6936554Sedward 	savetstp = signal(SIGTSTP, collstop);
7036554Sedward 	savettou = signal(SIGTTOU, collstop);
7136554Sedward 	savettin = signal(SIGTTIN, collstop);
7236554Sedward 	if (setjmp(collabort) || setjmp(colljmp)) {
7346349Sedward 		rm(tempMail);
741227Skas 		goto err;
751227Skas 	}
7631142Sedward 	sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP)));
7731142Sedward 
7836554Sedward 	noreset++;
7943865Sedward 	if ((collf = Fopen(tempMail, "w+")) == NULL) {
801227Skas 		perror(tempMail);
811227Skas 		goto err;
821227Skas 	}
8334963Sedward 	unlink(tempMail);
841227Skas 
851227Skas 	/*
861227Skas 	 * If we are going to prompt for a subject,
871227Skas 	 * refrain from printing a newline after
881227Skas 	 * the headers (since some people mind).
891227Skas 	 */
901227Skas 	t = GTO|GSUBJECT|GCC|GNL;
9116732Sralph 	getsub = 0;
9234750Sedward 	if (hp->h_subject == NOSTR && value("interactive") != NOSTR &&
9335375Sedward 	    (value("ask") != NOSTR || value("asksub") != NOSTR))
9416732Sralph 		t &= ~GNL, getsub++;
9534800Sedward 	if (printheaders) {
961227Skas 		puthead(hp, stdout, t);
971227Skas 		fflush(stdout);
981227Skas 	}
991227Skas 	if ((cp = value("escape")) != NOSTR)
1001227Skas 		escape = *cp;
10134750Sedward 	else
10234750Sedward 		escape = ESCAPE;
10336554Sedward 	eofcount = 0;
10431142Sedward 	hadintr = 0;
10513039Ssam 
10636554Sedward 	if (!setjmp(colljmp)) {
10731142Sedward 		if (getsub)
10816732Sralph 			grabh(hp, GSUBJECT);
10931142Sedward 	} else {
11031142Sedward 		/*
11131142Sedward 		 * Come here for printing the after-signal message.
11231142Sedward 		 * Duplicate messages won't be printed because
11331142Sedward 		 * the write is aborted if we get a SIGTTOU.
11431142Sedward 		 */
11531142Sedward cont:
11631142Sedward 		if (hadintr) {
11731142Sedward 			fflush(stdout);
11831142Sedward 			fprintf(stderr,
11931142Sedward 			"\n(Interrupt -- one more to kill letter)\n");
12031142Sedward 		} else {
12131142Sedward 			printf("(continue)\n");
12231142Sedward 			fflush(stdout);
12316732Sralph 		}
12431142Sedward 	}
12531142Sedward 	for (;;) {
12636554Sedward 		colljmp_p = 1;
12736554Sedward 		c = readline(stdin, linebuf, LINESIZE);
12836554Sedward 		colljmp_p = 0;
12936554Sedward 		if (c < 0) {
13034750Sedward 			if (value("interactive") != NOSTR &&
13136554Sedward 			    value("ignoreeof") != NOSTR && ++eofcount < 25) {
13231142Sedward 				printf("Use \".\" to terminate letter\n");
1334388Skurt 				continue;
1344388Skurt 			}
1351227Skas 			break;
1364388Skurt 		}
13736554Sedward 		eofcount = 0;
1381227Skas 		hadintr = 0;
13934750Sedward 		if (linebuf[0] == '.' && linebuf[1] == '\0' &&
14034750Sedward 		    value("interactive") != NOSTR &&
1414413Skurt 		    (value("dot") != NOSTR || value("ignoreeof") != NOSTR))
1421227Skas 			break;
14334750Sedward 		if (linebuf[0] != escape || value("interactive") == NOSTR) {
14434963Sedward 			if (putline(collf, linebuf) < 0)
1451227Skas 				goto err;
1461227Skas 			continue;
1471227Skas 		}
1481227Skas 		c = linebuf[1];
1491227Skas 		switch (c) {
1501227Skas 		default:
1511227Skas 			/*
1521227Skas 			 * On double escape, just send the single one.
1531227Skas 			 * Otherwise, it's an error.
1541227Skas 			 */
1551227Skas 			if (c == escape) {
15634963Sedward 				if (putline(collf, &linebuf[1]) < 0)
1571227Skas 					goto err;
1581227Skas 				else
1591227Skas 					break;
1601227Skas 			}
1611227Skas 			printf("Unknown tilde escape.\n");
1621227Skas 			break;
1631227Skas 		case 'C':
1641227Skas 			/*
1651227Skas 			 * Dump core.
1661227Skas 			 */
1671227Skas 			core();
1681227Skas 			break;
1691227Skas 		case '!':
1701227Skas 			/*
1711227Skas 			 * Shell escape, send the balance of the
1721227Skas 			 * line to sh -c.
1731227Skas 			 */
1741227Skas 			shell(&linebuf[2]);
1751227Skas 			break;
1761227Skas 		case ':':
1771227Skas 			/*
1781227Skas 			 * Escape to command mode, but be nice!
1791227Skas 			 */
1802117Skas 			execute(&linebuf[2], 1);
18131142Sedward 			goto cont;
1821227Skas 		case '.':
1831227Skas 			/*
1841227Skas 			 * Simulate end of file on input.
1851227Skas 			 */
18631142Sedward 			goto out;
1871227Skas 		case 'q':
1881227Skas 			/*
1891227Skas 			 * Force a quit of sending mail.
1901227Skas 			 * Act like an interrupt happened.
1911227Skas 			 */
1921227Skas 			hadintr++;
19336554Sedward 			collint(SIGINT);
1941227Skas 			exit(1);
1951227Skas 		case 'h':
1961227Skas 			/*
1971227Skas 			 * Grab a bunch of headers.
1981227Skas 			 */
1991227Skas 			grabh(hp, GTO|GSUBJECT|GCC|GBCC);
20031142Sedward 			goto cont;
2011227Skas 		case 't':
2021227Skas 			/*
2031227Skas 			 * Add to the To list.
2041227Skas 			 */
20534800Sedward 			hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO));
2061227Skas 			break;
2071227Skas 		case 's':
2081227Skas 			/*
2091227Skas 			 * Set the Subject list.
2101227Skas 			 */
2111227Skas 			cp = &linebuf[2];
21231142Sedward 			while (isspace(*cp))
2131227Skas 				cp++;
2141227Skas 			hp->h_subject = savestr(cp);
2151227Skas 			break;
2161227Skas 		case 'c':
2171227Skas 			/*
2181227Skas 			 * Add to the CC list.
2191227Skas 			 */
22034800Sedward 			hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC));
2211227Skas 			break;
2221227Skas 		case 'b':
2231227Skas 			/*
2241227Skas 			 * Add stuff to blind carbon copies list.
2251227Skas 			 */
22634800Sedward 			hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC));
2271227Skas 			break;
2281227Skas 		case 'd':
22935351Sedward 			strcpy(linebuf + 2, getdeadletter());
2301227Skas 			/* fall into . . . */
2311227Skas 		case 'r':
2321227Skas 			/*
2331227Skas 			 * Invoke a file:
2341227Skas 			 * Search for the file name,
23534963Sedward 			 * then open it and copy the contents to collf.
2361227Skas 			 */
2371227Skas 			cp = &linebuf[2];
23831142Sedward 			while (isspace(*cp))
2391227Skas 				cp++;
2401227Skas 			if (*cp == '\0') {
2411227Skas 				printf("Interpolate what file?\n");
2421227Skas 				break;
2431227Skas 			}
2441227Skas 			cp = expand(cp);
2451227Skas 			if (cp == NOSTR)
2461227Skas 				break;
2471227Skas 			if (isdir(cp)) {
24831142Sedward 				printf("%s: Directory\n", cp);
2491227Skas 				break;
2501227Skas 			}
25143865Sedward 			if ((fbuf = Fopen(cp, "r")) == NULL) {
2521227Skas 				perror(cp);
2531227Skas 				break;
2541227Skas 			}
2551227Skas 			printf("\"%s\" ", cp);
25616858Sralph 			fflush(stdout);
2571227Skas 			lc = 0;
2581227Skas 			cc = 0;
25936554Sedward 			while (readline(fbuf, linebuf, LINESIZE) >= 0) {
2601227Skas 				lc++;
26134963Sedward 				if ((t = putline(collf, linebuf)) < 0) {
26243865Sedward 					Fclose(fbuf);
2631227Skas 					goto err;
2641227Skas 				}
2651227Skas 				cc += t;
2661227Skas 			}
26743865Sedward 			Fclose(fbuf);
2681227Skas 			printf("%d/%d\n", lc, cc);
2691227Skas 			break;
2701227Skas 		case 'w':
2711227Skas 			/*
2721227Skas 			 * Write the message on a file.
2731227Skas 			 */
2741227Skas 			cp = &linebuf[2];
27534987Sedward 			while (*cp == ' ' || *cp == '\t')
2761227Skas 				cp++;
2771227Skas 			if (*cp == '\0') {
2781227Skas 				fprintf(stderr, "Write what file!?\n");
2791227Skas 				break;
2801227Skas 			}
2811227Skas 			if ((cp = expand(cp)) == NOSTR)
2821227Skas 				break;
28334963Sedward 			rewind(collf);
28434963Sedward 			exwrite(cp, collf, 1);
2851227Skas 			break;
2861227Skas 		case 'm':
28734969Sedward 		case 'M':
2881227Skas 		case 'f':
28934969Sedward 		case 'F':
2901227Skas 			/*
2911227Skas 			 * Interpolate the named messages, if we
2921227Skas 			 * are in receiving mail mode.  Does the
2931227Skas 			 * standard list processing garbage.
2941227Skas 			 * If ~f is given, we don't shift over.
2951227Skas 			 */
29634987Sedward 			if (forward(linebuf + 2, collf, c) < 0)
2971227Skas 				goto err;
29831142Sedward 			goto cont;
2991227Skas 		case '?':
30043865Sedward 			if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) {
30137870Sbostic 				perror(_PATH_TILDE);
3021227Skas 				break;
3031227Skas 			}
30433412Sedward 			while ((t = getc(fbuf)) != EOF)
30536554Sedward 				(void) putchar(t);
30643865Sedward 			Fclose(fbuf);
3071227Skas 			break;
3081227Skas 		case 'p':
3091227Skas 			/*
3101227Skas 			 * Print out the current state of the
3111227Skas 			 * message without altering anything.
3121227Skas 			 */
31334963Sedward 			rewind(collf);
3141227Skas 			printf("-------\nMessage contains:\n");
3151227Skas 			puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
31634963Sedward 			while ((t = getc(collf)) != EOF)
31736554Sedward 				(void) putchar(t);
31831142Sedward 			goto cont;
3191227Skas 		case '|':
3201227Skas 			/*
3211227Skas 			 * Pipe message through command.
3221227Skas 			 * Collect output as new message.
3231227Skas 			 */
32434963Sedward 			rewind(collf);
32534963Sedward 			mespipe(collf, &linebuf[2]);
32631142Sedward 			goto cont;
3271227Skas 		case 'v':
3281227Skas 		case 'e':
3291227Skas 			/*
3301227Skas 			 * Edit the current message.
3311227Skas 			 * 'e' means to use EDITOR
3321227Skas 			 * 'v' means to use VISUAL
3331227Skas 			 */
33434963Sedward 			rewind(collf);
33534963Sedward 			mesedit(collf, c);
33631142Sedward 			goto cont;
3371227Skas 		}
3381227Skas 	}
33931142Sedward 	goto out;
3401227Skas err:
34134963Sedward 	if (collf != NULL) {
34243865Sedward 		Fclose(collf);
34334963Sedward 		collf = NULL;
34431142Sedward 	}
34531142Sedward out:
34634963Sedward 	if (collf != NULL)
34734963Sedward 		rewind(collf);
34836554Sedward 	noreset--;
34936554Sedward 	sigblock(sigmask(SIGINT) | sigmask(SIGHUP));
35031142Sedward 	signal(SIGINT, saveint);
35131142Sedward 	signal(SIGHUP, savehup);
35236554Sedward 	signal(SIGTSTP, savetstp);
35336554Sedward 	signal(SIGTTOU, savettou);
35436554Sedward 	signal(SIGTTIN, savettin);
35531142Sedward 	sigsetmask(omask);
35634963Sedward 	return collf;
3571227Skas }
3581227Skas 
3591227Skas /*
3601227Skas  * Write a file, ex-like if f set.
3611227Skas  */
36254505Sbostic int
exwrite(name,fp,f)36331142Sedward exwrite(name, fp, f)
3641227Skas 	char name[];
36531142Sedward 	FILE *fp;
36654505Sbostic 	int f;
3671227Skas {
3681227Skas 	register FILE *of;
3691227Skas 	register int c;
3701227Skas 	long cc;
3711227Skas 	int lc;
3721227Skas 	struct stat junk;
3731227Skas 
3741227Skas 	if (f) {
3751227Skas 		printf("\"%s\" ", name);
3761227Skas 		fflush(stdout);
3771227Skas 	}
3784586Skurt 	if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) {
3791227Skas 		if (!f)
3801227Skas 			fprintf(stderr, "%s: ", name);
38131142Sedward 		fprintf(stderr, "File exists\n");
3821227Skas 		return(-1);
3831227Skas 	}
38443865Sedward 	if ((of = Fopen(name, "w")) == NULL) {
3851227Skas 		perror(NOSTR);
3861227Skas 		return(-1);
3871227Skas 	}
3881227Skas 	lc = 0;
3891227Skas 	cc = 0;
39031142Sedward 	while ((c = getc(fp)) != EOF) {
3911227Skas 		cc++;
3921227Skas 		if (c == '\n')
3931227Skas 			lc++;
39436554Sedward 		(void) putc(c, of);
3951227Skas 		if (ferror(of)) {
3961227Skas 			perror(name);
39743865Sedward 			Fclose(of);
3981227Skas 			return(-1);
3991227Skas 		}
4001227Skas 	}
40143865Sedward 	Fclose(of);
4021227Skas 	printf("%d/%ld\n", lc, cc);
4031227Skas 	fflush(stdout);
4041227Skas 	return(0);
4051227Skas }
4061227Skas 
4071227Skas /*
40831142Sedward  * Edit the message being collected on fp.
4091227Skas  * On return, make the edit file the new temp file.
4101227Skas  */
41154505Sbostic void
mesedit(fp,c)41231142Sedward mesedit(fp, c)
41331142Sedward 	FILE *fp;
41454505Sbostic 	int c;
4151227Skas {
41639162Sbostic 	sig_t sigint = signal(SIGINT, SIG_IGN);
41734963Sedward 	FILE *nf = run_editor(fp, (off_t)-1, c, 0);
4181227Skas 
41934963Sedward 	if (nf != NULL) {
42054505Sbostic 		fseek(nf, 0L, 2);
42134963Sedward 		collf = nf;
42243865Sedward 		Fclose(fp);
4231227Skas 	}
42434963Sedward 	(void) signal(SIGINT, sigint);
4251227Skas }
4261227Skas 
4271227Skas /*
4281227Skas  * Pipe the message through the command.
4291227Skas  * Old message is on stdin of command;
4301227Skas  * New message collected from stdout.
4311227Skas  * Sh -c must return 0 to accept the new message.
4321227Skas  */
43354505Sbostic void
mespipe(fp,cmd)43431142Sedward mespipe(fp, cmd)
43531142Sedward 	FILE *fp;
4361227Skas 	char cmd[];
4371227Skas {
43834963Sedward 	FILE *nf;
43939162Sbostic 	sig_t sigint = signal(SIGINT, SIG_IGN);
44033218Sbostic 	extern char tempEdit[];
441*66999Sedward 	char *shell;
4421227Skas 
44343865Sedward 	if ((nf = Fopen(tempEdit, "w+")) == NULL) {
4441227Skas 		perror(tempEdit);
44534963Sedward 		goto out;
4461227Skas 	}
44734963Sedward 	(void) unlink(tempEdit);
44834963Sedward 	/*
44934963Sedward 	 * stdin = current message.
45034963Sedward 	 * stdout = new message.
45134963Sedward 	 */
452*66999Sedward 	if ((shell = value("SHELL")) == NOSTR)
453*66999Sedward 		shell = _PATH_CSHELL;
454*66999Sedward 	if (run_command(shell,
455*66999Sedward 	    0, fileno(fp), fileno(nf), "-c", cmd, NOSTR) < 0) {
45643865Sedward 		(void) Fclose(nf);
45734963Sedward 		goto out;
4581227Skas 	}
45931142Sedward 	if (fsize(nf) == 0) {
4601227Skas 		fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
46143865Sedward 		(void) Fclose(nf);
46234963Sedward 		goto out;
4631227Skas 	}
4641227Skas 	/*
4651227Skas 	 * Take new files.
4661227Skas 	 */
46734963Sedward 	(void) fseek(nf, 0L, 2);
46831142Sedward 	collf = nf;
46943865Sedward 	(void) Fclose(fp);
47034963Sedward out:
47134963Sedward 	(void) signal(SIGINT, sigint);
4721227Skas }
4731227Skas 
4741227Skas /*
4751227Skas  * Interpolate the named messages into the current
4761227Skas  * message, preceding each line with a tab.
4771227Skas  * Return a count of the number of characters now in
4781227Skas  * the message, or -1 if an error is encountered writing
4791227Skas  * the message temporary.  The flag argument is 'm' if we
4801227Skas  * should shift over and 'f' if not.
4811227Skas  */
48254505Sbostic int
forward(ms,fp,f)48331142Sedward forward(ms, fp, f)
4841227Skas 	char ms[];
48531142Sedward 	FILE *fp;
48654505Sbostic 	int f;
4871227Skas {
48834987Sedward 	register int *msgvec;
4891227Skas 	extern char tempMail[];
49034969Sedward 	struct ignoretab *ig;
49134969Sedward 	char *tabst;
4921227Skas 
4931227Skas 	msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
4941227Skas 	if (msgvec == (int *) NOSTR)
4951227Skas 		return(0);
4961227Skas 	if (getmsglist(ms, msgvec, 0) < 0)
4971227Skas 		return(0);
49834987Sedward 	if (*msgvec == 0) {
4991227Skas 		*msgvec = first(0, MMNORM);
5001227Skas 		if (*msgvec == NULL) {
5011227Skas 			printf("No appropriate messages\n");
5021227Skas 			return(0);
5031227Skas 		}
5041227Skas 		msgvec[1] = NULL;
5051227Skas 	}
50634969Sedward 	if (f == 'f' || f == 'F')
50734969Sedward 		tabst = NOSTR;
50839160Sedward 	else if ((tabst = value("indentprefix")) == NOSTR)
50934969Sedward 		tabst = "\t";
51034969Sedward 	ig = isupper(f) ? NULL : ignore;
5111227Skas 	printf("Interpolating:");
51234987Sedward 	for (; *msgvec != 0; msgvec++) {
51334987Sedward 		struct message *mp = message + *msgvec - 1;
51434987Sedward 
51534987Sedward 		touch(mp);
51634987Sedward 		printf(" %d", *msgvec);
51734987Sedward 		if (send(mp, fp, ig, tabst) < 0) {
51834969Sedward 			perror(tempMail);
51934969Sedward 			return(-1);
52034969Sedward 		}
5211227Skas 	}
5221227Skas 	printf("\n");
5231227Skas 	return(0);
5241227Skas }
5251227Skas 
5261227Skas /*
5273420Skurt  * Print (continue) when continued after ^Z.
5283420Skurt  */
52931142Sedward /*ARGSUSED*/
53047706Sbostic void
collstop(s)53136554Sedward collstop(s)
53254505Sbostic 	int s;
5333420Skurt {
53439162Sbostic 	sig_t old_action = signal(s, SIG_DFL);
5353420Skurt 
53636554Sedward 	sigsetmask(sigblock(0) & ~sigmask(s));
53736554Sedward 	kill(0, s);
53836554Sedward 	sigblock(sigmask(s));
53936554Sedward 	signal(s, old_action);
54036554Sedward 	if (colljmp_p) {
54136554Sedward 		colljmp_p = 0;
54236554Sedward 		hadintr = 0;
54336554Sedward 		longjmp(colljmp, 1);
54436554Sedward 	}
5453420Skurt }
5463420Skurt 
5473420Skurt /*
54836554Sedward  * On interrupt, come here to save the partial message in ~/dead.letter.
54936554Sedward  * Then jump out of the collection loop.
5501227Skas  */
55136554Sedward /*ARGSUSED*/
55247706Sbostic void
collint(s)55336554Sedward collint(s)
55454505Sbostic 	int s;
5551227Skas {
55636554Sedward 	/*
55736554Sedward 	 * the control flow is subtle, because we can be called from ~q.
55836554Sedward 	 */
55936554Sedward 	if (!hadintr) {
56036554Sedward 		if (value("ignore") != NOSTR) {
56136554Sedward 			puts("@");
56236554Sedward 			fflush(stdout);
56336554Sedward 			clearerr(stdin);
56436554Sedward 			return;
56536554Sedward 		}
56631142Sedward 		hadintr = 1;
56736554Sedward 		longjmp(colljmp, 1);
5681227Skas 	}
56931142Sedward 	rewind(collf);
57036554Sedward 	if (value("nosave") == NOSTR)
57135351Sedward 		savedeadletter(collf);
57236554Sedward 	longjmp(collabort, 1);
5731227Skas }
5741227Skas 
57536554Sedward /*ARGSUSED*/
57647706Sbostic void
collhup(s)57736554Sedward collhup(s)
57854505Sbostic 	int s;
57936554Sedward {
58036554Sedward 	rewind(collf);
58136554Sedward 	savedeadletter(collf);
58236554Sedward 	/*
58336554Sedward 	 * Let's pretend nobody else wants to clean up,
58436554Sedward 	 * a true statement at this time.
58536554Sedward 	 */
58636554Sedward 	exit(1);
58736554Sedward }
58836554Sedward 
58954505Sbostic void
savedeadletter(fp)59035351Sedward savedeadletter(fp)
59135351Sedward 	register FILE *fp;
59235351Sedward {
59335351Sedward 	register FILE *dbuf;
59435351Sedward 	register int c;
59535351Sedward 	char *cp;
59635351Sedward 
59735351Sedward 	if (fsize(fp) == 0)
59835351Sedward 		return;
59935351Sedward 	cp = getdeadletter();
60035351Sedward 	c = umask(077);
60143865Sedward 	dbuf = Fopen(cp, "a");
60236554Sedward 	(void) umask(c);
60335351Sedward 	if (dbuf == NULL)
60435351Sedward 		return;
60535351Sedward 	while ((c = getc(fp)) != EOF)
60636554Sedward 		(void) putc(c, dbuf);
60743865Sedward 	Fclose(dbuf);
60835351Sedward 	rewind(fp);
60935351Sedward }
610