Commit | Line | Data |
---|---|---|
9552e6b8 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
0c5f72fb KB |
3 | * All rights reserved. |
4 | * | |
f15db449 | 5 | * %sccs.include.redist.c% |
9552e6b8 DF |
6 | */ |
7 | ||
acfc7e9b | 8 | #ifndef lint |
f15db449 | 9 | static char sccsid[] = "@(#)collect.c 5.21 (Berkeley) %G%"; |
acfc7e9b | 10 | #endif /* not lint */ |
06300dd9 KS |
11 | |
12 | /* | |
13 | * Mail -- a mail program | |
14 | * | |
15 | * Collect input from standard input, handling | |
16 | * ~ escapes. | |
17 | */ | |
18 | ||
06300dd9 KS |
19 | #include "rcv.h" |
20 | #include <sys/stat.h> | |
21 | ||
22 | /* | |
23 | * Read a message from standard output and return a read file to it | |
24 | * or NULL on error. | |
25 | */ | |
26 | ||
27 | /* | |
28 | * The following hokiness with global variables is so that on | |
29 | * receipt of an interrupt signal, the partial message can be salted | |
828615a1 | 30 | * away on dead.letter. |
06300dd9 KS |
31 | */ |
32 | ||
392fe950 KB |
33 | static sig_t saveint; /* Previous SIGINT value */ |
34 | static sig_t savehup; /* Previous SIGHUP value */ | |
35 | static sig_t savetstp; /* Previous SIGTSTP value */ | |
36 | static sig_t savettou; /* Previous SIGTTOU value */ | |
37 | static sig_t savettin; /* Previous SIGTTIN value */ | |
828615a1 | 38 | static FILE *collf; /* File for saving away */ |
06300dd9 KS |
39 | static int hadintr; /* Have seen one SIGINT so far */ |
40 | ||
2ee3bce2 EW |
41 | static jmp_buf colljmp; /* To get back to work */ |
42 | static int colljmp_p; /* whether to long jump */ | |
43 | static jmp_buf collabort; /* To end collection with error */ | |
06300dd9 KS |
44 | |
45 | FILE * | |
3d6f01e5 | 46 | collect(hp, printheaders) |
06300dd9 KS |
47 | struct header *hp; |
48 | { | |
d33aa50d | 49 | FILE *fbuf; |
2ee3bce2 EW |
50 | int lc, cc, escape, eofcount; |
51 | int collint(), collhup(), collstop(); | |
06300dd9 KS |
52 | register int c, t; |
53 | char linebuf[LINESIZE], *cp; | |
54 | extern char tempMail[]; | |
4e161d3b | 55 | char getsub; |
828615a1 | 56 | int omask; |
06300dd9 | 57 | |
828615a1 | 58 | collf = NULL; |
828615a1 EW |
59 | /* |
60 | * Start catching signals from here, but we're still die on interrupts | |
61 | * until we're in the main loop. | |
62 | */ | |
63 | omask = sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); | |
64 | if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) | |
2ee3bce2 | 65 | signal(SIGINT, collint); |
828615a1 | 66 | if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) |
2ee3bce2 EW |
67 | signal(SIGHUP, collhup); |
68 | savetstp = signal(SIGTSTP, collstop); | |
69 | savettou = signal(SIGTTOU, collstop); | |
70 | savettin = signal(SIGTTIN, collstop); | |
71 | if (setjmp(collabort) || setjmp(colljmp)) { | |
828615a1 | 72 | remove(tempMail); |
06300dd9 KS |
73 | goto err; |
74 | } | |
828615a1 EW |
75 | sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP))); |
76 | ||
2ee3bce2 | 77 | noreset++; |
d33aa50d | 78 | if ((collf = fopen(tempMail, "w+")) == NULL) { |
06300dd9 | 79 | perror(tempMail); |
06300dd9 KS |
80 | goto err; |
81 | } | |
d33aa50d | 82 | unlink(tempMail); |
06300dd9 KS |
83 | |
84 | /* | |
85 | * If we are going to prompt for a subject, | |
86 | * refrain from printing a newline after | |
87 | * the headers (since some people mind). | |
88 | */ | |
06300dd9 | 89 | t = GTO|GSUBJECT|GCC|GNL; |
4e161d3b | 90 | getsub = 0; |
686f6134 | 91 | if (hp->h_subject == NOSTR && value("interactive") != NOSTR && |
638cc92d | 92 | (value("ask") != NOSTR || value("asksub") != NOSTR)) |
4e161d3b | 93 | t &= ~GNL, getsub++; |
3d6f01e5 | 94 | if (printheaders) { |
06300dd9 KS |
95 | puthead(hp, stdout, t); |
96 | fflush(stdout); | |
97 | } | |
06300dd9 KS |
98 | if ((cp = value("escape")) != NOSTR) |
99 | escape = *cp; | |
686f6134 EW |
100 | else |
101 | escape = ESCAPE; | |
2ee3bce2 | 102 | eofcount = 0; |
828615a1 EW |
103 | hadintr = 0; |
104 | ||
2ee3bce2 | 105 | if (!setjmp(colljmp)) { |
828615a1 | 106 | if (getsub) |
4e161d3b | 107 | grabh(hp, GSUBJECT); |
828615a1 EW |
108 | } else { |
109 | /* | |
110 | * Come here for printing the after-signal message. | |
111 | * Duplicate messages won't be printed because | |
112 | * the write is aborted if we get a SIGTTOU. | |
113 | */ | |
114 | cont: | |
115 | if (hadintr) { | |
116 | fflush(stdout); | |
117 | fprintf(stderr, | |
118 | "\n(Interrupt -- one more to kill letter)\n"); | |
119 | } else { | |
120 | printf("(continue)\n"); | |
121 | fflush(stdout); | |
4e161d3b | 122 | } |
828615a1 EW |
123 | } |
124 | for (;;) { | |
2ee3bce2 EW |
125 | colljmp_p = 1; |
126 | c = readline(stdin, linebuf, LINESIZE); | |
127 | colljmp_p = 0; | |
128 | if (c < 0) { | |
686f6134 | 129 | if (value("interactive") != NOSTR && |
2ee3bce2 | 130 | value("ignoreeof") != NOSTR && ++eofcount < 25) { |
828615a1 | 131 | printf("Use \".\" to terminate letter\n"); |
0fa68535 KS |
132 | continue; |
133 | } | |
06300dd9 | 134 | break; |
0fa68535 | 135 | } |
2ee3bce2 | 136 | eofcount = 0; |
06300dd9 | 137 | hadintr = 0; |
686f6134 EW |
138 | if (linebuf[0] == '.' && linebuf[1] == '\0' && |
139 | value("interactive") != NOSTR && | |
b068a67e | 140 | (value("dot") != NOSTR || value("ignoreeof") != NOSTR)) |
06300dd9 | 141 | break; |
686f6134 | 142 | if (linebuf[0] != escape || value("interactive") == NOSTR) { |
d33aa50d | 143 | if (putline(collf, linebuf) < 0) |
06300dd9 KS |
144 | goto err; |
145 | continue; | |
146 | } | |
147 | c = linebuf[1]; | |
06300dd9 KS |
148 | switch (c) { |
149 | default: | |
150 | /* | |
151 | * On double escape, just send the single one. | |
152 | * Otherwise, it's an error. | |
153 | */ | |
06300dd9 | 154 | if (c == escape) { |
d33aa50d | 155 | if (putline(collf, &linebuf[1]) < 0) |
06300dd9 KS |
156 | goto err; |
157 | else | |
158 | break; | |
159 | } | |
160 | printf("Unknown tilde escape.\n"); | |
161 | break; | |
06300dd9 KS |
162 | case 'C': |
163 | /* | |
164 | * Dump core. | |
165 | */ | |
06300dd9 KS |
166 | core(); |
167 | break; | |
06300dd9 KS |
168 | case '!': |
169 | /* | |
170 | * Shell escape, send the balance of the | |
171 | * line to sh -c. | |
172 | */ | |
06300dd9 KS |
173 | shell(&linebuf[2]); |
174 | break; | |
06300dd9 | 175 | case ':': |
06300dd9 KS |
176 | /* |
177 | * Escape to command mode, but be nice! | |
178 | */ | |
343c874e | 179 | execute(&linebuf[2], 1); |
828615a1 | 180 | goto cont; |
06300dd9 KS |
181 | case '.': |
182 | /* | |
183 | * Simulate end of file on input. | |
184 | */ | |
828615a1 | 185 | goto out; |
06300dd9 | 186 | case 'q': |
06300dd9 KS |
187 | /* |
188 | * Force a quit of sending mail. | |
189 | * Act like an interrupt happened. | |
190 | */ | |
06300dd9 | 191 | hadintr++; |
2ee3bce2 | 192 | collint(SIGINT); |
06300dd9 | 193 | exit(1); |
06300dd9 KS |
194 | case 'h': |
195 | /* | |
196 | * Grab a bunch of headers. | |
197 | */ | |
06300dd9 | 198 | grabh(hp, GTO|GSUBJECT|GCC|GBCC); |
828615a1 | 199 | goto cont; |
06300dd9 KS |
200 | case 't': |
201 | /* | |
202 | * Add to the To list. | |
203 | */ | |
3d6f01e5 | 204 | hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO)); |
06300dd9 | 205 | break; |
06300dd9 KS |
206 | case 's': |
207 | /* | |
208 | * Set the Subject list. | |
209 | */ | |
06300dd9 | 210 | cp = &linebuf[2]; |
828615a1 | 211 | while (isspace(*cp)) |
06300dd9 KS |
212 | cp++; |
213 | hp->h_subject = savestr(cp); | |
06300dd9 | 214 | break; |
06300dd9 KS |
215 | case 'c': |
216 | /* | |
217 | * Add to the CC list. | |
218 | */ | |
3d6f01e5 | 219 | hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC)); |
06300dd9 | 220 | break; |
06300dd9 KS |
221 | case 'b': |
222 | /* | |
223 | * Add stuff to blind carbon copies list. | |
224 | */ | |
3d6f01e5 | 225 | hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); |
06300dd9 | 226 | break; |
06300dd9 | 227 | case 'd': |
62e28b79 | 228 | strcpy(linebuf + 2, getdeadletter()); |
06300dd9 | 229 | /* fall into . . . */ |
06300dd9 KS |
230 | case 'r': |
231 | /* | |
232 | * Invoke a file: | |
233 | * Search for the file name, | |
d33aa50d | 234 | * then open it and copy the contents to collf. |
06300dd9 | 235 | */ |
06300dd9 | 236 | cp = &linebuf[2]; |
828615a1 | 237 | while (isspace(*cp)) |
06300dd9 KS |
238 | cp++; |
239 | if (*cp == '\0') { | |
240 | printf("Interpolate what file?\n"); | |
241 | break; | |
242 | } | |
243 | cp = expand(cp); | |
244 | if (cp == NOSTR) | |
245 | break; | |
246 | if (isdir(cp)) { | |
828615a1 | 247 | printf("%s: Directory\n", cp); |
06300dd9 KS |
248 | break; |
249 | } | |
250 | if ((fbuf = fopen(cp, "r")) == NULL) { | |
251 | perror(cp); | |
252 | break; | |
253 | } | |
254 | printf("\"%s\" ", cp); | |
80187484 | 255 | fflush(stdout); |
06300dd9 KS |
256 | lc = 0; |
257 | cc = 0; | |
2ee3bce2 | 258 | while (readline(fbuf, linebuf, LINESIZE) >= 0) { |
06300dd9 | 259 | lc++; |
d33aa50d | 260 | if ((t = putline(collf, linebuf)) < 0) { |
06300dd9 KS |
261 | fclose(fbuf); |
262 | goto err; | |
263 | } | |
264 | cc += t; | |
265 | } | |
266 | fclose(fbuf); | |
267 | printf("%d/%d\n", lc, cc); | |
268 | break; | |
06300dd9 KS |
269 | case 'w': |
270 | /* | |
271 | * Write the message on a file. | |
272 | */ | |
06300dd9 | 273 | cp = &linebuf[2]; |
470c33f3 | 274 | while (*cp == ' ' || *cp == '\t') |
06300dd9 KS |
275 | cp++; |
276 | if (*cp == '\0') { | |
277 | fprintf(stderr, "Write what file!?\n"); | |
278 | break; | |
279 | } | |
280 | if ((cp = expand(cp)) == NOSTR) | |
281 | break; | |
d33aa50d EW |
282 | rewind(collf); |
283 | exwrite(cp, collf, 1); | |
06300dd9 | 284 | break; |
06300dd9 | 285 | case 'm': |
2de8fc95 | 286 | case 'M': |
06300dd9 | 287 | case 'f': |
2de8fc95 | 288 | case 'F': |
06300dd9 KS |
289 | /* |
290 | * Interpolate the named messages, if we | |
291 | * are in receiving mail mode. Does the | |
292 | * standard list processing garbage. | |
293 | * If ~f is given, we don't shift over. | |
294 | */ | |
470c33f3 | 295 | if (forward(linebuf + 2, collf, c) < 0) |
06300dd9 | 296 | goto err; |
828615a1 | 297 | goto cont; |
06300dd9 | 298 | case '?': |
435e8dff KB |
299 | if ((fbuf = fopen(_PATH_TILDE, "r")) == NULL) { |
300 | perror(_PATH_TILDE); | |
06300dd9 KS |
301 | break; |
302 | } | |
4ee3e718 | 303 | while ((t = getc(fbuf)) != EOF) |
2ee3bce2 | 304 | (void) putchar(t); |
06300dd9 KS |
305 | fclose(fbuf); |
306 | break; | |
06300dd9 KS |
307 | case 'p': |
308 | /* | |
309 | * Print out the current state of the | |
310 | * message without altering anything. | |
311 | */ | |
d33aa50d | 312 | rewind(collf); |
06300dd9 KS |
313 | printf("-------\nMessage contains:\n"); |
314 | puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); | |
d33aa50d | 315 | while ((t = getc(collf)) != EOF) |
2ee3bce2 | 316 | (void) putchar(t); |
828615a1 | 317 | goto cont; |
06300dd9 KS |
318 | case '|': |
319 | /* | |
320 | * Pipe message through command. | |
321 | * Collect output as new message. | |
322 | */ | |
d33aa50d EW |
323 | rewind(collf); |
324 | mespipe(collf, &linebuf[2]); | |
828615a1 | 325 | goto cont; |
06300dd9 KS |
326 | case 'v': |
327 | case 'e': | |
328 | /* | |
329 | * Edit the current message. | |
330 | * 'e' means to use EDITOR | |
331 | * 'v' means to use VISUAL | |
332 | */ | |
d33aa50d EW |
333 | rewind(collf); |
334 | mesedit(collf, c); | |
828615a1 | 335 | goto cont; |
06300dd9 KS |
336 | } |
337 | } | |
828615a1 | 338 | goto out; |
06300dd9 | 339 | err: |
d33aa50d EW |
340 | if (collf != NULL) { |
341 | fclose(collf); | |
342 | collf = NULL; | |
828615a1 EW |
343 | } |
344 | out: | |
d33aa50d EW |
345 | if (collf != NULL) |
346 | rewind(collf); | |
2ee3bce2 EW |
347 | noreset--; |
348 | sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); | |
828615a1 EW |
349 | signal(SIGINT, saveint); |
350 | signal(SIGHUP, savehup); | |
2ee3bce2 EW |
351 | signal(SIGTSTP, savetstp); |
352 | signal(SIGTTOU, savettou); | |
353 | signal(SIGTTIN, savettin); | |
828615a1 | 354 | sigsetmask(omask); |
d33aa50d | 355 | return collf; |
06300dd9 KS |
356 | } |
357 | ||
358 | /* | |
359 | * Write a file, ex-like if f set. | |
360 | */ | |
361 | ||
828615a1 | 362 | exwrite(name, fp, f) |
06300dd9 | 363 | char name[]; |
828615a1 | 364 | FILE *fp; |
06300dd9 KS |
365 | { |
366 | register FILE *of; | |
367 | register int c; | |
368 | long cc; | |
369 | int lc; | |
370 | struct stat junk; | |
371 | ||
372 | if (f) { | |
373 | printf("\"%s\" ", name); | |
374 | fflush(stdout); | |
375 | } | |
6d1cdf8d | 376 | if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) { |
06300dd9 KS |
377 | if (!f) |
378 | fprintf(stderr, "%s: ", name); | |
828615a1 | 379 | fprintf(stderr, "File exists\n"); |
06300dd9 KS |
380 | return(-1); |
381 | } | |
382 | if ((of = fopen(name, "w")) == NULL) { | |
383 | perror(NOSTR); | |
384 | return(-1); | |
385 | } | |
386 | lc = 0; | |
387 | cc = 0; | |
828615a1 | 388 | while ((c = getc(fp)) != EOF) { |
06300dd9 KS |
389 | cc++; |
390 | if (c == '\n') | |
391 | lc++; | |
2ee3bce2 | 392 | (void) putc(c, of); |
06300dd9 KS |
393 | if (ferror(of)) { |
394 | perror(name); | |
395 | fclose(of); | |
396 | return(-1); | |
397 | } | |
398 | } | |
399 | fclose(of); | |
400 | printf("%d/%ld\n", lc, cc); | |
401 | fflush(stdout); | |
402 | return(0); | |
403 | } | |
404 | ||
405 | /* | |
828615a1 | 406 | * Edit the message being collected on fp. |
06300dd9 KS |
407 | * On return, make the edit file the new temp file. |
408 | */ | |
828615a1 EW |
409 | mesedit(fp, c) |
410 | FILE *fp; | |
06300dd9 | 411 | { |
392fe950 | 412 | sig_t sigint = signal(SIGINT, SIG_IGN); |
d33aa50d | 413 | FILE *nf = run_editor(fp, (off_t)-1, c, 0); |
06300dd9 | 414 | |
d33aa50d EW |
415 | if (nf != NULL) { |
416 | fseek(nf, (off_t)0, 2); | |
417 | collf = nf; | |
418 | fclose(fp); | |
06300dd9 | 419 | } |
d33aa50d | 420 | (void) signal(SIGINT, sigint); |
06300dd9 KS |
421 | } |
422 | ||
423 | /* | |
424 | * Pipe the message through the command. | |
425 | * Old message is on stdin of command; | |
426 | * New message collected from stdout. | |
427 | * Sh -c must return 0 to accept the new message. | |
428 | */ | |
828615a1 EW |
429 | mespipe(fp, cmd) |
430 | FILE *fp; | |
06300dd9 KS |
431 | char cmd[]; |
432 | { | |
d33aa50d | 433 | FILE *nf; |
392fe950 | 434 | sig_t sigint = signal(SIGINT, SIG_IGN); |
001d60ad | 435 | extern char tempEdit[]; |
06300dd9 | 436 | |
828615a1 | 437 | if ((nf = fopen(tempEdit, "w+")) == NULL) { |
06300dd9 | 438 | perror(tempEdit); |
d33aa50d | 439 | goto out; |
06300dd9 | 440 | } |
d33aa50d EW |
441 | (void) unlink(tempEdit); |
442 | /* | |
443 | * stdin = current message. | |
444 | * stdout = new message. | |
445 | */ | |
446 | if (run_command(cmd, 0, fileno(fp), fileno(nf), NOSTR) < 0) { | |
447 | (void) fclose(nf); | |
448 | goto out; | |
06300dd9 | 449 | } |
828615a1 | 450 | if (fsize(nf) == 0) { |
06300dd9 | 451 | fprintf(stderr, "No bytes from \"%s\" !?\n", cmd); |
d33aa50d EW |
452 | (void) fclose(nf); |
453 | goto out; | |
06300dd9 | 454 | } |
06300dd9 KS |
455 | /* |
456 | * Take new files. | |
457 | */ | |
d33aa50d | 458 | (void) fseek(nf, 0L, 2); |
828615a1 | 459 | collf = nf; |
d33aa50d EW |
460 | (void) fclose(fp); |
461 | out: | |
462 | (void) signal(SIGINT, sigint); | |
06300dd9 KS |
463 | } |
464 | ||
465 | /* | |
466 | * Interpolate the named messages into the current | |
467 | * message, preceding each line with a tab. | |
468 | * Return a count of the number of characters now in | |
469 | * the message, or -1 if an error is encountered writing | |
470 | * the message temporary. The flag argument is 'm' if we | |
471 | * should shift over and 'f' if not. | |
472 | */ | |
828615a1 | 473 | forward(ms, fp, f) |
06300dd9 | 474 | char ms[]; |
828615a1 | 475 | FILE *fp; |
06300dd9 | 476 | { |
470c33f3 | 477 | register int *msgvec; |
06300dd9 | 478 | extern char tempMail[]; |
2de8fc95 EW |
479 | struct ignoretab *ig; |
480 | char *tabst; | |
06300dd9 KS |
481 | |
482 | msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec); | |
483 | if (msgvec == (int *) NOSTR) | |
484 | return(0); | |
485 | if (getmsglist(ms, msgvec, 0) < 0) | |
486 | return(0); | |
470c33f3 | 487 | if (*msgvec == 0) { |
06300dd9 KS |
488 | *msgvec = first(0, MMNORM); |
489 | if (*msgvec == NULL) { | |
490 | printf("No appropriate messages\n"); | |
491 | return(0); | |
492 | } | |
493 | msgvec[1] = NULL; | |
494 | } | |
2de8fc95 EW |
495 | if (f == 'f' || f == 'F') |
496 | tabst = NOSTR; | |
0f642f7e | 497 | else if ((tabst = value("indentprefix")) == NOSTR) |
2de8fc95 EW |
498 | tabst = "\t"; |
499 | ig = isupper(f) ? NULL : ignore; | |
06300dd9 | 500 | printf("Interpolating:"); |
470c33f3 EW |
501 | for (; *msgvec != 0; msgvec++) { |
502 | struct message *mp = message + *msgvec - 1; | |
503 | ||
504 | touch(mp); | |
505 | printf(" %d", *msgvec); | |
506 | if (send(mp, fp, ig, tabst) < 0) { | |
2de8fc95 EW |
507 | perror(tempMail); |
508 | return(-1); | |
509 | } | |
06300dd9 KS |
510 | } |
511 | printf("\n"); | |
512 | return(0); | |
513 | } | |
514 | ||
2d55c063 KS |
515 | /* |
516 | * Print (continue) when continued after ^Z. | |
517 | */ | |
828615a1 | 518 | /*ARGSUSED*/ |
2ee3bce2 | 519 | collstop(s) |
2d55c063 | 520 | { |
392fe950 | 521 | sig_t old_action = signal(s, SIG_DFL); |
2d55c063 | 522 | |
2ee3bce2 EW |
523 | sigsetmask(sigblock(0) & ~sigmask(s)); |
524 | kill(0, s); | |
525 | sigblock(sigmask(s)); | |
526 | signal(s, old_action); | |
527 | if (colljmp_p) { | |
528 | colljmp_p = 0; | |
529 | hadintr = 0; | |
530 | longjmp(colljmp, 1); | |
531 | } | |
2d55c063 KS |
532 | } |
533 | ||
06300dd9 | 534 | /* |
2ee3bce2 EW |
535 | * On interrupt, come here to save the partial message in ~/dead.letter. |
536 | * Then jump out of the collection loop. | |
06300dd9 | 537 | */ |
2ee3bce2 EW |
538 | /*ARGSUSED*/ |
539 | collint(s) | |
06300dd9 | 540 | { |
2ee3bce2 EW |
541 | /* |
542 | * the control flow is subtle, because we can be called from ~q. | |
543 | */ | |
544 | if (!hadintr) { | |
545 | if (value("ignore") != NOSTR) { | |
546 | puts("@"); | |
547 | fflush(stdout); | |
548 | clearerr(stdin); | |
549 | return; | |
550 | } | |
828615a1 | 551 | hadintr = 1; |
2ee3bce2 | 552 | longjmp(colljmp, 1); |
06300dd9 | 553 | } |
828615a1 | 554 | rewind(collf); |
2ee3bce2 | 555 | if (value("nosave") == NOSTR) |
62e28b79 | 556 | savedeadletter(collf); |
2ee3bce2 EW |
557 | longjmp(collabort, 1); |
558 | } | |
559 | ||
560 | /*ARGSUSED*/ | |
561 | collhup(s) | |
562 | { | |
563 | rewind(collf); | |
564 | savedeadletter(collf); | |
565 | /* | |
566 | * Let's pretend nobody else wants to clean up, | |
567 | * a true statement at this time. | |
568 | */ | |
569 | exit(1); | |
06300dd9 KS |
570 | } |
571 | ||
62e28b79 EW |
572 | savedeadletter(fp) |
573 | register FILE *fp; | |
574 | { | |
575 | register FILE *dbuf; | |
576 | register int c; | |
577 | char *cp; | |
578 | ||
579 | if (fsize(fp) == 0) | |
580 | return; | |
581 | cp = getdeadletter(); | |
582 | c = umask(077); | |
583 | dbuf = fopen(cp, "a"); | |
2ee3bce2 | 584 | (void) umask(c); |
62e28b79 EW |
585 | if (dbuf == NULL) |
586 | return; | |
587 | while ((c = getc(fp)) != EOF) | |
2ee3bce2 | 588 | (void) putc(c, dbuf); |
62e28b79 EW |
589 | fclose(dbuf); |
590 | rewind(fp); | |
591 | } |