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