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 KB |
18 | #ifndef lint |
19 | static char sccsid[] = "@(#)collect.c 5.10 (Berkeley) %G%"; | |
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> | |
828615a1 | 31 | #include <sys/wait.h> |
06300dd9 KS |
32 | |
33 | /* | |
34 | * Read a message from standard output and return a read file to it | |
35 | * or NULL on error. | |
36 | */ | |
37 | ||
38 | /* | |
39 | * The following hokiness with global variables is so that on | |
40 | * receipt of an interrupt signal, the partial message can be salted | |
828615a1 | 41 | * away on dead.letter. |
06300dd9 KS |
42 | */ |
43 | ||
828615a1 | 44 | static int (*saveint)(); /* Previous SIGINT value */ |
7feecf47 | 45 | static int (*savehup)(); /* Previous SIGHUP value */ |
2d55c063 | 46 | static int (*savecont)(); /* Previous SIGCONT value */ |
828615a1 | 47 | static FILE *collf; /* File for saving away */ |
06300dd9 KS |
48 | static int hadintr; /* Have seen one SIGINT so far */ |
49 | ||
50 | static jmp_buf coljmp; /* To get back to work */ | |
51 | ||
52 | FILE * | |
3d6f01e5 | 53 | collect(hp, printheaders) |
06300dd9 KS |
54 | struct header *hp; |
55 | { | |
828615a1 EW |
56 | FILE *fp, *fbuf; |
57 | int lc, cc, escape, eof; | |
58 | int collrub(), intack(), collcont(); | |
06300dd9 KS |
59 | register int c, t; |
60 | char linebuf[LINESIZE], *cp; | |
61 | extern char tempMail[]; | |
97bff179 | 62 | int notify(); |
4e161d3b | 63 | char getsub; |
828615a1 | 64 | int omask; |
06300dd9 KS |
65 | |
66 | noreset++; | |
828615a1 EW |
67 | fp = NULL; |
68 | collf = NULL; | |
69 | ||
70 | /* | |
71 | * Start catching signals from here, but we're still die on interrupts | |
72 | * until we're in the main loop. | |
73 | */ | |
74 | omask = sigblock(sigmask(SIGINT) | sigmask(SIGHUP)); | |
75 | if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) | |
76 | signal(SIGINT, value("ignore") != NOSTR ? intack : collrub); | |
77 | if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) | |
78 | signal(SIGHUP, collrub); | |
79 | savecont = signal(SIGCONT, SIG_DFL); | |
80 | if (setjmp(coljmp)) { | |
81 | remove(tempMail); | |
06300dd9 KS |
82 | goto err; |
83 | } | |
828615a1 EW |
84 | sigsetmask(omask & ~(sigmask(SIGINT) | sigmask(SIGHUP))); |
85 | ||
86 | if ((fp = fopen(tempMail, "w+")) == NULL) { | |
06300dd9 | 87 | perror(tempMail); |
06300dd9 KS |
88 | goto err; |
89 | } | |
828615a1 | 90 | collf = fp; |
06300dd9 KS |
91 | remove(tempMail); |
92 | ||
93 | /* | |
94 | * If we are going to prompt for a subject, | |
95 | * refrain from printing a newline after | |
96 | * the headers (since some people mind). | |
97 | */ | |
06300dd9 | 98 | t = GTO|GSUBJECT|GCC|GNL; |
4e161d3b | 99 | getsub = 0; |
686f6134 EW |
100 | if (hp->h_subject == NOSTR && value("interactive") != NOSTR && |
101 | value("ask")) | |
4e161d3b | 102 | t &= ~GNL, getsub++; |
3d6f01e5 | 103 | if (printheaders) { |
06300dd9 KS |
104 | puthead(hp, stdout, t); |
105 | fflush(stdout); | |
106 | } | |
06300dd9 KS |
107 | if ((cp = value("escape")) != NOSTR) |
108 | escape = *cp; | |
686f6134 EW |
109 | else |
110 | escape = ESCAPE; | |
0fa68535 | 111 | eof = 0; |
828615a1 EW |
112 | hadintr = 0; |
113 | ||
114 | /* | |
115 | * We can put the setjmp here because register variable | |
116 | * needs to be saved in the loop. | |
117 | */ | |
118 | if (!setjmp(coljmp)) { | |
119 | signal(SIGCONT, collcont); | |
120 | if (getsub) | |
4e161d3b | 121 | grabh(hp, GSUBJECT); |
828615a1 EW |
122 | } else { |
123 | /* | |
124 | * Come here for printing the after-signal message. | |
125 | * Duplicate messages won't be printed because | |
126 | * the write is aborted if we get a SIGTTOU. | |
127 | */ | |
128 | cont: | |
129 | if (hadintr) { | |
130 | fflush(stdout); | |
131 | fprintf(stderr, | |
132 | "\n(Interrupt -- one more to kill letter)\n"); | |
133 | } else { | |
134 | printf("(continue)\n"); | |
135 | fflush(stdout); | |
4e161d3b | 136 | } |
828615a1 EW |
137 | } |
138 | for (;;) { | |
139 | if (readline(stdin, linebuf) < 0) { | |
686f6134 EW |
140 | if (value("interactive") != NOSTR && |
141 | value("ignoreeof") != NOSTR) { | |
0fa68535 KS |
142 | if (++eof > 35) |
143 | break; | |
828615a1 | 144 | printf("Use \".\" to terminate letter\n"); |
0fa68535 KS |
145 | continue; |
146 | } | |
06300dd9 | 147 | break; |
0fa68535 KS |
148 | } |
149 | eof = 0; | |
06300dd9 | 150 | hadintr = 0; |
686f6134 EW |
151 | if (linebuf[0] == '.' && linebuf[1] == '\0' && |
152 | value("interactive") != NOSTR && | |
b068a67e | 153 | (value("dot") != NOSTR || value("ignoreeof") != NOSTR)) |
06300dd9 | 154 | break; |
686f6134 | 155 | if (linebuf[0] != escape || value("interactive") == NOSTR) { |
828615a1 | 156 | if (putline(fp, linebuf) < 0) |
06300dd9 KS |
157 | goto err; |
158 | continue; | |
159 | } | |
160 | c = linebuf[1]; | |
06300dd9 KS |
161 | switch (c) { |
162 | default: | |
163 | /* | |
164 | * On double escape, just send the single one. | |
165 | * Otherwise, it's an error. | |
166 | */ | |
06300dd9 | 167 | if (c == escape) { |
828615a1 | 168 | if (putline(fp, &linebuf[1]) < 0) |
06300dd9 KS |
169 | goto err; |
170 | else | |
171 | break; | |
172 | } | |
173 | printf("Unknown tilde escape.\n"); | |
174 | break; | |
06300dd9 KS |
175 | case 'C': |
176 | /* | |
177 | * Dump core. | |
178 | */ | |
06300dd9 KS |
179 | core(); |
180 | break; | |
06300dd9 KS |
181 | case '!': |
182 | /* | |
183 | * Shell escape, send the balance of the | |
184 | * line to sh -c. | |
185 | */ | |
06300dd9 KS |
186 | shell(&linebuf[2]); |
187 | break; | |
06300dd9 | 188 | case ':': |
06300dd9 KS |
189 | /* |
190 | * Escape to command mode, but be nice! | |
191 | */ | |
343c874e | 192 | execute(&linebuf[2], 1); |
828615a1 | 193 | goto cont; |
06300dd9 KS |
194 | case '.': |
195 | /* | |
196 | * Simulate end of file on input. | |
197 | */ | |
828615a1 | 198 | goto out; |
06300dd9 | 199 | case 'q': |
06300dd9 KS |
200 | /* |
201 | * Force a quit of sending mail. | |
202 | * Act like an interrupt happened. | |
203 | */ | |
06300dd9 KS |
204 | hadintr++; |
205 | collrub(SIGINT); | |
206 | exit(1); | |
06300dd9 KS |
207 | case 'h': |
208 | /* | |
209 | * Grab a bunch of headers. | |
210 | */ | |
06300dd9 | 211 | grabh(hp, GTO|GSUBJECT|GCC|GBCC); |
828615a1 | 212 | goto cont; |
06300dd9 KS |
213 | case 't': |
214 | /* | |
215 | * Add to the To list. | |
216 | */ | |
3d6f01e5 | 217 | hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO)); |
06300dd9 | 218 | break; |
06300dd9 KS |
219 | case 's': |
220 | /* | |
221 | * Set the Subject list. | |
222 | */ | |
06300dd9 | 223 | cp = &linebuf[2]; |
828615a1 | 224 | while (isspace(*cp)) |
06300dd9 KS |
225 | cp++; |
226 | hp->h_subject = savestr(cp); | |
06300dd9 | 227 | break; |
06300dd9 KS |
228 | case 'c': |
229 | /* | |
230 | * Add to the CC list. | |
231 | */ | |
3d6f01e5 | 232 | hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC)); |
06300dd9 | 233 | break; |
06300dd9 KS |
234 | case 'b': |
235 | /* | |
236 | * Add stuff to blind carbon copies list. | |
237 | */ | |
3d6f01e5 | 238 | hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); |
06300dd9 | 239 | break; |
06300dd9 | 240 | case 'd': |
828615a1 | 241 | strcpy(linebuf + 2, deadletter); |
06300dd9 | 242 | /* fall into . . . */ |
06300dd9 KS |
243 | case 'r': |
244 | /* | |
245 | * Invoke a file: | |
246 | * Search for the file name, | |
828615a1 | 247 | * then open it and copy the contents to fp. |
06300dd9 | 248 | */ |
06300dd9 | 249 | cp = &linebuf[2]; |
828615a1 | 250 | while (isspace(*cp)) |
06300dd9 KS |
251 | cp++; |
252 | if (*cp == '\0') { | |
253 | printf("Interpolate what file?\n"); | |
254 | break; | |
255 | } | |
256 | cp = expand(cp); | |
257 | if (cp == NOSTR) | |
258 | break; | |
259 | if (isdir(cp)) { | |
828615a1 | 260 | printf("%s: Directory\n", cp); |
06300dd9 KS |
261 | break; |
262 | } | |
263 | if ((fbuf = fopen(cp, "r")) == NULL) { | |
264 | perror(cp); | |
265 | break; | |
266 | } | |
267 | printf("\"%s\" ", cp); | |
80187484 | 268 | fflush(stdout); |
06300dd9 KS |
269 | lc = 0; |
270 | cc = 0; | |
828615a1 | 271 | while (readline(fbuf, linebuf) >= 0) { |
06300dd9 | 272 | lc++; |
828615a1 | 273 | if ((t = putline(fp, linebuf)) < 0) { |
06300dd9 KS |
274 | fclose(fbuf); |
275 | goto err; | |
276 | } | |
277 | cc += t; | |
278 | } | |
279 | fclose(fbuf); | |
280 | printf("%d/%d\n", lc, cc); | |
281 | break; | |
06300dd9 KS |
282 | case 'w': |
283 | /* | |
284 | * Write the message on a file. | |
285 | */ | |
06300dd9 KS |
286 | cp = &linebuf[2]; |
287 | while (any(*cp, " \t")) | |
288 | cp++; | |
289 | if (*cp == '\0') { | |
290 | fprintf(stderr, "Write what file!?\n"); | |
291 | break; | |
292 | } | |
293 | if ((cp = expand(cp)) == NOSTR) | |
294 | break; | |
828615a1 EW |
295 | rewind(fp); |
296 | exwrite(cp, fp, 1); | |
06300dd9 | 297 | break; |
06300dd9 KS |
298 | case 'm': |
299 | case 'f': | |
300 | /* | |
301 | * Interpolate the named messages, if we | |
302 | * are in receiving mail mode. Does the | |
303 | * standard list processing garbage. | |
304 | * If ~f is given, we don't shift over. | |
305 | */ | |
06300dd9 KS |
306 | if (!rcvmode) { |
307 | printf("No messages to send from!?!\n"); | |
308 | break; | |
309 | } | |
310 | cp = &linebuf[2]; | |
311 | while (any(*cp, " \t")) | |
312 | cp++; | |
828615a1 | 313 | if (forward(cp, fp, c) < 0) |
06300dd9 | 314 | goto err; |
828615a1 | 315 | goto cont; |
06300dd9 | 316 | case '?': |
06300dd9 | 317 | if ((fbuf = fopen(THELPFILE, "r")) == NULL) { |
e5cd0021 | 318 | perror(THELPFILE); |
06300dd9 KS |
319 | break; |
320 | } | |
4ee3e718 | 321 | while ((t = getc(fbuf)) != EOF) |
06300dd9 | 322 | putchar(t); |
06300dd9 KS |
323 | fclose(fbuf); |
324 | break; | |
06300dd9 KS |
325 | case 'p': |
326 | /* | |
327 | * Print out the current state of the | |
328 | * message without altering anything. | |
329 | */ | |
828615a1 | 330 | rewind(fp); |
06300dd9 KS |
331 | printf("-------\nMessage contains:\n"); |
332 | puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); | |
828615a1 | 333 | while ((t = getc(fp)) != EOF) |
06300dd9 | 334 | putchar(t); |
828615a1 | 335 | goto cont; |
06300dd9 KS |
336 | case '|': |
337 | /* | |
338 | * Pipe message through command. | |
339 | * Collect output as new message. | |
340 | */ | |
828615a1 EW |
341 | rewind(fp); |
342 | fp = mespipe(fp, &linebuf[2]); | |
343 | goto cont; | |
06300dd9 KS |
344 | case 'v': |
345 | case 'e': | |
346 | /* | |
347 | * Edit the current message. | |
348 | * 'e' means to use EDITOR | |
349 | * 'v' means to use VISUAL | |
350 | */ | |
828615a1 EW |
351 | rewind(fp); |
352 | if ((fp = mesedit(fp, c)) == NULL) | |
06300dd9 | 353 | goto err; |
828615a1 | 354 | goto cont; |
06300dd9 KS |
355 | } |
356 | } | |
828615a1 | 357 | goto out; |
06300dd9 | 358 | err: |
828615a1 EW |
359 | if (fp != NULL) { |
360 | fclose(fp); | |
361 | fp = NULL; | |
362 | } | |
363 | out: | |
364 | if (fp != NULL) | |
365 | rewind(fp); | |
366 | signal(SIGINT, saveint); | |
367 | signal(SIGHUP, savehup); | |
368 | signal(SIGCONT, savecont); | |
369 | sigsetmask(omask); | |
06300dd9 | 370 | noreset = 0; |
828615a1 | 371 | return(fp); |
06300dd9 KS |
372 | } |
373 | ||
374 | /* | |
375 | * Write a file, ex-like if f set. | |
376 | */ | |
377 | ||
828615a1 | 378 | exwrite(name, fp, f) |
06300dd9 | 379 | char name[]; |
828615a1 | 380 | FILE *fp; |
06300dd9 KS |
381 | { |
382 | register FILE *of; | |
383 | register int c; | |
384 | long cc; | |
385 | int lc; | |
386 | struct stat junk; | |
387 | ||
388 | if (f) { | |
389 | printf("\"%s\" ", name); | |
390 | fflush(stdout); | |
391 | } | |
6d1cdf8d | 392 | if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) { |
06300dd9 KS |
393 | if (!f) |
394 | fprintf(stderr, "%s: ", name); | |
828615a1 | 395 | fprintf(stderr, "File exists\n"); |
06300dd9 KS |
396 | return(-1); |
397 | } | |
398 | if ((of = fopen(name, "w")) == NULL) { | |
399 | perror(NOSTR); | |
400 | return(-1); | |
401 | } | |
402 | lc = 0; | |
403 | cc = 0; | |
828615a1 | 404 | while ((c = getc(fp)) != EOF) { |
06300dd9 KS |
405 | cc++; |
406 | if (c == '\n') | |
407 | lc++; | |
408 | putc(c, of); | |
409 | if (ferror(of)) { | |
410 | perror(name); | |
411 | fclose(of); | |
412 | return(-1); | |
413 | } | |
414 | } | |
415 | fclose(of); | |
416 | printf("%d/%ld\n", lc, cc); | |
417 | fflush(stdout); | |
418 | return(0); | |
419 | } | |
420 | ||
421 | /* | |
828615a1 | 422 | * Edit the message being collected on fp. |
06300dd9 KS |
423 | * Write the message out onto some poorly-named temp file |
424 | * and point an editor at it. | |
425 | * | |
426 | * On return, make the edit file the new temp file. | |
427 | */ | |
428 | ||
429 | FILE * | |
828615a1 EW |
430 | mesedit(fp, c) |
431 | FILE *fp; | |
06300dd9 | 432 | { |
828615a1 EW |
433 | int pid; |
434 | union wait s; | |
06300dd9 KS |
435 | FILE *fbuf; |
436 | register int t; | |
828615a1 | 437 | int (*sigint)(), (*sigcont)(); |
06300dd9 | 438 | struct stat sbuf; |
001d60ad | 439 | extern char tempEdit[]; |
06300dd9 KS |
440 | register char *edit; |
441 | ||
828615a1 EW |
442 | sigint = signal(SIGINT, SIG_IGN); |
443 | sigcont = signal(SIGCONT, SIG_DFL); | |
06300dd9 KS |
444 | if (stat(tempEdit, &sbuf) >= 0) { |
445 | printf("%s: file exists\n", tempEdit); | |
446 | goto out; | |
447 | } | |
448 | close(creat(tempEdit, 0600)); | |
449 | if ((fbuf = fopen(tempEdit, "w")) == NULL) { | |
450 | perror(tempEdit); | |
451 | goto out; | |
452 | } | |
828615a1 | 453 | while ((t = getc(fp)) != EOF) |
06300dd9 | 454 | putc(t, fbuf); |
06300dd9 KS |
455 | fflush(fbuf); |
456 | if (ferror(fbuf)) { | |
457 | perror(tempEdit); | |
458 | remove(tempEdit); | |
459 | goto fix; | |
460 | } | |
461 | fclose(fbuf); | |
462 | if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) | |
463 | edit = c == 'e' ? EDITOR : VISUAL; | |
464 | pid = vfork(); | |
465 | if (pid == 0) { | |
828615a1 EW |
466 | if (sigint != SIG_IGN) |
467 | signal(SIGINT, SIG_DFL); | |
06300dd9 KS |
468 | execl(edit, edit, tempEdit, 0); |
469 | perror(edit); | |
470 | _exit(1); | |
471 | } | |
472 | if (pid == -1) { | |
473 | perror("fork"); | |
474 | remove(tempEdit); | |
475 | goto out; | |
476 | } | |
477 | while (wait(&s) != pid) | |
478 | ; | |
828615a1 | 479 | if (s.w_status != 0) { |
06300dd9 KS |
480 | printf("Fatal error in \"%s\"\n", edit); |
481 | remove(tempEdit); | |
482 | goto out; | |
483 | } | |
484 | ||
485 | /* | |
486 | * Now switch to new file. | |
487 | */ | |
488 | ||
828615a1 | 489 | if ((fbuf = fopen(tempEdit, "a+")) == NULL) { |
06300dd9 KS |
490 | perror(tempEdit); |
491 | remove(tempEdit); | |
492 | goto out; | |
493 | } | |
06300dd9 | 494 | remove(tempEdit); |
828615a1 EW |
495 | collf = fbuf; |
496 | fclose(fp); | |
497 | fp = fbuf; | |
06300dd9 KS |
498 | goto out; |
499 | fix: | |
500 | perror(tempEdit); | |
501 | out: | |
828615a1 EW |
502 | signal(SIGCONT, sigcont); |
503 | signal(SIGINT, sigint); | |
504 | return(fp); | |
06300dd9 KS |
505 | } |
506 | ||
507 | /* | |
508 | * Pipe the message through the command. | |
509 | * Old message is on stdin of command; | |
510 | * New message collected from stdout. | |
511 | * Sh -c must return 0 to accept the new message. | |
512 | */ | |
513 | ||
514 | FILE * | |
828615a1 EW |
515 | mespipe(fp, cmd) |
516 | FILE *fp; | |
06300dd9 KS |
517 | char cmd[]; |
518 | { | |
001d60ad | 519 | extern char tempEdit[]; |
828615a1 EW |
520 | register FILE *nf; |
521 | int pid; | |
522 | union wait s; | |
523 | int (*saveint)(); | |
06300dd9 KS |
524 | char *Shell; |
525 | ||
828615a1 | 526 | if ((nf = fopen(tempEdit, "w+")) == NULL) { |
06300dd9 | 527 | perror(tempEdit); |
828615a1 | 528 | return(fp); |
06300dd9 KS |
529 | } |
530 | remove(tempEdit); | |
828615a1 | 531 | saveint = signal(SIGINT, SIG_IGN); |
06300dd9 KS |
532 | if ((Shell = value("SHELL")) == NULL) |
533 | Shell = "/bin/sh"; | |
534 | if ((pid = vfork()) == -1) { | |
535 | perror("fork"); | |
536 | goto err; | |
537 | } | |
538 | if (pid == 0) { | |
828615a1 | 539 | int fd; |
06300dd9 KS |
540 | /* |
541 | * stdin = current message. | |
542 | * stdout = new message. | |
543 | */ | |
544 | ||
545 | close(0); | |
828615a1 | 546 | dup(fileno(fp)); |
06300dd9 | 547 | close(1); |
828615a1 EW |
548 | dup(fileno(nf)); |
549 | for (fd = getdtablesize(); --fd > 2;) | |
550 | close(fd); | |
06300dd9 KS |
551 | execl(Shell, Shell, "-c", cmd, 0); |
552 | perror(Shell); | |
553 | _exit(1); | |
554 | } | |
555 | while (wait(&s) != pid) | |
556 | ; | |
828615a1 | 557 | if (s.w_status != 0 || pid == -1) { |
06300dd9 KS |
558 | fprintf(stderr, "\"%s\" failed!?\n", cmd); |
559 | goto err; | |
560 | } | |
828615a1 | 561 | if (fsize(nf) == 0) { |
06300dd9 KS |
562 | fprintf(stderr, "No bytes from \"%s\" !?\n", cmd); |
563 | goto err; | |
564 | } | |
565 | ||
566 | /* | |
567 | * Take new files. | |
568 | */ | |
569 | ||
828615a1 EW |
570 | fseek(nf, 0L, 2); |
571 | collf = nf; | |
572 | fclose(fp); | |
573 | signal(SIGINT, saveint); | |
574 | return(nf); | |
06300dd9 KS |
575 | |
576 | err: | |
828615a1 EW |
577 | fclose(nf); |
578 | signal(SIGINT, saveint); | |
579 | return(fp); | |
06300dd9 KS |
580 | } |
581 | ||
582 | /* | |
583 | * Interpolate the named messages into the current | |
584 | * message, preceding each line with a tab. | |
585 | * Return a count of the number of characters now in | |
586 | * the message, or -1 if an error is encountered writing | |
587 | * the message temporary. The flag argument is 'm' if we | |
588 | * should shift over and 'f' if not. | |
589 | */ | |
828615a1 | 590 | forward(ms, fp, f) |
06300dd9 | 591 | char ms[]; |
828615a1 | 592 | FILE *fp; |
06300dd9 KS |
593 | { |
594 | register int *msgvec, *ip; | |
595 | extern char tempMail[]; | |
596 | ||
597 | msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec); | |
598 | if (msgvec == (int *) NOSTR) | |
599 | return(0); | |
600 | if (getmsglist(ms, msgvec, 0) < 0) | |
601 | return(0); | |
602 | if (*msgvec == NULL) { | |
603 | *msgvec = first(0, MMNORM); | |
604 | if (*msgvec == NULL) { | |
605 | printf("No appropriate messages\n"); | |
606 | return(0); | |
607 | } | |
608 | msgvec[1] = NULL; | |
609 | } | |
610 | printf("Interpolating:"); | |
611 | for (ip = msgvec; *ip != NULL; ip++) { | |
612 | touch(*ip); | |
613 | printf(" %d", *ip); | |
614 | if (f == 'm') { | |
828615a1 | 615 | if (transmit(&message[*ip-1], fp) < 0L) { |
06300dd9 KS |
616 | perror(tempMail); |
617 | return(-1); | |
618 | } | |
619 | } else | |
828615a1 | 620 | if (send(&message[*ip-1], fp, 0) < 0) { |
06300dd9 KS |
621 | perror(tempMail); |
622 | return(-1); | |
623 | } | |
624 | } | |
625 | printf("\n"); | |
626 | return(0); | |
627 | } | |
628 | ||
629 | /* | |
630 | * Send message described by the passed pointer to the | |
631 | * passed output buffer. Insert a tab in front of each | |
632 | * line. Return a count of the characters sent, or -1 | |
633 | * on error. | |
634 | */ | |
5deb0e1e | 635 | long |
828615a1 | 636 | transmit(mailp, fp) |
06300dd9 | 637 | struct message *mailp; |
828615a1 | 638 | FILE *fp; |
06300dd9 KS |
639 | { |
640 | register struct message *mp; | |
5deb0e1e CS |
641 | register int ch; |
642 | long c, n; | |
643 | int bol; | |
06300dd9 | 644 | FILE *ibuf; |
1d6cdde7 | 645 | char *tabst; |
06300dd9 KS |
646 | |
647 | mp = mailp; | |
648 | ibuf = setinput(mp); | |
5deb0e1e | 649 | c = mp->m_size; |
06300dd9 KS |
650 | n = c; |
651 | bol = 1; | |
1d6cdde7 EW |
652 | if ((tabst = value("tabstr")) == NOSTR) |
653 | tabst = "\t"; | |
5deb0e1e | 654 | while (c-- > 0L) { |
828615a1 EW |
655 | ch = getc(ibuf); |
656 | if (ch == '\n') | |
657 | bol = 1; | |
658 | else if (bol) { | |
06300dd9 | 659 | bol = 0; |
1d6cdde7 | 660 | fputs(tabst, fp); |
06300dd9 | 661 | n++; |
06300dd9 | 662 | } |
828615a1 EW |
663 | putc(ch, fp); |
664 | if (ferror(fp)) { | |
06300dd9 | 665 | perror("/tmp"); |
5deb0e1e | 666 | return(-1L); |
06300dd9 KS |
667 | } |
668 | } | |
669 | return(n); | |
670 | } | |
671 | ||
2d55c063 KS |
672 | /* |
673 | * Print (continue) when continued after ^Z. | |
674 | */ | |
828615a1 | 675 | /*ARGSUSED*/ |
2d55c063 KS |
676 | collcont(s) |
677 | { | |
678 | ||
828615a1 EW |
679 | hadintr = 0; |
680 | longjmp(coljmp, 1); | |
2d55c063 KS |
681 | } |
682 | ||
06300dd9 KS |
683 | /* |
684 | * On interrupt, go here to save the partial | |
7feecf47 | 685 | * message on ~/dead.letter. |
06300dd9 KS |
686 | * Then restore signals and execute the normal |
687 | * signal routine. We only come here if signals | |
688 | * were previously set anyway. | |
689 | */ | |
06300dd9 KS |
690 | collrub(s) |
691 | { | |
692 | register FILE *dbuf; | |
693 | register int c; | |
694 | ||
7feecf47 | 695 | if (s == SIGINT && hadintr == 0) { |
828615a1 | 696 | hadintr = 1; |
06300dd9 KS |
697 | longjmp(coljmp, 1); |
698 | } | |
828615a1 EW |
699 | rewind(collf); |
700 | if (s == SIGINT && value("nosave") != NOSTR || fsize(collf) == 0) | |
06300dd9 KS |
701 | goto done; |
702 | if ((dbuf = fopen(deadletter, "w")) == NULL) | |
703 | goto done; | |
704 | chmod(deadletter, 0600); | |
828615a1 | 705 | while ((c = getc(collf)) != EOF) |
06300dd9 KS |
706 | putc(c, dbuf); |
707 | fclose(dbuf); | |
06300dd9 | 708 | done: |
828615a1 EW |
709 | fclose(collf); |
710 | signal(SIGINT, saveint); | |
711 | signal(SIGHUP, savehup); | |
712 | signal(SIGCONT, savecont); | |
7feecf47 KS |
713 | if (rcvmode) { |
714 | if (s == SIGHUP) | |
715 | hangup(SIGHUP); | |
716 | else | |
2d55c063 | 717 | stop(s); |
828615a1 | 718 | } else |
06300dd9 KS |
719 | exit(1); |
720 | } | |
721 | ||
722 | /* | |
723 | * Acknowledge an interrupt signal from the tty by typing an @ | |
724 | */ | |
828615a1 | 725 | /*ARGSUSED*/ |
06300dd9 KS |
726 | intack(s) |
727 | { | |
828615a1 | 728 | |
06300dd9 KS |
729 | puts("@"); |
730 | fflush(stdout); | |
731 | clearerr(stdin); | |
06300dd9 | 732 | } |