]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/post.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / post.c
1 /* post.c - enter messages into the transport system */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: post.c,v 2.26 1996/02/10 00:22:14 jromine Exp $";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include "../h/addrsbr.h"
8 #include "../h/aliasbr.h"
9 #include "../h/dropsbr.h"
10 #include "../zotnet/tws.h"
11 #ifndef MMDFMTS
12 #include <ctype.h>
13 #include <errno.h>
14 #include <setjmp.h>
15 #include <stdio.h>
16 #include <sys/types.h>
17 #else /* MMDFMTS */
18 #include "../mts/mmdf/util.h"
19 #include "../mts/mmdf/mmdf.h"
20 #endif /* MMDFMTS */
21 #include "../zotnet/mts.h"
22 #ifdef MHMTS
23 #ifndef V7
24 #include <sys/ioctl.h>
25 #endif /* not V7 */
26 #include <sys/stat.h>
27 #endif /* MHMTS */
28 #ifdef SENDMTS
29 #include "../mts/sendmail/smail.h"
30 #undef MF
31 #endif /* SENDMTS */
32 #include <signal.h>
33 #ifdef MIME
34 #include "../h/mhn.h"
35 #endif /* MIME */
36 #ifdef LOCALE
37 #include <locale.h>
38 #endif
39
40
41 #ifndef MMDFMTS
42 #define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : (c))
43 #endif /* not MMDFMTS */
44
45 #define FCCS 10 /* max number of fccs allowed */
46
47 /* \f */
48
49 #ifndef MIME
50 #define MIMEminc(a) (a)
51 #else
52 #define MIMEminc(a) 0
53 #endif
54
55 #ifndef TMA
56 #define TMAminc(a) (a)
57 #else /* TMA */
58 #define TMAminc(a) 0
59 #endif /* TMA */
60
61 static struct swit switches[] = {
62 #define ALIASW 0
63 "alias aliasfile", 0,
64
65 #define CHKSW 1
66 "check", -1, /* interface from whom */
67 #define NCHKSW 2
68 "nocheck", -3, /* interface from whom */
69
70 #define DEBUGSW 3
71 "debug", -5,
72
73 #define DISTSW 4
74 "dist", -4, /* interface from dist */
75
76 #define ENCRSW 5
77 "encrypt", TMAminc (-7),
78 #define NENCRSW 6
79 "noencrypt", TMAminc (-9),
80
81 #define FILTSW 7
82 "filter filterfile", 0,
83 #define NFILTSW 8
84 "nofilter", 0,
85
86 #define FRMTSW 9
87 "format", 0,
88 #define NFRMTSW 10
89 "noformat", 0,
90
91 #define LIBSW 11 /* interface from send, whom */
92 "library directory", -7,
93
94 #define MIMESW 12
95 "mime", MIMEminc(-4),
96 #define NMIMESW 13
97 "nomime", MIMEminc(-6),
98
99 #define MSGDSW 14
100 "msgid", 0,
101 #define NMSGDSW 15
102 "nomsgid", 0,
103
104 #define VERBSW 16
105 "verbose", 0,
106 #define NVERBSW 17
107 "noverbose", 0,
108
109 #define WATCSW 18
110 "watch", 0,
111 #define NWATCSW 19
112 "nowatch", 0,
113
114 #define WHOMSW 20 /* interface from whom */
115 "whom", -4,
116
117 #define WIDTHSW 21
118 "width columns", 0,
119
120 #define HELPSW 22
121 "help", 4,
122
123 #define MAILSW 23
124 "mail", -4,
125 #define SAMLSW 24
126 "saml", -4,
127 #define SENDSW 25
128 "send", -4,
129 #define SOMLSW 26
130 "soml", -4,
131
132 #define ANNOSW 27 /* interface from send */
133 "idanno number", -6,
134
135 #define DLVRSW 28
136 "deliver address-list", -7,
137
138 #define CLIESW 29
139 "client host", -6,
140 #define SERVSW 30
141 "server host", -6,
142 #define SNOOPSW 31
143 "snoop", -5,
144
145 #define FILLSW 32
146 "fill-in file", -7,
147 #define FILLUSW 33
148 "fill-up", -7,
149 #define PARTSW 34
150 "partno", -6,
151
152 #define QUEUESW 35
153 "queued", -6,
154
155 #define RECORSW 36
156 "record program", -6,
157 #define NRECOSW 37
158 "norecord", -8,
159
160 NULL, 0
161 };
162
163 /* \f */
164
165 struct headers {
166 char *value;
167
168 unsigned int flags;
169 #define HNOP 0x0000 /* just used to keep .set around */
170 #define HBAD 0x0001 /* bad header - don't let it through */
171 #define HADR 0x0002 /* header has an address field */
172 #define HSUB 0x0004 /* Subject: header */
173 #define HTRY 0x0008 /* try to send to addrs on header */
174 #define HBCC 0x0010 /* don't output this header */
175 #define HMNG 0x0020 /* munge this header */
176 #define HNGR 0x0040 /* no groups allowed in this header */
177 #define HFCC 0x0080 /* FCC: type header */
178 #define HNIL 0x0100 /* okay for this header not to have addrs */
179 #define HIGN 0x0200 /* ignore this header */
180 #define HDCC 0x0400 /* another undocumented feature */
181
182 unsigned int set;
183 #define MFRM 0x0001 /* we've seen a From: */
184 #define MDAT 0x0002 /* we've seen a Date: */
185 #define MRFM 0x0004 /* we've seen a Resent-From: */
186 #define MVIS 0x0008 /* we've seen sighted addrs */
187 #define MINV 0x0010 /* we've seen blind addrs */
188 #define MRPY 0x0020 /* we've seen a Reply-to: */
189 };
190
191 /* \f */
192
193 static struct headers NHeaders[] = {
194 "Return-Path", HBAD, 0,
195 "Received", HBAD, 0,
196 "Reply-To", HADR | HNGR, MRPY,
197 "From", HADR | HNGR, MFRM,
198 "Sender", HADR | HBAD, 0,
199 "Date", HBAD, 0,
200 "Subject", HSUB, 0,
201 "To", HADR | HTRY, MVIS,
202 "cc", HADR | HTRY, MVIS,
203 "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
204 "Dcc", HADR | HTRY | HDCC | HNIL, MVIS, /* sorta cc & bcc combined */
205 "Message-ID", HBAD, 0,
206 "Fcc", HFCC, 0,
207
208 NULL
209 };
210
211 static struct headers RHeaders[] = {
212 "Resent-Reply-To", HADR | HNGR, MRPY,
213 "Resent-From", HADR | HNGR, MRFM,
214 "Resent-Sender", HADR | HBAD, 0,
215 "Resent-Date", HBAD, 0,
216 "Resent-Subject", HSUB, 0,
217 "Resent-To", HADR | HTRY, MVIS,
218 "Resent-cc", HADR | HTRY, MVIS,
219 "Resent-Bcc", HADR | HTRY | HBCC, MINV,
220 "Resent-Message-ID", HBAD, 0,
221 "Resent-Fcc", HFCC, 0,
222 "Reply-To", HADR, MRPY,
223 "From", HADR | HNGR, MFRM,
224 #ifdef MMDFI
225 "Sender", HADR | HMNG | HNGR, 0,
226 #else /* not MMFDI */
227 "Sender", HADR | HNGR, 0,
228 #endif /* not MMDFI */
229 "Date", HNOP, MDAT,
230 "To", HADR | HNIL, 0,
231 "cc", HADR | HNIL, 0,
232 "Bcc", HADR | HTRY | HBCC | HNIL, 0,
233 "Fcc", HIGN, 0,
234
235 NULL
236 };
237
238 /* \f */
239
240
241 static short fccind = 0; /* index into fccfold[] */
242 static short outputlinelen = OUTPUTLINELEN;
243
244 static int pfd = NOTOK; /* fd to write annotation list to */
245 static int myuid= -1; /* my user id */
246 static int mygid= -1; /* my group id */
247 static int recipients = 0; /* how many people will get a copy */
248 static int unkadr = 0; /* how many of those were unknown */
249 static int badadr = 0; /* number of bad addrs */
250 static int badmsg = 0; /* message has bad semantics */
251 static int verbose = 0; /* spell it out */
252 static int format = 1; /* format addresses */
253 static int mime = 0; /* use MIME-style encapsulations */
254 static int msgid = 0; /* add msgid */
255 static int debug = 0; /* debugging post */
256 static int watch = 0; /* watch the delivery process */
257 static int whomsw = 0; /* we are whom not post */
258 static int checksw = 0; /* whom -check */
259 static int linepos=0; /* putadr()'s position on the line */
260 static int nameoutput=0; /* putadr() has output header name */
261
262 static unsigned msgflags = 0; /* what we've seen */
263
264 #define NORMAL 0
265 #define RESENT 1
266 static int msgstate = NORMAL;
267
268 static long tclock = 0L; /* the time we started (more or less) */
269
270 static TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
271
272 static char tmpfil[BUFSIZ];
273 static char bccfil[BUFSIZ];
274
275 static char from[BUFSIZ]; /* my network address */
276 static char signature[BUFSIZ]; /* my signature */
277 static char *filter = NULL; /* the filter for BCC'ing */
278 static char *msgfrom = NULL; /* the From: field for Bcc'ing */
279 static char *subject = NULL; /* the subject field for BCC'ing */
280 static char *fccfold[FCCS]; /* foldernames for FCC'ing */
281
282 static struct headers *hdrtab; /* table for the message we're doing */
283
284 static struct mailname localaddrs={NULL}; /* local addrs */
285 static struct mailname netaddrs={NULL}; /* network addrs */
286 static struct mailname uuaddrs={NULL}; /* uucp addrs */
287 static struct mailname tmpaddrs={NULL}; /* temporary queue */
288
289 /* \f */
290
291 #ifdef MMDFMTS
292 static char *submitmode = "m"; /* deliver to mailbox only */
293 static char submitopts[6] = "vl";/* initial options for submit */
294 #endif /* MMDFMTS */
295
296 #ifdef MHMTS
297 static char *deliver = NULL;
298
299 extern char **environ;
300
301 TYPESIG sigser ();
302 #endif /* MHMTS */
303
304 #ifdef SENDMTS
305 static int smtpmode = S_MAIL;
306 static int snoop = 0;
307 static char *clientsw = NULL;
308 static char *serversw = NULL;
309
310 extern struct smtp sm_reply;
311 #endif /* SENDMTS */
312
313 #ifdef TMA
314 #define post(a,b,c) \
315 if (encryptsw) postcipher ((a), (b), (c)); else postplain ((a), (b), (c))
316
317 #ifndef SENDMTS
318 #define tmasnoop 0
319 #else /* SENDMTS */
320 #define tmasnoop snoop
321 #endif /* SENDMTS */
322 #endif /* TMA */
323
324 static int encryptsw = 0; /* encrypt it */
325
326
327 #ifdef BERK
328 #undef WP
329 #endif
330
331 #ifdef MIME
332 static char prefix[] = "----- =_aaaaaaaaaa";
333 static int find_prefix();
334 #endif /* MIME */
335
336 static int fill_up = 0;
337 static char *fill_in = NULLCP;
338 static char *partno = NULLCP;
339
340 static int queued = 0;
341
342 static char *record = NULLCP;
343
344 off_t lseek ();
345 long time ();
346
347 static putfmt(), start_headers(), finish_headers(), putgrp(), pl();
348 static anno(), make_bcc_file(), verify_all_addresses();
349 static chkadr(), do_addresses(), do_text(), do_an_address(), sigon();
350 static sigoff(), p_refile(), fcc(), die(), insert_fcc(), p_record ();
351 static int get_header(), putadr(), insert(), annoaux();
352 #ifdef TMA
353 static postplain();
354 #else
355 static post();
356 #endif /* !TMA */
357 /* \f MAIN */
358
359 /* ARGSUSED */
360
361 main (argc, argv)
362 int argc;
363 char *argv[];
364 {
365 int state,
366 compnum;
367 char *cp,
368 *msg = NULL,
369 **argp = argv + 1,
370 buf[BUFSIZ],
371 name[NAMESZ];
372 FILE *in,
373 *out;
374
375 #ifdef LOCALE
376 setlocale(LC_ALL, "");
377 #endif
378 invo_name = r1bindex (argv[0], '/');
379 m_foil (NULLCP);
380 mts_init (invo_name);
381 #ifdef MMDFMTS
382 #ifdef MMDFII
383 mmdf_init (invo_name);
384 #endif /* MMDFII */
385 #endif /* MMDFMTS */
386
387 /* \f */
388
389 while (cp = *argp++) {
390 if (*cp == '-')
391 switch (smatch (++cp, switches)) {
392 case AMBIGSW:
393 ambigsw (cp, switches);
394 done (1);
395 case UNKWNSW:
396 adios (NULLCP, "-%s unknown", cp);
397 case HELPSW:
398 (void) sprintf (buf, "%s [switches] file", invo_name);
399 help (buf, switches);
400 done (1);
401
402 case LIBSW:
403 if (!(cp = *argp++) || *cp == '-')
404 adios (NULLCP, "missing argument to %s", argp[-2]);
405 m_foil (cp);
406 continue;
407
408 case ALIASW:
409 if (!(cp = *argp++) || *cp == '-')
410 adios (NULLCP, "missing argument to %s", argp[-2]);
411 #ifdef MHMTS
412 if (access (libpath (cp), 04) == NOTOK)
413 adios (cp, "unable to read");
414 #endif /* MHMTS */
415 if ((state = alias (cp)) != AK_OK)
416 adios (NULLCP, "aliasing error in %s - %s",
417 cp, akerror (state));
418 continue;
419
420 case CHKSW:
421 checksw++;
422 continue;
423 case NCHKSW:
424 checksw = 0;
425 continue;
426
427 case DEBUGSW:
428 debug++;
429 continue;
430
431 case DISTSW:
432 msgstate = RESENT;
433 continue;
434
435 case FILTSW:
436 if (!(filter = *argp++) || *filter == '-')
437 adios (NULLCP, "missing argument to %s", argp[-2]);
438 mime = 0;
439 continue;
440 case NFILTSW:
441 filter = NULL;
442 continue;
443
444 case FRMTSW:
445 format++;
446 continue;
447 case NFRMTSW:
448 format = 0;
449 continue;
450
451 case MIMESW:
452 #ifdef MIME
453 mime++;
454 filter = 0;
455 #endif
456 continue;
457 case NMIMESW:
458 mime = 0;
459 continue;
460
461 case MSGDSW:
462 msgid++;
463 continue;
464 case NMSGDSW:
465 msgid = 0;
466 continue;
467
468 case VERBSW:
469 verbose++;
470 continue;
471 case NVERBSW:
472 verbose = 0;
473 continue;
474
475 case WATCSW:
476 watch++;
477 continue;
478 case NWATCSW:
479 watch = 0;
480 continue;
481
482 case WHOMSW:
483 whomsw++;
484 continue;
485
486 case WIDTHSW:
487 if (!(cp = *argp++) || *cp == '-')
488 adios (NULLCP, "missing argument to %s", argp[-2]);
489 if ((outputlinelen = atoi (cp)) < 10)
490 adios (NULLCP, "impossible width %d", outputlinelen);
491 continue;
492
493 case ENCRSW:
494 encryptsw++;
495 continue;
496 case NENCRSW:
497 encryptsw = 0;
498 continue;
499
500 case ANNOSW:
501 if (!(cp = *argp++) || *cp == '-')
502 adios (NULLCP, "missing argument to %s", argp[-2]);
503 if ((pfd = atoi (cp)) <= 2)
504 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
505 continue;
506
507 #ifdef MMDFMTS
508 case MAILSW:
509 submitmode = "m";
510 continue;
511 case SOMLSW: /* for right now, sigh... */
512 case SAMLSW:
513 submitmode = "b";
514 continue;
515 case SENDSW:
516 submitmode = "y";
517 continue;
518 #endif /* MMDFMTS */
519
520 #ifndef MHMTS
521 case DLVRSW:
522 if (!(cp = *argp++) || *cp == '-')
523 adios (NULLCP, "missing argument to %s", argp[-2]);
524 continue;
525 #else /* MHMTS */
526 case MAILSW:
527 case SAMLSW:
528 case SOMLSW:
529 case SENDSW:
530 continue;
531 case DLVRSW:
532 if (!(deliver = *argp++) || *deliver == '-')
533 adios (NULLCP, "missing argument to %s", argp[-2]);
534 continue;
535 #endif /* MHMTS */
536
537 #ifndef SENDMTS
538 case CLIESW:
539 case SERVSW:
540 if (!(cp = *argp++) || *cp == '-')
541 adios (NULLCP, "missing argument to %s", argp[-2]);
542 continue;
543
544 case SNOOPSW:
545 continue;
546 #else /* SENDMTS */
547 case MAILSW:
548 smtpmode = S_MAIL;
549 continue;
550 case SAMLSW:
551 smtpmode = S_SAML;
552 continue;
553 case SOMLSW:
554 smtpmode = S_SOML;
555 continue;
556 case SENDSW:
557 smtpmode = S_SEND;
558 continue;
559 case CLIESW:
560 if (!(clientsw = *argp++) || *clientsw == '-')
561 adios (NULLCP, "missing argument to %s", argp[-2]);
562 continue;
563 case SERVSW:
564 if (!(serversw = *argp++) || *serversw == '-')
565 adios (NULLCP, "missing argument to %s", argp[-2]);
566 continue;
567 case SNOOPSW:
568 snoop++;
569 continue;
570 #endif /* SENDMTS */
571
572 case FILLSW:
573 if (!(fill_in = *argp++) || *fill_in == '-')
574 adios (NULLCP, "missing argument to %s", argp[-2]);
575 continue;
576 case FILLUSW:
577 fill_up++;
578 continue;
579 case PARTSW:
580 if (!(partno = *argp++) || *partno == '-')
581 adios (NULLCP, "missing argument to %s", argp[-2]);
582 continue;
583
584 case QUEUESW:
585 queued++;
586 continue;
587
588 case RECORSW:
589 if (!(record = *argp++) || *record == '-')
590 adios (NULLCP, "missing argument to %s", argp[-2]);
591 continue;
592 case NRECOSW:
593 record = NULLCP;
594 continue;
595 }
596 if (msg)
597 adios (NULLCP, "only one message at a time!");
598 else
599 msg = cp;
600 }
601
602 (void) alias (AliasFile);
603
604 /* \f */
605
606 if (!msg)
607 adios (NULLCP, "usage: %s [switches] file", invo_name);
608
609 if (outputlinelen < 10)
610 adios (NULLCP, "impossible width %d", outputlinelen);
611
612 #ifdef MHMTS
613 if (access (msg, 04) == NOTOK)
614 adios (msg, "unable to read");
615 #endif /* MHMTS */
616 if ((in = fopen (msg, "r")) == NULL)
617 adios (msg, "unable to open");
618
619 start_headers ();
620 if (debug) {
621 verbose++;
622 discard (out = stdout); /* XXX: reference discard() to help loader */
623 #ifdef MHMTS
624 if (deliver) {
625 (void) strcpy (tmpfil, msg);
626 putfmt ("To", deliver, out);
627 goto daemon;
628 }
629 #endif /* MHMTS */
630 }
631 else
632 #ifdef MHMTS
633 if (deliver) {
634 if ((out = fopen ("/dev/null", "r")) == NULL)
635 adios ("/dev/null", "unable to write");
636 (void) strcpy (tmpfil, msg);
637 putfmt ("To", deliver, out);
638 goto daemon;
639 }
640 else
641 #endif /* MHMTS */
642 if (whomsw) {
643 if ((out = fopen (fill_in ? fill_in : "/dev/null", "w")) == NULL)
644 adios ("/dev/null", "unable to open");
645 }
646 else {
647 (void) strcpy (tmpfil, m_scratch ("", m_maildir (invo_name)));
648 if ((out = fopen (tmpfil, "w")) == NULL) {
649 (void) strcpy (tmpfil, m_tmpfil (invo_name));
650 if ((out = fopen (tmpfil, "w")) == NULL)
651 adios (tmpfil, "unable to create");
652 }
653 #ifdef MHMTS
654 (void) chown (tmpfil, myuid, mygid);
655 #endif /* MHMTS */
656 (void) chmod (tmpfil, 0600);
657 }
658
659 /* \f */
660
661 hdrtab = msgstate == NORMAL ? NHeaders : RHeaders;
662
663 for (compnum = 1, state = FLD;;) {
664 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
665 case FLD:
666 case FLDEOF:
667 case FLDPLUS:
668 compnum++;
669 cp = add (buf, NULLCP);
670 while (state == FLDPLUS) {
671 state = m_getfld (state, name, buf, sizeof buf, in);
672 cp = add (buf, cp);
673 }
674 putfmt (name, cp, out);
675 free (cp);
676 if (state != FLDEOF)
677 continue;
678 finish_headers (out);
679 break;
680
681 case BODY:
682 case BODYEOF:
683 finish_headers (out);
684 if (whomsw && !fill_in)
685 break;
686 fprintf (out, "\n%s", buf);
687 while (state == BODY) {
688 state = m_getfld (state, name, buf, sizeof buf, in);
689 fputs (buf, out);
690 }
691 break;
692
693 case FILEEOF:
694 finish_headers (out);
695 break;
696
697 case LENERR:
698 case FMTERR:
699 adios (NULLCP, "message format error in component #%d",
700 compnum);
701
702 default:
703 adios (NULLCP, "getfld() returned %d", state);
704 }
705 break;
706 }
707
708 /* \f */
709
710 #ifdef MHMTS
711 daemon: ;
712 #endif /* MHMTS */
713 if (pfd != NOTOK)
714 anno ();
715 (void) fclose (in);
716 if (debug) {
717 pl ();
718 done (0);
719 }
720 else
721 (void) fclose (out);
722
723 #ifdef TMA
724 if (encryptsw)
725 tmastart (tmasnoop);
726 #endif /* TMA */
727 if (whomsw) {
728 if (!fill_up)
729 verify_all_addresses (1);
730 done (0);
731 }
732
733 #ifdef MMDFMTS
734 (void) strcat (submitopts, submitmode);
735 if (watch)
736 (void) strcat (submitopts, "nw");
737 #endif /* MMDFMTS */
738 #ifdef MHMTS
739 verify_all_addresses (0);
740 #endif /* MHMTS */
741 if (encryptsw)
742 verify_all_addresses (verbose);
743 if (msgflags & MINV) {
744 make_bcc_file ();
745 if (msgflags & MVIS) {
746 #ifndef MHMTS
747 if (!encryptsw)
748 verify_all_addresses (verbose);
749 #endif /* not MHMTS */
750 post (tmpfil, 0, verbose);
751 }
752 post (bccfil, 1, verbose);
753 (void) unlink (bccfil);
754 }
755 else
756 post (tmpfil, 0, isatty (1));
757 #ifdef TMA
758 if (encryptsw)
759 tmastop ();
760 #endif /* TMA */
761
762 p_refile (tmpfil);
763
764 p_record ();
765
766 #ifdef MHMTS
767 if (!deliver)
768 #endif /* MHMTS */
769 (void) unlink (tmpfil);
770
771 if (verbose)
772 printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n",
773 partno);
774
775 done (0);
776 }
777
778 /* \f DRAFT GENERATION */
779
780 static putfmt (name, str, out)
781 register char *name,
782 *str;
783 register FILE *out;
784 {
785 int count,
786 grp,
787 i,
788 keep;
789 register char *cp,
790 *pp,
791 *qp;
792 char namep[BUFSIZ];
793 register struct mailname *mp,
794 *np;
795 register struct headers *hdr;
796
797 while (*str == ' ' || *str == '\t')
798 str++;
799
800 if (msgstate == NORMAL && uprf (name, "resent")) {
801 advise (NULLCP, "illegal header line -- %s:", name);
802 badmsg++;
803 return;
804 }
805
806 if ((i = get_header (name, hdrtab)) == NOTOK) {
807 fprintf (out, "%s: %s", name, str);
808 return;
809 }
810
811 hdr = &hdrtab[i];
812 if (hdr -> flags & HIGN) {
813 if (fill_in)
814 fprintf (out, "%s: %s", name, str);
815 return;
816 }
817 if (hdr -> flags & HBAD) {
818 if (fill_in)
819 fprintf (out, "%s: %s", name, str);
820 else {
821 advise (NULLCP, "illegal header line -- %s:", name);
822 badmsg++;
823 }
824 return;
825 }
826 msgflags |= (hdr -> set & ~(MVIS | MINV));
827
828 if (hdr -> set & MFRM)
829 msgfrom = msgfrom ? add (str, add (",", msgfrom)) : getcpy (str);
830 if (hdr -> flags & HSUB)
831 subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
832 if (hdr -> flags & HFCC) {
833 if (fill_in) {
834 fprintf (out, "%s: %s", name, str);
835 return;
836 }
837
838 if (cp = rindex (str, '\n'))
839 *cp = 0;
840 for (cp = pp = str; cp = index (pp, ','); pp = cp) {
841 *cp++ = 0;
842 insert_fcc (hdr, pp);
843 }
844 insert_fcc (hdr, pp);
845 return;
846 }
847
848 /* \f */
849
850 if (!(hdr -> flags & HADR)) {
851 fprintf (out, "%s: %s", name, str);
852 return;
853 }
854
855 tmpaddrs.m_next = NULL;
856 for (count = 0; cp = getname (str); count++)
857 if (mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP)) {
858 if (tmpaddrs.m_next)
859 np -> m_next = mp;
860 else
861 tmpaddrs.m_next = mp;
862 np = mp;
863 }
864 else
865 if (hdr -> flags & HTRY)
866 badadr++;
867 else
868 badmsg++;
869
870 if (count < 1) {
871 if (hdr -> flags & HNIL) {
872 if (!(hdr -> flags & HBCC))
873 fprintf (out, "%s: %s", name, str);
874 }
875 else {
876 #ifdef notdef
877 advise (NULLCP, "%s: field requires at least one address", name);
878 badmsg++;
879 #endif /* notdef */
880 }
881 return;
882 }
883
884 /* \f */
885
886 nameoutput = linepos = 0;
887 (void) sprintf (namep, "%s%s",
888 !fill_in && (hdr -> flags & HMNG) ? "Original-" : "",
889 name);
890
891 for (grp = 0, mp = tmpaddrs.m_next; mp; mp = np)
892 if (mp -> m_nohost) { /* also used to test (hdr -> flags & HTRY) */
893 pp = akvalue (mp -> m_mbox);
894 qp = akvisible () ? mp -> m_mbox : "";
895 np = mp;
896 if (np -> m_gname)
897 putgrp (namep, np -> m_gname, out, hdr -> flags);
898 while (cp = getname (pp)) {
899 if (!(mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP))) {
900 badadr++;
901 continue;
902 }
903 if (hdr -> flags & HBCC)
904 mp -> m_bcc++;
905 if (np -> m_ingrp)
906 mp -> m_ingrp = np -> m_ingrp;
907 else
908 if (mp -> m_gname)
909 putgrp (namep, mp -> m_gname, out, hdr -> flags);
910 if (mp -> m_ingrp)
911 grp++;
912 #ifdef MHMTS
913 mp -> m_aka = getcpy (np -> m_mbox);
914 #endif /* MHMTS */
915 if (putadr (namep, qp, mp, out, hdr -> flags))
916 msgflags |= (hdr -> set & (MVIS | MINV));
917 else
918 mnfree (mp);
919 }
920 mp = np;
921 np = np -> m_next;
922 mnfree (mp);
923 }
924 else {
925 if (hdr -> flags & HBCC)
926 mp -> m_bcc++;
927 if (mp -> m_gname)
928 putgrp (namep, mp -> m_gname, out, hdr -> flags);
929 if (mp -> m_ingrp)
930 grp++;
931 keep = putadr (namep, "", mp, out, hdr -> flags);
932 np = mp -> m_next;
933 if (keep) {
934 mp -> m_next = NULL;
935 msgflags |= (hdr -> set & (MVIS | MINV));
936 }
937 else
938 mnfree (mp);
939 }
940
941 if (grp > 0 && (hdr -> flags & HNGR)) {
942 advise (NULLCP, "%s: field does not allow groups", name);
943 badmsg++;
944 }
945 if (linepos) {
946 if (fill_in && grp > 0)
947 (void) putc (';', out);
948 (void) putc ('\n', out);
949 }
950 }
951
952 /* \f */
953
954 static start_headers () {
955 register char *cp;
956 char myhost[BUFSIZ],
957 sigbuf[BUFSIZ];
958 register struct mailname *mp;
959
960 myuid = getuid ();
961 mygid = getgid ();
962 (void) time (&tclock);
963
964 (void) strcpy (from, adrsprintf (NULLCP, NULLCP));
965
966 (void) strcpy (myhost, LocalName ());
967 for (cp = myhost; *cp; cp++)
968 *cp = uptolow (*cp);
969
970 #ifdef MHMTS
971 if (deliver) {
972 if (geteuid () == 0 && myuid != 0 && myuid != 1 && mygid != 1)
973 adios (NULLCP, "-deliver unknown");
974 (void) strcpy (signature, from);
975 }
976 #endif /* MHMTS */
977
978 if ((cp = getfullname ()) && *cp) {
979 (void) strcpy (sigbuf, cp);
980 (void) sprintf (signature, "%s <%s>", sigbuf, adrsprintf (NULLCP, NULLCP));
981 if ((cp = getname (signature)) == NULL)
982 adios (NULLCP, "getname () failed -- you lose extraordinarily big");
983 if ((mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP)) == NULL)
984 adios (NULLCP, "bad signature '%s'", sigbuf);
985 mnfree (mp);
986 while (getname (""))
987 continue;
988 }
989 else
990 (void) strcpy (signature, adrsprintf (NULLCP, NULLCP));
991 }
992
993 /* \f */
994
995 static finish_headers (out)
996 register FILE *out;
997 {
998 switch (msgstate) {
999 case NORMAL:
1000 if (whomsw && !fill_up)
1001 break;
1002
1003 fprintf (out, "Date: %s\n", dtime (&tclock));
1004 if (msgid)
1005 fprintf (out, "Message-ID: <%d.%ld@%s>\n",
1006 getpid (), tclock, LocalName ());
1007 if (msgflags & MFRM)
1008 fprintf (out, "Sender: %s\n", from);
1009 else
1010 fprintf (out, "From: %s\n", signature);
1011 if (whomsw)
1012 break;
1013
1014 if (!(msgflags & MVIS))
1015 fprintf (out, "Bcc: Blind Distribution List: ;\n");
1016 break;
1017
1018 case RESENT:
1019 if (!(msgflags & MDAT)) {
1020 advise (NULLCP, "message has no Date: header");
1021 badmsg++;
1022 }
1023 if (!(msgflags & MFRM)) {
1024 advise (NULLCP, "message has no From: header");
1025 badmsg++;
1026 }
1027 if (whomsw && !fill_up)
1028 break;
1029
1030 #ifdef MMDFI /* sigh */
1031 fprintf (out, "Sender: %s\n", from);
1032 #endif /* MMDFI */
1033
1034 fprintf (out, "Resent-Date: %s\n", dtime (&tclock));
1035 if (msgid)
1036 fprintf (out, "Resent-Message-ID: <%d.%ld@%s>\n",
1037 getpid (), tclock, LocalName ());
1038 if (msgflags & MRFM)
1039 fprintf (out, "Resent-Sender: %s\n", from);
1040 else
1041 fprintf (out, "Resent-From: %s\n", signature);
1042 if (whomsw)
1043 break;
1044 if (!(msgflags & MVIS))
1045 fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
1046 break;
1047 }
1048
1049 if (badmsg)
1050 adios (NULLCP, "re-format message and try again");
1051 if (!recipients)
1052 adios (NULLCP, "no addressees");
1053 }
1054
1055 /* \f */
1056
1057 static int get_header (header, table)
1058 register char *header;
1059 register struct headers *table;
1060 {
1061 register struct headers *h;
1062
1063 for (h = table; h -> value; h++)
1064 if (uleq (header, h -> value))
1065 return (h - table);
1066
1067 return NOTOK;
1068 }
1069
1070 /* \f */
1071
1072 static int putadr (name, aka, mp, out, flags)
1073 register char *name,
1074 *aka;
1075 register struct mailname *mp;
1076 register FILE *out;
1077 unsigned int flags;
1078 {
1079 int len;
1080 register char *cp;
1081 char buffer[BUFSIZ];
1082
1083 if (mp -> m_mbox == NULL || ((flags & HTRY) && !insert (mp)))
1084 return 0;
1085 if (!fill_in && (flags & (HBCC | HDCC)) || mp -> m_ingrp)
1086 return 1;
1087
1088 if (!nameoutput) {
1089 fprintf (out, "%s: ", name);
1090 linepos += (nameoutput = strlen (name) + 2);
1091 }
1092
1093 if (*aka && mp -> m_type != UUCPHOST && !mp -> m_pers)
1094 mp -> m_pers = getcpy (aka);
1095 if (format) {
1096 if (mp -> m_gname && !fill_in)
1097 (void) sprintf (cp = buffer, "%s;", mp -> m_gname);
1098 else
1099 cp = adrformat (mp);
1100 }
1101 else
1102 cp = mp -> m_text;
1103 len = strlen (cp);
1104
1105 if (linepos != nameoutput)
1106 if (len + linepos + 2 > outputlinelen)
1107 fprintf (out, ",\n%*s", linepos = nameoutput, "");
1108 else {
1109 fputs (", ", out);
1110 linepos += 2;
1111 }
1112
1113 fputs (cp, out);
1114 linepos += len;
1115
1116 return (flags & HTRY);
1117 }
1118
1119 /* \f */
1120
1121 static putgrp (name, group, out, flags)
1122 register char *name,
1123 *group;
1124 register FILE *out;
1125 unsigned int flags;
1126 {
1127 int len;
1128 char *cp;
1129
1130 if (!fill_in && (flags & HBCC))
1131 return;
1132
1133 if (!nameoutput) {
1134 fprintf (out, "%s: ", name);
1135 linepos += (nameoutput = strlen (name) + 2);
1136 if (fill_in)
1137 linepos -= strlen (group);
1138 }
1139
1140 cp = fill_in ? group : concat (group, ";", NULLCP);
1141 len = strlen (cp);
1142
1143 if (linepos > nameoutput)
1144 if (len + linepos + 2 > outputlinelen) {
1145 fprintf (out, ",\n%*s", nameoutput, "");
1146 linepos = nameoutput;
1147 }
1148 else {
1149 fputs (", ", out);
1150 linepos += 2;
1151 }
1152
1153 fputs (cp, out);
1154 linepos += len;
1155 }
1156
1157 /* \f */
1158
1159 static int insert (np)
1160 register struct mailname *np;
1161 {
1162 register struct mailname *mp;
1163
1164 if (np -> m_mbox == NULL)
1165 return 0;
1166
1167 for (mp = np -> m_type == LOCALHOST ? &localaddrs
1168 : np -> m_type == UUCPHOST ? &uuaddrs
1169 : &netaddrs;
1170 mp -> m_next;
1171 mp = mp -> m_next)
1172 if (uleq (np -> m_host, mp -> m_next -> m_host)
1173 && uleq (np -> m_mbox, mp -> m_next -> m_mbox)
1174 && np -> m_bcc == mp -> m_next -> m_bcc)
1175 return 0;
1176
1177 mp -> m_next = np;
1178 recipients++;
1179 return 1;
1180 }
1181
1182
1183 static pl () {
1184 register int i;
1185 register struct mailname *mp;
1186
1187 printf ("-------\n\t-- Addresses --\nlocal:\t");
1188 for (mp = localaddrs.m_next; mp; mp = mp -> m_next)
1189 printf ("%s%s%s", mp -> m_mbox,
1190 mp -> m_bcc ? "[BCC]" : "",
1191 mp -> m_next ? ",\n\t" : "");
1192
1193 printf ("\nnet:\t");
1194 for (mp = netaddrs.m_next; mp; mp = mp -> m_next)
1195 printf ("%s%s@%s%s%s", mp -> m_path ? mp -> m_path : "",
1196 mp -> m_mbox, mp -> m_host,
1197 mp -> m_bcc ? "[BCC]" : "",
1198 mp -> m_next ? ",\n\t" : "");
1199
1200 printf ("\nuucp:\t");
1201 for (mp = uuaddrs.m_next; mp; mp = mp -> m_next)
1202 printf ("%s!%s%s", mp -> m_host, mp -> m_mbox,
1203 mp -> m_bcc ? "[BCC]" : "",
1204 mp -> m_next ? ",\n\t" : "");
1205
1206 printf ("\n\t-- Folder Copies --\nfcc:\t");
1207 for (i = 0; i < fccind; i++)
1208 printf ("%s%s", fccfold[i], i + 1 < fccind ? ",\n\t" : "");
1209 printf ("\n");
1210 }
1211
1212 /* \f */
1213
1214 static anno () {
1215 register struct mailname *mp;
1216
1217 for (mp = localaddrs.m_next; mp; mp = mp -> m_next)
1218 if (annoaux (mp) == NOTOK)
1219 goto oops;
1220
1221 for (mp = netaddrs.m_next; mp; mp = mp -> m_next)
1222 if (annoaux (mp) == NOTOK)
1223 goto oops;
1224
1225 for (mp = uuaddrs.m_next; mp; mp = mp -> m_next)
1226 if (annoaux (mp) == NOTOK)
1227 break;
1228
1229 oops: ;
1230 (void) close (pfd);
1231 pfd = NOTOK;
1232 }
1233
1234
1235 static int annoaux (mp)
1236 register struct mailname *mp;
1237 {
1238 int i;
1239 char buffer[BUFSIZ];
1240
1241 (void) sprintf (buffer, "%s\n", adrformat (mp));
1242 i = strlen (buffer);
1243
1244 return (write (pfd, buffer, i) == i ? OK : NOTOK);
1245 }
1246
1247 /* \f */
1248
1249 static insert_fcc (hdr, pp)
1250 register struct headers *hdr;
1251 register char *pp;
1252 {
1253 register char *cp;
1254
1255 for (cp = pp; isspace (*cp); cp++)
1256 continue;
1257 for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
1258 continue;
1259 if (pp >= cp)
1260 *++pp = 0;
1261 if (*cp == 0)
1262 return;
1263
1264 if (fccind >= FCCS)
1265 adios (NULLCP, "too many %ss", hdr -> value);
1266 fccfold[fccind++] = getcpy (cp);
1267 }
1268
1269 /* \f BCC GENERATION */
1270
1271 static make_bcc_file () {
1272 int fd,
1273 i,
1274 child_id;
1275 char *vec[6];
1276 register FILE *out;
1277
1278 (void) strcpy (bccfil, m_tmpfil ("bccs"));
1279 if ((out = fopen (bccfil, "w")) == NULL)
1280 adios (bccfil, "unable to create");
1281 (void) chmod (bccfil, 0600);
1282
1283 fprintf (out, "Date: %s\n", dtime (&tclock));
1284 if (msgid)
1285 fprintf (out, "Message-ID: <%d.%ld.1@%s>\n",
1286 getpid (), tclock, LocalName ());
1287 if (msgflags & MFRM) {
1288 fprintf (out, "From: %s", msgfrom);
1289 fprintf (out, "Sender: %s\n", from);
1290 }
1291 else
1292 fprintf (out, "From: %s\n", signature);
1293 if (subject)
1294 fprintf (out, "Subject: %s", subject);
1295 fprintf (out, "BCC:\n");
1296 #ifdef MIME
1297 if (mime) {
1298 char *cp;
1299
1300 if ((cp = index (prefix, 'a')) == NULL)
1301 adios (NULLCP, "lost prefix start");
1302 while (find_prefix () == NOTOK)
1303 if (*cp < 'z')
1304 (*cp)++;
1305 else
1306 if (*++cp == 0)
1307 adios (NULLCP,
1308 "giving up trying to find a unique delimiter string");
1309 else
1310 (*cp)++;
1311
1312 fprintf (out, "%s: %s\n%s: multipart/digest; boundary=\"",
1313 VRSN_FIELD, VRSN_VALUE, TYPE_FIELD);
1314 fprintf (out, "%s\"\n%s: %s\n\n--%s\n%s: %s\n%s: %s\n\n", prefix,
1315 DESCR_FIELD, "Blind Carbon Copy", prefix,
1316 TYPE_FIELD, "message/rfc822",
1317 DESCR_FIELD, "Original Message");
1318 }
1319 else
1320 #endif /* MIME */
1321 fprintf (out, "\n------- Blind-Carbon-Copy\n\n");
1322 (void) fflush (out);
1323
1324 if (filter == NULL) {
1325 if ((fd = open (tmpfil, 0)) == NOTOK)
1326 adios (tmpfil, "unable to re-open");
1327 #ifdef MIME
1328 if (mime)
1329 cpydata (fd, fileno (out), tmpfil, bccfil);
1330 else
1331 #endif /* MIME */
1332 cpydgst (fd, fileno (out), tmpfil, bccfil);
1333 (void) close (fd);
1334 }
1335 else {
1336 vec[0] = r1bindex (mhlproc, '/');
1337
1338 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
1339 sleep (5);
1340 switch (child_id) {
1341 case NOTOK:
1342 adios ("fork", "unable to");
1343
1344 case OK:
1345 (void) dup2 (fileno (out), 1);
1346
1347 i = 1;
1348 vec[i++] = "-forward";
1349 vec[i++] = "-form";
1350 vec[i++] = filter;
1351 vec[i++] = tmpfil;
1352 vec[i] = NULL;
1353
1354 execvp (mhlproc, vec);
1355 fprintf (stderr, "unable to exec ");
1356 perror (mhlproc);
1357 _exit (-1);
1358
1359 default:
1360 (void) pidXwait (child_id, mhlproc);
1361 break;
1362 }
1363 }
1364
1365 (void) fseek (out, 0L, 2);
1366 #ifdef MIME
1367 if (mime)
1368 fprintf (out, "\n--%s--\n", prefix);
1369 else
1370 #endif /* MIME */
1371 fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
1372 (void) fclose (out);
1373 }
1374
1375 /* \f */
1376
1377 #ifdef MIME
1378 static int find_prefix ()
1379 {
1380 int len,
1381 result;
1382 char buffer[BUFSIZ];
1383 FILE *in;
1384
1385 if ((in = fopen (tmpfil, "r")) == NULL)
1386 adios (tmpfil, "unable to re-open");
1387
1388 len = strlen (prefix);
1389
1390 result = OK;
1391 while (fgets (buffer, sizeof buffer - 1, in))
1392 if (buffer[0] == '-' && buffer[1] == '-') {
1393 register char *cp;
1394
1395 for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
1396 if (!isspace (*cp))
1397 break;
1398 *++cp = NULL;
1399 if (strcmp (buffer + 2, prefix) == 0) {
1400 result = NOTOK;
1401 break;
1402 }
1403 }
1404
1405 (void) fclose (in);
1406
1407 return result;
1408 }
1409 #endif /* MIME */
1410
1411 /* \f ADDRESS VERIFICATION */
1412
1413 static verify_all_addresses (talk)
1414 int talk;
1415 {
1416 #ifndef MHMTS
1417 int retval;
1418 #endif /* not MHMTS */
1419 #ifdef MMDFMTS
1420 #ifdef RP_NS
1421 int len;
1422 struct rp_bufstruct reply;
1423 #endif /* RP_NS */
1424 #endif /* MMDFMTS */
1425 register struct mailname *lp;
1426
1427 #ifndef MHMTS
1428 sigon ();
1429 #endif /* not MHMTS */
1430
1431 #ifdef MMDFMTS
1432 if (!whomsw || checksw) {
1433 if (rp_isbad (retval = mm_init ())
1434 || rp_isbad (retval = mm_sbinit ())
1435 || rp_isbad (retval = mm_winit (NULLCP, submitopts, from)))
1436 die (NULLCP, "problem initializing MMDF system [%s]",
1437 rp_valstr (retval));
1438 #ifdef RP_NS
1439 if (rp_isbad (retval = mm_rrply (&reply, &len)))
1440 die (NULLCP, "problem with sender address [%s]",
1441 rp_valstr (retval));
1442 #endif /* RP_NS */
1443 }
1444 #endif /* MMDFMTS */
1445 #ifdef SENDMTS
1446 if (!whomsw || checksw)
1447 if (rp_isbad (retval = sm_init (clientsw, serversw, 0, 0, snoop, 0, 0))
1448 || rp_isbad (retval = sm_winit (smtpmode, from)))
1449 die (NULLCP, "problem initializing server; %s",
1450 rp_string (retval));
1451 #endif /* SENDMTS */
1452
1453 if (talk && !whomsw)
1454 printf (" -- Address Verification --\n");
1455 #ifndef BERK
1456 if (talk && localaddrs.m_next)
1457 printf (" -- Local Recipients --\n");
1458 #endif /* BERK */
1459 for (lp = localaddrs.m_next; lp; lp = lp -> m_next)
1460 do_an_address (lp, talk, encryptsw);
1461
1462 #ifndef BERK
1463 if (talk && uuaddrs.m_next)
1464 printf (" -- UUCP Recipients --\n");
1465 #endif /* BERK */
1466 for (lp = uuaddrs.m_next; lp; lp = lp -> m_next)
1467 do_an_address (lp, talk, encryptsw);
1468
1469 #ifndef BERK
1470 if (talk && netaddrs.m_next)
1471 printf (" -- Network Recipients --\n");
1472 #endif /* BERK */
1473 for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
1474 do_an_address (lp, talk, encryptsw);
1475
1476 chkadr ();
1477 if (talk && !whomsw)
1478 printf (" -- Address Verification Successful --\n");
1479
1480 #ifdef MMDFMTS
1481 if (!whomsw || checksw)
1482 (void) mm_end (NOTOK);
1483 #endif /* MMDFMTS */
1484 #ifdef SENDMTS
1485 if (!whomsw || checksw)
1486 (void) sm_end (DONE);
1487 #endif /* SENDMTS */
1488 (void) fflush (stdout);
1489
1490 #ifndef MHMTS
1491 sigoff ();
1492 #endif /* not MHMTS */
1493 }
1494
1495 /* \f */
1496
1497 static chkadr () {
1498 #define plural(x) (x == 1 ? "" : "s")
1499
1500 if (badadr && unkadr)
1501 die (NULLCP, "%d address%s unparsable, %d addressee%s undeliverable",
1502 badadr, plural (badadr), unkadr, plural (badadr));
1503 if (badadr)
1504 die (NULLCP, "%d address%s unparsable", badadr, plural (badadr));
1505 if (unkadr)
1506 die (NULLCP, "%d addressee%s undeliverable", unkadr, plural (unkadr));
1507 }
1508
1509 /* \f MTS INTERACTION */
1510
1511 #ifdef TMA
1512 static postplain (file, bccque, talk)
1513 #else /* TMA */
1514 static post (file, bccque, talk)
1515 #endif /* TMA */
1516 register char *file;
1517 int bccque,
1518 talk;
1519 {
1520 int fd,
1521 onex = !(msgflags & MINV) || bccque;
1522 #ifndef MHMTS
1523 int retval;
1524 #ifdef MMDFMTS
1525 #ifdef RP_NS
1526 int len;
1527 struct rp_bufstruct reply;
1528 #endif /* RP_NS */
1529 #endif /* MMDFMTS */
1530 #else /* MHMTS */
1531 int ud;
1532 #endif /* MHMTS */
1533
1534 if (verbose)
1535 if (msgflags & MINV)
1536 printf (" -- Posting for %s Recipients --\n",
1537 bccque ? "Blind" : "Sighted");
1538 else
1539 printf (" -- Posting for All Recipients --\n");
1540
1541 sigon ();
1542
1543 #ifdef MMDFMTS
1544 if (rp_isbad (retval = mm_init ())
1545 || rp_isbad (retval = mm_sbinit ())
1546 || rp_isbad (retval = mm_winit (NULLCP, submitopts, from)))
1547 die (NULLCP, "problem initializing MMDF system [%s]",
1548 rp_valstr (retval));
1549 #ifdef RP_NS
1550 if (rp_isbad (retval = mm_rrply (&reply, &len)))
1551 die (NULLCP, "problem with sender address [%s]",
1552 rp_valstr (retval));
1553 #endif /* RP_NS */
1554 #endif /* MMDFMTS */
1555 #ifdef SENDMTS
1556 if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose, snoop,
1557 onex, queued))
1558 || rp_isbad (retval = sm_winit (smtpmode, from)))
1559 die (NULLCP, "problem initializing server; %s", rp_string (retval));
1560 #endif /* SENDMTS */
1561
1562 #ifndef MHMTS
1563 do_addresses (bccque, talk && verbose);
1564 if ((fd = open (file, 0)) == NOTOK)
1565 die (file, "unable to re-open");
1566 do_text (file, fd);
1567 #else /* MHMTS */
1568 if ((fd = open (file, 0)) == NULL)
1569 adios (file, "unable to re-open");
1570 #ifdef MF
1571 ud = UucpChan () && uuaddrs.m_next ? make_uucp_file (fd) : NOTOK;
1572 #else /* not MF */
1573 ud = NOTOK;
1574 #endif /* not MF */
1575 do_addresses (file, fd, ud, bccque, talk && verbose);
1576 if (ud != NOTOK)
1577 (void) close (ud);
1578 #endif /* MHMTS */
1579 (void) close (fd);
1580 (void) fflush (stdout);
1581
1582 #ifdef MMDFMTS
1583 (void) mm_sbend ();
1584 (void) mm_end (OK);
1585 #endif /* MMDFMTS */
1586 #ifdef SENDMTS
1587 (void) sm_end (onex ? OK : DONE);
1588 #endif /* SENDMTS */
1589
1590 sigoff ();
1591
1592 if (verbose)
1593 if (msgflags & MINV)
1594 printf (" -- %s Recipient Copies Posted --\n",
1595 bccque ? "Blind" : "Sighted");
1596 else
1597 printf (" -- Recipient Copies Posted --\n");
1598 (void) fflush (stdout);
1599 }
1600
1601 /* \f */
1602
1603 #ifdef TMA
1604 static postcipher (file, bccque, talk)
1605 register char *file;
1606 int bccque,
1607 talk;
1608 {
1609 int fdP,
1610 state;
1611 char reason[BUFSIZ];
1612 struct mailname *lp;
1613
1614 if (verbose)
1615 if (msgflags & MINV)
1616 printf (" -- Posting for %s Recipients --\n",
1617 bccque ? "Blind" : "Sighted");
1618 else
1619 printf (" -- Posting for All Recipients --\n");
1620
1621 if ((fdP = open (file, 0)) == NOTOK)
1622 adios (file, "unable to re-open");
1623 if (ciphinit (fdP, reason) == NOTOK)
1624 adios (NULLCP, "%s", reason);
1625 (void) close (fdP);
1626
1627 for (state = 0, lp = localaddrs.m_next; lp; lp = lp -> m_next)
1628 if (lp -> m_bcc ? bccque : !bccque) {
1629 #ifndef BERK
1630 if (talk && !state)
1631 printf (" -- Local Recipients --\n");
1632 #endif /* BERK */
1633 do_a_cipher (lp, talk);
1634 #ifndef BERK
1635 state++;
1636 #endif /* BERK */
1637 }
1638
1639 for (state = 0, lp = uuaddrs.m_next; lp; lp = lp -> m_next)
1640 if (lp -> m_bcc ? bccque : !bccque) {
1641 #ifndef BERK
1642 if (talk && !state)
1643 printf (" -- UUCP Recipients --\n");
1644 #endif /* BERK */
1645 do_a_cipher (lp, talk);
1646 #ifndef BERK
1647 state++;
1648 #endif /* BERK */
1649 }
1650
1651 for (state = 0, lp = netaddrs.m_next; lp; lp = lp -> m_next)
1652 if (lp -> m_bcc ? bccque : !bccque) {
1653 #ifndef BERK
1654 if (talk && !state)
1655 printf (" -- Network Recipients --\n");
1656 #endif /* BERK */
1657 do_a_cipher (lp, talk);
1658 #ifndef BERK
1659 state++;
1660 #endif /* BERK */
1661 }
1662
1663 if (ciphdone (reason) == NOTOK)
1664 admonish (NULLCP, "%s", reason);
1665 #ifdef SENDMTS
1666 if (!(msgflags & MINV) || bccque)
1667 (void) sm_end (OK);
1668 #endif /* SENDMTS */
1669
1670 if (verbose)
1671 if (msgflags & MINV)
1672 printf (" -- %s Recipient Copies Posted --\n",
1673 bccque ? "Blind" : "Sighted");
1674 else
1675 printf (" -- Recipient Copies Posted --\n");
1676 (void) fflush (stdout);
1677 }
1678
1679 /* \f */
1680
1681 static do_a_cipher (lp, talk)
1682 register struct mailname *lp;
1683 int talk;
1684 {
1685 int fd,
1686 retval;
1687 register char *mbox,
1688 *host;
1689 char addr[BUFSIZ],
1690 reason[BUFSIZ];
1691 #ifdef MMDFMTS
1692 #ifdef RP_NS
1693 int len;
1694 struct rp_bufstruct reply;
1695 #endif /* RP_NS */
1696 #endif /* MMDFMTS */
1697
1698 sigon ();
1699
1700 #ifdef MMDFMTS
1701 if (rp_isbad (retval = mm_init ())
1702 || rp_isbad (retval = mm_sbinit ())
1703 || rp_isbad (retval = mm_winit (NULL, submitopts, from)))
1704 die (NULLCP, "problem initializing MMDF system [%s]",
1705 rp_valstr (retval));
1706 #ifdef RP_NS
1707 if (rp_isbad (retval = mm_rrply (&reply, &len)))
1708 die (NULLCP, "problem with sender address [%s]",
1709 rp_valstr (retval));
1710 #endif /* RP_NS */
1711 #endif /* MMDFMTS */
1712 #ifdef SENDMTS
1713 if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose, snoop,
1714 0, 0))
1715 || rp_isbad (retval = sm_winit (smtpmode, from)))
1716 die (NULLCP, "problem initializing server; %s", rp_string (retval));
1717 #endif /* SENDMTS */
1718
1719 do_an_address (lp, talk, 0);
1720
1721 switch (lp -> m_type) {
1722 case LOCALHOST:
1723 mbox = lp -> m_mbox;
1724 host = LocalName ();
1725 (void) strcpy (addr, mbox);
1726 break;
1727
1728 case UUCPHOST:
1729 #ifdef MMDFMTS
1730 mbox = concat (lp -> m_host, "!", lp -> m_mbox, NULLCP);
1731 host = UucpChan ();
1732 #endif /* MMDFMTS */
1733 #ifdef SENDMTS
1734 mbox = auxformat (lp, 0);
1735 host = NULL;
1736 #endif /* SENDMTS */
1737 (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
1738 break;
1739
1740 default:
1741 mbox = lp -> m_mbox;
1742 host = lp -> m_host;
1743 (void) sprintf (addr, "%s at %s", lp -> m_mbox, lp -> m_host);
1744 break;
1745 }
1746 chkadr (); /* XXX */
1747
1748 #ifdef MMDFMTS
1749 if (rp_isbad (retval = mm_waend ()))
1750 die (NULLCP, "problem ending addresses [%s]\n",
1751 rp_valstr (retval));
1752 #endif /* MMDFMTS */
1753 #ifdef SENDMTS
1754 if (rp_isbad (retval = sm_waend ()))
1755 die (NULLCP, "problem ending addresses; %s", rp_string (retval));
1756 #endif /* SENDMTS */
1757
1758 if ((fd = encipher (mbox, host, reason)) == NOTOK)
1759 die (NULLCP, "%s: %s", addr, reason);
1760 do_text ("temporary file", fd);
1761 (void) close (fd);
1762 (void) fflush (stdout);
1763
1764 #ifdef MMDFMTS
1765 (void) mm_sbend ();
1766 (void) mm_end (OK);
1767 #endif /* MMDFMTS */
1768 #ifdef SENDMTS
1769 (void) sm_end (DONE);
1770 #endif /* SENDMTS */
1771
1772 sigoff ();
1773 }
1774 #endif /* TMA */
1775
1776 /* \f */
1777
1778 #ifndef MHMTS
1779 static do_addresses (bccque, talk)
1780 #else /* MHMTS */
1781 static do_addresses (file, fd, ud, bccque, talk)
1782 register char *file;
1783 int fd,
1784 ud;
1785 #endif /* MHMTS */
1786 int bccque,
1787 talk;
1788 {
1789 int retval;
1790 #ifndef BERK
1791 int state;
1792 #endif /* not BERK */
1793 register struct mailname *lp;
1794
1795 #ifndef BERK
1796 state = 0;
1797 #endif /* not BERK */
1798 for (lp = localaddrs.m_next; lp; lp = lp -> m_next)
1799 if (lp -> m_bcc ? bccque : !bccque) {
1800 #ifndef BERK
1801 if (talk && !state)
1802 printf (" -- Local Recipients --\n");
1803 #endif /* not BERK */
1804 #ifndef MHMTS
1805 do_an_address (lp, talk, 0);
1806 #else /* MHMTS */
1807 localmail (lp, talk, fd);
1808 #endif /* MHMTS */
1809 #ifndef BERK
1810 state++;
1811 #endif /* not BERK */
1812 }
1813
1814 #ifndef BERK
1815 state = 0;
1816 #endif /* not BERK */
1817 for (lp = uuaddrs.m_next; lp; lp = lp -> m_next)
1818 if (lp -> m_bcc ? bccque : !bccque) {
1819 #ifndef BERK
1820 if (talk && !state)
1821 printf (" -- UUCP Recipients --\n");
1822 #endif /* not BERK */
1823 #ifndef MHMTS
1824 do_an_address (lp, talk, 0);
1825 #else /* MHMTS */
1826 uucpmail (lp, talk, ud != NOTOK ? ud : fd, ud == NOTOK);
1827 #endif /* MHMTS */
1828 #ifndef BERK
1829 state++;
1830 #endif /* not BERK */
1831 }
1832
1833 #ifndef BERK
1834 state = 0;
1835 #endif /* not BERK */
1836 for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
1837 if (lp -> m_bcc ? bccque : !bccque) {
1838 #ifndef BERK
1839 if (talk && !state)
1840 printf (" -- Network Recipients --\n");
1841 #endif /* not BERK */
1842 #ifndef MHMTS
1843 do_an_address (lp, talk, 0);
1844 #else /* MHMTS */
1845 netmail (talk, fd, bccque);
1846 #endif /* MHMTS */
1847 #ifndef BERK
1848 state++;
1849 #endif /* not BERK */
1850 }
1851
1852 /* \f */
1853
1854 chkadr ();
1855
1856 #ifdef MMDFMTS
1857 if (rp_isbad (retval = mm_waend ()))
1858 die (NULLCP, "problem ending addresses [%s]\n",
1859 rp_valstr (retval));
1860 #endif /* MMDFMTS */
1861 #ifdef SENDMTS
1862 if (rp_isbad (retval = sm_waend ()))
1863 die (NULLCP, "problem ending addresses; %s", rp_string (retval));
1864 #endif /* SENDMTS */
1865 }
1866
1867 /* \f */
1868
1869 #ifndef MHMTS
1870 static do_text (file, fd)
1871 register char *file;
1872 int fd;
1873 {
1874 int retval,
1875 state;
1876 char buf[BUFSIZ];
1877 #ifdef MMDFMTS
1878 struct rp_bufstruct reply;
1879 #endif /* MMDFMTS */
1880
1881 (void) lseek (fd, (off_t)0, 0);
1882 while ((state = read (fd, buf, sizeof buf)) > 0)
1883 #ifdef MMDFMTS
1884 if (rp_isbad (mm_wtxt (buf, state)))
1885 die (NULLCP, "problem writing text [%s]\n", rp_valstr (retval));
1886 #endif /* MMDFMTS */
1887 #ifdef SENDMTS
1888 if (rp_isbad (retval = sm_wtxt (buf, state)))
1889 die (NULLCP, "problem writing text; %s\n", rp_string (retval));
1890 #endif /* SENDMTS */
1891
1892 if (state == NOTOK)
1893 die (file, "problem reading from");
1894
1895 #ifdef MMDFMTS
1896 if (rp_isbad (retval = mm_wtend ()))
1897 die (NULLCP, "problem ending text [%s]\n", rp_valstr (retval));
1898
1899 if (rp_isbad (retval = mm_rrply (&reply, &state)))
1900 die (NULLCP, "problem getting submission status [%s]\n",
1901 rp_valstr (retval));
1902
1903 switch (rp_gval (reply.rp_val)) {
1904 case RP_OK:
1905 case RP_MOK:
1906 break;
1907
1908 case RP_NO:
1909 die (NULLCP, "you lose; %s", reply.rp_line);
1910
1911 case RP_NDEL:
1912 die (NULLCP, "no delivery occurred; %s", reply.rp_line);
1913
1914 case RP_AGN:
1915 die (NULLCP, "try again later; %s", reply.rp_line);
1916
1917 case RP_NOOP:
1918 die (NULLCP, "nothing done; %s", reply.rp_line);
1919
1920 default:
1921 die (NULLCP, "unexpected response;\n\t[%s] -- %s",
1922 rp_valstr (reply.rp_val), reply.rp_line);
1923 }
1924 #endif /* MMDFMTS */
1925 #ifdef SENDMTS
1926 switch (retval = sm_wtend ()) {
1927 case RP_OK:
1928 break;
1929
1930 case RP_NO:
1931 case RP_NDEL:
1932 die (NULLCP, "posting failed; %s", rp_string (retval));
1933
1934 default:
1935 die (NULLCP, "unexpected response; %s", rp_string (retval));
1936 }
1937 #endif /* SENDMTS */
1938 }
1939 #endif /* not MHMTS */
1940
1941 /* \f MTS-SPECIFIC INTERACTION */
1942
1943 #ifdef MMDFMTS
1944
1945 #ifndef TMA
1946 /* ARGSUSED */
1947 #endif /* TMA */
1948
1949 static do_an_address (lp, talk, tma)
1950 register struct mailname *lp;
1951 int talk,
1952 tma;
1953 {
1954 int len,
1955 retval;
1956 register char *mbox,
1957 *host,
1958 *text,
1959 *path;
1960 char addr[BUFSIZ];
1961 #ifdef TMA
1962 char reason[BUFSIZ];
1963 #endif /* TMA */
1964 struct rp_bufstruct reply;
1965
1966 switch (lp -> m_type) {
1967 case LOCALHOST:
1968 mbox = lp -> m_mbox;
1969 host = LocalName ();
1970 (void) strcpy (addr, mbox);
1971 break;
1972
1973 case UUCPHOST:
1974 #ifdef MF
1975 mbox = concat (lp -> m_host, "!", lp -> m_mbox, NULLCP);
1976 host = UucpChan ();
1977 (void) strcpy (addr, mbox);
1978 break;
1979 #else /* MF */
1980 fprintf (talk ? stdout : stderr, " %s!%s: %s\n",
1981 lp -> m_host, lp -> m_mbox, "not supported; UUCP address");
1982 unkadr++;
1983 (void) fflush (stdout);
1984 return;
1985 #endif /* MF */
1986
1987 default: /* let MMDF decide if the host is bad */
1988 mbox = lp -> m_mbox;
1989 host = lp -> m_host;
1990 (void) sprintf (addr, "%s at %s", mbox, host);
1991 break;
1992 }
1993 #ifdef TMA
1994 if ((!whomsw || checksw)
1995 && tma
1996 && seekaddr (mbox, host, reason) == NOTOK) {
1997 fprintf (talk ? stdout : stderr, " %s%s: %s\n",
1998 addr, "[TMA]", reason);
1999 unkadr++;
2000 }
2001 #endif /* TMA */
2002
2003 if (talk)
2004 printf (" %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
2005
2006 if (whomsw && !checksw) {
2007 (void) putchar ('\n');
2008 return;
2009 }
2010 if (talk)
2011 printf (": ");
2012 (void) fflush (stdout);
2013
2014 /* \f */
2015
2016 #ifdef MMDFII
2017 if (lp -> m_path)
2018 path = concat (lp -> m_path, mbox, "@", host, NULLCP);
2019 else
2020 #endif /* MMDFII */
2021 path = NULLCP;
2022 if (rp_isbad (retval = mm_wadr (path ? NULLCP : host, path ? path : mbox))
2023 || rp_isbad (retval = mm_rrply (&reply, &len)))
2024 die (NULLCP, "problem submitting address [%s]", rp_valstr (retval));
2025
2026 switch (rp_gval (reply.rp_val)) {
2027 case RP_AOK:
2028 if (talk)
2029 printf ("address ok\n");
2030 (void) fflush (stdout);
2031 return;
2032
2033 #ifdef RP_DOK
2034 case RP_DOK:
2035 if (talk)
2036 printf ("nameserver timeout - queued for checking\n");
2037 (void) fflush (stdout);
2038 return;
2039 #endif /* RP_DOK */
2040
2041 case RP_NO:
2042 text = "you lose";
2043 break;
2044
2045 #ifdef RP_NS
2046 case RP_NS:
2047 text = "temporary nameserver failure";
2048 break;
2049
2050 #endif /* RP_NS */
2051
2052 case RP_USER:
2053 case RP_NDEL:
2054 text = "not deliverable";
2055 break;
2056
2057 case RP_AGN:
2058 text = "try again later";
2059 break;
2060
2061 case RP_NOOP:
2062 text = "nothing done";
2063 break;
2064
2065 default:
2066 if (!talk)
2067 fprintf (stderr, " %s: ", addr);
2068 text = "unexpected response";
2069 die (NULLCP, "%s;\n [%s] -- %s", text,
2070 rp_valstr (reply.rp_val), reply.rp_line);
2071 }
2072
2073 if (!talk)
2074 fprintf (stderr, " %s: ", addr);
2075 fprintf (talk ? stdout : stderr, "%s;\n %s\n", text, reply.rp_line);
2076 unkadr++;
2077
2078 (void) fflush (stdout);
2079 }
2080 #endif /* MMDFMTS */
2081
2082 /* \f */
2083
2084 #ifdef MHMTS
2085 /* ARGSUSED */
2086
2087 static do_an_address (lp, talk, tma)
2088 register struct mailname *lp;
2089 int talk,
2090 tma;
2091 {
2092 register char *mbox;
2093 char addr[BUFSIZ];
2094
2095 switch (lp -> m_type) {
2096 case LOCALHOST:
2097 (void) strcpy (addr, lp -> m_mbox);
2098 break;
2099
2100 case UUCPHOST:
2101 (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
2102 break;
2103
2104 default:
2105 (void) sprintf (addr, "%s at %s", lp -> m_mbox, lp -> m_host);
2106 break;
2107 }
2108 if (talk)
2109 printf (" %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
2110
2111 if (whomsw && !checksw) {
2112 (void) putchar ('\n');
2113 return;
2114 }
2115 if (talk)
2116 printf (": ");
2117 (void) fflush (stdout);
2118
2119 /* \f */
2120
2121 switch (lp -> m_type) {
2122 case LOCALHOST:
2123 mbox = lp -> m_mbox;
2124 if (*mbox == '~')
2125 mbox++;
2126 if (seek_home (mbox)) {
2127 lp -> m_mbox = mbox;
2128 if (talk)
2129 printf ("address ok\n");
2130 }
2131 else {
2132 if (!talk)
2133 fprintf (stderr, " %s: ", addr);
2134 fprintf (talk ? stdout : stderr,
2135 "not deliverable; unknown user\n");
2136 unkadr++;
2137 }
2138 break;
2139
2140 case UUCPHOST:
2141 if (uucpsite (lp -> m_host) == OK) {
2142 if (talk)
2143 printf ("address ok\n");
2144 }
2145 else {
2146 if (!talk)
2147 fprintf (stderr, " %s: ", addr);
2148 fprintf (talk ? stdout : stderr,
2149 "not deliverable; unknown system\n");
2150 unkadr++;
2151 }
2152 break;
2153
2154 case NETHOST:
2155 if (talk)
2156 printf ("address ok\n");
2157 break;
2158
2159 default:
2160 if (!talk)
2161 fprintf (stderr, " %s: ", addr);
2162 fprintf (talk ? stdout : stderr,
2163 "not deliverable; unknown host\n");
2164 unkadr++;
2165 break;
2166 }
2167
2168 (void) fflush (stdout);
2169 }
2170 #endif /* MHMTS */
2171
2172 /* \f */
2173
2174 #ifdef SENDMTS
2175
2176 #ifndef TMA
2177 /* ARGSUSED */
2178 #endif /* TMA */
2179
2180 static do_an_address (lp, talk, tma)
2181 register struct mailname *lp;
2182 int talk,
2183 tma;
2184 {
2185 int retval;
2186 register char *mbox,
2187 *host;
2188 char addr[BUFSIZ];
2189 #ifdef TMA
2190 char reason[BUFSIZ];
2191 #endif /* TMA */
2192
2193 switch (lp -> m_type) {
2194 case LOCALHOST:
2195 mbox = lp -> m_mbox;
2196 host = lp -> m_host;
2197 (void) strcpy (addr, mbox);
2198 break;
2199
2200 case UUCPHOST:
2201 mbox = auxformat (lp, 0);
2202 host = NULL;
2203 (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
2204 break;
2205
2206 default: /* let SendMail decide if the host is bad */
2207 mbox = lp -> m_mbox;
2208 host = lp -> m_host;
2209 (void) sprintf (addr, "%s at %s", mbox, host);
2210 break;
2211 }
2212
2213 #ifdef TMA
2214 if ((!whomsw || checksw)
2215 && tma
2216 && seekaddr (mbox, host, reason) == NOTOK) {
2217 fprintf (talk ? stdout : stderr, " %s%s: %s\n",
2218 addr, "[TMA]", reason);
2219 unkadr++;
2220 }
2221 #endif /* TMA */
2222
2223 if (talk)
2224 printf (" %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
2225
2226 if (whomsw && !checksw) {
2227 (void) putchar ('\n');
2228 return;
2229 }
2230 if (talk)
2231 printf (": ");
2232 (void) fflush (stdout);
2233
2234 /* \f */
2235
2236 switch (retval = sm_wadr (mbox, host,
2237 lp -> m_type != UUCPHOST ? lp -> m_path : NULLCP)) {
2238 case RP_OK:
2239 if (talk)
2240 printf ("address ok\n");
2241 break;
2242
2243 case RP_NO:
2244 case RP_USER:
2245 if (!talk)
2246 fprintf (stderr, " %s: ", addr);
2247 fprintf (talk ? stdout : stderr, "loses; %s\n",
2248 rp_string (retval));
2249 unkadr++;
2250 break;
2251
2252 default:
2253 if (!talk)
2254 fprintf (stderr, " %s: ", addr);
2255 die (NULLCP, "unexpected response; %s", rp_string (retval));
2256 }
2257
2258 (void) fflush (stdout);
2259 }
2260 #endif /* SENDMTS */
2261
2262 /* \f SIGNAL HANDLING */
2263
2264 #ifndef MHMTS
2265
2266 /* ARGSUSED */
2267
2268 static TYPESIG sigser (i)
2269 int i;
2270 {
2271 #ifndef BSD42
2272 (void) signal (i, SIG_IGN);
2273 #endif /* not BSD42 */
2274 (void) unlink (tmpfil);
2275 if (msgflags & MINV)
2276 (void) unlink (bccfil);
2277 #ifdef MMDFMTS
2278 if (!whomsw || checksw)
2279 (void) mm_end (NOTOK);
2280 #endif /* MMDFMTS */
2281 #ifdef SENDMTS
2282 if (!whomsw || checksw)
2283 (void) sm_end (NOTOK);
2284 #endif /* SENDMTS */
2285 done (1);
2286 }
2287 #endif /* not MHMTS */
2288
2289
2290 static sigon () {
2291 if (debug)
2292 return;
2293
2294 #ifndef MHMTS
2295 setsigx (hstat, SIGHUP, sigser);
2296 setsigx (istat, SIGINT, sigser);
2297 setsigx (qstat, SIGQUIT, sigser);
2298 setsigx (tstat, SIGTERM, sigser);
2299 #else /* MHMTS */
2300 setsigx (hstat, SIGHUP, SIG_IGN);
2301 setsigx (istat, SIGINT, SIG_IGN);
2302 setsigx (qstat, SIGQUIT, SIG_IGN);
2303 setsigx (tstat, SIGTERM, SIG_IGN);
2304 #endif /* MHMTS */
2305 }
2306
2307
2308 static sigoff () {
2309 if (debug)
2310 return;
2311
2312 (void) signal (SIGHUP, hstat);
2313 (void) signal (SIGINT, istat);
2314 (void) signal (SIGQUIT, qstat);
2315 (void) signal (SIGTERM, tstat);
2316 }
2317
2318 /* \f FCC INTERACTION */
2319
2320 static p_refile (file)
2321 register char *file;
2322 {
2323 register int i;
2324
2325 if (fccind == 0)
2326 return;
2327
2328 #ifdef MHMTS
2329 (void) setuid (myuid);
2330 #endif /* MHMTS */
2331 if (verbose)
2332 printf (" -- Filing Folder Copies --\n");
2333 for (i = 0; i < fccind; i++)
2334 fcc (file, fccfold[i]);
2335 if (verbose)
2336 printf (" -- Folder Copies Filed --\n");
2337 }
2338
2339
2340 static fcc (file, folder)
2341 register char *file,
2342 *folder;
2343 {
2344 int i,
2345 child_id,
2346 status;
2347 char fold[BUFSIZ];
2348
2349 if (verbose)
2350 printf (" %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder);
2351 (void) fflush (stdout);
2352
2353 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
2354 sleep (5);
2355 switch (child_id) {
2356 case NOTOK:
2357 if (!verbose)
2358 fprintf (stderr, " %sFcc %s: ",
2359 msgstate == RESENT ? "Resent-" : "", folder);
2360 fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
2361 break;
2362
2363 case OK:
2364 (void) sprintf (fold, "%s%s",
2365 *folder == '+' || *folder == '@' ? "" : "+", folder);
2366 execlp (fileproc, r1bindex (fileproc, '/'),
2367 "-link", "-file", file, fold, NULLCP);
2368 _exit (-1);
2369
2370 default:
2371 if (status = pidwait (child_id, OK)) {
2372 if (!verbose)
2373 fprintf (stderr, " %sFcc %s: ",
2374 msgstate == RESENT ? "Resent-" : "", folder);
2375 (void) pidstatus (status, verbose ? stdout : stderr, NULLCP);
2376 }
2377 else
2378 if (verbose)
2379 printf ("folder ok\n");
2380 }
2381
2382 (void) fflush (stdout);
2383 }
2384
2385 /* \f RECORD RECIPIENTS */
2386
2387 static p_record ()
2388 {
2389 int i,
2390 child_id,
2391 status;
2392 char recfile[BUFSIZ];
2393 register struct mailname *ap,
2394 **app;
2395 struct mailname *addrs[3];
2396 register FILE *out;
2397
2398 if (!record || (msgflags & (MFRM | MRFM | MRPY)))
2399 return;
2400
2401 addrs[0] = &localaddrs;
2402 addrs[1] = &netaddrs;
2403 addrs[2] = NULL;
2404 if (verbose) {
2405 printf ("recording recipients... ");
2406 fflush (stdout);
2407 }
2408
2409 (void) strcpy (recfile, m_tmpfil ("record"));
2410 if ((out = fopen (recfile, "w")) == NULL) {
2411 fprintf (verbose ? stdout : stderr, "unable to create temporary file");
2412 if (!verbose)
2413 fprintf (stderr, ", so can't record recipients");
2414 fprintf (verbose ? stdout : stderr, "\n");
2415 return;
2416 }
2417 (void) chmod (recfile, 0600);
2418
2419 for (app = addrs; ap = *app; app++) {
2420 register struct mailname *mp;
2421
2422 for (mp = ap -> m_next; mp; mp = mp -> m_next)
2423 fprintf (out, "%s\n", adrformat (mp));
2424 }
2425
2426 (void) fclose (out);
2427
2428 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
2429 sleep (5);
2430 switch (child_id) {
2431 case NOTOK:
2432 fprintf (verbose ? stdout : stderr, "unable to fork");
2433 if (!verbose)
2434 fprintf (stderr, ", so can't record recipients");
2435 fprintf (verbose ? stdout : stderr, "\n");
2436 break;
2437
2438 case OK:
2439 execlp (record, r1bindex (record, '/'), recfile, NULLCP);
2440 _exit (-1);
2441
2442 default:
2443 if (status = pidwait (child_id, OK)) {
2444 if (!verbose)
2445 fprintf (stderr, "problem with %s: ", recfile);
2446 (void) pidstatus (status, verbose ? stdout : stderr, NULLCP);
2447 }
2448 else
2449 if (verbose)
2450 printf ("done\n");
2451 }
2452
2453 (void) unlink (recfile);
2454 }
2455
2456 /* \f TERMINATION */
2457
2458 /* VARARGS2 */
2459
2460 static die (what, fmt, a, b, c, d)
2461 char *what,
2462 *fmt,
2463 *a,
2464 *b,
2465 *c,
2466 *d;
2467 {
2468 #ifndef MHMTS
2469 (void) unlink (tmpfil);
2470 if (msgflags & MINV)
2471 (void) unlink (bccfil);
2472 #endif /* MHMTS */
2473 #ifdef MMDFMTS
2474 if (!whomsw || checksw)
2475 (void) mm_end (NOTOK);
2476 #endif /* MMDFMTS */
2477 #ifdef SENDMTS
2478 if (!whomsw || checksw)
2479 (void) sm_end (NOTOK);
2480 #endif /* SENDMTS */
2481
2482 adios (what, fmt, a, b, c, d);
2483 }
2484
2485
2486 #ifdef MMDFMTS
2487 /*
2488 * err_abrt() is used by the mm_ routines
2489 * do not, under *ANY* circumstances, remove it from post,
2490 * or you will lose *BIG*
2491 */
2492
2493 err_abrt (code, fmt, a, b, c)
2494 int code;
2495 char *fmt,
2496 *a,
2497 *b,
2498 *c;
2499 {
2500 char buffer[BUFSIZ];
2501
2502 (void) sprintf (buffer, "[%s]", rp_valstr (code));
2503
2504 adios (buffer, fmt, a, b, c);
2505 }
2506 #endif /* MMDFMTS */
2507
2508 /* \f STAND-ALONE DELIVERY */
2509
2510 #ifdef MHMTS
2511
2512 /* BUG: MHMTS ignores 822-style route addresses... */
2513
2514 static localmail (lp, talk, fd)
2515 register struct mailname *lp;
2516 int talk,
2517 fd;
2518 {
2519 int md;
2520 char mailbox[BUFSIZ],
2521 ddate[BUFSIZ];
2522 register struct home *hp;
2523
2524 if (talk)
2525 printf (" %s: ", lp -> m_mbox);
2526 (void) fflush (stdout);
2527
2528 if ((hp = seek_home (lp -> m_mbox)) == NULL) {
2529 if (!talk)
2530 fprintf (stderr, " %s: ", lp -> m_mbox);
2531 fprintf (talk ? stdout : stderr,
2532 "not deliverable; unknown address\n");
2533 unkadr++;
2534 return;
2535 }
2536
2537 (void) sprintf (mailbox, "%s/%s",
2538 mmdfldir[0] ? mmdfldir : hp -> h_home,
2539 mmdflfil[0] ? mmdflfil : hp -> h_name);
2540
2541 /* \f */
2542
2543 switch (access (slocalproc, 01)) {
2544 default:
2545 if (talk)
2546 printf ("(invoking hook)\n\t");
2547 (void) fflush (stdout);
2548
2549 if (usr_hook (lp, talk, fd, hp, mailbox) != NOTOK)
2550 return;
2551 if (talk)
2552 printf (" %s: ", lp -> m_mbox);
2553 (void) fflush (stdout);
2554
2555 case NOTOK:
2556 (void) lseek (fd, (off_t)0, 0);
2557 if ((md = mbx_open (mailbox, hp -> h_uid, hp -> h_gid, m_gmprot ()))
2558 == NOTOK) {
2559 if (!talk)
2560 fprintf (stderr, " %s: ", lp -> m_mbox);
2561 fprintf (talk ? stdout : stderr,
2562 "error in transmission; unable to open maildrop\n");
2563 unkadr++;
2564 return;
2565 }
2566 (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ());
2567 if (mbx_copy (mailbox, md, fd, 0, ddate, 0) == NOTOK) {
2568 if (!talk)
2569 fprintf (stderr, " %s: ", lp -> m_mbox);
2570 fprintf (talk ? stdout : stderr,
2571 "error in transmission; write to maildrop failed\n");
2572 unkadr++;
2573 (void) close (md);
2574 return;
2575 }
2576 mbx_close (mailbox, md);
2577
2578 if (talk)
2579 printf ("sent\n");
2580 break;
2581 }
2582
2583 (void) fflush (stdout);
2584 }
2585
2586 /* \f */
2587
2588 static int usr_hook (lp, talk, fd, hp, mailbox)
2589 register struct mailname *lp;
2590 int talk,
2591 fd;
2592 register struct home *hp;
2593 register char *mailbox;
2594 {
2595 int i,
2596 child_id,
2597 status;
2598 char tmpfil[BUFSIZ];
2599
2600 if ((fd = copyfile (fd, tmpfil)) == NOTOK) {
2601 if (!talk)
2602 fprintf (stderr, " %s: ", lp -> m_mbox);
2603 fprintf (talk ? stdout : stderr,
2604 "unable to copy message; skipping hook\n");
2605 return NOTOK;
2606 }
2607 (void) chown (tmpfil, hp -> h_uid, hp -> h_gid);
2608
2609 (void) fflush (stdout);
2610
2611 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
2612 sleep (5);
2613 switch (child_id) {
2614 case NOTOK:
2615 if (!talk)
2616 fprintf (stderr, " %s: ", lp -> m_mbox);
2617 fprintf (talk ? stdout : stderr,
2618 "unable to invoke hook; fork() failed\n");
2619 return NOTOK;
2620
2621 case OK:
2622 if (fd != 0)
2623 (void) dup2 (fd, 0);
2624 (void) freopen ("/dev/null", "w", stdout);
2625 (void) freopen ("/dev/null", "w", stderr);
2626 if (fd != 3) /* backwards compatible... */
2627 (void) dup2 (fd, 3);
2628 closefds (4);
2629 #ifdef TIOCNOTTY
2630 if ((fd = open ("/dev/tty", 2)) != NOTOK) {
2631 (void) ioctl (fd, TIOCNOTTY, NULLCP);
2632 (void) close (fd);
2633 }
2634 #endif /* TIOCNOTTY */
2635 #ifdef BSD42
2636 (void) setpgrp (0, getpid ());
2637 #endif /* BSD42 */
2638
2639 *environ = NULL;
2640 (void) m_putenv ("USER", hp -> h_name);
2641 (void) m_putenv ("HOME", hp -> h_home);
2642 (void) m_putenv ("SHELL", hp -> h_shell);
2643 if (chdir (hp -> h_home) == NOTOK)
2644 (void) chdir ("/");
2645 (void) umask (0077);
2646 #ifdef BSD41A
2647 (void) inigrp (hp -> h_name, hp -> h_gid);
2648 #endif /* BSD41A */
2649 (void) setgid (hp -> h_gid);
2650 #ifdef BSD42
2651 (void) initgroups (hp -> h_name, hp -> h_gid);
2652 #endif /* BSD42 */
2653 (void) setuid (hp -> h_uid);
2654
2655 execlp (slocalproc, r1bindex (slocalproc, '/'),
2656 "-file", tmpfil, "-mailbox", mailbox,
2657 "-home", hp -> h_home, "-addr", lp -> m_aka,
2658 "-user", hp -> h_name, "-sender", from,
2659 talk ? "-verbose" : NULLCP, NULLCP);
2660 _exit (-1);
2661
2662 /* \f */
2663
2664 default:
2665 (void) close (fd);
2666
2667 status = pidwait (child_id, OK);
2668
2669 (void) unlink (tmpfil);
2670 if (status == 0) {
2671 if (talk)
2672 printf ("accepted\n");
2673 return OK;
2674 }
2675 if (!talk)
2676 fprintf (stderr, " %s: ", lp -> m_mbox);
2677 fprintf (talk ? stdout : stderr,
2678 "%s error on hook; status=0%o\n",
2679 status & 0x00ff ? "system" : "user",
2680 status & 0x00ff ? status & 0xff
2681 : (status & 0xff00) >> 8);
2682 return NOTOK;
2683 }
2684 }
2685
2686 /* \f */
2687
2688 static int copyfile (qd, tmpfil)
2689 int qd;
2690 register char *tmpfil;
2691 {
2692 int i,
2693 fd;
2694 char buffer[BUFSIZ];
2695
2696 (void) strcpy (tmpfil, m_tmpfil ("hook"));
2697 if ((fd = creat (tmpfil, 0600)) == NOTOK)
2698 return NOTOK;
2699 (void) close (fd);
2700 if ((fd = open (tmpfil, 2)) == NOTOK)
2701 return NOTOK;
2702
2703 (void) lseek (qd, (off_t)0, 0);
2704 while ((i = read (qd, buffer, sizeof buffer)) > 0)
2705 if (write (fd, buffer, i) != i) {
2706 (void) close (fd);
2707 return NOTOK;
2708 }
2709 if (i == NOTOK) {
2710 (void) close (fd);
2711 return NOTOK;
2712 }
2713
2714 (void) lseek (fd, (off_t)0, 0);
2715
2716 return fd;
2717 }
2718
2719 /* \f */
2720
2721 static uucpmail (lp, talk, fd, from)
2722 register struct mailname *lp;
2723 int talk,
2724 fd,
2725 from;
2726 {
2727 int i;
2728 TYPESIG (*pstat) ();
2729 char addr[BUFSIZ],
2730 buffer[BUFSIZ];
2731 register FILE *fp;
2732
2733 (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
2734 if (talk)
2735 printf (" %s: ", addr);
2736 (void) fflush (stdout);
2737
2738 #ifndef UCI
2739 (void) sprintf (buffer, "uux -r -p %s!rmail \\(%s\\)",
2740 lp -> m_host, lp -> m_mbox);
2741 #else /* UCI */
2742 (void) sprintf (buffer, "uux -p %s!rmail \\(%s\\)", lp -> m_host,
2743 lp -> m_mbox);
2744 #endif /* UCI */
2745 if ((fp = popen (buffer, "w")) == NULL) {
2746 if (!talk)
2747 fprintf (stderr, " %s: ", addr);
2748 fprintf (talk ? stdout : stderr,
2749 "unable to start uux; popen() failed\n");
2750 unkadr++;
2751 return;
2752 }
2753
2754 pstat = signal (SIGPIPE, SIG_IGN);
2755 if (from) { /* no mail filtering, so... */
2756 (void) sprintf (buffer, "From %s %.24s remote from %s\n",
2757 getusr (), ctime (&tclock), SystemName ());
2758 i = strlen (buffer);
2759 if (fwrite (buffer, sizeof *buffer, i, fp) != i)
2760 goto oops;
2761 }
2762
2763 (void) lseek (fd, (off_t)0, 0);
2764 while ((i = read (fd, buffer, sizeof buffer)) > 0)
2765 if (fwrite (buffer, sizeof *buffer, i, fp) != i) {
2766 oops: ;
2767 if (!talk)
2768 fprintf (stderr, " %s: ", addr);
2769 fprintf (talk ? stdout : stderr,
2770 "error in transmission; write to uux failed\n");
2771 unkadr++;
2772 (void) pclose (fp);
2773 return;
2774 }
2775 if (pclose (fp))
2776 goto oops;
2777 (void) signal (SIGPIPE, pstat);
2778
2779 if (i < 0) {
2780 if (!talk)
2781 fprintf (stderr, " %s: ", addr);
2782 fprintf (talk ? stdout : stderr,
2783 "error in transmission; read failed\n");
2784 unkadr++;
2785 return;
2786 }
2787
2788 if (talk)
2789 printf ("queued (via uux)\n");
2790 (void) fflush (stdout);
2791 }
2792
2793 /* \f */
2794
2795 #ifdef MF
2796 static int make_uucp_file (td)
2797 int td;
2798 {
2799 int i,
2800 qd,
2801 fd;
2802 char tmpfil[BUFSIZ];
2803
2804 (void) lseek (td, (off_t)0, 0);
2805 if ((qd = dup (td)) == NOTOK)
2806 adios ("fd", "unable to dup");
2807
2808 (void) strcpy (tmpfil, m_tmpfil ("uumf"));
2809 if ((fd = creat (tmpfil, 0600)) == NOTOK)
2810 adios (tmpfil, "unable to create");
2811 (void) close (fd);
2812 if ((fd = open (tmpfil, 2)) == NOTOK)
2813 adios (tmpfil, "unable to re-open");
2814
2815 switch (i = mmdf2uucp (qd, fd, 1)) {
2816 case OK:
2817 if (!debug)
2818 (void) unlink (tmpfil);
2819 break;
2820
2821 default:
2822 adios (NULLCP, "unable to filter mail(%d), examine %s", i, tmpfil);
2823 }
2824 (void) close (qd);
2825
2826 return fd;
2827 }
2828 #endif /* MF */
2829
2830 /* \f */
2831
2832 static netmail (talk, fd, bccque)
2833 int talk,
2834 fd,
2835 bccque;
2836 {
2837 int i,
2838 naddrs;
2839 char buffer[BUFSIZ];
2840 register struct mailname *lp;
2841
2842 naddrs = 0;
2843 if (nm_init (getusr (), &tclock) == NOTOK) {
2844 for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
2845 if (lp -> m_bcc ? bccque : !bccque)
2846 fprintf (stderr, " %s at %s: unable to get queue file\n",
2847 lp -> m_mbox, lp -> m_host);
2848 return;
2849 }
2850
2851 for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
2852 if (lp -> m_bcc ? bccque : !bccque) {
2853 (void) nm_wadr (lp -> m_mbox, lp -> m_host);
2854 naddrs++;
2855 if (talk)
2856 printf (" %s at %s: queued\n", lp -> m_mbox, lp -> m_host);
2857 (void) fflush (stdout);
2858 }
2859 nm_waend ();
2860
2861 (void) lseek (fd, (off_t)0, 0);
2862 while ((i = read (fd, buffer, sizeof buffer)) > 0)
2863 if (nm_wtxt (buffer, i) == NOTOK) {
2864 fprintf (stderr,
2865 "error in transmission; write to temporary failed");
2866 unkadr += naddrs;
2867 return;
2868 }
2869
2870 if (i < 0) {
2871 fprintf (stderr, "error in transmission; read failed\n");
2872 unkadr += naddrs;
2873 return;
2874 }
2875
2876 if (nm_wtend () == NOTOK) {
2877 fprintf (stderr, "error in transmission; unable to queue message\n");
2878 unkadr += naddrs;
2879 return;
2880 }
2881 }
2882 #endif /* MHMTS */