9 date 92.12.15.00.20.22; author jromine; state Exp;
14 date 92.11.04.01.04.35; author jromine; state Exp;
19 date 92.01.31.22.28.25; author jromine; state Exp;
24 date 90.04.05.15.02.47; author sources; state Exp;
29 date 90.03.27.19.15.37; author sources; state Exp;
34 date 90.02.09.10.59.36; author sources; state Exp;
39 date 90.02.06.13.33.24; author sources; state Exp;
44 date 90.02.06.13.32.41; author sources; state Exp;
59 static char sccsid[] = "@@(#)spost.c 1.6 (Berkeley) 11/2/85";
62 static char ident[] = "@@(#)$Id: spost.c,v 1.7 1992/11/04 01:04:35 jromine Exp jromine $";
65 /* spost.c - feed messages to sendmail */
67 * (This is a simpler, faster, replacement for "post" for use when "sendmail"
68 * is the transport system)
75 #include "../h/addrsbr.h"
76 #include "../h/aliasbr.h"
77 #include "../h/dropsbr.h"
78 #include "../zotnet/tws.h"
83 extern char *getfullname (), *getusr ();
84 extern char *sendmail;
87 #define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : c)
89 #define MAX_SM_FIELD 1476 /* < largest hdr field sendmail will accept */
90 #define FCCS 10 /* max number of fccs allowed */
94 struct swit switches[] = {
96 "filter filterfile", 0,
127 "dist", -4, /* interface from dist */
135 "check", -5, /* interface from whom */
137 "nocheck", -7, /* interface from whom */
139 "whom", -4, /* interface from whom */
141 #define PUSHSW 18 /* fork to sendmail then exit */
143 #define NPUSHSW 19 /* exec sendmail */
147 "alias aliasfile", 0,
155 "library directory", -7,
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 /* mung 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 */
182 #define MFRM 0x0001 /* we've seen a From: */
183 #define MDAT 0x0002 /* we've seen a Date: */
184 #define MRFM 0x0004 /* we've seen a Resent-From: */
185 #define MVIS 0x0008 /* we've seen sighted addrs */
186 #define MINV 0x0010 /* we've seen blind addrs */
187 #define MRDT 0x0020 /* we've seen a Resent-Date: */
192 static struct headers NHeaders[] = {
193 "Return-Path", HBAD, 0,
195 "Reply-To", HADR | HNGR, 0,
196 "From", HADR | HNGR, MFRM,
197 "Sender", HADR | HBAD, 0,
200 "To", HADR | HTRY, MVIS,
201 "cc", HADR | HTRY, MVIS,
202 "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
203 "Message-Id", HBAD, 0,
209 static struct headers RHeaders[] = {
210 "Resent-Reply-To", HADR | HNGR, 0,
211 "Resent-From", HADR | HNGR, MRFM,
212 "Resent-Sender", HADR | HBAD, 0,
213 "Resent-Date", HNOP, MRDT,
214 "Resent-Subject", HSUB, 0,
215 "Resent-To", HADR | HTRY, MVIS,
216 "Resent-cc", HADR | HTRY, MVIS,
217 "Resent-Bcc", HADR | HTRY | HBCC, MINV,
218 "Resent-Message-Id", HBAD, 0,
219 "Resent-Fcc", HFCC, 0,
229 static short fccind = 0; /* index into fccfold[] */
231 static int badmsg = 0; /* message has bad semantics */
232 static int verbose = 0; /* spell it out */
233 static int debug = 0; /* debugging post */
234 static int rmflg = 1; /* remove temporary file when done */
235 static int watch = 0; /* watch the delivery process */
236 static int backflg = 0; /* rename input file as *.bak when done */
237 static int whomflg = 0; /* if just checking addresses */
238 static int pushflg = 0; /* if going to fork to sendmail */
239 static int aliasflg = -1; /* if going to process aliases */
240 static int outputlinelen=72;
242 static unsigned msgflags = 0; /* what we've seen */
248 static char tmpfil[] = "/tmp/pstXXXXXX";
250 static char from[BUFSIZ]; /* my network address */
251 static char signature[BUFSIZ]; /* my signature */
252 static char *filter = NULL; /* the filter for BCC'ing */
253 static char *subject = NULL; /* the subject field for BCC'ing */
254 static char *fccfold[FCCS]; /* foldernames for FCC'ing */
256 static struct headers *hdrtab; /* table for the message we're doing */
257 static FILE *out; /* output (temp) file */
259 static putfmt(), start_headers(), finish_headers(), putadr(),
261 static file(), fcc();
262 static int get_header(), putone();
285 setlocale(LC_ALL, "");
287 invo_name = r1bindex (argv[0], '/');
288 mts_init (invo_name);
289 if ((cp = m_find (invo_name)) != NULL) {
290 argp = copyip (brkstring (cp, " ", "\n"), arguments);
291 (void) copyip (argv+1, argp);
297 while (cp = *argp++) {
299 switch (smatch (++cp, switches)) {
301 ambigsw (cp, switches);
304 adios (NULLCP, "-%s unknown", cp);
306 (void)sprintf (buf, "%s [switches] file", invo_name);
307 help (buf, switches);
323 if (!(filter = *argp++) || *filter == '-')
324 adios (NULLCP, "missing argument to %s", argp[-2]);
366 if (!(cp = *argp++) || *cp == '-')
367 adios (NULLCP, "missing argument to %s", argp[-2]);
369 (void) alias (AliasFile);/* load default aka's */
371 if ((state = alias(cp)) != AK_OK)
372 adios (NULLCP, "aliasing error in file %s - %s",
373 cp, akerror(state) );
380 if (!(cp = *argp++) || *cp == '-')
381 adios (NULLCP, "missing argument to %s", argp[-2]);
382 outputlinelen = atoi (cp);
383 if (outputlinelen <= 10)
389 /* -library & -idanno switch ignored */
390 if (!(cp = *argp++) || *cp == '-')
391 adios (NULLCP, "missing argument to %s", argp[-2]);
395 adios (NULLCP, "only one message at a time!");
403 (void) alias (AliasFile); /* load default aka's */
406 adios (NULLCP, "usage: %s [switches] file", invo_name);
408 if ((in = fopen (msg, "r")) == NULL)
409 adios (msg, "unable to open");
417 (void)mktemp (tmpfil);
418 if ((out = fopen (tmpfil, "w")) == NULL)
419 adios (tmpfil, "unable to create");
420 (void)chmod (tmpfil, 0600);
423 hdrtab = (msgstate == normal) ? NHeaders : RHeaders;
425 for (compnum = 1, state = FLD;;) {
426 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
429 putfmt (name, buf, out);
435 while (state == FLDPLUS) {
436 state = m_getfld (state, name, buf, sizeof buf, in);
439 putfmt (name, cp, out);
444 finish_headers (out);
445 fprintf (out, "\n%s", buf);
447 while (state == BODY) {
448 state = m_getfld (state, name, buf, sizeof buf, in);
454 finish_headers (out);
459 adios (NULLCP, "message format error in component #%d",
463 adios (NULLCP, "getfld() returned %d", state);
471 if (backflg && !whomflg) {
472 (void) strcpy (buf, m_backup (msg));
473 if (rename (msg, buf) == NOTOK)
474 advise (buf, "unable to rename %s to", msg);
486 * re-open the temp file, unlink it and exec sendmail, giving it
487 * the msg temp file as std in.
489 if ( freopen( tmpfil, "r", stdin) == NULL)
490 adios (tmpfil, "can't reopen for sendmail");
492 (void)unlink (tmpfil);
495 *argp++ = "send-mail";
496 *argp++ = "-m"; /* send to me too */
497 *argp++ = "-t"; /* read msg for recipients */
498 *argp++ = "-i"; /* don't stop on "." */
501 if (watch || verbose)
505 if (pushflg && !(watch || verbose)) {
506 /* fork to a child to run sendmail */
507 for (i=0; (pid = vfork()) == NOTOK && i < 5; i++)
511 fprintf (verbose ? stdout : stderr, "%s: can't fork to %s\n",
512 invo_name, sendmail);
515 /* we're the child .. */
521 execv ( sendmail, sargv);
522 adios ( sendmail, "can't exec");
525 /*
\f DRAFT GENERATION */
527 static putfmt (name, str, out)
544 while (*str == ' ' || *str == '\t')
547 if ((i = get_header (name, hdrtab)) == NOTOK) {
548 fprintf (out, "%s: %s", name, str);
553 if (hdr -> flags & HIGN)
555 if (hdr -> flags & HBAD) {
556 advise (NULLCP, "illegal header line -- %s:", name);
560 msgflags |= hdr -> set;
562 if (hdr -> flags & HSUB)
563 subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
565 if (hdr -> flags & HFCC) {
566 if (cp = rindex (str, '\n'))
568 for (cp = pp = str; cp = index (pp, ','); pp = cp) {
570 insert_fcc (hdr, pp);
572 insert_fcc (hdr, pp);
577 if (hdr -> flags & HBCC) {
583 if (*str != '\n' && *str != '\0')
584 if (aliasflg && hdr->flags & HTRY) {
585 /* this header contains address(es) that we have to do
586 * alias expansion on. Because of the saved state in
587 * getname we have to put all the addresses into a list.
588 * We then let putadr munch on that list, possibly
591 register struct mailname *f = 0;
592 register struct mailname *mp = 0;
594 while (cp = getname( str ) ) {
595 mp = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
600 mp->m_next = f->m_next;
605 f = mp->m_next; mp->m_next = 0;
608 fprintf (out, "%s: %s", name, str );
620 (void)strcpy( from, getusr() );
622 if ((cp = getfullname ()) && *cp) {
623 (void)strcpy (sigbuf, cp);
624 (void)sprintf (signature, "%s <%s>", sigbuf, from);
627 (void)sprintf (signature, "%s", from);
638 if (!(msgflags & MDAT))
639 fprintf (out, "Date: %s\n", dtimenow ());
641 fprintf (out, "Sender: %s\n", from);
643 fprintf (out, "From: %s\n", signature);
645 if (!(msgflags & MVIS))
646 fprintf (out, "Bcc: Blind Distribution List: ;\n");
651 if (!(msgflags & MRDT))
652 fprintf (out, "Resent-Date: %s\n", dtimenow());
654 fprintf (out, "Resent-Sender: %s\n", from);
656 fprintf (out, "Resent-From: %s\n", signature);
658 if (!(msgflags & MVIS))
659 fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
665 adios (NULLCP, "re-format message and try again");
671 get_header (header, table)
673 struct headers *table;
677 for (h = table; h -> value; h++)
678 if (uleq (header, h -> value))
686 /* output the address list for header "name". The address list
687 * is a linked list of mailname structs. "nl" points to the head
688 * of the list. Alias substitution should be done on nl.
690 static putadr (name, nl)
694 register struct mailname *mp, *mp2;
695 register int linepos;
699 fprintf (out, "%s: ", name);
700 namelen = strlen(name) + 2;
703 for (mp = nl; mp; ) {
704 if (linepos > MAX_SM_FIELD) {
705 fprintf (out, "\n%s: ", name);
709 /* a local name - see if it's an alias */
710 cp = akvalue(mp->m_mbox);
711 if (cp == mp->m_mbox)
712 /* wasn't an alias - use what the user typed */
713 linepos = putone( mp->m_text, linepos, namelen );
715 /* an alias - expand it */
716 while (cp = getname(cp) ) {
717 if (linepos > MAX_SM_FIELD) {
718 fprintf (out, "\n%s: ", name);
721 mp2 = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
723 mp2->m_pers = getcpy(mp->m_mbox);
724 linepos = putone( adrformat(mp2), linepos, namelen );
726 linepos = putone( mp2->m_text, linepos, namelen );
731 /* not a local name - use what the user typed */
732 linepos = putone( mp->m_text, linepos, namelen );
741 static int putone ( adr, pos, indent )
752 else if ( linepos+len > outputlinelen ) {
753 fprintf ( out, ",\n%*s", indent, "");
770 static insert_fcc (hdr, pp)
776 for (cp = pp; isspace (*cp); cp++)
778 for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
786 adios (NULLCP, "too many %ss", hdr -> value);
787 fccfold[fccind++] = getcpy (cp);
791 /*
\f BCC GENERATION */
793 static make_bcc_file () {
801 (void)mktemp (bccfil);
802 if ((out = fopen (bccfil, "w")) == NULL)
803 adios (bccfil, "unable to create");
804 (void)chmod (bccfil, 0600);
806 fprintf (out, "Date: %s\n", dtimenow ());
807 fprintf (out, "From: %s\n", signature);
809 fprintf (out, "Subject: %s", subject);
810 fprintf (out, "BCC:\n\n------- Blind-Carbon-Copy\n\n");
813 if (filter == NULL) {
814 if ((fd = open (tmpfil, 0)) == NOTOK)
815 adios (NULLCP, "unable to re-open");
816 cpydgst (fd, fileno (out), tmpfil, bccfil);
820 vec[0] = r1bindex (mhlproc, '/');
822 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
826 adios ("vfork", "unable to");
829 dup2 (fileno (out), 1);
832 vec[i++] = "-forward";
838 execvp (mhlproc, vec);
839 adios (mhlproc, "unable to exec");
842 if (status = pidwait (child_id, OK))
843 admonish (NULL, "%s lost (status=0%o)", vec[0], status);
849 fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
854 /*
\f FCC INTERACTION */
864 for (i = 0; i < fccind; i++)
866 printf ("Fcc: %s\n", fccfold[i]);
868 fcc (path, fccfold[i]);
872 static fcc (file, folder)
882 printf ("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", folder);
883 (void)fflush (stdout);
885 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
890 fprintf (stderr, " %sFcc %s: ",
891 msgstate == resent ? "Resent-" : "", folder);
892 fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
896 (void)sprintf (fold, "%s%s",
897 *folder == '+' || *folder == '@@' ? "" : "+", folder);
898 execlp (fileproc, r1bindex (fileproc, '/'),
899 "-link", "-file", file, fold, NULL);
903 if (status = pidwait (child_id, OK)) {
905 fprintf (stderr, " %sFcc %s: ",
906 msgstate == resent ? "Resent-" : "", folder);
907 fprintf (verbose ? stdout : stderr,
908 " errored (0%o)\n", status);
912 (void)fflush (stdout);
919 static die (what, fmt, a, b, c, d)
927 adios (what, fmt, a, b, c, d);
940 static char ident[] = "@@(#)$Id: spost.c,v 1.6 1992/01/31 22:28:25 jromine Exp jromine $";
964 static char ident[] = "@@(#)$Id: spost.c,v 1.5 1990/04/05 15:02:47 sources Exp jromine $";
968 #define uptolow(c) (isupper (c) ? tolower (c) : c)
980 static char ident[] = "@@(#)$Id:$";
986 "Return-Path", HBAD, NULL,
987 "Received", HBAD, NULL,
988 "Reply-To", HADR | HNGR, NULL,
991 "Sender", HADR | HBAD, NULL,
994 "Subject", HSUB, NULL,
997 "Message-Id", HBAD, NULL,
1001 "Resent-Reply-To", HADR | HNGR, NULL,
1004 "Resent-Sender", HADR | HBAD, NULL,
1007 "Resent-Subject", HSUB, NULL,
1010 "Resent-Message-Id", HBAD, NULL,
1011 "Resent-Fcc", HFCC, NULL,
1012 "Reply-To", HADR, NULL,
1029 @let sendmail be defined from mtstailor
1038 @Fixes from Van Jacobson
1043 #define SENDMAIL "/usr/lib/sendmail"
1046 invo_name, SENDMAIL);
1049 execv ( SENDMAIL, sargv);
1050 adios ( SENDMAIL, "can't exec");
1065 if ( pos+len > outputlinelen ) {
1069 } else if ( pos > indent ) {