diff uip/post.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children 441a2190cfae
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uip/post.c	Mon Apr 18 23:46:02 2005 +0900
@@ -0,0 +1,3058 @@
+/* post.c - enter messages into the transport system */
+#ifndef	lint
+static char ident[] = "@(#)$Id$";
+#endif	/* lint */
+
+#include "../h/mh.h"
+#include "../h/addrsbr.h"
+#include "../h/aliasbr.h"
+#include "../h/dropsbr.h"
+#include "../zotnet/tws.h"
+#ifndef	MMDFMTS
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <sys/types.h>
+#else	/* MMDFMTS */
+#include "../mts/mmdf/util.h"
+#include "../mts/mmdf/mmdf.h"
+#endif	/* MMDFMTS */
+#include "../zotnet/mts.h"
+#ifdef	MHMTS
+#ifndef	V7
+#include <sys/ioctl.h>
+#endif	/* not V7 */
+#include <sys/stat.h>
+#endif	/* MHMTS */
+#ifdef	SENDMTS
+#include "../mts/sendmail/smail.h"
+#undef	MF
+#endif	/* SENDMTS */
+#include <signal.h>
+#ifdef MIME
+#include "../h/mhn.h"
+#endif	/* MIME */
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+
+#ifndef	MMDFMTS
+#define	uptolow(c)	((isalpha(c) && isupper (c)) ? tolower (c) : (c))
+#endif	/* not MMDFMTS */
+
+#define FCCS		10	/* max number of fccs allowed */
+
+/*  */
+
+#ifndef	MIME
+#define	MIMEminc(a)	(a)
+#else
+#define	MIMEminc(a)	0
+#endif
+
+#ifndef	TMA
+#define	TMAminc(a)	(a)
+#else	/* TMA */
+#define	TMAminc(a)	0
+#endif	/* TMA */
+
+static struct swit switches[] = {
+#define	ALIASW	0
+    "alias aliasfile", 0,
+
+#define	CHKSW	1
+    "check", -5,		/* interface from whom */
+#define	NCHKSW	2
+    "nocheck", -7,		/* interface from whom */
+
+#define	DEBUGSW	3
+    "debug", -5,
+
+#define	DISTSW	4
+    "dist", -4,			/* interface from dist */
+
+#define	ENCRSW	5
+    "encrypt", TMAminc (-7),
+#define	NENCRSW	6
+    "noencrypt", TMAminc (-9),
+
+#define	FILTSW	7
+    "filter filterfile", 0,
+#define	NFILTSW	8
+    "nofilter", 0,
+
+#define	FRMTSW	9
+    "format", 0,
+#define	NFRMTSW	10
+    "noformat", 0,
+
+#define	LIBSW	11		/* interface from send, whom */
+    "library directory", -7,
+
+#define	MIMESW	12
+    "mime", MIMEminc(-4),
+#define	NMIMESW	13
+    "nomime", MIMEminc(-6),
+
+#define	MSGDSW	14
+    "msgid", 0,
+#define	NMSGDSW	15
+    "nomsgid", 0,
+
+#define	VERBSW	16
+    "verbose", 0,
+#define	NVERBSW	17
+    "noverbose", 0,
+
+#define	WATCSW	18
+    "watch", 0,
+#define	NWATCSW	19
+    "nowatch", 0,
+
+#define	WHOMSW	20	/* interface from whom */
+    "whom", -4,		
+
+#define	WIDTHSW	21
+    "width columns", 0,
+
+#define	HELPSW	22
+    "help", 4,
+
+#define	MAILSW	23
+    "mail", -4,
+#define	SAMLSW	24
+    "saml", -4,
+#define	SENDSW	25
+    "send", -4,
+#define	SOMLSW	26
+    "soml", -4,
+
+#define	ANNOSW	27		/* interface from send */
+    "idanno number", -6,
+
+#define	DLVRSW	28
+    "deliver address-list", -7,
+
+#define	CLIESW	29
+    "client host", -6,
+#define	SERVSW	30
+    "server host", -6,
+#define	SNOOPSW	31
+    "snoop", -5,
+
+#define	FILLSW	32
+    "fill-in file", -7,
+#define	FILLUSW	33
+    "fill-up", -7,
+#define	PARTSW	34
+    "partno", -6,
+
+#define	QUEUESW 35
+    "queued", -6,
+
+#define	RECORSW 36
+    "record program", -6,
+#define	NRECOSW 37
+    "norecord", -8,
+
+#ifdef MIME_HEADERS
+#define	HENCDSW	38
+    "hencode", 0,
+#define	NHENCDSW 39
+    "nohencode", 0,
+#endif /* MIME_HEADERS */
+
+#ifdef MH_PLUS
+#define        USERSW  40
+    "user", -4,
+#define        FROMSW  41
+    "from", -4,
+#endif /* MH_PLUS */
+
+    NULL, 0
+};
+
+/*  */
+
+struct headers {
+    char   *value;
+
+    unsigned int    flags;
+#define	HNOP	0x0000		/* just used to keep .set around */
+#define	HBAD	0x0001		/* bad header - don't let it through */
+#define	HADR	0x0002		/* header has an address field */
+#define	HSUB	0x0004		/* Subject: header */
+#define	HTRY	0x0008		/* try to send to addrs on header */
+#define	HBCC	0x0010		/* don't output this header */
+#define	HMNG	0x0020		/* munge this header */
+#define	HNGR	0x0040		/* no groups allowed in this header */
+#define	HFCC	0x0080		/* FCC: type header */
+#define	HNIL	0x0100		/* okay for this header not to have addrs */
+#define	HIGN	0x0200		/* ignore this header */
+#define	HDCC	0x0400		/* another undocumented feature */
+
+    unsigned int    set;
+#define	MFRM	0x0001		/* we've seen a From: */
+#define	MDAT	0x0002		/* we've seen a Date: */
+#define	MRFM	0x0004		/* we've seen a Resent-From: */
+#define	MVIS	0x0008		/* we've seen sighted addrs */
+#define	MINV	0x0010		/* we've seen blind addrs */
+#define	MRPY	0x0020		/* we've seen a Reply-to: */
+};
+
+/*  */
+
+static struct headers  NHeaders[] = {
+    "Return-Path", HBAD, 0,
+    "Received", HBAD, 0,
+    "Reply-To", HADR | HNGR, MRPY,
+    "From", HADR | HNGR, MFRM,
+    "Sender", HADR | HBAD, 0,
+    "Date", HBAD, 0,
+    "Subject", HSUB, 0,
+    "To", HADR | HTRY, MVIS,
+    "cc", HADR | HTRY, MVIS,
+    "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
+    "Dcc", HADR | HTRY | HDCC | HNIL, MVIS,	/* sorta cc & bcc combined */
+    "Message-ID", HBAD, 0,
+    "Fcc", HFCC, 0,
+
+    NULL
+};
+
+static struct headers  RHeaders[] = {
+    "Resent-Reply-To", HADR | HNGR, MRPY,
+    "Resent-From", HADR | HNGR, MRFM,
+    "Resent-Sender", HADR | HBAD, 0,
+    "Resent-Date", HBAD, 0,
+    "Resent-Subject", HSUB, 0,
+    "Resent-To", HADR | HTRY, MVIS,
+    "Resent-cc", HADR | HTRY, MVIS,
+    "Resent-Bcc", HADR | HTRY | HBCC, MINV,
+    "Resent-Message-ID", HBAD, 0,
+    "Resent-Fcc", HFCC, 0,
+    "Reply-To", HADR, MRPY,
+    "From", HADR | HNGR, MFRM,
+#ifdef	MMDFI
+    "Sender", HADR | HMNG | HNGR, 0,
+#else	/* not MMFDI */
+    "Sender", HADR | HNGR, 0,
+#endif	/* not MMDFI */
+    "Date", HNOP, MDAT,
+    "To", HADR | HNIL, 0,
+    "cc", HADR | HNIL, 0,
+    "Bcc", HADR | HTRY | HBCC | HNIL, 0,
+    "Fcc", HIGN, 0,
+
+    NULL
+};
+
+/*  */
+
+
+static short    fccind = 0;	/* index into fccfold[] */
+static short    outputlinelen = OUTPUTLINELEN;
+
+static int  pfd = NOTOK;	/* fd to write annotation list to */
+static int  myuid= -1;		/* my user id */
+static int  mygid= -1;		/* my group id */
+static int  recipients = 0;	/* how many people will get a copy */
+static int  unkadr = 0;		/* how many of those were unknown */
+static int  badadr = 0;		/* number of bad addrs */
+static int  badmsg = 0;		/* message has bad semantics */
+static int  verbose = 0;	/* spell it out */
+static int  format = 1;		/* format addresses */
+static int  mime = 0;		/* use MIME-style encapsulations */
+static int  msgid = 0;		/* add msgid */
+static int  debug = 0;		/* debugging post */
+static int  watch = 0;		/* watch the delivery process */
+static int  whomsw = 0;		/* we are whom not post */
+static int  checksw = 0;	/* whom -check */
+static int  linepos=0;		/* putadr()'s position on the line */
+static int  nameoutput=0;	/* putadr() has output header name */
+#ifdef MIME_HEADERS
+static int  hencode = -1;	/* encode header in RFC-2047 style */
+#endif /* MIME_HEADERS */
+
+static unsigned msgflags = 0;	/* what we've seen */
+
+#define	NORMAL 0
+#define	RESENT 1
+static int msgstate = NORMAL;
+
+static time_t tclock = 0L;		/* the time we started (more or less) */
+
+static TYPESIG  (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
+
+static char tmpfil[BUFSIZ];
+static char bccfil[BUFSIZ];
+
+static char from[BUFSIZ];	/* my network address */
+static char signature[BUFSIZ];	/* my signature */
+static char *filter = NULL;	/* the filter for BCC'ing */
+static char *msgfrom = NULL;	/* the From: field for Bcc'ing */
+static char *subject = NULL;	/* the subject field for BCC'ing */
+static char *fccfold[FCCS];	/* foldernames for FCC'ing */
+
+static struct headers  *hdrtab;	/* table for the message we're doing */
+
+static struct mailname localaddrs={NULL};	/* local addrs */
+static struct mailname netaddrs={NULL};		/* network addrs */
+static struct mailname uuaddrs={NULL};		/* uucp addrs */
+static struct mailname tmpaddrs={NULL};		/* temporary queue */
+
+/*  */
+
+#ifdef	MMDFMTS
+static char *submitmode = "m";	/* deliver to mailbox only */
+static char submitopts[6] = "vl";/* initial options for submit */
+#endif	/* MMDFMTS */
+
+#ifdef	MHMTS
+static char *deliver = NULL;
+
+extern char **environ;
+
+TYPESIG	sigser ();
+#endif	/* MHMTS */
+
+#ifdef	SENDMTS
+static int smtpmode = S_MAIL;
+static int snoop = 0;
+static char *clientsw = NULL;
+static char *serversw = NULL;
+
+extern struct smtp  sm_reply;
+#endif	/* SENDMTS */
+
+#ifdef	TMA
+#define	post(a,b,c) \
+    if (encryptsw) postcipher ((a), (b), (c)); else postplain ((a), (b), (c))
+
+#ifndef	SENDMTS
+#define	tmasnoop	0
+#else	/* SENDMTS */
+#define	tmasnoop	snoop
+#endif	/* SENDMTS */
+#endif	/* TMA */
+
+static int  encryptsw = 0;	/* encrypt it */
+#ifdef MH_PLUS
+static char *usersw = NULLCP;
+static char *fromsw = NULLCP;
+#endif /* MH_PLUS */
+
+
+#ifdef	BERK
+#undef	WP
+#endif
+
+#ifdef MIME
+static char	prefix[] = "----- =_aaaaaaaaaa";
+static int      find_prefix();
+#endif /* MIME */
+
+static int	fill_up = 0;
+static char    *fill_in = NULLCP;
+static char    *partno = NULLCP;
+
+static	int	queued = 0;
+
+static	char   *record = NULLCP;
+
+off_t	lseek ();
+time_t	time ();
+
+static	putfmt(), start_headers(), finish_headers(), putgrp(), pl();
+static	anno(), make_bcc_file(), verify_all_addresses();
+static	chkadr(), do_addresses(), do_text(), do_an_address(), sigon();
+static 	sigoff(), p_refile(), fcc(), die(), insert_fcc(), p_record ();
+static int	get_header(), putadr(), insert(), annoaux();
+#ifdef TMA
+static	postplain();
+#else
+static	post();
+#endif	/* !TMA */
+
+/*    MAIN */
+
+/* ARGSUSED */
+
+main (argc, argv)
+int     argc;
+char   *argv[];
+{
+    int     state,
+            compnum;
+    char   *cp,
+           *msg = NULL,
+          **argp = argv + 1,
+            buf[BUFSIZ],
+            name[NAMESZ];
+    FILE   *in,
+	   *out;
+
+#ifdef LOCALE
+	setlocale(LC_ALL, "");
+#endif
+#ifdef JAPAN
+	ml_init();
+#endif /* JAPAN */
+    invo_name = r1bindex (argv[0], '/');
+    m_foil (NULLCP);
+    mts_init (invo_name);
+#ifdef	MMDFMTS
+#ifdef	MMDFII
+    mmdf_init (invo_name);
+#endif	/* MMDFII */
+#endif	/* MMDFMTS */
+
+/*  */
+
+    while (cp = *argp++) {
+	if (*cp == '-')
+	    switch (smatch (++cp, switches)) {
+		case AMBIGSW: 
+		    ambigsw (cp, switches);
+		    done (1);
+		case UNKWNSW: 
+		    adios (NULLCP, "-%s unknown", cp);
+		case HELPSW: 
+		    (void) sprintf (buf, "%s [switches] file", invo_name);
+		    help (buf, switches);
+		    done (1);
+
+		case LIBSW:
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    m_foil (cp);
+		    continue;
+
+		case ALIASW: 
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+#ifdef	MHMTS
+		    if (access (libpath (cp), 04) == NOTOK)
+			adios (cp, "unable to read");
+#endif	/* MHMTS */
+		    if ((state = alias (cp)) != AK_OK)
+			adios (NULLCP, "aliasing error in %s - %s",
+				cp, akerror (state));
+		    continue;
+
+		case CHKSW: 
+		    checksw++;
+		    continue;
+		case NCHKSW: 
+		    checksw = 0;
+		    continue;
+
+		case DEBUGSW: 
+		    debug++;
+		    continue;
+
+		case DISTSW:
+		    msgstate = RESENT;
+		    continue;
+
+		case FILTSW:
+		    if (!(filter = *argp++) || *filter == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    mime = 0;
+		    continue;
+		case NFILTSW:
+		    filter = NULL;
+		    continue;
+		
+		case FRMTSW: 
+		    format++;
+		    continue;
+		case NFRMTSW: 
+		    format = 0;
+		    continue;
+
+		case MIMESW:
+#ifdef	MIME
+		    mime++;
+		    filter = 0;
+#endif
+		    continue;
+		case NMIMESW: 
+		    mime = 0;
+		    continue;
+
+		case MSGDSW: 
+		    msgid++;
+		    continue;
+		case NMSGDSW: 
+		    msgid = 0;
+		    continue;
+
+		case VERBSW: 
+		    verbose++;
+		    continue;
+		case NVERBSW: 
+		    verbose = 0;
+		    continue;
+
+		case WATCSW: 
+		    watch++;
+		    continue;
+		case NWATCSW: 
+		    watch = 0;
+		    continue;
+
+		case WHOMSW: 
+		    whomsw++;
+		    continue;
+
+		case WIDTHSW: 
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    if ((outputlinelen = atoi (cp)) < 10)
+			adios (NULLCP, "impossible width %d", outputlinelen);
+		    continue;
+
+		case ENCRSW:
+		    encryptsw++;
+		    continue;
+		case NENCRSW:
+		    encryptsw = 0;
+		    continue;
+
+		case ANNOSW: 
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    if ((pfd = atoi (cp)) <= 2)
+			adios (NULLCP, "bad argument %s %s", argp[-2], cp);
+		    continue;
+
+#ifdef	MMDFMTS
+		case MAILSW:
+		    submitmode = "m";
+		    continue;
+		case SOMLSW:	/* for right now, sigh... */
+		case SAMLSW:
+		    submitmode = "b";
+		    continue;
+		case SENDSW:
+		    submitmode = "y";
+		    continue;
+#endif	/* MMDFMTS */
+
+#ifndef	MHMTS
+		case DLVRSW:
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+#else	/* MHMTS */
+		case MAILSW:
+		case SAMLSW:
+		case SOMLSW:
+		case SENDSW:
+		    continue;
+		case DLVRSW: 
+		    if (!(deliver = *argp++) || *deliver == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+#endif	/* MHMTS */
+
+#ifndef	SENDMTS
+		case CLIESW:
+		case SERVSW:
+		    if (!(cp = *argp++) || *cp == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+
+		case SNOOPSW:
+		    continue;
+#else	/* SENDMTS */
+		case MAILSW:
+		    smtpmode = S_MAIL;
+		    continue;
+		case SAMLSW:
+		    smtpmode = S_SAML;
+		    continue;
+		case SOMLSW:
+		    smtpmode = S_SOML;
+		    continue;
+		case SENDSW:
+		    smtpmode = S_SEND;
+		    continue;
+		case CLIESW:
+		    if (!(clientsw = *argp++) || *clientsw == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case SERVSW:
+		    if (!(serversw = *argp++) || *serversw == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case SNOOPSW:
+		    snoop++;
+		    continue;
+#endif	/* SENDMTS */
+
+		case FILLSW:
+		    if (!(fill_in = *argp++) || *fill_in == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case FILLUSW:
+		    fill_up++;
+		    continue;
+		case PARTSW:
+		    if (!(partno = *argp++) || *partno == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+
+		case QUEUESW:
+		    queued++;
+		    continue;
+
+		case RECORSW:
+		    if (!(record = *argp++) || *record == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case NRECOSW:
+		    record = NULLCP;
+		    continue;
+#ifdef MIME_HEADERS
+		case HENCDSW:
+		    hencode = 1;
+		    continue;
+		case NHENCDSW:
+		    hencode = 0;
+		    continue;
+#endif /* MIME_HEADERS */
+
+#ifdef MH_PLUS
+		case USERSW:
+		    if (!(usersw = *argp++) || *usersw == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+		case FROMSW:
+		    if (!(fromsw = *argp++) || *fromsw == '-')
+			adios (NULLCP, "missing argument to %s", argp[-2]);
+		    continue;
+#endif /* MH_PLUS */
+	    }
+	if (msg)
+	    adios (NULLCP, "only one message at a time!");
+	else
+	    msg = cp;
+    }
+
+    (void) alias (AliasFile);
+
+/*  */
+
+    if (!msg)
+	adios (NULLCP, "usage: %s [switches] file", invo_name);
+
+    if (outputlinelen < 10)
+	adios (NULLCP, "impossible width %d", outputlinelen);
+
+#ifdef	MHMTS
+    if (access (msg, 04) == NOTOK)
+	adios (msg, "unable to read");
+#endif	/* MHMTS */
+    if ((in = fopen (msg, "r")) == NULL)
+	adios (msg, "unable to open");
+
+#ifdef MIME_HEADERS
+    if (hencode == -1) {
+	hencode = 0;
+	for (state = FLD;;) {
+	    switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
+		case FLD: 
+		case FLDEOF: 
+		case FLDPLUS: 
+		    if (uleq (name, "MIME-Version")) {
+			hencode = 1;
+			break;
+		    }
+		    continue;
+
+		default:
+		    break;
+	    }
+	    break;
+	}
+	(void) fseek (in, 0L, 0);
+    }
+#endif /* MIME_HEADERS */
+
+    start_headers ();
+    if (debug) {
+	verbose++;
+	discard (out = stdout);	/* XXX: reference discard() to help loader */
+#ifdef	MHMTS
+	if (deliver) {
+	    (void) strcpy (tmpfil, msg);
+	    putfmt ("To", deliver, out);
+	    goto daemon;
+	}
+#endif	/* MHMTS */
+    }
+    else
+#ifdef	MHMTS
+    if (deliver) {
+	if ((out = fopen ("/dev/null", "r")) == NULL)
+	    adios ("/dev/null", "unable to write");
+	(void) strcpy (tmpfil, msg);
+	putfmt ("To", deliver, out);
+	goto daemon;
+    }
+    else
+#endif	/* MHMTS */
+	if (whomsw) {
+	    if ((out = fopen (fill_in ? fill_in : "/dev/null", "w")) == NULL)
+		adios ("/dev/null", "unable to open");
+	}
+	else {
+	    (void) strcpy (tmpfil, m_scratch ("", m_maildir (invo_name)));
+	    if ((out = fopen (tmpfil, "w")) == NULL) {
+		(void) strcpy (tmpfil, m_tmpfil (invo_name));
+		if ((out = fopen (tmpfil, "w")) == NULL)
+		    adios (tmpfil, "unable to create");
+	    }
+#ifdef	MHMTS
+	    (void) chown (tmpfil, myuid, mygid);
+#endif	/* MHMTS */
+	    (void) chmod (tmpfil, 0600);
+	}
+
+/*  */
+
+    hdrtab = msgstate == NORMAL ? NHeaders : RHeaders;
+
+    for (compnum = 1, state = FLD;;) {
+	switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
+	    case FLD: 
+	    case FLDEOF: 
+	    case FLDPLUS: 
+		compnum++;
+		cp = add (buf, NULLCP);
+		while (state == FLDPLUS) {
+		    state = m_getfld (state, name, buf, sizeof buf, in);
+		    cp = add (buf, cp);
+		}
+		putfmt (name, cp, out);
+		free (cp);
+		if (state != FLDEOF)
+		    continue;
+		finish_headers (out);
+		break;
+
+	    case BODY: 
+	    case BODYEOF: 
+		finish_headers (out);
+		if (whomsw && !fill_in)
+		    break;
+		fprintf (out, "\n%s", buf);
+		while (state == BODY) {
+		    state = m_getfld (state, name, buf, sizeof buf, in);
+		    fputs (buf, out);
+		}
+		break;
+
+	    case FILEEOF: 
+		finish_headers (out);
+		break;
+
+	    case LENERR: 
+	    case FMTERR: 
+		adios (NULLCP, "message format error in component #%d",
+			compnum);
+
+	    default: 
+		adios (NULLCP, "getfld() returned %d", state);
+	}
+	break;
+    }
+
+/*  */
+
+#ifdef	MHMTS
+daemon: ;
+#endif	/* MHMTS */
+    if (pfd != NOTOK)
+	anno ();
+    (void) fclose (in);
+    if (debug) {
+	pl ();
+	done (0);
+    }
+    else
+	(void) fclose (out);
+
+#ifdef	TMA
+    if (encryptsw)
+	tmastart (tmasnoop);
+#endif	/* TMA */
+    if (whomsw) {
+	if (!fill_up)
+	    verify_all_addresses (1);
+	done (0);
+    }
+
+#ifdef	MMDFMTS
+    (void) strcat (submitopts, submitmode);
+    if (watch)
+	(void) strcat (submitopts, "nw");
+#endif	/* MMDFMTS */
+#ifdef	MHMTS
+    verify_all_addresses (0);
+#endif	/* MHMTS */
+    if (encryptsw)
+	verify_all_addresses (verbose);
+    if (msgflags & MINV) {
+	make_bcc_file ();
+	if (msgflags & MVIS) {
+#ifndef	MHMTS
+	    if (!encryptsw)
+		verify_all_addresses (verbose);
+#endif	/* not MHMTS */
+	    post (tmpfil, 0, verbose);
+	}
+	post (bccfil, 1, verbose);
+	(void) unlink (bccfil);
+    }
+    else
+	post (tmpfil, 0, isatty (1));
+#ifdef	TMA
+    if (encryptsw)
+	tmastop ();
+#endif	/* TMA */
+
+    p_refile (tmpfil);
+
+    p_record ();
+
+#ifdef	MHMTS
+    if (!deliver)
+#endif	/* MHMTS */
+	(void) unlink (tmpfil);
+
+    if (verbose)
+	printf (partno ? "Partial Message #%s Processed\n" : "Message Processed\n",
+		partno);
+
+    done (0);
+}
+
+/*    DRAFT GENERATION */
+
+static putfmt (name, str, out)
+register char   *name,
+		*str;
+register FILE *out;
+{
+    int     count,
+            grp,
+            i,
+            keep;
+    register char  *cp,
+                   *pp,
+                   *qp;
+#ifdef MIME_HEADERS
+    char   *origstr;
+#endif /* MIME_HEADERS */
+    char    namep[BUFSIZ];
+    register struct mailname   *mp,
+                               *np;
+    register struct headers *hdr;
+
+    while (*str == ' ' || *str == '\t')
+	str++;
+
+    if (msgstate == NORMAL && uprf (name, "resent")) {
+	advise (NULLCP, "illegal header line -- %s:", name);
+	badmsg++;
+	return;
+    }
+
+#ifdef MIME_HEADERS
+    if (hencode) {
+	char *ep;
+	if ((ep = malloc((unsigned)strlen(str)*10+1)) == NULL)
+	    adios(NULLCP, "out of memory");
+#ifdef JAPAN
+	(void) ml_conv(str);
+#endif /* JAPAN */
+	(void) exthdr_encode(str, ep, strlen(name)+2, name);
+	origstr = str;
+	str = ep;
+    }
+#endif /* MIME_HEADERS */
+
+    if ((i = get_header (name, hdrtab)) == NOTOK) {
+	fprintf (out, "%s: %s", name, str);
+	return;
+    }
+
+    hdr = &hdrtab[i];
+    if (hdr -> flags & HIGN) {
+	if (fill_in)
+	    fprintf (out, "%s: %s", name, str);
+	return;
+    }
+    if (hdr -> flags & HBAD) {
+	if (fill_in)
+	    fprintf (out, "%s: %s", name, str);
+	else {
+	    advise (NULLCP, "illegal header line -- %s:", name);
+	    badmsg++;
+	}
+	return;
+    }
+    msgflags |= (hdr -> set & ~(MVIS | MINV));
+
+    if (hdr -> set & MFRM)
+	msgfrom = msgfrom ? add (str, add (",", msgfrom)) : getcpy (str);
+    if (hdr -> flags & HSUB)
+	subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
+    if (hdr -> flags & HFCC) {
+	if (fill_in) {
+	    fprintf (out, "%s: %s", name, str);
+	    return;
+	}
+
+	if (cp = rindex (str, '\n'))
+	    *cp = 0;
+	for (cp = pp = str; cp = index (pp, ','); pp = cp) {
+	    *cp++ = 0;
+	    insert_fcc (hdr, pp);
+	}
+	insert_fcc (hdr, pp);
+	return;
+    }
+
+/*  */
+
+    if (!(hdr -> flags & HADR)) {
+	fprintf (out, "%s: %s", name, str);
+	return;
+    }
+
+#ifdef MIME_HEADERS
+    if (hencode && format)
+	/* encode again after format */
+	(void) exthdr_decode(origstr, str);
+#endif /* MIME_HEADERS */
+
+    tmpaddrs.m_next = NULL;
+    for (count = 0; cp = getname (str); count++)
+	if (mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP)) {
+	    if (tmpaddrs.m_next)
+		np -> m_next = mp;
+	    else
+		tmpaddrs.m_next = mp;
+	    np = mp;
+	}
+	else
+	    if (hdr -> flags & HTRY)
+		badadr++;
+	    else
+		badmsg++;
+
+    if (count < 1) {
+	if (hdr -> flags & HNIL) {
+	    if (!(hdr -> flags & HBCC))
+		fprintf (out, "%s: %s", name, str);
+	}
+	else {
+#ifdef	notdef
+	    advise (NULLCP, "%s: field requires at least one address", name);
+	    badmsg++;
+#endif	/* notdef */
+	}
+	return;
+    }
+
+/*  */
+
+    nameoutput = linepos = 0;
+    (void) sprintf (namep, "%s%s",
+		    !fill_in && (hdr -> flags & HMNG) ? "Original-" : "",
+		    name);
+
+    for (grp = 0, mp = tmpaddrs.m_next; mp; mp = np)
+	if (mp -> m_nohost) {	/* also used to test (hdr -> flags & HTRY) */
+	    pp = akvalue (mp -> m_mbox);
+	    qp = akvisible () ? mp -> m_mbox : "";
+	    np = mp;
+	    if (np -> m_gname)
+		putgrp (namep, np -> m_gname, out, hdr -> flags);
+	    while (cp = getname (pp)) {
+		if (!(mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP))) {
+		    badadr++;
+		    continue;
+		}
+		if (hdr -> flags & HBCC)
+		    mp -> m_bcc++;
+		if (np -> m_ingrp)
+		    mp -> m_ingrp = np -> m_ingrp;
+		else
+		    if (mp -> m_gname)
+			putgrp (namep, mp -> m_gname, out, hdr -> flags);
+		if (mp -> m_ingrp)
+		    grp++;
+#ifdef	MHMTS
+		mp -> m_aka = getcpy (np -> m_mbox);
+#endif	/* MHMTS */
+		if (putadr (namep, qp, mp, out, hdr -> flags))
+		    msgflags |= (hdr -> set & (MVIS | MINV));
+		else
+		    mnfree (mp);
+	    }
+	    mp = np;
+	    np = np -> m_next;
+	    mnfree (mp);
+	}
+	else {
+	    if (hdr -> flags & HBCC)
+		mp -> m_bcc++;
+	    if (mp -> m_gname)
+		putgrp (namep, mp -> m_gname, out, hdr -> flags);
+	    if (mp -> m_ingrp)
+		grp++;
+	    keep = putadr (namep, "", mp, out, hdr -> flags);
+	    np = mp -> m_next;
+	    if (keep) {
+		mp -> m_next = NULL;
+		msgflags |= (hdr -> set & (MVIS | MINV));
+	    }
+	    else
+		mnfree (mp);
+	}
+
+    if (grp > 0 && (hdr -> flags & HNGR)) {
+	advise (NULLCP, "%s: field does not allow groups", name);
+	badmsg++;
+    }
+    if (linepos) {
+	if (fill_in && grp > 0)
+	    (void) putc (';', out);
+	(void) putc ('\n', out);
+    }
+}
+
+/*  */
+
+static  start_headers () {
+    register char  *cp;
+    char *user = NULLCP, *addr;
+    char    myhost[BUFSIZ],
+            sigbuf[BUFSIZ];
+    register struct mailname   *mp;
+
+    myuid = getuid ();
+    mygid = getgid ();
+    (void) time (&tclock);
+
+#ifdef MH_PLUS
+    if (LocalUser && usersw)
+	user = usersw;
+#endif /* MH_PLUS */
+    (void) strcpy (from, adrsprintf (user, NULLCP));
+
+    (void) strcpy (myhost, LocalName ());
+    for (cp = myhost; *cp; cp++)
+	*cp = uptolow (*cp);
+
+#ifdef	MHMTS
+    if (deliver) {
+	if (geteuid () == 0 && myuid != 0 && myuid != 1 && mygid != 1)
+	    adios (NULLCP, "-deliver unknown");
+	(void) strcpy (signature, from);
+    }
+#endif	/* MHMTS */
+
+    addr = adrsprintf (user, NULLCP);
+#ifdef MH_PLUS
+    if (fromsw) {
+	if (strcmp(fromsw, addr) == 0) fromsw = NULL;
+	else addr = fromsw;
+    }
+#endif /* MH_PLUS */
+    if ((cp = getfullname ()) && *cp) {
+	(void) strcpy (sigbuf, cp);
+	(void) sprintf (signature, "%s <%s>", sigbuf, addr);
+#ifdef MIME_HEADERS
+	if (hencode) {
+	    char *ep;
+#ifdef JAPAN
+	    (void) ml_conv(signature);
+#endif /* JAPAN */
+	    ep = getcpy (signature);
+	    (void) exthdr_encode (ep, signature, 5, "From");
+	    free(ep);
+	}
+#endif /* MIME_HEADERS */
+	if ((cp = getname (signature)) == NULL)
+	    adios (NULLCP, "getname () failed -- you lose extraordinarily big");
+	if ((mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP)) == NULL)
+	    adios (NULLCP, "bad signature '%s'", sigbuf);
+	mnfree (mp);
+	while (getname (""))
+	    continue;
+    }
+    else
+	(void) strcpy (signature, addr);
+}
+
+/*  */
+
+static finish_headers (out)
+register FILE *out;
+{
+    switch (msgstate) {
+	case NORMAL: 
+	    if (whomsw && !fill_up)
+		break;
+
+	    fprintf (out, "Date: %s\n", dtime (&tclock));
+	    if (msgid)
+		fprintf (out, "Message-ID: <%d.%ld@%s>\n",
+			getpid (), (long)tclock, LocalName ());
+	    if (msgflags & MFRM)
+		fprintf (out, "Sender: %s\n", from);
+	    else {
+		fprintf (out, "From: %s\n", signature);
+#ifdef MH_PLUS
+		if (fromsw) fprintf (out, "Sender: %s\n", from);
+#endif /* MH_PLUS */
+	    }
+	    if (whomsw)
+		break;
+
+	    if (!(msgflags & MVIS) && (msgflags & MINV))
+		fprintf (out, "Bcc: Blind Distribution List: ;\n");
+	    break;
+
+	case RESENT: 
+	    if (!(msgflags & MDAT)) {
+		advise (NULLCP, "message has no Date: header");
+		badmsg++;
+	    }
+	    if (!(msgflags & MFRM)) {
+		advise (NULLCP, "message has no From: header");
+		badmsg++;
+	    }
+	    if (whomsw && !fill_up)
+		break;
+
+#ifdef	MMDFI			/* sigh */
+	    fprintf (out, "Sender: %s\n", from);
+#endif	/* MMDFI */
+
+	    fprintf (out, "Resent-Date: %s\n", dtime (&tclock));
+	    if (msgid)
+		fprintf (out, "Resent-Message-ID: <%d.%ld@%s>\n",
+			getpid (), (long)tclock, LocalName ());
+	    if (msgflags & MRFM)
+		fprintf (out, "Resent-Sender: %s\n", from);
+	    else {
+		fprintf (out, "Resent-From: %s\n", signature);
+#ifdef MH_PLUS
+		if (fromsw) fprintf (out, "Resent-Sender: %s\n", from);
+#endif /* MH_PLUS */
+	    }
+	    if (whomsw)
+		break;
+	    if (!(msgflags & MVIS) && (msgflags & MINV))
+		fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
+	    break;
+    }
+
+    if (badmsg)
+	adios (NULLCP, "re-format message and try again");
+    if (!recipients)
+	adios (NULLCP, "no addresses");
+}
+
+/*  */
+
+static int     get_header (header, table)
+register char   *header;
+register struct headers *table;
+{
+    register struct headers *h;
+
+    for (h = table; h -> value; h++)
+	if (uleq (header, h -> value))
+	    return (h - table);
+
+    return NOTOK;
+}
+
+/*  */
+
+static int     putadr (name, aka, mp, out, flags)
+register char   *name,
+		*aka;
+register struct mailname *mp;
+register FILE *out;
+unsigned int    flags;
+{
+    int     len;
+    register char   *cp;
+#ifdef MIME_HEADERS
+    char   *ep = NULL;
+#endif /* MIME_HEADERS */
+    char    buffer[BUFSIZ];
+
+    if (mp -> m_mbox == NULL || ((flags & HTRY) && !insert (mp)))
+	return 0;
+    if (!fill_in && (flags & (HBCC | HDCC)) || mp -> m_ingrp)
+	return 1;
+
+    if (!nameoutput) {
+	fprintf (out, "%s: ", name);
+	linepos += (nameoutput = strlen (name) + 2);
+    }
+
+    if (*aka && mp -> m_type != UUCPHOST && !mp -> m_pers)
+	mp -> m_pers = getcpy (aka);
+    if (format) {
+	if (mp -> m_gname && !fill_in)
+	    (void) sprintf (cp = buffer, "%s;", mp -> m_gname);
+	else
+	    cp = adrformat (mp);
+    }
+    else
+	cp = mp -> m_text;
+#ifdef MIME_HEADERS
+    if (hencode) {
+	if ((ep = malloc((unsigned)strlen(cp)*10+1)) == NULL)
+	    adios(NULLCP, "out of memory");
+	(void) exthdr_encode(cp, ep, linepos + 2, name);
+	len = strlen (ep);
+    } else
+#endif /* MIME_HEADERS */
+    len = strlen (cp);
+
+    if (linepos != nameoutput)
+	if (len + linepos + 2 > outputlinelen) {
+	    fprintf (out, ",\n%*s", linepos = nameoutput, "");
+#ifdef MIME_HEADERS
+	    if (hencode)
+		(void) exthdr_encode (cp, ep, linepos, name);
+#endif /* MIME_HEADERS */
+	} else {
+	    fputs (", ", out);
+	    linepos += 2;
+	}
+#ifdef MIME_HEADERS
+    if (hencode) {
+	char *p;
+	fputs (ep, out);
+	if ((p = rindex (ep, '\n')))
+	    len -= (p+1) - ep;
+	free(ep);
+    } else
+	fputs (cp, out);
+#else /* MIME_HEADERS */
+    fputs (cp, out);
+#endif /* MIME_HEADERS */
+    linepos += len;
+
+    return (flags & HTRY);
+}
+
+/*  */
+
+static putgrp (name, group, out, flags)
+register char   *name,
+		*group;
+register FILE *out;
+unsigned int    flags;
+{
+    int     len;
+    char   *cp;
+#ifdef MIME_HEADERS
+    char   *ep;
+#endif /* MIME_HEADERS */
+
+    if (!fill_in && (flags & HBCC))
+	return;
+
+    if (!nameoutput) {
+	fprintf (out, "%s: ", name);
+	linepos += (nameoutput = strlen (name) + 2);
+	if (fill_in)
+	    linepos -= strlen (group);
+    }
+
+    cp = fill_in ? group : concat (group, ";", NULLCP);
+#ifdef MIME_HEADERS
+    if (hencode) {
+	if ((ep = malloc((unsigned)strlen(cp)*10+1)) == NULL)
+	    adios(NULLCP, "out of memory");
+	(void) exthdr_encode(cp, ep, linepos + 2, name);
+	len = strlen (ep);
+    } else
+#endif /* MIME_HEADERS */
+    len = strlen (cp);
+
+    if (linepos > nameoutput)
+	if (len + linepos + 2 > outputlinelen) {
+	    fprintf (out, ",\n%*s", nameoutput, "");
+	    linepos = nameoutput;
+#ifdef MIME_HEADERS
+	    if (hencode)
+		(void) exthdr_encode (cp, ep, linepos, name);
+#endif /* MIME_HEADERS */
+	}
+	else {
+	    fputs (", ", out);
+	    linepos += 2;
+	}
+
+#ifdef MIME_HEADERS
+    if (hencode) {
+	char *p;
+	fputs (ep, out);
+	if ((p = rindex (ep, '\n')))
+	    len -= (p+1) - ep;
+	free(ep);
+    } else
+	fputs (cp, out);
+#else /* MIME_HEADERS */
+    fputs (cp, out);
+#endif /* MIME_HEADERS */
+    linepos += len;
+}
+
+/*  */
+
+static int     insert (np)
+register struct mailname   *np;
+{
+    register struct mailname   *mp;
+
+    if (np -> m_mbox == NULL)
+	return 0;
+
+    for (mp = np -> m_type == LOCALHOST ? &localaddrs
+	    : np -> m_type == UUCPHOST ? &uuaddrs
+	    : &netaddrs;
+	    mp -> m_next;
+	    mp = mp -> m_next)
+	if (uleq (np -> m_host, mp -> m_next -> m_host)
+		&& uleq (np -> m_mbox, mp -> m_next -> m_mbox)
+		&& np -> m_bcc == mp -> m_next -> m_bcc)
+	    return 0;
+
+    mp -> m_next = np;
+    recipients++;
+    return 1;
+}
+
+
+static  pl () {
+    register int     i;
+    register struct mailname *mp;
+
+    printf ("-------\n\t-- Addresses --\nlocal:\t");
+    for (mp = localaddrs.m_next; mp; mp = mp -> m_next)
+	printf ("%s%s%s", mp -> m_mbox,
+		mp -> m_bcc ? "[BCC]" : "",
+		mp -> m_next ? ",\n\t" : "");
+
+    printf ("\nnet:\t");
+    for (mp = netaddrs.m_next; mp; mp = mp -> m_next)
+	printf ("%s%s@%s%s%s", mp -> m_path ? mp -> m_path : "",
+		mp -> m_mbox, mp -> m_host,
+		mp -> m_bcc ? "[BCC]" : "",
+		mp -> m_next ? ",\n\t" : "");
+
+    printf ("\nuucp:\t");
+    for (mp = uuaddrs.m_next; mp; mp = mp -> m_next)
+	printf ("%s!%s%s", mp -> m_host, mp -> m_mbox,
+		mp -> m_bcc ? "[BCC]" : "",
+		mp -> m_next ? ",\n\t" : "");
+
+    printf ("\n\t-- Folder Copies --\nfcc:\t");
+    for (i = 0; i < fccind; i++)
+	printf ("%s%s", fccfold[i], i + 1 < fccind ? ",\n\t" : "");
+    printf ("\n");
+}
+
+/*  */
+
+static  anno () {
+    register struct mailname *mp;
+
+    for (mp = localaddrs.m_next; mp; mp = mp -> m_next)
+	if (annoaux (mp) == NOTOK)
+	    goto oops;
+
+    for (mp = netaddrs.m_next; mp; mp = mp -> m_next)
+	if (annoaux (mp) == NOTOK)
+	    goto oops;
+
+    for (mp = uuaddrs.m_next; mp; mp = mp -> m_next)
+	if (annoaux (mp) == NOTOK)
+	    break;
+
+oops: ;
+    (void) close (pfd);
+    pfd = NOTOK;
+}
+
+
+static int  annoaux (mp)
+register struct mailname *mp;
+{
+    int     i;
+    char    buffer[BUFSIZ];
+
+    (void) sprintf (buffer, "%s\n", adrformat (mp));
+    i = strlen (buffer);
+
+    return (write (pfd, buffer, i) == i ? OK : NOTOK);
+}
+
+/*  */
+
+static  insert_fcc (hdr, pp)
+register struct	headers *hdr;
+register char   *pp;
+{
+    register char   *cp;
+
+    for (cp = pp; isspace (*cp); cp++)
+	continue;
+    for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
+	continue;
+    if (pp >= cp)
+	*++pp = 0;
+    if (*cp == 0)
+	return;
+
+    if (fccind >= FCCS)
+	adios (NULLCP, "too many %ss", hdr -> value);
+    fccfold[fccind++] = getcpy (cp);
+}
+
+/*    BCC GENERATION */
+
+static  make_bcc_file () {
+    int     fd,
+	    i,
+            child_id;
+    char   *vec[6];
+    register FILE   *out;
+
+    (void) strcpy (bccfil, m_tmpfil ("bccs"));
+    if ((out = fopen (bccfil, "w")) == NULL)
+	adios (bccfil, "unable to create");
+    (void) chmod (bccfil, 0600);
+
+    fprintf (out, "Date: %s\n", dtime (&tclock));
+    if (msgid)
+	fprintf (out, "Message-ID: <%d.%ld.1@%s>\n",
+		getpid (), (long)tclock, LocalName ());
+    if (msgflags & MFRM) {
+	fprintf (out, "From: %s", msgfrom);
+	fprintf (out, "Sender: %s\n", from);
+    }
+    else {
+	fprintf (out, "From: %s\n", signature);
+#ifdef MH_PLUS
+	if (fromsw) fprintf (out, "Sender: %s\n", from);
+#endif /* MH_PLUS */
+    }
+    if (subject)
+	fprintf (out, "Subject: %s", subject);
+    fprintf (out, "BCC:\n");
+#ifdef MIME
+    if (mime) {
+	char   *cp;
+
+	if ((cp = index (prefix, 'a')) == NULL)
+	    adios (NULLCP, "lost prefix start");
+	while (find_prefix () == NOTOK)
+	    if (*cp < 'z')
+		(*cp)++;
+	    else
+		if (*++cp == 0)
+		    adios (NULLCP,
+			   "giving up trying to find a unique delimiter string");
+		else
+		    (*cp)++;
+
+	fprintf (out, "%s: %s\n%s: multipart/digest; boundary=\"",
+		 VRSN_FIELD, VRSN_VALUE, TYPE_FIELD);
+	fprintf (out, "%s\"\n%s: %s\n\n--%s\n%s: %s\n%s: %s\n\n", prefix,
+		 DESCR_FIELD, "Blind Carbon Copy", prefix,
+		 TYPE_FIELD, "message/rfc822",
+		 DESCR_FIELD, "Original Message");
+    }
+    else
+#endif /* MIME */
+	fprintf (out, "\n------- Blind-Carbon-Copy\n\n");
+    (void) fflush (out);
+
+    if (filter == NULL) {
+	if ((fd = open (tmpfil, 0)) == NOTOK)
+	    adios (tmpfil, "unable to re-open");
+#ifdef MIME
+	if (mime)
+	    cpydata (fd, fileno (out), tmpfil, bccfil);
+	else
+#endif /* MIME */
+	    cpydgst (fd, fileno (out), tmpfil, bccfil);
+	(void) close (fd);
+    }
+    else {
+	vec[0] = r1bindex (mhlproc, '/');
+
+	for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
+	    sleep (5);
+	switch (child_id) {
+	    case NOTOK: 
+		adios ("fork", "unable to");
+
+	    case OK: 
+		(void) dup2 (fileno (out), 1);
+
+		i = 1;
+		vec[i++] = "-forward";
+		vec[i++] = "-form";
+		vec[i++] = filter;
+		vec[i++] = tmpfil;
+		vec[i] = NULL;
+
+		execvp (mhlproc, vec);
+		fprintf (stderr, "unable to exec ");
+		perror (mhlproc);
+		_exit (-1);
+
+	    default: 
+		(void) pidXwait (child_id, mhlproc);
+		break;
+	}
+    }
+
+    (void) fseek (out, 0L, 2);
+#ifdef	MIME
+    if (mime)
+	fprintf (out, "\n--%s--\n", prefix);
+    else
+#endif /* MIME */
+	fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
+    (void) fclose (out);
+}
+
+/*  */
+
+#ifdef MIME
+static int  find_prefix ()
+{
+    int	    len,
+	    result;
+    char    buffer[BUFSIZ];
+    FILE   *in;
+
+    if ((in = fopen (tmpfil, "r")) == NULL)
+	adios (tmpfil, "unable to re-open");
+
+    len = strlen (prefix);
+
+    result = OK;
+    while (fgets (buffer, sizeof buffer - 1, in))
+	if (buffer[0] == '-' && buffer[1] == '-') {
+	    register char *cp;
+
+	    for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
+		if (!isspace (*cp & 0xff))
+		    break;
+	    *++cp = '\0';
+	    if (strcmp (buffer + 2, prefix) == 0) {
+		result = NOTOK;
+		break;
+	    }
+	}
+
+    (void) fclose (in);
+	
+    return result;
+}
+#endif /* MIME */
+
+/*    ADDRESS VERIFICATION */
+
+static  verify_all_addresses (talk)
+int     talk;
+{
+#ifndef	MHMTS
+    int     retval;
+#endif	/* not MHMTS */
+#ifdef	MMDFMTS
+#ifdef	RP_NS
+    int	    len;
+    struct rp_bufstruct reply;
+#endif	/* RP_NS */
+#endif	/* MMDFMTS */
+    register struct mailname *lp;
+
+#ifndef	MHMTS
+    sigon ();
+#endif	/* not MHMTS */
+
+#ifdef	MMDFMTS
+    if (!whomsw || checksw) {
+	if (rp_isbad (retval = mm_init ())
+		|| rp_isbad (retval = mm_sbinit ())
+		|| rp_isbad (retval = mm_winit (NULLCP, submitopts, from)))
+	    die (NULLCP, "problem initializing MMDF system [%s]",
+		    rp_valstr (retval));
+#ifdef	RP_NS
+	if (rp_isbad (retval = mm_rrply (&reply, &len)))
+	    die (NULLCP, "problem with sender address [%s]",
+		    rp_valstr (retval));
+#endif	/* RP_NS */
+    }
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (!whomsw || checksw)
+	if (rp_isbad (retval = sm_init (clientsw, serversw, 0, 0, snoop, 0, 0))
+		|| rp_isbad (retval = sm_winit (smtpmode, from)))
+	    die (NULLCP, "problem initializing server; %s",
+		    rp_string (retval));
+#endif	/* SENDMTS */
+
+    if (talk && !whomsw)
+	printf (" -- Address Verification --\n");
+#ifndef	BERK
+    if (talk && localaddrs.m_next)
+	printf ("  -- Local Recipients --\n");
+#endif	/* BERK */
+    for (lp = localaddrs.m_next; lp; lp = lp -> m_next)
+	do_an_address (lp, talk, encryptsw);
+
+#ifndef	BERK
+    if (talk && uuaddrs.m_next)
+	printf ("  -- UUCP Recipients --\n");
+#endif	/* BERK */
+    for (lp = uuaddrs.m_next; lp; lp = lp -> m_next)
+	do_an_address (lp, talk, encryptsw);
+
+#ifndef	BERK
+    if (talk && netaddrs.m_next)
+	printf ("  -- Network Recipients --\n");
+#endif	/* BERK */
+    for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
+	do_an_address (lp, talk, encryptsw);
+
+    chkadr ();
+    if (talk && !whomsw)
+	printf (" -- Address Verification Successful --\n");
+
+#ifdef	MMDFMTS
+    if (!whomsw || checksw)
+	(void) mm_end (NOTOK);
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (!whomsw || checksw)
+	(void) sm_end (DONE);
+#endif	/* SENDMTS */
+    (void) fflush (stdout);
+
+#ifndef	MHMTS
+    sigoff ();
+#endif	/* not MHMTS */
+}
+
+/*  */
+
+static  chkadr () {
+#define	plural(x) (x == 1 ? "" : "s")
+
+    if (badadr && unkadr)
+	die (NULLCP, "%d address%s unparsable, %d addressee%s undeliverable",
+		badadr, plural (badadr), unkadr, plural (badadr));
+    if (badadr)
+	die (NULLCP, "%d address%s unparsable", badadr, plural (badadr));
+    if (unkadr)
+	die (NULLCP, "%d addressee%s undeliverable", unkadr, plural (unkadr));
+}
+
+/*    MTS INTERACTION */
+
+#ifdef	TMA
+static postplain (file, bccque, talk)
+#else	/* TMA */
+static post (file, bccque, talk)
+#endif	/* TMA */
+register char   *file;
+int     bccque,
+        talk;
+{
+    int     fd,
+    	    onex = !(msgflags & MINV) || bccque;
+#ifndef	MHMTS
+    int	    retval;
+#ifdef	MMDFMTS
+#ifdef	RP_NS
+    int	    len;
+    struct rp_bufstruct reply;
+#endif	/* RP_NS */
+#endif	/* MMDFMTS */
+#else	/* MHMTS */
+    int	    ud;
+#endif	/* MHMTS */
+
+    if (verbose)
+	if (msgflags & MINV)
+	    printf (" -- Posting for %s Recipients --\n",
+		    bccque ? "Blind" : "Sighted");
+	else
+	    printf (" -- Posting for All Recipients --\n");
+
+    sigon ();
+
+#ifdef	MMDFMTS
+    if (rp_isbad (retval = mm_init ())
+	    || rp_isbad (retval = mm_sbinit ())
+	    || rp_isbad (retval = mm_winit (NULLCP, submitopts, from)))
+	die (NULLCP, "problem initializing MMDF system [%s]",
+		rp_valstr (retval));
+#ifdef	RP_NS
+	if (rp_isbad (retval = mm_rrply (&reply, &len)))
+	    die (NULLCP, "problem with sender address [%s]",
+		    rp_valstr (retval));
+#endif	/* RP_NS */
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose, snoop,
+				    onex, queued))
+	    || rp_isbad (retval = sm_winit (smtpmode, from)))
+	die (NULLCP, "problem initializing server; %s", rp_string (retval));
+#endif	/* SENDMTS */
+
+#ifndef	MHMTS
+    do_addresses (bccque, talk && verbose);
+    if ((fd = open (file, 0)) == NOTOK)
+	die (file, "unable to re-open");
+    do_text (file, fd);
+#else	/* MHMTS */
+    if ((fd = open (file, 0)) == NULL)
+	adios (file, "unable to re-open");
+#ifdef	MF
+    ud = UucpChan () && uuaddrs.m_next ? make_uucp_file (fd) : NOTOK;
+#else	/* not MF */
+    ud = NOTOK;
+#endif	/* not MF */
+    do_addresses (file, fd, ud, bccque, talk && verbose);
+    if (ud != NOTOK)
+	(void) close (ud);
+#endif	/* MHMTS */
+    (void) close (fd);
+    (void) fflush (stdout);
+
+#ifdef	MMDFMTS
+    (void) mm_sbend ();
+    (void) mm_end (OK);
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    (void) sm_end (onex ? OK : DONE);
+#endif	/* SENDMTS */
+
+    sigoff ();
+
+    if (verbose)
+	if (msgflags & MINV)
+	    printf (" -- %s Recipient Copies Posted --\n",
+		    bccque ? "Blind" : "Sighted");
+	else
+	    printf (" -- Recipient Copies Posted --\n");
+    (void) fflush (stdout);
+}
+
+/*  */
+
+#ifdef	TMA
+static postcipher (file, bccque, talk)
+register char   *file;
+int     bccque,
+        talk;
+{
+    int     fdP,
+            state;
+    char    reason[BUFSIZ];
+    struct mailname *lp;
+
+    if (verbose)
+	if (msgflags & MINV)
+	    printf (" -- Posting for %s Recipients --\n",
+		    bccque ? "Blind" : "Sighted");
+	else
+	    printf (" -- Posting for All Recipients --\n");
+
+    if ((fdP = open (file, 0)) == NOTOK)
+	adios (file, "unable to re-open");
+    if (ciphinit (fdP, reason) == NOTOK)
+	adios (NULLCP, "%s", reason);
+    (void) close (fdP);
+
+    for (state = 0, lp = localaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- Local Recipients --\n");
+#endif	/* BERK */
+	    do_a_cipher (lp, talk);
+#ifndef	BERK
+	    state++;
+#endif	/* BERK */
+	}
+
+    for (state = 0, lp = uuaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- UUCP Recipients --\n");
+#endif	/* BERK */
+	    do_a_cipher (lp, talk);
+#ifndef	BERK
+	    state++;
+#endif	/* BERK */
+	}
+
+    for (state = 0, lp = netaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- Network Recipients --\n");
+#endif	/* BERK */
+	    do_a_cipher (lp, talk);
+#ifndef	BERK
+	    state++;
+#endif	/* BERK */
+	}
+
+    if (ciphdone (reason) == NOTOK)
+	admonish (NULLCP, "%s", reason);
+#ifdef	SENDMTS
+    if (!(msgflags & MINV) || bccque)
+	(void) sm_end (OK);
+#endif	/* SENDMTS */
+
+    if (verbose)
+	if (msgflags & MINV)
+	    printf (" -- %s Recipient Copies Posted --\n",
+		    bccque ? "Blind" : "Sighted");
+	else
+	    printf (" -- Recipient Copies Posted --\n");
+    (void) fflush (stdout);
+}
+
+/*  */
+
+static do_a_cipher (lp, talk)
+register struct mailname *lp;
+int	talk;
+{
+    int     fd,
+            retval;
+    register char  *mbox,
+                   *host;
+    char    addr[BUFSIZ],
+            reason[BUFSIZ];
+#ifdef	MMDFMTS
+#ifdef	RP_NS
+    int	    len;
+    struct rp_bufstruct reply;
+#endif	/* RP_NS */
+#endif	/* MMDFMTS */
+
+    sigon ();
+
+#ifdef	MMDFMTS
+    if (rp_isbad (retval = mm_init ())
+	    || rp_isbad (retval = mm_sbinit ())
+	    || rp_isbad (retval = mm_winit (NULL, submitopts, from)))
+	die (NULLCP, "problem initializing MMDF system [%s]",
+		rp_valstr (retval));
+#ifdef	RP_NS
+	if (rp_isbad (retval = mm_rrply (&reply, &len)))
+	    die (NULLCP, "problem with sender address [%s]",
+		    rp_valstr (retval));
+#endif	/* RP_NS */
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose, snoop,
+				    0, 0))
+	    || rp_isbad (retval = sm_winit (smtpmode, from)))
+	die (NULLCP, "problem initializing server; %s", rp_string (retval));
+#endif	/* SENDMTS */
+
+    do_an_address (lp, talk, 0);
+
+    switch (lp -> m_type) {
+	case LOCALHOST: 
+	    mbox = lp -> m_mbox;
+	    host = LocalName ();
+	    (void) strcpy (addr, mbox);
+	    break;
+
+	case UUCPHOST: 
+#ifdef	MMDFMTS
+	    mbox = concat (lp -> m_host, "!", lp -> m_mbox, NULLCP);
+	    host = UucpChan ();
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+	    mbox = auxformat (lp, 0);
+	    host = NULL;
+#endif	/* SENDMTS */
+	    (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
+	    break;
+
+	default: 
+	    mbox = lp -> m_mbox;
+	    host = lp -> m_host;
+	    (void) sprintf (addr, "%s at %s", lp -> m_mbox, lp -> m_host);
+	    break;
+    }
+    chkadr ();			/* XXX */
+
+#ifdef	MMDFMTS
+    if (rp_isbad (retval = mm_waend ()))
+	die (NULLCP, "problem ending addresses [%s]\n",
+		rp_valstr (retval));
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (rp_isbad (retval = sm_waend ()))
+	die (NULLCP, "problem ending addresses; %s", rp_string (retval));
+#endif	/* SENDMTS */
+
+    if ((fd = encipher (mbox, host, reason)) == NOTOK)
+	die (NULLCP, "%s: %s", addr, reason);
+    do_text ("temporary file", fd);
+    (void) close (fd);
+    (void) fflush (stdout);
+
+#ifdef	MMDFMTS
+    (void) mm_sbend ();
+    (void) mm_end (OK);
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    (void) sm_end (DONE);
+#endif	/* SENDMTS */
+
+    sigoff ();
+}
+#endif	/* TMA */
+
+/*  */
+
+#ifndef	MHMTS
+static do_addresses (bccque, talk)
+#else	/* MHMTS */
+static do_addresses (file, fd, ud, bccque, talk)
+register char   *file;
+int	fd,
+	ud;
+#endif	/* MHMTS */
+int	bccque,
+	talk;
+{
+    int     retval;
+#ifndef	BERK
+    int	    state;
+#endif	/* not BERK */
+    register struct mailname *lp;
+
+#ifndef	BERK
+    state = 0;
+#endif	/* not BERK */
+    for (lp = localaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- Local Recipients --\n");
+#endif	/* not BERK */
+#ifndef	MHMTS
+	    do_an_address (lp, talk, 0);
+#else	/* MHMTS */
+	    localmail (lp, talk, fd);
+#endif	/* MHMTS */
+#ifndef	BERK
+	    state++;
+#endif	/* not BERK */
+	}
+
+#ifndef	BERK
+    state = 0;
+#endif	/* not BERK */
+    for (lp = uuaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- UUCP Recipients --\n");
+#endif	/* not BERK */
+#ifndef	MHMTS
+	    do_an_address (lp, talk, 0);
+#else	/* MHMTS */
+	    uucpmail (lp, talk, ud != NOTOK ? ud : fd, ud == NOTOK);
+#endif	/* MHMTS */
+#ifndef	BERK
+	    state++;
+#endif	/* not BERK */
+	}
+
+#ifndef	BERK
+    state = 0;
+#endif	/* not BERK */
+    for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+#ifndef	BERK
+	    if (talk && !state)
+		printf ("  -- Network Recipients --\n");
+#endif	/* not BERK */
+#ifndef	MHMTS
+	    do_an_address (lp, talk, 0);
+#else	/* MHMTS */
+	    netmail (talk, fd, bccque);
+#endif	/* MHMTS */
+#ifndef	BERK
+	    state++;
+#endif	/* not BERK */
+	}
+
+/*  */
+
+    chkadr ();
+
+#ifdef	MMDFMTS
+    if (rp_isbad (retval = mm_waend ()))
+	die (NULLCP, "problem ending addresses [%s]\n",
+		rp_valstr (retval));
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (rp_isbad (retval = sm_waend ()))
+	die (NULLCP, "problem ending addresses; %s", rp_string (retval));
+#endif	/* SENDMTS */
+}
+
+/*  */
+
+#ifndef	MHMTS
+static  do_text (file, fd)
+register char   *file;
+int     fd;
+{
+    int     retval,
+            state;
+    char    buf[BUFSIZ];
+#ifdef	MMDFMTS
+    struct rp_bufstruct reply;
+#endif	/* MMDFMTS */
+
+    (void) lseek (fd, (off_t)0, 0);
+    while ((state = read (fd, buf, sizeof buf)) > 0)
+#ifdef	MMDFMTS
+	if (rp_isbad (mm_wtxt (buf, state)))
+	    die (NULLCP, "problem writing text [%s]\n", rp_valstr (retval));
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+	if (rp_isbad (retval = sm_wtxt (buf, state)))
+	    die (NULLCP, "problem writing text; %s\n", rp_string (retval));
+#endif	/* SENDMTS */
+
+    if (state == NOTOK)
+	die (file, "problem reading from");
+
+#ifdef	MMDFMTS
+    if (rp_isbad (retval = mm_wtend ()))
+	die (NULLCP, "problem ending text [%s]\n", rp_valstr (retval));
+
+    if (rp_isbad (retval = mm_rrply (&reply, &state)))
+	die (NULLCP, "problem getting submission status [%s]\n",
+		rp_valstr (retval));
+
+    switch (rp_gval (reply.rp_val)) {
+	case RP_OK: 
+	case RP_MOK: 
+	    break;
+
+	case RP_NO: 
+	    die (NULLCP, "you lose; %s", reply.rp_line);
+
+	case RP_NDEL: 
+	    die (NULLCP, "no delivery occurred; %s", reply.rp_line);
+
+	case RP_AGN: 
+	    die (NULLCP, "try again later; %s", reply.rp_line);
+
+	case RP_NOOP: 
+	    die (NULLCP, "nothing done; %s", reply.rp_line);
+
+	default: 
+	    die (NULLCP, "unexpected response;\n\t[%s] -- %s",
+		    rp_valstr (reply.rp_val), reply.rp_line);
+    }
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    switch (retval = sm_wtend ()) {
+	case RP_OK: 
+	    break;
+
+	case RP_NO: 
+	case RP_NDEL: 
+	    die (NULLCP, "posting failed; %s", rp_string (retval));
+
+	default: 
+	    die (NULLCP, "unexpected response; %s", rp_string (retval));
+    }
+#endif	/* SENDMTS */
+}
+#endif	/* not MHMTS */
+
+/*    MTS-SPECIFIC INTERACTION */
+
+#ifdef	MMDFMTS
+
+#ifndef	TMA
+/* ARGSUSED */
+#endif	/* TMA */
+
+static do_an_address (lp, talk, tma)
+register struct mailname *lp;
+int     talk,
+	tma;
+{
+    int     len,
+            retval;
+    register char  *mbox,
+                   *host,
+                   *text,
+                   *path;
+    char    addr[BUFSIZ];
+#ifdef	TMA
+    char    reason[BUFSIZ];
+#endif	/* TMA */
+    struct rp_bufstruct reply;
+
+    switch (lp -> m_type) {
+	case LOCALHOST: 
+	    mbox = lp -> m_mbox;
+	    host = LocalName ();
+	    (void) strcpy (addr, mbox);
+	    break;
+
+	case UUCPHOST: 
+#ifdef	MF
+	    mbox = concat (lp -> m_host, "!", lp -> m_mbox, NULLCP);
+	    host = UucpChan ();
+	    (void) strcpy (addr, mbox);
+	    break;
+#else	/* MF */
+	    fprintf (talk ? stdout : stderr, "  %s!%s: %s\n",
+		lp -> m_host, lp -> m_mbox, "not supported; UUCP address");
+	    unkadr++;
+	    (void) fflush (stdout);
+	    return;
+#endif	/* MF */
+
+	default: 		/* let MMDF decide if the host is bad */
+	    mbox = lp -> m_mbox;
+	    host = lp -> m_host;
+	    (void) sprintf (addr, "%s at %s", mbox, host);
+	    break;
+    }
+#ifdef	TMA
+    if ((!whomsw || checksw)
+	    && tma
+	    && seekaddr (mbox, host, reason) == NOTOK) {
+	fprintf (talk ? stdout : stderr, "  %s%s: %s\n",
+		addr, "[TMA]", reason);
+	unkadr++;
+    }
+#endif	/* TMA */
+
+    if (talk)
+	printf ("  %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
+
+    if (whomsw && !checksw) {
+	(void) putchar ('\n');
+	return;
+    }
+    if (talk)
+	printf (": ");
+    (void) fflush (stdout);
+
+/*  */
+
+#ifdef	MMDFII
+    if (lp -> m_path)
+	path = concat (lp -> m_path, mbox, "@", host, NULLCP);
+    else
+#endif	/* MMDFII */
+	path = NULLCP;
+    if (rp_isbad (retval = mm_wadr (path ? NULLCP : host, path ? path : mbox))
+	    || rp_isbad (retval = mm_rrply (&reply, &len)))
+	die (NULLCP, "problem submitting address [%s]", rp_valstr (retval));
+
+    switch (rp_gval (reply.rp_val)) {
+	case RP_AOK: 
+	    if (talk)
+		printf ("address ok\n");
+	    (void) fflush (stdout);
+	    return;
+
+#ifdef	RP_DOK
+	case RP_DOK: 
+	    if (talk)
+		printf ("nameserver timeout - queued for checking\n");
+	    (void) fflush (stdout);
+	    return;
+#endif	/* RP_DOK */
+
+	case RP_NO: 
+	    text = "you lose";
+	    break;
+
+#ifdef	RP_NS
+	case RP_NS: 
+	    text = "temporary nameserver failure";
+	    break;
+
+#endif	/* RP_NS */
+
+	case RP_USER: 
+	case RP_NDEL: 
+	    text = "not deliverable";
+	    break;
+
+	case RP_AGN: 
+	    text = "try again later";
+	    break;
+
+	case RP_NOOP: 
+	    text = "nothing done";
+	    break;
+
+	default: 
+	    if (!talk)
+		fprintf (stderr, "  %s: ", addr);
+	    text = "unexpected response";
+	    die (NULLCP, "%s;\n    [%s] -- %s", text,
+		    rp_valstr (reply.rp_val), reply.rp_line);
+    }
+
+    if (!talk)
+	fprintf (stderr, "  %s: ", addr);
+    fprintf (talk ? stdout : stderr, "%s;\n    %s\n", text, reply.rp_line);
+    unkadr++;
+
+    (void) fflush (stdout);
+}
+#endif	/* MMDFMTS */
+
+/*  */
+
+#ifdef	MHMTS
+/* ARGSUSED */
+
+static do_an_address (lp, talk, tma)
+register struct mailname *lp;
+int     talk,
+	tma;
+{
+    register char  *mbox;
+    char    addr[BUFSIZ];
+
+    switch (lp -> m_type) {
+	case LOCALHOST: 
+	    (void) strcpy (addr, lp -> m_mbox);
+	    break;
+
+	case UUCPHOST: 
+	    (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
+	    break;
+
+	default: 
+	    (void) sprintf (addr, "%s at %s", lp -> m_mbox, lp -> m_host);
+	    break;
+    }
+    if (talk)
+	printf ("  %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
+
+    if (whomsw && !checksw) {
+	(void) putchar ('\n');
+	return;
+    }
+    if (talk)
+	printf (": ");
+    (void) fflush (stdout);
+
+/*  */
+
+    switch (lp -> m_type) {
+	case LOCALHOST: 
+	    mbox = lp -> m_mbox;
+	    if (*mbox == '~')
+		mbox++;
+	    if (seek_home (mbox)) {
+		lp -> m_mbox = mbox;
+		if (talk)
+		    printf ("address ok\n");
+	    }
+	    else {
+		if (!talk)
+		    fprintf (stderr, "  %s: ", addr);
+		fprintf (talk ? stdout : stderr,
+			"not deliverable; unknown user\n");
+		unkadr++;
+	    }
+	    break;
+
+	case UUCPHOST: 
+	    if (uucpsite (lp -> m_host) == OK) {
+		if (talk)
+		    printf ("address ok\n");
+	    }
+	    else {
+		if (!talk)
+		    fprintf (stderr, "  %s: ", addr);
+		fprintf (talk ? stdout : stderr,
+			"not deliverable; unknown system\n");
+		unkadr++;
+	    }
+	    break;
+
+	case NETHOST: 
+	    if (talk)
+		printf ("address ok\n");
+	    break;
+
+	default: 
+	    if (!talk)
+		fprintf (stderr, "  %s: ", addr);
+	    fprintf (talk ? stdout : stderr,
+		    "not deliverable; unknown host\n");
+	    unkadr++;
+	    break;
+    }
+
+    (void) fflush (stdout);
+}
+#endif	/* MHMTS */
+
+/*  */
+
+#ifdef	SENDMTS
+
+#ifndef	TMA
+/* ARGSUSED */
+#endif	/* TMA */
+
+static do_an_address (lp, talk, tma)
+register struct mailname *lp;
+int     talk,
+	tma;
+{
+    int     retval;
+    register char  *mbox,
+                   *host;
+    char    addr[BUFSIZ];
+#ifdef	TMA
+    char    reason[BUFSIZ];
+#endif	/* TMA */
+
+    switch (lp -> m_type) {
+	case LOCALHOST: 
+	    mbox = lp -> m_mbox;
+	    host = lp -> m_host;
+	    (void) strcpy (addr, mbox);
+	    break;
+
+	case UUCPHOST: 
+	    mbox = auxformat (lp, 0);
+	    host = NULL;
+	    (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
+	    break;
+
+	default: 		/* let SendMail decide if the host is bad  */
+	    mbox = lp -> m_mbox;
+	    host = lp -> m_host;
+	    (void) sprintf (addr, "%s at %s", mbox, host);
+	    break;
+    }
+
+#ifdef	TMA
+    if ((!whomsw || checksw)
+	    && tma
+	    && seekaddr (mbox, host, reason) == NOTOK) {
+	fprintf (talk ? stdout : stderr, "  %s%s: %s\n",
+		addr, "[TMA]", reason);
+	unkadr++;
+    }
+#endif	/* TMA */
+
+    if (talk)
+	printf ("  %s%s", addr, whomsw && lp -> m_bcc ? "[BCC]" : "");
+
+    if (whomsw && !checksw) {
+	(void) putchar ('\n');
+	return;
+    }
+    if (talk)
+	printf (": ");
+    (void) fflush (stdout);
+
+/*  */
+
+    switch (retval = sm_wadr (mbox, host,
+			 lp -> m_type != UUCPHOST ? lp -> m_path : NULLCP)) {
+	case RP_OK: 
+	    if (talk)
+		printf ("address ok\n");
+	    break;
+
+	case RP_NO: 
+	case RP_USER: 
+	    if (!talk)
+		fprintf (stderr, "  %s: ", addr);
+	    fprintf (talk ? stdout : stderr, "loses; %s\n",
+			rp_string (retval));
+	    unkadr++;
+	    break;
+
+	default: 
+	    if (!talk)
+		fprintf (stderr, "  %s: ", addr);
+	    die (NULLCP, "unexpected response; %s", rp_string (retval));
+    }
+
+    (void) fflush (stdout);
+}
+#endif	/* SENDMTS */
+
+/*    SIGNAL HANDLING */
+
+#ifndef	MHMTS
+
+/* ARGSUSED */
+
+static	TYPESIG sigser (i)
+int     i;
+{
+#ifndef	BSD42
+    (void) signal (i, SIG_IGN);
+#endif	/* not BSD42 */
+    (void) unlink (tmpfil);
+    if (msgflags & MINV)
+	(void) unlink (bccfil);
+#ifdef	MMDFMTS
+    if (!whomsw || checksw)
+	(void) mm_end (NOTOK);
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (!whomsw || checksw)
+	(void) sm_end (NOTOK);
+#endif	/* SENDMTS */
+    done (1);
+}
+#endif	/* not MHMTS */
+
+
+static  sigon () {
+    if (debug)
+	return;
+
+#ifndef	MHMTS
+    setsigx (hstat, SIGHUP, sigser);
+    setsigx (istat, SIGINT, sigser);
+    setsigx (qstat, SIGQUIT, sigser);
+    setsigx (tstat, SIGTERM, sigser);
+#else	/* MHMTS */
+    setsigx (hstat, SIGHUP, SIG_IGN);
+    setsigx (istat, SIGINT, SIG_IGN);
+    setsigx (qstat, SIGQUIT, SIG_IGN);
+    setsigx (tstat, SIGTERM, SIG_IGN);
+#endif	/* MHMTS */
+}
+
+
+static sigoff () {
+    if (debug)
+	return;
+
+    (void) signal (SIGHUP, hstat);
+    (void) signal (SIGINT, istat);
+    (void) signal (SIGQUIT, qstat);
+    (void) signal (SIGTERM, tstat);
+}
+
+/*    FCC INTERACTION */
+
+static  p_refile (file)
+register char   *file;
+{
+    register int     i;
+
+    if (fccind == 0)
+	return;
+
+#ifdef	MHMTS
+    (void) setuid (myuid);
+#endif	/* MHMTS */
+    if (verbose)
+	printf (" -- Filing Folder Copies --\n");
+    for (i = 0; i < fccind; i++)
+	fcc (file, fccfold[i]);
+    if (verbose)
+	printf (" -- Folder Copies Filed --\n");
+}
+
+
+static fcc (file, folder)
+register char   *file,
+		*folder;
+{
+    int     i,
+            child_id,
+	    status;
+    char    fold[BUFSIZ];
+
+    if (verbose)
+	printf ("  %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder);
+    (void) fflush (stdout);
+
+    for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
+	sleep (5);
+    switch (child_id) {
+	case NOTOK: 
+	    if (!verbose)
+		fprintf (stderr, "  %sFcc %s: ",
+			msgstate == RESENT ? "Resent-" : "", folder);
+	    fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
+	    break;
+
+	case OK: 
+	    (void) sprintf (fold, "%s%s",
+		    *folder == '+' || *folder == '@' ? "" : "+", folder);
+	    execlp (fileproc, r1bindex (fileproc, '/'),
+		    "-link", "-file", file, fold, NULLCP);
+	    _exit (-1);
+
+	default: 
+	    if (status = pidwait (child_id, OK)) {
+		if (!verbose)
+		    fprintf (stderr, "  %sFcc %s: ",
+			    msgstate == RESENT ? "Resent-" : "", folder);
+		(void) pidstatus (status, verbose ? stdout : stderr, NULLCP);
+	    }
+	    else
+		if (verbose)
+		    printf ("folder ok\n");
+    }
+
+    (void) fflush (stdout);
+}
+
+/*    RECORD RECIPIENTS */
+
+static	p_record ()
+{
+    int	    i,
+	    child_id,
+	    status;
+    char    recfile[BUFSIZ];
+    register struct mailname  *ap,
+			     **app;
+    struct mailname *addrs[3];
+    register FILE   *out;
+
+    if (!record || (msgflags & (MFRM | MRFM | MRPY)))
+	return;
+
+    addrs[0] = &localaddrs;
+    addrs[1] = &netaddrs;
+    addrs[2] = NULL;
+    if (verbose) {
+	printf ("recording recipients... ");
+	fflush (stdout);
+    }
+
+    (void) strcpy (recfile, m_tmpfil ("record"));
+    if ((out = fopen (recfile, "w")) == NULL) {
+	fprintf (verbose ? stdout : stderr, "unable to create temporary file");
+	if (!verbose)
+	    fprintf (stderr, ", so can't record recipients");
+	fprintf (verbose ? stdout : stderr, "\n");
+	return;
+    }
+    (void) chmod (recfile, 0600);
+
+    for (app = addrs; ap = *app; app++) {
+	register struct mailname *mp;
+
+	for (mp = ap -> m_next; mp; mp = mp -> m_next)
+	    fprintf (out, "%s\n", adrformat (mp));
+    }
+
+    (void) fclose (out);
+
+    for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
+	sleep (5);
+    switch (child_id) {
+	case NOTOK:
+	    fprintf (verbose ? stdout : stderr, "unable to fork");
+	    if (!verbose)
+		fprintf (stderr, ", so can't record recipients");
+	    fprintf (verbose ? stdout : stderr, "\n");
+	    break;
+
+	case OK:
+	    execlp (record, r1bindex (record, '/'), recfile, NULLCP);
+	    _exit (-1);
+
+	default:
+	    if (status = pidwait (child_id, OK)) {
+		if (!verbose)
+		    fprintf (stderr, "problem with %s: ", recfile);
+		(void) pidstatus (status, verbose ? stdout : stderr, NULLCP);
+	    }
+	    else
+		if (verbose)
+		    printf ("done\n");
+    }
+
+    (void) unlink (recfile);
+}
+
+/*    TERMINATION */
+
+/* VARARGS2 */
+
+static die (what, fmt, a, b, c, d)
+char   *what,
+       *fmt,
+       *a,
+       *b,
+       *c,
+       *d;
+{
+#ifndef	MHMTS
+    (void) unlink (tmpfil);
+    if (msgflags & MINV)
+	(void) unlink (bccfil);
+#endif	/* MHMTS */
+#ifdef	MMDFMTS
+    if (!whomsw || checksw)
+	(void) mm_end (NOTOK);
+#endif	/* MMDFMTS */
+#ifdef	SENDMTS
+    if (!whomsw || checksw)
+	(void) sm_end (NOTOK);
+#endif	/* SENDMTS */
+
+    adios (what, fmt, a, b, c, d);
+}
+
+
+#ifdef	MMDFMTS
+/* 
+ *    err_abrt() is used by the mm_ routines
+ *    		 do not, under *ANY* circumstances, remove it from post,
+ *		 or you will lose *BIG*
+ */
+
+err_abrt (code, fmt, a, b, c)
+int     code;
+char   *fmt,
+       *a,
+       *b,
+       *c;
+{
+    char    buffer[BUFSIZ];
+
+    (void) sprintf (buffer, "[%s]", rp_valstr (code));
+
+    adios (buffer, fmt, a, b, c);
+}
+#endif	/* MMDFMTS */
+
+/*    STAND-ALONE DELIVERY */
+
+#ifdef	MHMTS
+
+/* BUG: MHMTS ignores 822-style route addresses... */
+
+static  localmail (lp, talk, fd)
+register struct mailname *lp;
+int     talk,
+        fd;
+{
+    int     md;
+    char    mailbox[BUFSIZ],
+	    ddate[BUFSIZ];
+    register struct home *hp;
+
+    if (talk)
+	printf ("  %s: ", lp -> m_mbox);
+    (void) fflush (stdout);
+
+    if ((hp = seek_home (lp -> m_mbox)) == NULL) {
+	if (!talk)
+	    fprintf (stderr, "  %s: ", lp -> m_mbox);
+	fprintf (talk ? stdout : stderr,
+		"not deliverable; unknown address\n");
+	unkadr++;
+	return;
+    }
+
+    (void) sprintf (mailbox, "%s/%s",
+	    mmdfldir[0] ? mmdfldir : hp -> h_home,
+	    mmdflfil[0] ? mmdflfil : hp -> h_name);
+
+/*  */
+
+    switch (access (slocalproc, 01)) {
+	default: 
+	    if (talk)
+		printf ("(invoking hook)\n\t");
+	    (void) fflush (stdout);
+
+	    if (usr_hook (lp, talk, fd, hp, mailbox) != NOTOK)
+		return;
+	    if (talk)
+		printf ("  %s: ", lp -> m_mbox);
+	    (void) fflush (stdout);
+
+	case NOTOK: 
+	    (void) lseek (fd, (off_t)0, 0);
+	    if ((md = mbx_open (mailbox, hp -> h_uid, hp -> h_gid, m_gmprot ()))
+		    == NOTOK) {
+		if (!talk)
+		    fprintf (stderr, "  %s: ", lp -> m_mbox);
+		fprintf (talk ? stdout : stderr,
+			"error in transmission; unable to open maildrop\n");
+		unkadr++;
+		return;
+	    }
+	    (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ());
+	    if (mbx_copy (mailbox, md, fd, 0, ddate, 0) == NOTOK) {
+		if (!talk)
+		    fprintf (stderr, "  %s: ", lp -> m_mbox);
+		fprintf (talk ? stdout : stderr,
+			"error in transmission; write to maildrop failed\n");
+		unkadr++;
+		(void) close (md);
+		return;
+	    }
+	    mbx_close (mailbox, md);
+
+	    if (talk)
+		printf ("sent\n");
+	    break;
+    }
+
+    (void) fflush (stdout);
+}
+
+/*  */
+
+static int  usr_hook (lp, talk, fd, hp, mailbox)
+register struct mailname *lp;
+int     talk,
+        fd;
+register struct home *hp;
+register char   *mailbox;
+{
+    int     i,
+            child_id,
+            status;
+    char    tmpfil[BUFSIZ];
+
+    if ((fd = copyfile (fd, tmpfil)) == NOTOK) {
+	if (!talk)
+	    fprintf (stderr, "  %s: ", lp -> m_mbox);
+	fprintf (talk ? stdout : stderr,
+		"unable to copy message; skipping hook\n");
+	return NOTOK;
+    }
+    (void) chown (tmpfil, hp -> h_uid, hp -> h_gid);
+
+    (void) fflush (stdout);
+
+    for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
+	sleep (5);
+    switch (child_id) {
+	case NOTOK: 
+	    if (!talk)
+		fprintf (stderr, "  %s: ", lp -> m_mbox);
+	    fprintf (talk ? stdout : stderr,
+		    "unable to invoke hook; fork() failed\n");
+	    return NOTOK;
+
+	case OK: 
+	    if (fd != 0)
+		(void) dup2 (fd, 0);
+	    (void) freopen ("/dev/null", "w", stdout);
+	    (void) freopen ("/dev/null", "w", stderr);
+	    if (fd != 3)	/* backwards compatible... */
+		(void) dup2 (fd, 3);
+	    closefds (4);
+#ifdef	TIOCNOTTY
+	    if ((fd = open ("/dev/tty", 2)) != NOTOK) {
+		(void) ioctl (fd, TIOCNOTTY, NULLCP);
+		(void) close (fd);
+	    }
+#endif	/* TIOCNOTTY */
+#ifdef	BSD42
+	    (void) setpgrp (0, getpid ());
+#endif	/* BSD42 */
+
+	    *environ = NULL;
+	    (void) m_putenv ("USER", hp -> h_name);
+	    (void) m_putenv ("HOME", hp -> h_home);
+	    (void) m_putenv ("SHELL", hp -> h_shell);
+	    if (chdir (hp -> h_home) == NOTOK)
+		(void) chdir ("/");
+	    (void) umask (0077);
+#ifdef	BSD41A
+	    (void) inigrp (hp -> h_name, hp -> h_gid);
+#endif	/* BSD41A */
+	    (void) setgid (hp -> h_gid);
+#if defined(BSD42) || defiined(SVR4)
+	    (void) initgroups (hp -> h_name, hp -> h_gid);
+#endif	/* BSD42 || SVR4 */
+	    (void) setuid (hp -> h_uid);
+
+	    execlp (slocalproc, r1bindex (slocalproc, '/'),
+		    "-file", tmpfil, "-mailbox", mailbox,
+		    "-home", hp -> h_home, "-addr", lp -> m_aka,
+		    "-user", hp -> h_name, "-sender", from,
+		    talk ? "-verbose" : NULLCP, NULLCP);
+	    _exit (-1);
+
+/*  */
+
+	default: 
+	    (void) close (fd);
+
+	    status = pidwait (child_id, OK);
+
+	    (void) unlink (tmpfil);
+	    if (status == 0) {
+		if (talk)
+		    printf ("accepted\n");
+		return OK;
+	    }
+	    if (!talk)
+		fprintf (stderr, "  %s: ", lp -> m_mbox);
+	    fprintf (talk ? stdout : stderr,
+		    "%s error on hook; status=0%o\n",
+		    status & 0x00ff ? "system" : "user",
+		    status & 0x00ff ? status & 0xff
+		    : (status & 0xff00) >> 8);
+	    return NOTOK;
+    }
+}
+
+/*  */
+
+static int  copyfile (qd, tmpfil)
+int     qd;
+register char   *tmpfil;
+{
+    int     i,
+            fd;
+    char    buffer[BUFSIZ];
+
+    (void) strcpy (tmpfil, m_tmpfil ("hook"));
+    if ((fd = creat (tmpfil, 0600)) == NOTOK)
+	return NOTOK;
+    (void) close (fd);
+    if ((fd = open (tmpfil, 2)) == NOTOK)
+	return NOTOK;
+
+    (void) lseek (qd, (off_t)0, 0);
+    while ((i = read (qd, buffer, sizeof buffer)) > 0)
+	if (write (fd, buffer, i) != i) {
+	    (void) close (fd);
+	    return NOTOK;
+	}
+    if (i == NOTOK) {
+	(void) close (fd);
+	return NOTOK;
+    }
+
+    (void) lseek (fd, (off_t)0, 0);
+
+    return fd;
+}
+
+/*  */
+
+static  uucpmail (lp, talk, fd, from)
+register struct mailname *lp;
+int     talk,
+        fd,
+	from;
+{
+    int     i;
+    TYPESIG     (*pstat) ();
+    char    addr[BUFSIZ],
+            buffer[BUFSIZ];
+    register FILE *fp;
+
+    (void) sprintf (addr, "%s!%s", lp -> m_host, lp -> m_mbox);
+    if (talk)
+	printf ("  %s: ", addr);
+    (void) fflush (stdout);
+
+#ifndef	UCI
+    (void) sprintf (buffer, "uux -r -p %s!rmail \\(%s\\)",
+		lp -> m_host, lp -> m_mbox);
+#else	/* UCI */
+    (void) sprintf (buffer, "uux -p %s!rmail \\(%s\\)", lp -> m_host,
+	    lp -> m_mbox);
+#endif	/* UCI */
+    if ((fp = popen (buffer, "w")) == NULL) {
+	if (!talk)
+	    fprintf (stderr, "  %s: ", addr);
+	fprintf (talk ? stdout : stderr,
+		"unable to start uux; popen() failed\n");
+	unkadr++;
+	return;
+    }
+
+    pstat = signal (SIGPIPE, SIG_IGN);
+    if (from) {			/* no mail filtering, so... */
+	(void) sprintf (buffer, "From %s %.24s remote from %s\n",
+		getusr (), ctime (&tclock), SystemName ());
+	i = strlen (buffer);
+	if (fwrite (buffer, sizeof *buffer, i, fp) != i)
+	    goto oops;
+    }
+
+    (void) lseek (fd, (off_t)0, 0);
+    while ((i = read (fd, buffer, sizeof buffer)) > 0)
+	if (fwrite (buffer, sizeof *buffer, i, fp) != i) {
+    oops:   ;
+	    if (!talk)
+		fprintf (stderr, "  %s: ", addr);
+	    fprintf (talk ? stdout : stderr,
+		    "error in transmission; write to uux failed\n");
+	    unkadr++;
+	    (void) pclose (fp);
+	    return;
+	}
+    if (pclose (fp))
+	goto oops;
+    (void) signal (SIGPIPE, pstat);
+
+    if (i < 0) {
+	if (!talk)
+	    fprintf (stderr, "  %s: ", addr);
+	fprintf (talk ? stdout : stderr,
+		"error in transmission; read failed\n");
+	unkadr++;
+	return;
+    }
+
+    if (talk)
+	printf ("queued (via uux)\n");
+    (void) fflush (stdout);
+}
+
+/*  */
+
+#ifdef	MF
+static int  make_uucp_file (td)
+int     td;
+{
+    int     i,
+            qd,
+            fd;
+    char    tmpfil[BUFSIZ];
+
+    (void) lseek (td, (off_t)0, 0);
+    if ((qd = dup (td)) == NOTOK)
+	adios ("fd", "unable to dup");
+
+    (void) strcpy (tmpfil, m_tmpfil ("uumf"));
+    if ((fd = creat (tmpfil, 0600)) == NOTOK)
+	adios (tmpfil, "unable to create");
+    (void) close (fd);
+    if ((fd = open (tmpfil, 2)) == NOTOK)
+	adios (tmpfil, "unable to re-open");
+
+    switch (i = mmdf2uucp (qd, fd, 1)) {
+	case OK: 
+	    if (!debug)
+		(void) unlink (tmpfil);
+	    break;
+
+	default: 
+	    adios (NULLCP, "unable to filter mail(%d), examine %s", i, tmpfil);
+    }
+    (void) close (qd);
+
+    return fd;
+}
+#endif	/* MF */
+
+/*  */
+
+static  netmail (talk, fd, bccque)
+int     talk,
+        fd,
+        bccque;
+{
+    int     i,
+            naddrs;
+    char    buffer[BUFSIZ];
+    register struct mailname *lp;
+
+    naddrs = 0;
+    if (nm_init (getusr (), &tclock) == NOTOK) {
+	for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
+	    if (lp -> m_bcc ? bccque : !bccque)
+		fprintf (stderr, "  %s at %s: unable to get queue file\n",
+			lp -> m_mbox, lp -> m_host);
+	return;
+    }
+
+    for (lp = netaddrs.m_next; lp; lp = lp -> m_next)
+	if (lp -> m_bcc ? bccque : !bccque) {
+	    (void) nm_wadr (lp -> m_mbox, lp -> m_host);
+	    naddrs++;
+	    if (talk)
+		printf ("  %s at %s: queued\n", lp -> m_mbox, lp -> m_host);
+	    (void) fflush (stdout);
+	}
+    nm_waend ();
+
+    (void) lseek (fd, (off_t)0, 0);
+    while ((i = read (fd, buffer, sizeof buffer)) > 0)
+	if (nm_wtxt (buffer, i) == NOTOK) {
+	    fprintf (stderr,
+		    "error in transmission; write to temporary failed");
+	    unkadr += naddrs;
+	    return;
+	}
+
+    if (i < 0) {
+	fprintf (stderr, "error in transmission; read failed\n");
+	unkadr += naddrs;
+	return;
+    }
+
+    if (nm_wtend () == NOTOK) {
+	fprintf (stderr, "error in transmission; unable to queue message\n");
+	unkadr += naddrs;
+	return;
+    }
+}
+#endif	/* MHMTS */