|
|
1.1 root 1: #ident "@(#)collect.c 1.7 'attmail mail(1) command'"
2: #ident "@(#)mailx:collect.c 1.18.1.1"
3: /* Copyright (c) 1984 AT&T */
4: /* All Rights Reserved */
5:
6: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
7: /* The copyright notice above does not evidence any */
8: /* actual or intended publication of such source code. */
9:
10: #ident "@(#)mailx:collect.c 1.16.1.1"
11:
12: /*
13: * mailx -- a modified version of a University of California at Berkeley
14: * mail program
15: *
16: * Collect input from standard input, handling
17: * ~ escapes.
18: */
19:
20: #include "rcv.h"
21:
22: #ifdef SIGCONT
23: static void collcont();
24: #endif
25: static void collrub();
26: static void cpout();
27: static int exwrite();
28: static int forward();
29: static void intack();
30: static FILE *mesedit();
31: static FILE *mespipe();
32: static void resetsigs();
33: static int stripnulls();
34: static long transmit();
35: static void xhalt();
36: static char **Xaddone();
37:
38: /*
39: * Read a message from standard output and return a read file to it
40: * or NULL on error.
41: */
42:
43: /*
44: * The following hokiness with global variables is so that on
45: * receipt of an interrupt signal, the partial message can be salted
46: * away on dead.letter. The output file must be available to flush,
47: * and the input to read. Several open files could be saved all through
48: * mailx if stdio allowed simultaneous read/write access.
49: */
50:
51: static void (*savesig)(); /* Previous SIGINT value */
52: static void (*savehup)(); /* Previous SIGHUP value */
53: #ifdef SIGCONT
54: static void (*savecont)(); /* Previous SIGCONT value */
55: #endif
56: static FILE *newi; /* File for saving away */
57: static FILE *newo; /* Output side of same */
58: static int hf; /* Ignore interrups */
59: static int hadintr; /* Have seen one SIGINT so far */
60: static struct header *savehp;
61: static jmp_buf coljmp; /* To get back to work */
62:
63: FILE *
64: collect(hp)
65: struct header *hp;
66: {
67: FILE *ibuf, *fbuf, *obuf;
68: int escape, eof;
69: long lc, cc;
70: register int c, t;
71: char linebuf[LINESIZE+1], *cp;
72: char *iprompt;
73: void (*sigpipe)(), (*sigint)();
74:
75: noreset++;
76: ibuf = obuf = NULL;
77: newi = newo = NULL;
78: if ((obuf = fopen(tempMail, "w")) == NULL) {
79: perror(tempMail);
80: goto err;
81: }
82: newo = obuf;
83: if ((ibuf = fopen(tempMail, "r")) == NULL) {
84: perror(tempMail);
85: newo = NULL;
86: fclose(obuf);
87: goto err;
88: }
89: newi = ibuf;
90: removefile(tempMail);
91:
92: hf = !!value("ignore");
93: hadintr = 1;
94: savehp = hp;
95: if ((savesig = sigset(SIGINT, SIG_IGN)) != (void (*)())SIG_IGN)
96: sigset(SIGINT, hf ? (void (*)())intack : (void (*)())collrub);
97: if ((savehup = sigset(SIGHUP, SIG_IGN)) != (void (*)())SIG_IGN)
98: sigset(SIGHUP, collrub);
99: #ifdef SIGCONT
100: # ifdef preSVr4
101: savecont = sigset(SIGCONT, collcont);
102: # else
103: {
104: struct sigaction nsig, osig;
105: nsig.sa_handler = collcont;
106: sigemptyset(&nsig.sa_mask);
107: nsig.sa_flags = SA_RESTART;
108: (void) sigaction(SIGCONT, &nsig, &osig);
109: savecont = osig.sa_handler;
110: }
111: # endif
112: #endif
113: /*
114: * If we are going to prompt for subject/cc/bcc,
115: * refrain from printing a newline after
116: * the headers (since some people mind).
117: */
118:
119: if (hp->h_subject == NOSTR) {
120: hp->h_subject = sflag;
121: sflag = NOSTR;
122: }
123: t = GMASK;
124: c = 0;
125: if (intty) {
126: if (hp->h_subject == NOSTR && value("asksub"))
127: c |= GSUBJECT;
128: /* adb: due to popular demand, these were moved to the end of the letter
129: * adb: if (hp->h_cc == NOSTR && value("askcc"))
130: * adb: c |= GCC;
131: * adb: if (hp->h_bcc == NOSTR && value("askbcc"))
132: * adb: c |= GBCC;
133: * adb */
134: if (c)
135: t &= ~GNL;
136: }
137: if (hp->h_seq != 0) {
138: puthead(hp, stdout, t);
139: fflush(stdout);
140: }
141: if (setjmp(coljmp))
142: goto err;
143: if (c)
144: grabh(hp, c, 1);
145: escape = SENDESC;
146: if ((cp = value("escape")) != NOSTR)
147: escape = *cp;
148: eof = 0;
149: if ((cp = value("MAILX_HEAD")) != NOSTR) {
150: cpout( cp, obuf);
151: if (isatty(fileno(stdin)))
152: cpout( cp, stdout);
153: }
154: iprompt = value("iprompt");
155: fflush(obuf);
156: hadintr = 0;
157: for (;;) {
158: int nread, hasnulls;
159: setjmp(coljmp);
160: sigrelse(SIGINT);
161: sigrelse(SIGHUP);
162: if (intty && outtty && iprompt)
163: fputs(iprompt, stdout);
164: flush();
165: if ((nread = getline(linebuf,LINESIZE,stdin,&hasnulls)) == NULL) {
166: if (intty && value("ignoreeof") != NOSTR) {
167: if (++eof > 35)
168: break;
169: printf("Use \".\" to terminate letter\n");
170: continue;
171: }
172: break;
173: }
174: eof = 0;
175: hadintr = 0;
176: if (intty && equal(".\n", linebuf) &&
177: (value("dot") != NOSTR || value("ignoreeof") != NOSTR))
178: break;
179: if ((linebuf[0] != escape) || (rflag != NOSTR) || !intty) {
180: if (write(fileno(obuf),linebuf,nread) != nread)
181: goto err;
182: continue;
183: }
184: /*
185: * On double escape, just send the single one.
186: */
187: if ((nread > 1) && (linebuf[1] == escape)) {
188: if (write(fileno(obuf),linebuf+1,nread-1) != (nread-1))
189: goto err;
190: continue;
191: }
192: if (hasnulls)
193: nread = stripnulls(linebuf, nread);
194: c = linebuf[1];
195: linebuf[nread - 1] = '\0';
196: switch (c) {
197: default:
198: /*
199: * Otherwise, it's an error.
200: */
201: printf("Unknown tilde escape.\n");
202: break;
203:
204: case 'a':
205: case 'A':
206: /*
207: * autograph; sign the letter.
208: */
209:
210: if (cp = value(c=='a' ? "sign":"Sign")) {
211: cpout( cp, obuf);
212: if (isatty(fileno(stdin)))
213: cpout( cp, stdout);
214: }
215:
216: break;
217:
218: case 'i':
219: /*
220: * insert string
221: */
222: for (cp = &linebuf[2]; any(*cp, " \t"); cp++)
223: ;
224: if (*cp)
225: cp = value(cp);
226: if (cp != NOSTR) {
227: cpout(cp, obuf);
228: if (isatty(fileno(stdout)))
229: cpout(cp, stdout);
230: }
231: break;
232:
233: case '!':
234: /*
235: * Shell escape, send the balance of the
236: * line to sh -c.
237: */
238:
239: shell(&linebuf[2]);
240: break;
241:
242: case ':':
243: case '_':
244: /*
245: * Escape to command mode, but be nice!
246: */
247:
248: execute(&linebuf[2], 1);
249: iprompt = value("iprompt");
250: if (cp = value("escape"))
251: escape = *cp;
252: printf("(continue)\n");
253: break;
254:
255: case '.':
256: /*
257: * Simulate end of file on input.
258: */
259: goto eofl;
260:
261: case 'q':
262: case 'Q':
263: /*
264: * Force a quit of sending mail.
265: * Act like an interrupt happened.
266: */
267:
268: hadintr++;
269: collrub(SIGINT);
270: exit(1);
271: /* NOTREACHED */
272:
273: case 'x':
274: xhalt();
275: break; /* not reached */
276:
277: case 'h':
278: /*
279: * Grab a bunch of headers.
280: */
281: if (!intty || !outtty) {
282: printf("~h: no can do!?\n");
283: break;
284: }
285: grabh(hp, GMASK, 0);
286: printf("(continue)\n");
287: break;
288:
289: case 't':
290: /*
291: * Add to the To list.
292: */
293:
294: hp->h_to = addto(hp->h_to, &linebuf[2]);
295: hp->h_seq++;
296: break;
297:
298: case 's':
299: /*
300: * Set the Subject list.
301: */
302:
303: cp = &linebuf[2];
304: while (any(*cp, " \t"))
305: cp++;
306: hp->h_subject = savestr(cp);
307: hp->h_seq++;
308: break;
309:
310: case 'c':
311: /*
312: * Add to the CC list.
313: */
314:
315: hp->h_cc = addto(hp->h_cc, &linebuf[2]);
316: hp->h_seq++;
317: break;
318:
319: case 'b':
320: /*
321: * Add stuff to blind carbon copies list.
322: */
323: hp->h_bcc = addto(hp->h_bcc, &linebuf[2]);
324: hp->h_seq++;
325: break;
326:
327: case 'R':
328: hp->h_defopt = addone(hp->h_defopt, "/receipt");
329: hp->h_seq++;
330: fprintf(stderr, "Return receipt marked.\n");
331: break;
332:
333: case 'd':
334: copy(Getf("DEAD"), &linebuf[2]);
335: /* FALLTHROUGH */
336:
337: case '<':
338: case 'r': {
339: int ispip;
340: /*
341: * Invoke a file:
342: * Search for the file name,
343: * then open it and copy the contents to obuf.
344: *
345: * if name begins with '!', read from a command
346: */
347:
348: cp = &linebuf[2];
349: while (any(*cp, " \t"))
350: cp++;
351: if (*cp == '\0') {
352: printf("Interpolate what file?\n");
353: break;
354: }
355: if (*cp=='!') {
356: /* take input from a command */
357: ispip = 1;
358: if ((fbuf = npopen(++cp, "r"))==NULL) {
359: perror("");
360: break;
361: }
362: sigint = sigset(SIGINT, SIG_IGN);
363: } else {
364: ispip = 0;
365: cp = expand(cp);
366: if (cp == NOSTR)
367: break;
368: if (isdir(cp)) {
369: printf("%s: directory\n",cp);
370: break;
371: }
372: if ((fbuf = fopen(cp, "r")) == NULL) {
373: perror(cp);
374: break;
375: }
376: }
377: printf("\"%s\" ", cp);
378: flush();
379: lc = cc = 0;
380: while ((t = getc(fbuf)) != EOF) {
381: if (t == '\n')
382: lc++;
383: if (putc(t, obuf) == EOF) {
384: if (ispip) {
385: npclose(fbuf);
386: sigset(SIGINT, sigint);
387: } else
388: fclose(fbuf);
389: goto err;
390: }
391: cc++;
392: }
393: if (ispip) {
394: npclose(fbuf);
395: sigset(SIGINT, sigint);
396: } else
397: fclose(fbuf);
398: printf("%ld/%ld\n", lc, cc);
399: fflush(obuf);
400: break;
401: }
402:
403: case 'w':
404: /*
405: * Write the message on a file.
406: */
407:
408: cp = &linebuf[2];
409: while (any(*cp, " \t"))
410: cp++;
411: if (*cp == '\0') {
412: fprintf(stderr, "Write what file!?\n");
413: break;
414: }
415: if ((cp = expand(cp)) == NOSTR)
416: break;
417: fflush(obuf);
418: rewind(ibuf);
419: exwrite(cp, ibuf);
420: break;
421:
422: case 'm':
423: case 'f':
424: /*
425: * Interpolate the named messages, if we
426: * are in receiving mail mode. Does the
427: * standard list processing garbage.
428: * If ~f is given, we don't shift over.
429: */
430:
431: if (!rcvmode) {
432: printf("No messages to send from!?!\n");
433: break;
434: }
435: cp = &linebuf[2];
436: while (any(*cp, " \t"))
437: cp++;
438: if (forward(cp, obuf, c) < 0)
439: goto err;
440: fflush(obuf);
441: printf("(continue)\n");
442: break;
443:
444: case '?':
445: if ((fbuf = fopen(THELPFILE, "r")) == NULL) {
446: printf("No help just now.\n");
447: break;
448: }
449: t = getc(fbuf);
450: while (t != -1) {
451: putchar(t);
452: t = getc(fbuf);
453: }
454: fclose(fbuf);
455: break;
456:
457: case 'p':
458: /*
459: * Print out the current state of the
460: * message without altering anything.
461: */
462:
463: fflush(obuf);
464: rewind(ibuf);
465: if (value("crt")) {
466: char *pg = PG;
467: if (!*pg)
468: pg = "cat";
469: if (fbuf = npopen(pg, "w")) { /* adb */
470: sigint = sigset(SIGINT, SIG_IGN);
471: sigpipe = sigset(SIGPIPE, SIG_IGN);
472: } else
473: fbuf = stdout;
474: } else
475: fbuf = stdout;
476: fprintf(fbuf, "-------\nMessage contains:\n");
477: puthead(hp, fbuf, GMASK);
478: while ((t = getc(ibuf))!=EOF)
479: putc(t, fbuf);
480: if (fbuf != stdout) {
481: npclose(fbuf);
482: sigset(SIGPIPE, sigpipe);
483: sigset(SIGINT, sigint);
484: }
485: printf("(continue)\n");
486: break;
487:
488: case '^':
489: case '|':
490: /*
491: * Pipe message through command.
492: * Collect output as new message.
493: */
494:
495: obuf = mespipe(ibuf, obuf, &linebuf[2]);
496: newo = obuf;
497: ibuf = newi;
498: newi = ibuf;
499: printf("(continue)\n");
500: break;
501:
502: case 'v':
503: case 'e':
504: /*
505: * Edit the current message.
506: * 'e' means to use EDITOR
507: * 'v' means to use VISUAL
508: */
509:
510: if ((obuf = mesedit(ibuf, obuf, c, hp)) == NULL)
511: goto err;
512: newo = obuf;
513: ibuf = newi;
514: printf("(continue)\n");
515: break;
516: }
517: fflush(obuf);
518: }
519: eofl:
520: c = 0; /* adb */
521: if (intty) { /* adb */
522: if (hp->h_cc == NOSTR && value("askcc")) /* adb */
523: c |= GCC; /* adb */
524: if (hp->h_bcc == NOSTR && value("askbcc")) /* adb */
525: c |= GBCC; /* adb */
526: } /* adb */
527: if (c) /* adb */
528: grabh(hp, c, 1); /* adb */
529: fflush(obuf);
530: if ((cp = value("MAILX_TAIL")) != NOSTR) {
531: cpout( cp, obuf);
532: if (isatty(fileno(stdin)))
533: cpout( cp, stdout);
534: }
535: fclose(obuf);
536: rewind(ibuf);
537: resetsigs(0);
538: noreset = 0;
539: return(ibuf);
540:
541: err:
542: if (ibuf != NULL)
543: fclose(ibuf);
544: if (obuf != NULL)
545: fclose(obuf);
546: resetsigs(0);
547: noreset = 0;
548: return(NULL);
549: }
550:
551: static void resetsigs(resethup)
552: int resethup;
553: {
554: (void) sigset(SIGINT, savesig);
555: if (resethup)
556: (void) sigset(SIGHUP, savehup);
557: #ifdef SIGCONT
558: # ifdef preSVr4
559: (void) sigset(SIGCONT, savecont);
560: # else
561: {
562: struct sigaction nsig;
563: nsig.sa_handler = savecont;
564: sigemptyset(&nsig.sa_mask);
565: nsig.sa_flags = SA_RESTART;
566: (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0);
567: }
568: # endif
569: #endif
570: }
571:
572: /*
573: * Write a file ex-like.
574: */
575:
576: static int
577: exwrite(name, ibuf)
578: char name[];
579: FILE *ibuf;
580: {
581: register FILE *of;
582: struct stat junk;
583: void (*sigint)(), (*sigpipe)();
584: int pi = (*name == '!');
585:
586: if (!pi && stat(name, &junk) >= 0
587: && (junk.st_mode & S_IFMT) == S_IFREG) {
588: fprintf(stderr, "%s: File exists\n", name);
589: return(-1);
590: }
591: if ((of = pi ? npopen(++name, "w") : fopen(name, "w")) == NULL) {
592: perror(name);
593: return(-1);
594: }
595: if (pi) {
596: sigint = sigset(SIGINT, SIG_IGN);
597: sigpipe = sigset(SIGPIPE, SIG_IGN);
598: }
599: lcwrite(name, ibuf, of);
600: pi ? npclose(of) : fclose(of);
601: if (pi) {
602: sigset(SIGPIPE, sigpipe);
603: sigset(SIGINT, sigint);
604: }
605: return(0);
606: }
607:
608: void
609: lcwrite(fn, fi, fo)
610: char *fn;
611: FILE *fi, *fo;
612: {
613: register int c;
614: long lc, cc;
615:
616: printf("\"%s\" ", fn);
617: fflush(stdout);
618: lc = cc = 0;
619: while ((c = getc(fi)) != EOF) {
620: cc++;
621: if (putc(c, fo) == '\n')
622: lc++;
623: if (ferror(fo)) {
624: perror("");
625: return;
626: }
627: }
628: printf("%ld/%ld\n", lc, cc);
629: fflush(stdout);
630: }
631:
632: /*
633: * Edit the message being collected on ibuf and obuf.
634: * Write the message out onto some poorly-named temp file
635: * and point an editor at it.
636: *
637: * On return, make the edit file the new temp file.
638: */
639:
640: static FILE *
641: mesedit(ibuf, obuf, c, hp)
642: FILE *ibuf, *obuf;
643: struct header *hp;
644: {
645: pid_t pid;
646: FILE *fbuf;
647: register int t;
648: void (*sigint)();
649: struct stat sbuf;
650: register char *edit;
651: char hdr[LINESIZE];
652:
653: if (stat(tempEdit, &sbuf) >= 0) {
654: printf("%s: file exists\n", tempEdit);
655: goto out;
656: }
657: close(creat(tempEdit, TEMPPERM));
658: if ((fbuf = fopen(tempEdit, "w")) == NULL) {
659: perror(tempEdit);
660: goto out;
661: }
662: fflush(obuf);
663: rewind(ibuf);
664: puthead(hp, fbuf, GMASK);
665: while ((t = getc(ibuf)) != EOF)
666: putc(t, fbuf);
667: fflush(fbuf);
668: if (ferror(fbuf)) {
669: perror(tempEdit);
670: removefile(tempEdit);
671: goto out;
672: }
673: fclose(fbuf);
674: if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
675: edit = c == 'e' ? EDITOR : VISUAL;
676: edit = expand(edit);
677:
678: /*
679: * Fork/execlp the editor on the edit file
680: */
681:
682: pid = fork();
683: if ( pid == (pid_t)-1 ) {
684: perror("fork");
685: removefile(tempEdit);
686: goto out;
687: }
688: if ( pid == 0 ) {
689: sigchild();
690: execlp(edit, edit, tempEdit, (char *)0);
691: perror(edit);
692: _exit(1);
693: }
694: sigint = sigset(SIGINT, SIG_IGN);
695: while (wait((int *)0) != pid)
696: ;
697: sigset(SIGINT, sigint);
698: /*
699: * Now switch to new file.
700: */
701:
702: if ((fbuf = fopen(tempEdit, "r")) == NULL) {
703: perror(tempEdit);
704: removefile(tempEdit);
705: goto out;
706: }
707: removefile(tempEdit);
708: hp->h_to = hp->h_subject = hp->h_cc = hp->h_bcc = hp->h_defopt = NOSTR;
709: hp->h_others = NOSTRPTR;
710: hp->h_seq = 0;
711: while (gethfield(fbuf, hdr, 9999L) > 0) {
712: if (ishfield(hdr, "to"))
713: hp->h_to = addto(hp->h_to, hcontents(hdr));
714: else if (ishfield(hdr, "subject"))
715: hp->h_subject = addone(hp->h_subject, hcontents(hdr));
716: else if (ishfield(hdr, "cc"))
717: hp->h_cc = addto(hp->h_cc, hcontents(hdr));
718: else if (ishfield(hdr, "bcc"))
719: hp->h_bcc = addto(hp->h_bcc, hcontents(hdr));
720: else if (ishfield(hdr, "default-options"))
721: hp->h_defopt = addone(hp->h_defopt, hcontents(hdr));
722: else
723: hp->h_others = Xaddone(hp->h_others, hdr);
724: hp->h_seq++;
725: }
726: if ((obuf = fopen(tempMail, "w")) == NULL) {
727: perror(tempMail);
728: fclose(fbuf);
729: goto out;
730: }
731: if ((ibuf = fopen(tempMail, "r")) == NULL) {
732: perror(tempMail);
733: removefile(tempMail);
734: fclose(fbuf);
735: fclose(obuf);
736: goto out;
737: }
738: removefile(tempMail);
739: if (strlen(hdr) > 0) {
740: fputs(hdr, obuf);
741: putc('\n', obuf);
742: }
743: while ((t = getc(fbuf)) != EOF)
744: putc(t, obuf);
745: fclose(fbuf);
746: fclose(newo);
747: fclose(newi);
748: newo = obuf;
749: newi = ibuf;
750: out:
751: return(newo);
752: }
753:
754: /*
755: * Pipe the message through the command.
756: * Old message is on stdin of command;
757: * New message collected from stdout.
758: * Sh -c must return 0 to accept the new message.
759: */
760:
761: static FILE *
762: mespipe(ibuf, obuf, cmd)
763: FILE *ibuf, *obuf;
764: char cmd[];
765: {
766: register FILE *ni, *no;
767: pid_t pid;
768: int s;
769: void (*sigint)();
770: char *Shell;
771:
772: newi = ibuf;
773: if ((no = fopen(tempEdit, "w")) == NULL) {
774: perror(tempEdit);
775: return(obuf);
776: }
777: if ((ni = fopen(tempEdit, "r")) == NULL) {
778: perror(tempEdit);
779: fclose(no);
780: removefile(tempEdit);
781: return(obuf);
782: }
783: removefile(tempEdit);
784: fflush(obuf);
785: rewind(ibuf);
786: if ((Shell = value("SHELL")) == NULL || *Shell=='\0')
787: Shell = SHELL;
788: if ((pid = fork()) == (pid_t)-1) {
789: perror("fork");
790: goto err;
791: }
792: if (pid == 0) {
793: /*
794: * stdin = current message.
795: * stdout = new message.
796: */
797:
798: sigchild();
799: close(0);
800: dup(fileno(ibuf));
801: close(1);
802: dup(fileno(no));
803: for (s = 4; s < 15; s++)
804: close(s);
805: execlp(Shell, Shell, "-c", cmd, (char *)0);
806: perror(Shell);
807: _exit(1);
808: }
809: sigint = sigset(SIGINT, SIG_IGN);
810: while (wait(&s) != pid)
811: ;
812: sigset(SIGINT, sigint);
813: if (s != 0 || pid == (pid_t)-1) {
814: fprintf(stderr, "\"%s\" failed!?\n", cmd);
815: goto err;
816: }
817: if (fsize(ni) == 0) {
818: fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
819: goto err;
820: }
821:
822: /*
823: * Take new files.
824: */
825:
826: newi = ni;
827: fclose(ibuf);
828: fclose(obuf);
829: return(no);
830:
831: err:
832: fclose(no);
833: fclose(ni);
834: return(obuf);
835: }
836:
837: /*
838: * Interpolate the named messages into the current
839: * message, preceding each line with a tab.
840: * Return a count of the number of characters now in
841: * the message, or -1 if an error is encountered writing
842: * the message temporary. The flag argument is 'm' if we
843: * should shift over and 'f' if not.
844: */
845: static int
846: forward(ms, obuf, f)
847: char ms[];
848: FILE *obuf;
849: {
850: register int *msgvec, *ip;
851:
852: msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
853: if (msgvec == NOINTPTR)
854: return(0);
855: if (getmsglist(ms, msgvec, 0) < 0)
856: return(0);
857: if (*msgvec == NULL) {
858: *msgvec = first(0, MMNORM);
859: if (*msgvec == NULL) {
860: printf("No appropriate messages\n");
861: return(0);
862: }
863: msgvec[1] = NULL;
864: }
865: printf("Interpolating:");
866: for (ip = msgvec; *ip != NULL; ip++) {
867: touch(*ip);
868: printf(" %d", *ip);
869: if (f == 'm') {
870: if (transmit(&message[*ip-1], obuf) < 0L) {
871: perror(tempMail);
872: return(-1);
873: }
874: } else
875: if (send(&message[*ip-1], obuf, 0) < 0) {
876: perror(tempMail);
877: return(-1);
878: }
879: }
880: printf("\n");
881: return(0);
882: }
883:
884: /*
885: * Send message described by the passed pointer to the
886: * passed output buffer. Insert a tab in front of each
887: * line. Return a count of the characters sent, or -1
888: * on error.
889: */
890:
891: static long
892: transmit(mailp, obuf)
893: struct message *mailp;
894: FILE *obuf;
895: {
896: register struct message *mp;
897: register int ch;
898: register long c, n;
899: int bol;
900: FILE *ibuf;
901: char *mprefix = value("mprefix");
902:
903: if (!mprefix)
904: mprefix = "\t";
905: mp = mailp;
906: ibuf = setinput(mp);
907: c = mp->m_size;
908: n = c;
909: bol = 1;
910: while (c-- > 0L) {
911: if (bol) {
912: bol = 0;
913: fputs(mprefix, obuf);
914: n++;
915: if (ferror(obuf)) {
916: perror("/tmp");
917: return(-1L);
918: }
919: }
920: ch = getc(ibuf);
921: if (ch == '\n')
922: bol++;
923: putc(ch, obuf);
924: if (ferror(obuf)) {
925: perror("/tmp");
926: return(-1L);
927: }
928: }
929: return(n);
930: }
931:
932: /*
933: * Print (continue) when continued after ^Z.
934: */
935: #ifdef SIGCONT
936: /*ARGSUSED*/
937: static void
938: collcont(s)
939: {
940: printf("(continue)\n",s); /* reference s to suppress warning -- adb */
941: fflush(stdout);
942: }
943: #endif /* SIGCONT */
944:
945: /*
946: * On interrupt, go here to save the partial
947: * message on ~/dead.letter.
948: * Then restore signals and execute the normal
949: * signal routine. We only come here if signals
950: * were previously set anyway.
951: */
952: static void
953: collrub(s)
954: {
955: register FILE *dbuf;
956: register int c;
957: register char *deadletter = Getf("DEAD");
958: long cc, lc;
959:
960: if (s == SIGHUP)
961: sigignore(SIGHUP);
962: if (s == SIGINT && hadintr == 0) {
963: hadintr++;
964: clrbuf(stdout);
965: printf("\n(Interrupt -- one more to kill letter)\n");
966: sigrelse(s);
967: longjmp(coljmp, 1);
968: }
969: fclose(newo);
970: rewind(newi);
971: if (s == SIGINT && value("save")==NOSTR || fsize(newi) == 0)
972: goto done;
973: if ((dbuf = fopen(deadletter, "w")) == NULL) { /* old behavior -- adb */
974: perror(deadletter);
975: goto done;
976: }
977: chmod(deadletter, DEADPERM);
978: printf("\"%s\" ", deadletter);
979: fflush(stdout);
980: puthead(savehp, dbuf, GMASK);
981: for (cc = lc = 0; (c = getc(newi)) != EOF; cc++)
982: if (putc(c, dbuf) == '\n')
983: lc++;
984: fclose(dbuf);
985: printf("%ld/%ld\n", lc, cc);
986: done:
987: fclose(newi);
988: resetsigs(1);
989: if (rcvmode) {
990: if (s == SIGHUP)
991: hangup();
992: else
993: stop(s);
994: }
995: else
996: exit(1);
997: }
998:
999: /*
1000: * Acknowledge an interrupt signal from the tty by typing an @
1001: */
1002: static void
1003: intack(s)
1004: {
1005: (void) s;
1006: puts("@");
1007: fflush(stdout);
1008: clearerr(stdin);
1009: longjmp(coljmp,1);
1010: }
1011:
1012: /* Read line from stdin, noting any NULL characters.
1013: Return the number of characters read. Note that the buffer
1014: passed must be 1 larger than "size" for the trailing NUL byte.
1015: */
1016: int
1017: getline(line,size,f,hasnulls)
1018: char *line;
1019: int size;
1020: FILE *f;
1021: int *hasnulls;
1022: {
1023: register int i, ch;
1024: for (i = 0; (i < size) && ((ch=getc(f)) != EOF); ) {
1025: if ( ch == '\0' )
1026: *hasnulls = 1;
1027: if ((line[i++] = ch) == '\n') break;
1028: }
1029: line[i] = '\0';
1030: return(i);
1031: }
1032:
1033: void
1034: savedead(s)
1035: {
1036: (void) s;
1037: collrub(SIGINT);
1038: exit(1);
1039: /* NOTREACHED */
1040: }
1041:
1042: /*
1043: * Add a list of addresses to the end of a header entry field.
1044: */
1045: char *
1046: addto(hf, news)
1047: char hf[], news[];
1048: {
1049: char name[LINESIZE];
1050: int comma = docomma(news);
1051:
1052: while (news = yankword(news, name, comma)) {
1053: strcat(name, ", ");
1054: hf = addone(hf, name);
1055: }
1056: return hf;
1057: }
1058:
1059: /*
1060: * Add a string to the end of a header entry field.
1061: */
1062: char *
1063: addone(hf, news)
1064: char hf[], news[];
1065: {
1066: register char *cp, *cp2, *linebuf;
1067:
1068: if (hf == NOSTR)
1069: hf = "";
1070: if (*news == '\0')
1071: return(hf);
1072: linebuf = salloc((unsigned)(strlen(hf) + strlen(news) + 2));
1073: for (cp = hf; any(*cp, " \t"); cp++)
1074: ;
1075: for (cp2 = linebuf; *cp;)
1076: *cp2++ = *cp++;
1077: if (cp2 > linebuf && cp2[-1] != ' ')
1078: *cp2++ = ' ';
1079: for (cp = news; any(*cp, " \t"); cp++)
1080: ;
1081: while (*cp != '\0')
1082: *cp2++ = *cp++;
1083: *cp2 = '\0';
1084: return(linebuf);
1085: }
1086:
1087: static int nptrs(hf)
1088: char **hf;
1089: {
1090: register int i;
1091: if (!hf)
1092: return 0;
1093: for (i = 0; *hf; hf++)
1094: i++;
1095: return i;
1096: }
1097:
1098: /*
1099: * Add a non-standard header to the end of the non-standard headers.
1100: */
1101: static char **
1102: Xaddone(hf, news)
1103: char **hf, news[];
1104: {
1105: register char *linebuf;
1106: char **ohf = hf;
1107: int nhf = nptrs(hf);
1108:
1109: if (hf == NOSTRPTR)
1110: hf = (char**)salloc(sizeof(char*) * 2);
1111: else
1112: hf = (char**)srealloc(hf, sizeof(char*) * (nhf + 2));
1113: if (hf == NOSTRPTR) {
1114: fprintf(stderr, "No room, header lost: %s\n", news);
1115: return(ohf);
1116: }
1117: linebuf = salloc((unsigned)(strlen(news) + 1));
1118: strcpy(linebuf, news);
1119: hf[nhf++] = linebuf;
1120: hf[nhf] = NOSTR;
1121: return(hf);
1122: }
1123:
1124: static void
1125: cpout( str, ofd )
1126: char *str;
1127: FILE *ofd;
1128: {
1129: register char *cp = str;
1130:
1131: while ( *cp ) {
1132: if ( *cp == '\\' ) {
1133: switch ( *(cp+1) ) {
1134: case 'n':
1135: putc('\n',ofd);
1136: cp++;
1137: break;
1138: case 't':
1139: putc('\t',ofd);
1140: cp++;
1141: break;
1142: default:
1143: putc('\\',ofd);
1144: }
1145: }
1146: else {
1147: putc(*cp,ofd);
1148: }
1149: cp++;
1150: }
1151: putc('\n',ofd);
1152: fflush(ofd);
1153: }
1154:
1155: static void
1156: xhalt()
1157: {
1158: fclose(newo);
1159: fclose(newi);
1160: sigset(SIGINT, savesig);
1161: sigset(SIGHUP, savehup);
1162: if (rcvmode)
1163: stop(0);
1164: exit(1);
1165: /* NOTREACHED */
1166: }
1167:
1168: /*
1169: Strip the nulls from a buffer of length n
1170: */
1171: static int
1172: stripnulls(linebuf, nread)
1173: register char *linebuf;
1174: register int nread;
1175: {
1176: register int i, j;
1177: for (i = 0; i < nread; i++)
1178: if (linebuf[i] == '\0')
1179: break;
1180: for (j = i; j < nread; j++)
1181: if (linebuf[j] != '\0')
1182: linebuf[i++] = linebuf[j];
1183: linebuf[i] = '\0';
1184: return i;
1185: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.