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