comparison uip/spost.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children 441a2190cfae
comparison
equal deleted inserted replaced
-1:000000000000 0:bce86c4163a3
1 #ifndef lint
2 static char sccsid[] = "@(#)spost.c 1.6 (Berkeley) 11/2/85";
3 #endif
4 #ifndef lint
5 static char ident[] = "@(#)$Id$";
6 #endif /* lint */
7
8 /* spost.c - feed messages to sendmail */
9 /*
10 * (This is a simpler, faster, replacement for "post" for use when "sendmail"
11 * is the transport system)
12 */
13
14 #include <ctype.h>
15 #include <stdio.h>
16 #include <signal.h>
17 #include "../h/mh.h"
18 #include "../h/addrsbr.h"
19 #include "../h/aliasbr.h"
20 #include "../h/dropsbr.h"
21 #include "../zotnet/tws.h"
22 #ifdef LOCALE
23 #include <locale.h>
24 #endif
25 #ifdef UNISTD
26 #include <unistd.h>
27 #endif
28
29 extern char *getfullname (), *getusr ();
30 extern char *sendmail;
31
32
33 #define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : c)
34
35 #define MAX_SM_FIELD 1476 /* < largest hdr field sendmail will accept */
36 #define FCCS 10 /* max number of fccs allowed */
37
38 /* */
39
40 struct swit switches[] = {
41 #define FILTSW 0
42 "filter filterfile", 0,
43 #define NFILTSW 1
44 "nofilter", 0,
45
46 #define FRMTSW 2
47 "format", 0,
48 #define NFRMTSW 3
49 "noformat", 0,
50
51 #define REMVSW 4
52 "remove", 0,
53 #define NREMVSW 5
54 "noremove", 0,
55
56 #define VERBSW 6
57 "verbose", 0,
58 #define NVERBSW 7
59 "noverbose", 0,
60
61 #define WATCSW 8
62 "watch", 0,
63 #define NWATCSW 9
64 "nowatch", 0,
65
66 #define HELPSW 10
67 "help", 4,
68
69 #define DEBUGSW 11
70 "debug", -5,
71
72 #define DISTSW 12
73 "dist", -4, /* interface from dist */
74
75 #define BACKSW 13
76 "backup", 0,
77 #define NBACKSW 14
78 "nobackup", 0,
79
80 #define CHKSW 15
81 "check", -5, /* interface from whom */
82 #define NCHKSW 16
83 "nocheck", -7, /* interface from whom */
84 #define WHOMSW 17
85 "whom", -4, /* interface from whom */
86
87 #define PUSHSW 18 /* fork to sendmail then exit */
88 "push", -4,
89 #define NPUSHSW 19 /* exec sendmail */
90 "nopush", -6,
91
92 #define ALIASW 20
93 "alias aliasfile", 0,
94 #define NALIASW 21
95 "noalias", 0,
96
97 #define WIDTHSW 22
98 "width columns", 0,
99
100 #define LIBSW 23
101 "library directory", -7,
102
103 #define ANNOSW 24
104 "idanno number", -6,
105
106 #ifdef MIME_HEADERS
107 #define HENCDSW 25
108 "hencode", 0,
109 #define NHENCDSW 26
110 "nohencode", 0,
111 #endif /* MIME_HEADERS */
112
113 NULL, 0
114 };
115
116 /* */
117
118 struct headers {
119 char *value;
120
121 unsigned int flags;
122 #define HNOP 0x0000 /* just used to keep .set around */
123 #define HBAD 0x0001 /* bad header - don't let it through */
124 #define HADR 0x0002 /* header has an address field */
125 #define HSUB 0x0004 /* Subject: header */
126 #define HTRY 0x0008 /* try to send to addrs on header */
127 #define HBCC 0x0010 /* don't output this header */
128 #define HMNG 0x0020 /* mung this header */
129 #define HNGR 0x0040 /* no groups allowed in this header */
130 #define HFCC 0x0080 /* FCC: type header */
131 #define HNIL 0x0100 /* okay for this header not to have addrs */
132 #define HIGN 0x0200 /* ignore this header */
133
134 unsigned int set;
135 #define MFRM 0x0001 /* we've seen a From: */
136 #define MDAT 0x0002 /* we've seen a Date: */
137 #define MRFM 0x0004 /* we've seen a Resent-From: */
138 #define MVIS 0x0008 /* we've seen sighted addrs */
139 #define MINV 0x0010 /* we've seen blind addrs */
140 #define MRDT 0x0020 /* we've seen a Resent-Date: */
141 };
142
143 /* */
144
145 static struct headers NHeaders[] = {
146 "Return-Path", HBAD, 0,
147 "Received", HBAD, 0,
148 "Reply-To", HADR | HNGR, 0,
149 "From", HADR | HNGR, MFRM,
150 "Sender", HADR | HBAD, 0,
151 "Date", HNOP, MDAT,
152 "Subject", HSUB, 0,
153 "To", HADR | HTRY, MVIS,
154 "cc", HADR | HTRY, MVIS,
155 "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
156 "Message-Id", HBAD, 0,
157 "Fcc", HFCC, 0,
158
159 NULL
160 };
161
162 static struct headers RHeaders[] = {
163 "Resent-Reply-To", HADR | HNGR, 0,
164 "Resent-From", HADR | HNGR, MRFM,
165 "Resent-Sender", HADR | HBAD, 0,
166 "Resent-Date", HNOP, MRDT,
167 "Resent-Subject", HSUB, 0,
168 "Resent-To", HADR | HTRY, MVIS,
169 "Resent-cc", HADR | HTRY, MVIS,
170 "Resent-Bcc", HADR | HTRY | HBCC, MINV,
171 "Resent-Message-Id", HBAD, 0,
172 "Resent-Fcc", HFCC, 0,
173 "Reply-To", HADR, 0,
174 "Fcc", HIGN, 0,
175
176 NULL
177 };
178
179 /* */
180
181
182 static short fccind = 0; /* index into fccfold[] */
183
184 static int badmsg = 0; /* message has bad semantics */
185 static int verbose = 0; /* spell it out */
186 static int debug = 0; /* debugging post */
187 static int rmflg = 1; /* remove temporary file when done */
188 static int watch = 0; /* watch the delivery process */
189 static int backflg = 0; /* rename input file as *.bak when done */
190 static int whomflg = 0; /* if just checking addresses */
191 static int pushflg = 0; /* if going to fork to sendmail */
192 static int aliasflg = -1; /* if going to process aliases */
193 static int outputlinelen=72;
194 #ifdef MIME_HEADERS
195 static int hencode = -1; /* encode header in RFC-2047 style */
196 #endif /* MIME_HEADERS */
197
198 static unsigned msgflags = 0; /* what we've seen */
199
200 static enum {
201 normal, resent
202 } msgstate = normal;
203
204 static char tmpfil[] = "/tmp/pstXXXXXX";
205
206 static char from[BUFSIZ]; /* my network address */
207 static char signature[BUFSIZ]; /* my signature */
208 static char *filter = NULL; /* the filter for BCC'ing */
209 static char *subject = NULL; /* the subject field for BCC'ing */
210 static char *fccfold[FCCS]; /* foldernames for FCC'ing */
211
212 static struct headers *hdrtab; /* table for the message we're doing */
213 static FILE *out; /* output (temp) file */
214
215 static putfmt(), start_headers(), finish_headers(), putadr(),
216 insert_fcc();
217 static file(), fcc();
218 static int get_header(), putone();
219 /* MAIN */
220
221 /* ARGSUSED */
222
223 main (argc, argv)
224 int argc;
225 char *argv[];
226 {
227 int state,
228 i,
229 pid,
230 compnum;
231 char *cp,
232 *msg = NULL,
233 **argp = argv + 1,
234 *sargv[16],
235 buf[BUFSIZ],
236 name[NAMESZ],
237 *arguments[MAXARGS];
238 FILE * in;
239
240 #ifdef LOCALE
241 setlocale(LC_ALL, "");
242 #endif
243 #ifdef JAPAN
244 ml_init();
245 #endif /* JAPAN */
246 invo_name = r1bindex (argv[0], '/');
247 mts_init (invo_name);
248 if ((cp = m_find (invo_name)) != NULL) {
249 argp = copyip (brkstring (cp, " ", "\n"), arguments);
250 (void) copyip (argv+1, argp);
251 argp = arguments;
252 }
253
254 /* */
255
256 while (cp = *argp++) {
257 if (*cp == '-')
258 switch (smatch (++cp, switches)) {
259 case AMBIGSW:
260 ambigsw (cp, switches);
261 done (1);
262 case UNKWNSW:
263 adios (NULLCP, "-%s unknown", cp);
264 case HELPSW:
265 (void)sprintf (buf, "%s [switches] file", invo_name);
266 help (buf, switches);
267 done (1);
268
269 case DEBUGSW:
270 debug++;
271 continue;
272
273 case DISTSW:
274 msgstate = resent;
275 continue;
276
277 case WHOMSW:
278 whomflg++;
279 continue;
280
281 case FILTSW:
282 if (!(filter = *argp++) || *filter == '-')
283 adios (NULLCP, "missing argument to %s", argp[-2]);
284 continue;
285 case NFILTSW:
286 filter = NULL;
287 continue;
288
289 case REMVSW:
290 rmflg++;
291 continue;
292 case NREMVSW:
293 rmflg = 0;
294 continue;
295
296 case BACKSW:
297 backflg++;
298 continue;
299 case NBACKSW:
300 backflg = 0;
301 continue;
302
303 case VERBSW:
304 verbose++;
305 continue;
306 case NVERBSW:
307 verbose = 0;
308 continue;
309
310 case WATCSW:
311 watch++;
312 continue;
313 case NWATCSW:
314 watch = 0;
315 continue;
316
317 case PUSHSW:
318 pushflg++;
319 continue;
320 case NPUSHSW:
321 pushflg = 0;
322 continue;
323
324 case ALIASW:
325 if (!(cp = *argp++) || *cp == '-')
326 adios (NULLCP, "missing argument to %s", argp[-2]);
327 if (aliasflg < 0)
328 (void) alias (AliasFile);/* load default aka's */
329 aliasflg = 1;
330 if ((state = alias(cp)) != AK_OK)
331 adios (NULLCP, "aliasing error in file %s - %s",
332 cp, akerror(state) );
333 continue;
334 case NALIASW:
335 aliasflg = 0;
336 continue;
337
338 case WIDTHSW:
339 if (!(cp = *argp++) || *cp == '-')
340 adios (NULLCP, "missing argument to %s", argp[-2]);
341 outputlinelen = atoi (cp);
342 if (outputlinelen <= 10)
343 outputlinelen = 72;
344 continue;
345
346 case LIBSW:
347 case ANNOSW:
348 /* -library & -idanno switch ignored */
349 if (!(cp = *argp++) || *cp == '-')
350 adios (NULLCP, "missing argument to %s", argp[-2]);
351 continue;
352 #ifdef MIME_HEADERS
353 case HENCDSW:
354 hencode = 1;
355 continue;
356 case NHENCDSW:
357 hencode = 0;
358 continue;
359 #endif /* MIME_HEADERS */
360 }
361 if (msg)
362 adios (NULLCP, "only one message at a time!");
363 else
364 msg = cp;
365 }
366
367 /* */
368
369 if (aliasflg < 0)
370 (void) alias (AliasFile); /* load default aka's */
371
372 if (!msg)
373 adios (NULLCP, "usage: %s [switches] file", invo_name);
374
375 if ((in = fopen (msg, "r")) == NULL)
376 adios (msg, "unable to open");
377
378 #ifdef MIME_HEADERS
379 if (hencode == -1) {
380 hencode = 0;
381 for (state = FLD;;) {
382 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
383 case FLD:
384 case FLDEOF:
385 case FLDPLUS:
386 if (uleq (name, "MIME-Version")) {
387 hencode = 1;
388 break;
389 }
390 continue;
391
392 default:
393 break;
394 }
395 break;
396 }
397 (void) fseek (in, 0L, 0);
398 }
399 #endif /* MIME_HEADERS */
400
401 start_headers ();
402 if (debug) {
403 verbose++;
404 out = stdout;
405 }
406 else {
407 (void)mktemp (tmpfil);
408 if ((out = fopen (tmpfil, "w")) == NULL)
409 adios (tmpfil, "unable to create");
410 (void)chmod (tmpfil, 0600);
411 }
412
413 hdrtab = (msgstate == normal) ? NHeaders : RHeaders;
414
415 for (compnum = 1, state = FLD;;) {
416 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
417 #if defined(JAPAN) || defined(MIME_HEADERS)
418 case FLD:
419 case FLDEOF:
420 case FLDPLUS:
421 compnum++;
422 cp = add (buf, NULLCP);
423 while (state == FLDPLUS) {
424 state = m_getfld (state, name, buf, sizeof buf, in);
425 cp = add (buf, cp);
426 }
427 putfmt (name, cp, out);
428 free (cp);
429 continue;
430 #else /* JAPAN || MIME_HEADERS */
431 case FLD:
432 compnum++;
433 putfmt (name, buf, out);
434 continue;
435
436 case FLDPLUS:
437 compnum++;
438 cp = add (buf, cp);
439 while (state == FLDPLUS) {
440 state = m_getfld (state, name, buf, sizeof buf, in);
441 cp = add (buf, cp);
442 }
443 putfmt (name, cp, out);
444 free (cp);
445 continue;
446 #endif /* JAPAN || MIME_HEADERS */
447
448 case BODY:
449 finish_headers (out);
450 fprintf (out, "\n%s", buf);
451 if(whomflg == 0)
452 while (state == BODY) {
453 state = m_getfld (state, name, buf, sizeof buf, in);
454 fputs (buf, out);
455 }
456 break;
457
458 case FILEEOF:
459 finish_headers (out);
460 break;
461
462 case LENERR:
463 case FMTERR:
464 adios (NULLCP, "message format error in component #%d",
465 compnum);
466
467 default:
468 adios (NULLCP, "getfld() returned %d", state);
469 }
470 break;
471 }
472
473 /* */
474
475 (void)fclose (in);
476 if (backflg && !whomflg) {
477 (void) strcpy (buf, m_backup (msg));
478 if (rename (msg, buf) == NOTOK)
479 advise (buf, "unable to rename %s to", msg);
480 }
481
482 if (debug) {
483 done (0);
484 }
485 else
486 (void)fclose (out);
487
488 file (tmpfil);
489
490 /*
491 * re-open the temp file, unlink it and exec sendmail, giving it
492 * the msg temp file as std in.
493 */
494 if ( freopen( tmpfil, "r", stdin) == NULL)
495 adios (tmpfil, "can't reopen for sendmail");
496 if (rmflg)
497 (void)unlink (tmpfil);
498
499 argp = sargv;
500 *argp++ = "send-mail";
501 *argp++ = "-m"; /* send to me too */
502 *argp++ = "-t"; /* read msg for recipients */
503 *argp++ = "-i"; /* don't stop on "." */
504 if (whomflg)
505 *argp++ = "-bv";
506 if (watch || verbose)
507 *argp++ = "-v";
508 *argp = NULL;
509
510 if (pushflg && !(watch || verbose)) {
511 /* fork to a child to run sendmail */
512 for (i=0; (pid = vfork()) == NOTOK && i < 5; i++)
513 sleep(5);
514 switch (pid) {
515 case NOTOK:
516 fprintf (verbose ? stdout : stderr, "%s: can't fork to %s\n",
517 invo_name, sendmail);
518 exit(-1);
519 case OK:
520 /* we're the child .. */
521 break;
522 default:
523 exit(0);
524 }
525 }
526 execv ( sendmail, sargv);
527 adios ( sendmail, "can't exec");
528 }
529
530 /* DRAFT GENERATION */
531
532 static putfmt (name, str, out)
533 char *name,
534 *str;
535 FILE * out;
536 {
537 int count,
538 grp,
539 i,
540 keep;
541 char *cp,
542 *pp,
543 *qp,
544 #ifdef MIME_HEADERS
545 *origstr,
546 #endif /* MIME_HEADERS */
547 namep[BUFSIZ];
548 struct mailname *mp,
549 *np;
550 struct headers *hdr;
551
552 while (*str == ' ' || *str == '\t')
553 str++;
554
555 #ifdef MIME_HEADERS
556 if (hencode) {
557 char *ep;
558 if ((ep = malloc((unsigned)strlen(str)*10+1)) == NULL)
559 adios(NULLCP, "out of memory");
560 #ifdef JAPAN
561 (void) ml_conv(str);
562 #endif /* JAPAN */
563 (void) exthdr_encode(str, ep, strlen(name)+2, name);
564 origstr = str;
565 str = ep;
566 }
567 #endif /* MIME_HEADERS */
568
569 if ((i = get_header (name, hdrtab)) == NOTOK) {
570 fprintf (out, "%s: %s", name, str);
571 return;
572 }
573
574 hdr = &hdrtab[i];
575 if (hdr -> flags & HIGN)
576 return;
577 if (hdr -> flags & HBAD) {
578 advise (NULLCP, "illegal header line -- %s:", name);
579 badmsg++;
580 return;
581 }
582 msgflags |= hdr -> set;
583
584 if (hdr -> flags & HSUB)
585 subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
586
587 if (hdr -> flags & HFCC) {
588 if (cp = rindex (str, '\n'))
589 *cp = 0;
590 for (cp = pp = str; cp = index (pp, ','); pp = cp) {
591 *cp++ = 0;
592 insert_fcc (hdr, pp);
593 }
594 insert_fcc (hdr, pp);
595 return;
596 }
597
598 #ifdef notdef
599 if (hdr -> flags & HBCC) {
600 insert_bcc(str);
601 return;
602 }
603 #endif /* notdef */
604
605 if (*str != '\n' && *str != '\0')
606 if (aliasflg && hdr->flags & HTRY) {
607 /* this header contains address(es) that we have to do
608 * alias expansion on. Because of the saved state in
609 * getname we have to put all the addresses into a list.
610 * We then let putadr munch on that list, possibly
611 * expanding aliases.
612 */
613 register struct mailname *f = 0;
614 register struct mailname *mp = 0;
615
616 #ifdef MIME_HEADERS
617 if (hencode)
618 /* encode again after format */
619 (void) exthdr_decode(origstr, str);
620 #endif /* MIME_HEADERS */
621
622 while (cp = getname( str ) ) {
623 mp = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
624 if (f == 0) {
625 f = mp;
626 mp->m_next = mp;
627 } else {
628 mp->m_next = f->m_next;
629 f->m_next = mp;
630 f = mp;
631 }
632 }
633 f = mp->m_next; mp->m_next = 0;
634 putadr( name, f );
635 } else {
636 fprintf (out, "%s: %s", name, str );
637 }
638 }
639
640 /* */
641
642 static
643 start_headers ()
644 {
645 char *cp;
646 char sigbuf[BUFSIZ];
647
648 (void)strcpy( from, getusr() );
649
650 if ((cp = getfullname ()) && *cp) {
651 (void)strcpy (sigbuf, cp);
652 (void)sprintf (signature, "%s <%s>", sigbuf, from);
653 #ifdef MIME_HEADERS
654 if (hencode) {
655 char *ep;
656 #ifdef JAPAN
657 (void) ml_conv(signature);
658 #endif /* JAPAN */
659 ep = getcpy (signature);
660 (void) exthdr_encode (ep, signature, 5, "From");
661 free(ep);
662 }
663 #endif /* MIME_HEADERS */
664 }
665 else
666 (void)sprintf (signature, "%s", from);
667 }
668
669 /* */
670
671 static
672 finish_headers (out)
673 FILE * out;
674 {
675 switch (msgstate) {
676 case normal:
677 if (!(msgflags & MDAT))
678 fprintf (out, "Date: %s\n", dtimenow ());
679 if (msgflags & MFRM)
680 fprintf (out, "Sender: %s\n", from);
681 else
682 fprintf (out, "From: %s\n", signature);
683 #ifdef notdef
684 if (!(msgflags & MVIS))
685 fprintf (out, "Bcc: Blind Distribution List: ;\n");
686 #endif /* notdef */
687 break;
688
689 case resent:
690 if (!(msgflags & MRDT))
691 fprintf (out, "Resent-Date: %s\n", dtimenow());
692 if (msgflags & MRFM)
693 fprintf (out, "Resent-Sender: %s\n", from);
694 else
695 fprintf (out, "Resent-From: %s\n", signature);
696 #ifdef notdef
697 if (!(msgflags & MVIS))
698 fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
699 #endif /* notdef */
700 break;
701 }
702
703 if (badmsg)
704 adios (NULLCP, "re-format message and try again");
705 }
706
707 /* */
708
709 static int
710 get_header (header, table)
711 char *header;
712 struct headers *table;
713 {
714 struct headers *h;
715
716 for (h = table; h -> value; h++)
717 if (uleq (header, h -> value))
718 return (h - table);
719
720 return NOTOK;
721 }
722
723 /* */
724
725 /* output the address list for header "name". The address list
726 * is a linked list of mailname structs. "nl" points to the head
727 * of the list. Alias substitution should be done on nl.
728 */
729 static putadr (name, nl)
730 char *name;
731 struct mailname *nl;
732 {
733 register struct mailname *mp, *mp2;
734 register int linepos;
735 register char *cp;
736 int namelen;
737
738 fprintf (out, "%s: ", name);
739 namelen = strlen(name) + 2;
740 linepos = namelen;
741
742 for (mp = nl; mp; ) {
743 if (linepos > MAX_SM_FIELD) {
744 fprintf (out, "\n%s: ", name);
745 linepos = namelen;
746 }
747 if (mp->m_nohost) {
748 /* a local name - see if it's an alias */
749 cp = akvalue(mp->m_mbox);
750 if (strcmp(cp, mp->m_mbox) == 0)
751 /* wasn't an alias - use what the user typed */
752 linepos = putone( mp->m_text, linepos, namelen );
753 else {
754 /* an alias - expand it */
755 while (cp = getname(cp) ) {
756 if (linepos > MAX_SM_FIELD) {
757 fprintf (out, "\n%s: ", name);
758 linepos = namelen;
759 }
760 mp2 = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
761 if (akvisible()) {
762 mp2->m_pers = getcpy(mp->m_mbox);
763 linepos = putone( adrformat(mp2), linepos, namelen );
764 } else {
765 linepos = putone( mp2->m_text, linepos, namelen );
766 }
767 mnfree( mp2 );
768 }
769 }
770 } else {
771 /* not a local name - use what the user typed */
772 linepos = putone( mp->m_text, linepos, namelen );
773 }
774 mp2 = mp;
775 mp = mp->m_next;
776 mnfree( mp2 );
777 }
778 putc( '\n', out );
779 }
780
781 static int putone ( adr, pos, indent )
782 register char *adr;
783 register int pos;
784 int indent;
785 {
786 register int len;
787 static int linepos;
788 #ifdef MIME_HEADERS
789 char name[BUFSIZ], *ep;
790
791 if (hencode) {
792 if ((ep = malloc((unsigned)strlen(adr)*10+1)) == NULL)
793 adios(NULLCP, "out of memory");
794 sprintf(name, "%*s", indent, ""); /* dummy */
795 (void) exthdr_encode(adr, ep, pos, name);
796 len = strlen(ep);
797 } else
798 #endif /* MIME_HEADERS */
799 len = strlen( adr );
800 if (pos == indent)
801 linepos = pos;
802 else if ( linepos+len > outputlinelen ) {
803 fprintf ( out, ",\n%*s", indent, "");
804 #ifdef MIME_HEADERS
805 if (hencode) {
806 (void) exthdr_encode(adr, ep, linepos, name);
807 len = strlen(ep);
808 }
809 #endif /* MIME_HEADERS */
810 linepos = indent;
811 pos += indent + 2;
812 }
813 else {
814 fputs( ", ", out );
815 linepos += 2;
816 pos += 2;
817 }
818 #ifdef MIME_HEADERS
819 if (hencode) {
820 char *p;
821 fputs(ep, out);
822 linepos = (p = rindex(ep, '\n')) ? (ep + len) - (p+1) : linepos + len;
823 free(ep);
824 } else {
825 fputs(adr, out);
826 linepos += len;
827 }
828 #else /* MIME_HEADERS */
829 fputs( adr, out );
830
831 linepos += len;
832 #endif /* MIME_HEADERS */
833 return (pos+len);
834 }
835
836 /* */
837
838 static insert_fcc (hdr, pp)
839 struct headers *hdr;
840 char *pp;
841 {
842 char *cp;
843
844 for (cp = pp; isspace (*cp); cp++)
845 continue;
846 for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
847 continue;
848 if (pp >= cp)
849 *++pp = 0;
850 if (*cp == 0)
851 return;
852
853 if (fccind >= FCCS)
854 adios (NULLCP, "too many %ss", hdr -> value);
855 fccfold[fccind++] = getcpy (cp);
856 }
857
858 #ifdef notdef
859 /* BCC GENERATION */
860
861 static make_bcc_file () {
862 int fd,
863 i,
864 child_id,
865 status;
866 char *vec[6];
867 FILE * in, *out;
868
869 (void)mktemp (bccfil);
870 if ((out = fopen (bccfil, "w")) == NULL)
871 adios (bccfil, "unable to create");
872 (void)chmod (bccfil, 0600);
873
874 fprintf (out, "Date: %s\n", dtimenow ());
875 fprintf (out, "From: %s\n", signature);
876 if (subject)
877 fprintf (out, "Subject: %s", subject);
878 fprintf (out, "BCC:\n\n------- Blind-Carbon-Copy\n\n");
879 (void)fflush (out);
880
881 if (filter == NULL) {
882 if ((fd = open (tmpfil, 0)) == NOTOK)
883 adios (NULLCP, "unable to re-open");
884 cpydgst (fd, fileno (out), tmpfil, bccfil);
885 close (fd);
886 }
887 else {
888 vec[0] = r1bindex (mhlproc, '/');
889
890 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
891 sleep (5);
892 switch (child_id) {
893 case NOTOK:
894 adios ("vfork", "unable to");
895
896 case OK:
897 dup2 (fileno (out), 1);
898
899 i = 1;
900 vec[i++] = "-forward";
901 vec[i++] = "-form";
902 vec[i++] = filter;
903 vec[i++] = tmpfil;
904 vec[i] = NULL;
905
906 execvp (mhlproc, vec);
907 adios (mhlproc, "unable to exec");
908
909 default:
910 if (status = pidwait (child_id, OK))
911 admonish (NULL, "%s lost (status=0%o)", vec[0], status);
912 break;
913 }
914 }
915
916 fseek (out, 0L, 2);
917 fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
918 (void)fclose (out);
919 }
920 #endif /* notdef */
921
922 /* FCC INTERACTION */
923
924 static file (path)
925 char *path;
926 {
927 int i;
928
929 if (fccind == 0)
930 return;
931
932 for (i = 0; i < fccind; i++)
933 if (whomflg)
934 printf ("Fcc: %s\n", fccfold[i]);
935 else
936 fcc (path, fccfold[i]);
937 }
938
939
940 static fcc (file, folder)
941 char *file,
942 *folder;
943 {
944 int i,
945 child_id,
946 status;
947 char fold[BUFSIZ];
948
949 if (verbose)
950 printf ("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", folder);
951 (void)fflush (stdout);
952
953 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
954 sleep (5);
955 switch (child_id) {
956 case NOTOK:
957 if (!verbose)
958 fprintf (stderr, " %sFcc %s: ",
959 msgstate == resent ? "Resent-" : "", folder);
960 fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
961 break;
962
963 case OK:
964 (void)sprintf (fold, "%s%s",
965 *folder == '+' || *folder == '@' ? "" : "+", folder);
966 execlp (fileproc, r1bindex (fileproc, '/'),
967 "-link", "-file", file, fold, NULL);
968 _exit (-1);
969
970 default:
971 if (status = pidwait (child_id, OK)) {
972 if (!verbose)
973 fprintf (stderr, " %sFcc %s: ",
974 msgstate == resent ? "Resent-" : "", folder);
975 fprintf (verbose ? stdout : stderr,
976 " errored (0%o)\n", status);
977 }
978 }
979
980 (void)fflush (stdout);
981 }
982
983 /* TERMINATION */
984
985 /* VARARGS2 */
986
987 static die (what, fmt, a, b, c, d)
988 char *what,
989 *fmt,
990 *a,
991 *b,
992 *c,
993 *d;
994 {
995 adios (what, fmt, a, b, c, d);
996 }