X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/68246559a5087f3a3c13ef2a6240a7c18dd9c155..ec173fd2c:/uip/post.c?ds=sidebyside diff --git a/uip/post.c b/uip/post.c index e78677f8..86c53ae7 100644 --- a/uip/post.c +++ b/uip/post.c @@ -1,29 +1,46 @@ - -/* - * post.c -- enter messages into the mail transport system +/* post.c -- enter messages into the mail transport system * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ -#include +#include "h/mh.h" +#include "sbr/dtime.h" +#include "sbr/m_getfld.h" +#include "sbr/getarguments.h" +#include "sbr/concat.h" +#include "sbr/smatch.h" +#include "sbr/cpydata.h" +#include "sbr/cpydgst.h" +#include "sbr/uprf.h" +#include "sbr/context_foil.h" +#include "sbr/readconfig.h" +#include "sbr/ambigsw.h" +#include "sbr/pidstatus.h" +#include "sbr/print_version.h" +#include "sbr/print_help.h" +#include "sbr/arglist.h" +#include "sbr/error.h" #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "h/signals.h" +#include "h/addrsbr.h" +#include "h/aliasbr.h" +#include "h/dropsbr.h" +#include "h/mime.h" +#include "h/done.h" +#include "h/utils.h" +#include "h/tws.h" +#include "h/mts.h" +#include "sbr/m_mktemp.h" +#include "sbr/message_id.h" #ifdef HAVE_SYS_TIME_H # include #endif #include -#include +#include "mts/smtp/smtp.h" #ifndef CYRUS_SASL # define SASLminc(a) (a) @@ -40,7 +57,7 @@ #ifndef OAUTH_SUPPORT # define OAUTHminc(a) (a) #else /* OAUTH_SUPPORT */ -# define OAUTHmine(a) 0 +# define OAUTHminc(a) 0 #endif /* OAUTH_SUPPORT */ #define FCCS 10 /* max number of fccs allowed */ @@ -82,28 +99,30 @@ X("server host", 6, SERVSW) /* specify alternate SMTP server */ \ X("snoop", -5, SNOOPSW) /* snoop the SMTP transaction */ \ X("partno", -6, PARTSW) \ - X("sasl", SASLminc(-4), SASLSW) \ - X("nosasl", SASLminc(-6), NOSASLSW) \ - X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ - X("saslmech", SASLminc(-5), SASLMECHSW) \ + X("sasl", SASLminc(4), SASLSW) \ + X("nosasl", SASLminc(6), NOSASLSW) \ + X("saslmech", SASLminc(5), SASLMECHSW) \ X("user", SASLminc(-4), USERSW) \ X("port server submission port name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NTLSSW) \ + X("certverify", TLSminc(-10), CERTVERSW) \ + X("nocertverify", TLSminc(-12), NOCERTVERSW) \ X("fileproc", -4, FILEPROCSW) \ X("mhlproc", -3, MHLPROCSW) \ X("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("credentials legacy|file:filename", 0, CREDENTIALSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ - X("oauthcredfile", OAUTHminc(-7), OAUTHCREDFILESW) \ - X("oauthclientid", OAUTHminc(-12), OAUTHCLIDSW) \ - X("oauthclientsecret", OAUTHminc(-12), OAUTHCLSECSW) \ - X("oauthauthendpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \ - X("oauthredirect", OAUTHminc(-6), OAUTHREDIRSW) \ - X("oauthtokenendpoint", OAUTHminc(-6), OAUTHTOKENDSW) \ - X("oauthscope", OAUTHminc(-6), OAUTHSCOPESW) \ + X("authservice auth-service-name", OAUTHminc(-11), AUTHSERVICESW) \ + X("oauthcredfile credential-file", OAUTHminc(-7), OAUTHCREDFILESW) \ + X("oauthclientid client-id", OAUTHminc(-12), OAUTHCLIDSW) \ + X("oauthclientsecret client-secret", OAUTHminc(-12), OAUTHCLSECSW) \ + X("oauthauthendpoint authentication-endpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \ + X("oauthredirect redirect-uri", OAUTHminc(-6), OAUTHREDIRSW) \ + X("oauthtokenendpoint token-endpoint", OAUTHminc(-6), OAUTHTOKENDSW) \ + X("oauthscope scope", OAUTHminc(-6), OAUTHSCOPESW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(POST); @@ -114,6 +133,26 @@ DEFINE_SWITCH_ARRAY(POST, switches); #undef X +/* + * Mapping between command-line switches and profile entries, communicated + * from 'send'. We use a service name of 'post' internally. + */ + +static struct { + const char *profname; + int switchnum; + const char *value; +} oauthswitches[] = { + { "oauth-%s-credential-file", OAUTHCREDFILESW, NULL }, + { "oauth-%s-client_id", OAUTHCLIDSW, NULL }, + { "oauth-%s-client_secret", OAUTHCLSECSW, NULL }, + { "oauth-%s-auth_endpoint", OAUTHAUTHENDSW, NULL }, + { "oauth-%s-redirect_uri", OAUTHREDIRSW, NULL }, + { "oauth-%s-token_endpoint", OAUTHTOKENDSW, NULL }, + { "oauth-%s-scope", OAUTHSCOPESW, NULL }, + { NULL, 0, NULL } +}; + struct headers { char *value; unsigned int flags; @@ -137,6 +176,8 @@ struct headers { #define HDCC 0x0400 /* another undocumented feature */ #define HONE 0x0800 /* Only (zero or) one address allowed */ #define HEFM 0x1000 /* Envelope-From: header */ +#define HMIM 0x2000 /* MIME-Version: header */ +#define HCTE 0x4000 /* Content-Transfer-Encoding: header */ /* * flags for headers->set @@ -147,9 +188,9 @@ struct headers { #define MVIS 0x0008 /* we've seen sighted addrs */ #define MINV 0x0010 /* we've seen blind addrs */ #define MSND 0x0020 /* we've seen a Sender: */ -#define MRSN 0x0040 /* We've seen a Resent-Sendr:*/ +#define MRSN 0x0040 /* We've seen a Resent-Sender: */ #define MEFM 0x0080 /* We've seen Envelope-From: */ - +#define MMIM 0x0100 /* We've seen Mime-Version: */ static struct headers NHeaders[] = { { "Return-Path", HBAD, 0 }, @@ -166,6 +207,8 @@ static struct headers NHeaders[] = { { "Message-ID", HBAD, 0 }, { "Fcc", HFCC, 0 }, { "Envelope-From", HADR|HONE|HEFM, MEFM }, + { "MIME-Version", HMIM, MMIM }, + { "Content-Transfer-Encoding", HCTE, 0 }, { NULL, 0, 0 } }; @@ -189,6 +232,8 @@ static struct headers RHeaders[] = { { "Bcc", HADR|HTRY|HBCC|HNIL, 0 }, { "Fcc", HIGN, 0 }, { "Envelope-From", HADR|HONE|HEFM, MEFM }, + { "MIME-Version", HMIM, MMIM }, + { "Content-Transfer-Encoding", HCTE, 0 }, { NULL, 0, 0 } }; @@ -196,28 +241,27 @@ static short fccind = 0; /* index into fccfold[] */ static short outputlinelen = OUTPUTLINELEN; static int pfd = NOTOK; /* fd to write annotation list to */ -static int recipients = 0; /* how many people will get a copy */ +static bool recipients; /* 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 for Bcc */ -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 bool badmsg; /* message has bad semantics */ +static bool verbose; /* spell it out */ +static bool format = true; /* format addresses */ +static bool mime; /* use MIME-style encapsulations for Bcc */ +static bool msgid; /* add msgid */ +static bool debug; /* debugging post */ +static bool watch; /* watch the delivery process */ +static bool whomsw; /* we are whom not post */ +static bool checksw; /* whom -check */ static int linepos=0; /* putadr()'s position on the line */ static int nameoutput=0; /* putadr() has output header name */ -static int sasl=0; /* Use SASL auth for SMTP */ -static int saslssf=-1; /* Our maximum SSF for SASL */ +static bool sasl; /* Use SASL auth for SMTP */ static char *saslmech=NULL; /* Force use of particular SASL mech */ static char *user=NULL; /* Authenticate as this user */ static char *port="submission"; /* Name of server port for SMTP submission */ -static int tls=-1; /* Use TLS for encryption */ +static int tlsflag=0; /* Flags to control TLS settings */ static int fromcount=0; /* Count of addresses on From: header */ -static int seensender=0; /* Have we seen a Sender: header? */ +static bool seensender; /* Have we seen a Sender: header? */ static unsigned msgflags = 0; /* what we've seen */ @@ -239,6 +283,8 @@ static char fullfrom[BUFSIZ]; /* full contents of From header */ static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ static char *fccfold[FCCS]; /* foldernames for FCC'ing */ +enum encoding { UNKNOWN = 0, BINARY = 1, SEVENBIT = 7, EIGHTBIT = 8 }; +static enum encoding cte = UNKNOWN; static struct headers *hdrtab; /* table for the message we're doing */ @@ -247,7 +293,7 @@ static struct mailname netaddrs; /* network addrs */ static struct mailname uuaddrs; /* uucp addrs */ static struct mailname tmpaddrs; /* temporary queue */ -static int snoop = 0; +static bool snoop; static char *clientsw = NULL; static char *serversw = NULL; @@ -258,11 +304,12 @@ static char *partno = NULL; /* * static prototypes */ -static void putfmt (char *, char *, FILE *); +static void putfmt (char *, char *, int *, FILE *); static void start_headers (void); static void finish_headers (FILE *); -static int get_header (char *, struct headers *); -static int putadr (char *, char *, struct mailname *, FILE *, unsigned int); +static int get_header (char *, struct headers *) PURE; +static int putadr (char *, char *, struct mailname *, FILE *, unsigned int, + char *, unsigned int); static void putgrp (char *, char *, FILE *, unsigned int); static int insert (struct mailname *); static void pl (void); @@ -270,14 +317,14 @@ static void anno (void); static int annoaux (struct mailname *); static void insert_fcc (struct headers *, char *); static void make_bcc_file (int); -static void verify_all_addresses (int, char *); +static void verify_all_addresses (int, int, char *, int, char *); static void chkadr (void); static void sigon (void); static void sigoff (void); static void p_refile (char *); static void fcc (char *, char *); -static void die (char *, char *, ...); -static void post (char *, int, int, char *); +static void fatal (char *, char *, ...) CHECK_PRINTF(2, 3); +static void post (char *, int, int, int, char *, int, char *); static void do_text (char *file, int fd); static void do_an_address (struct mailname *, int); static void do_addresses (int, int); @@ -287,26 +334,30 @@ static int find_prefix (void); int main (int argc, char **argv) { - int state, compnum, dashstuff = 0; + int state, compnum, dashstuff = 0, swnum; + bool oauth_flag = false; + int tls = -1; + bool noverify = false; + int eai = 0; /* use Email Address Internationalization (EAI) (SMTPUTF8) */ char *cp, *msg = NULL, **argp, **arguments, *envelope; - char buf[BUFSIZ], name[NAMESZ]; + char buf[NMH_BUFSIZ], name[NAMESZ], *auth_svc = NULL; FILE *in, *out; - m_getfld_state_t gstate = 0; + m_getfld_state_t gstate; - if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } + if (nmh_init(argv[0], false, false)) { return 1; } - mts_init (invo_name); + mts_init (); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { - switch (smatch (++cp, switches)) { + switch ((swnum = smatch (++cp, switches))) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: - adios (NULL, "-%s unknown", cp); + die("-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); @@ -318,7 +369,7 @@ main (int argc, char **argv) case LIBSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); /* create a minimal context */ if (context_foil (cp) == -1) done (1); @@ -326,21 +377,21 @@ main (int argc, char **argv) case ALIASW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); if ((state = alias (cp)) != AK_OK) - adios (NULL, "aliasing error in %s - %s", + die("aliasing error in %s - %s", cp, akerror (state)); continue; case CHKSW: - checksw++; + checksw = true; continue; case NCHKSW: - checksw = 0; + checksw = false; continue; case DEBUGSW: - debug++; + debug = true; continue; case DISTSW: @@ -349,18 +400,18 @@ main (int argc, char **argv) case FILTSW: if (!(filter = *argp++) || *filter == '-') - adios (NULL, "missing argument to %s", argp[-2]); - mime = 0; + die("missing argument to %s", argp[-2]); + mime = false; continue; case NFILTSW: filter = NULL; continue; case FRMTSW: - format++; + format = true; continue; case NFRMTSW: - format = 0; + format = false; continue; case BITSTUFFSW: @@ -371,96 +422,124 @@ main (int argc, char **argv) continue; case MIMESW: - mime++; + mime = true; filter = NULL; continue; case NMIMESW: - mime = 0; + mime = false; continue; case MSGDSW: - msgid++; + msgid = true; continue; case NMSGDSW: - msgid = 0; + msgid = false; continue; case VERBSW: - verbose++; + verbose = true; continue; case NVERBSW: - verbose = 0; + verbose = false; continue; case WATCSW: - watch++; + watch = true; continue; case NWATCSW: - watch = 0; + watch = false; continue; case WHOMSW: - whomsw++; + whomsw = true; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); if ((outputlinelen = atoi (cp)) < 10) - adios (NULL, "impossible width %d", outputlinelen); + die("impossible width %d", outputlinelen); continue; case ANNOSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); if ((pfd = atoi (cp)) <= 2) - adios (NULL, "bad argument %s %s", argp[-2], cp); + die("bad argument %s %s", argp[-2], cp); continue; case CLIESW: if (!(clientsw = *argp++) || *clientsw == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case SERVSW: if (!(serversw = *argp++) || *serversw == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case SNOOPSW: - snoop++; + snoop = true; continue; case PARTSW: if (!(partno = *argp++) || *partno == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case SASLSW: - sasl++; + sasl = true; continue; case NOSASLSW: - sasl = 0; + sasl = false; continue; - case SASLMXSSFSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - saslssf = atoi(cp); - continue; - case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; - + + case AUTHSERVICESW: + if (!(auth_svc = *argp++) || *auth_svc == '-') + die("missing argument to %s", argp[-2]); + oauth_flag = true; + continue; + + case OAUTHCREDFILESW: + case OAUTHCLIDSW: + case OAUTHCLSECSW: + case OAUTHAUTHENDSW: + case OAUTHREDIRSW: + case OAUTHTOKENDSW: + case OAUTHSCOPESW: + { + int i; + + if (!(cp = *argp++) || *cp == '-') + die("missing argument to %s", argp[-2]); + + for (i = 0; oauthswitches[i].profname != NULL; i++) { + if (oauthswitches[i].switchnum == swnum) { + oauthswitches[i].value = cp; + break; + } + } + + if (oauthswitches[i].profname == NULL) + die("internal error: cannot map switch %s " + "to profile entry", argp[-2]); + + oauth_flag = true; + continue; + } + case USERSW: if (!(user = *argp++) || *user == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case PORTSW: if (!(port = *argp++) || *port == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case TLSSW: @@ -475,65 +554,72 @@ main (int argc, char **argv) tls = 0; continue; + case CERTVERSW: + noverify = false; + continue; + + case NOCERTVERSW: + noverify = true; + continue; + case FILEPROCSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); fileproc = cp; continue; case MHLPROCSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); mhlproc = cp; continue; case MTSSM: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); sendmail = cp; continue; case MTSSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); save_mts_method (cp); continue; case CREDENTIALSSW: { if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); add_profile_entry ("credentials", cp); continue; } case MESSAGEIDSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); if (save_message_id_style (cp) != 0) - adios (NULL, "unsupported messageid \"%s\"", cp); + die("unsupported messageid \"%s\"", cp); continue; } } if (msg) - adios (NULL, "only one message at a time!"); - else - msg = cp; + die("only one message at a time!"); + msg = cp; } alias (AliasFile); if (!msg) - adios (NULL, "usage: %s [switches] file", invo_name); + die("usage: %s [switches] file", invo_name); if (outputlinelen < 10) - adios (NULL, "impossible width %d", outputlinelen); + die("impossible width %d", outputlinelen); if ((in = fopen (msg, "r")) == NULL) adios (msg, "unable to open"); start_headers (); if (debug) { - verbose++; + verbose = true; out = stdout; } else { if (whomsw) { @@ -542,7 +628,7 @@ main (int argc, char **argv) } else { char *cp = m_mktemp2(NULL, invo_name, NULL, &out); if (cp == NULL) { - adios(NULL, "unable to create temporary file in %s", + die("unable to create temporary file in %s", get_temp_dir()); } strncpy(tmpfil, cp, sizeof(tmpfil)); @@ -551,19 +637,20 @@ main (int argc, char **argv) hdrtab = msgstate == NORMAL ? NHeaders : RHeaders; + gstate = m_getfld_state_init(in); for (compnum = 1;;) { int bufsz = sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) { + switch (state = m_getfld2(&gstate, name, buf, &bufsz)) { case FLD: case FLDPLUS: - compnum++; - cp = add (buf, NULL); + compnum++; + cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, in); + state = m_getfld2(&gstate, name, buf, &bufsz); cp = add (buf, cp); } - putfmt (name, cp, out); + putfmt (name, cp, &eai, out); free (cp); continue; @@ -574,7 +661,7 @@ main (int argc, char **argv) fprintf (out, "\n%s", buf); while (state == BODY) { bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, in); + state = m_getfld2(&gstate, name, buf, &bufsz); fputs (buf, out); } break; @@ -585,10 +672,10 @@ main (int argc, char **argv) case LENERR: case FMTERR: - adios (NULL, "message format error in component #%d", compnum); + die("message format error in component #%d", compnum); default: - adios (NULL, "getfld() returned %d", state); + die("getfld() returned %d", state); } break; } @@ -601,9 +688,8 @@ main (int argc, char **argv) if (debug) { pl (); done (0); - } else { - fclose (out); } + fclose (out); /* * Here's how we decide which address to use as the envelope-from @@ -637,10 +723,45 @@ main (int argc, char **argv) #endif /* ! TLS_SUPPORT */ } + if (tls == 1) + tlsflag = S_STARTTLS; + else if (tls == 2) + tlsflag = S_INITTLS; + else + tlsflag = 0; + + if (noverify) + tlsflag |= S_NOVERIFY; + + /* + * If we were given any oauth flags, store the appropriate profile + * entries and make sure an authservice was given (we have to do this + * here because we aren't guaranteed the authservice will be given on + * the command line before the other OAuth flags are given). + */ + + if (oauth_flag) { + int i; + char sbuf[128]; + + if (auth_svc == NULL) { + die("No authentication service given with -authservice"); + } + + for (i = 0; oauthswitches[i].profname != NULL; i++) { + if (oauthswitches[i].value != NULL) { + snprintf(sbuf, sizeof(sbuf), + oauthswitches[i].profname, auth_svc); + sbuf[sizeof(sbuf) - 1] = '\0'; + add_profile_entry(sbuf, oauthswitches[i].value); + } + } + } + /* If we are doing a "whom" check */ if (whomsw) { /* This won't work with MTS_SENDMAIL_PIPE. */ - verify_all_addresses (1, envelope); + verify_all_addresses (1, eai, envelope, oauth_flag, auth_svc); done (0); } @@ -652,14 +773,15 @@ main (int argc, char **argv) verify_all_addresses with MTS_SENDMAIL_PIPE, but that might require running sendmail as root. Note that spost didn't verify addresses. */ - verify_all_addresses (verbose, envelope); + verify_all_addresses (verbose, eai, envelope, oauth_flag, + auth_svc); } - post (tmpfil, 0, verbose, envelope); + post (tmpfil, 0, verbose, eai, envelope, oauth_flag, auth_svc); } - post (bccfil, 1, verbose, envelope); + post (bccfil, 1, verbose, eai, envelope, oauth_flag, auth_svc); (void) m_unlink (bccfil); } else { - post (tmpfil, 0, isatty (1), envelope); + post (tmpfil, 0, isatty (1), eai, envelope, oauth_flag, auth_svc); } p_refile (tmpfil); @@ -669,7 +791,7 @@ main (int argc, char **argv) if (partno) printf ("Partial Message #%s Processed\n", partno); else - printf ("Message Processed\n"); + puts("Message Processed"); } done (0); @@ -682,11 +804,15 @@ main (int argc, char **argv) */ static void -putfmt (char *name, char *str, FILE *out) +putfmt (char *name, char *str, int *eai, FILE *out) { - int count, grp, i, keep; + int count; + bool grp; + int i, keep; char *cp, *pp, *qp; char namep[BUFSIZ], error[BUFSIZ]; + char *savehdr = NULL; + unsigned int savehdrlen = 0; struct mailname *mp = NULL, *np = NULL; struct headers *hdr; @@ -694,23 +820,38 @@ putfmt (char *name, char *str, FILE *out) str++; if (msgstate == NORMAL && uprf (name, "resent")) { - advise (NULL, "illegal header line -- %s:", name); - badmsg++; + inform("illegal header line -- %s:", name); + badmsg = true; return; } + if (! *eai) { + /* Check each header field value to see if it has any 8-bit characters. + If it does, enable EAI support. */ + if (contains8bit(str, NULL)) { + if (verbose) { + puts("EAI/SMTPUTF8 enabled"); + } + + /* Enable SMTPUTF8. */ + *eai = 1; + + /* Enable passing of utf-8 setting to getname()/getadrx(). */ + enable_eai(); + } + } + if ((i = get_header (name, hdrtab)) == NOTOK) { - if (strncasecmp (name, "nmh-", 4)) { + if (strncasecmp (name, "nmh-", 4)) { fprintf (out, "%s: %s", name, str); } else { /* Filter out all Nmh-* headers, because Norm asked. They should never have reached this point. Warn about any that are non-empty. */ if (strcmp (str, "\n")) { - char *newline = strchr (str, '\n'); - if (newline) *newline = '\0'; + trim_suffix_c(str, '\n'); if (! whomsw) { - advise (NULL, "ignoring header line -- %s: %s", name, str); + inform("ignoring header line -- %s: %s", name, str); } } } @@ -723,14 +864,14 @@ putfmt (char *name, char *str, FILE *out) return; } if (hdr->flags & HBAD) { - advise (NULL, "illegal header line -- %s:", name); - badmsg++; + inform("illegal header line -- %s:", name); + badmsg = true; return; } msgflags |= (hdr->set & ~(MVIS | MINV)); if (hdr->flags & HSUB) - subject = subject ? add (str, add ("\t", subject)) : getcpy (str); + subject = subject ? add (str, add ("\t", subject)) : mh_xstrdup(str); if (hdr->flags & HFCC) { if ((cp = strrchr(str, '\n'))) *cp = 0; @@ -741,14 +882,36 @@ putfmt (char *name, char *str, FILE *out) insert_fcc (hdr, pp); return; } - + if (hdr->flags & HCTE) { + if (strncasecmp (str, "7bit", 4) == 0) { + cte = SEVENBIT; + } else if (strncasecmp (str, "8bit", 4) == 0) { + cte = EIGHTBIT; + } else if (strncasecmp (str, "binary", 6) == 0) { + cte = BINARY; + } + } if (!(hdr->flags & HADR)) { fprintf (out, "%s: %s", name, str); return; } + /* + * If this is a From:/Resent-From: header, save the full thing for + * later in case we need it for use when constructing a Bcc draft message. + * Because we want to capture the results of alias expansion, save + * the output from putadr(). + */ + + if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { + savehdr = fullfrom; + savehdr[0] = '\0'; + savehdrlen = sizeof(fullfrom); + } + tmpaddrs.m_next = NULL; - for (count = 0; (cp = getname (str)); count++) + + for (count = 0; (cp = getname (str)); count++) { if ((mp = getm (cp, NULL, 0, error, sizeof(error)))) { if (tmpaddrs.m_next) np->m_next = mp; @@ -761,8 +924,9 @@ putfmt (char *name, char *str, FILE *out) if (hdr->flags & HTRY) badadr++; else - badmsg++; + badmsg = true; } + } if (count < 1) { if (hdr->flags & HNIL) @@ -773,20 +937,20 @@ putfmt (char *name, char *str, FILE *out) */ if ((msgstate == RESENT) ? (hdr->set & MRSN) : (hdr->set & MSND)) { - advise (NULL, "%s: field requires one address", name); - badmsg++; + inform("%s: field requires one address", name); + badmsg = true; } #ifdef notdef - advise (NULL, "%s: field requires at least one address", name); - badmsg++; + inform("%s: field requires at least one address", name); + badmsg = true; #endif /* notdef */ } return; } if (count > 1 && (hdr->flags & HONE)) { - advise (NULL, "%s: field only permits one address", name); - badmsg++; + inform("%s: field only permits one address", name); + badmsg = true; return; } @@ -794,7 +958,7 @@ putfmt (char *name, char *str, FILE *out) snprintf (namep, sizeof(namep), "%s%s", (hdr->flags & HMNG) ? "Original-" : "", name); - for (grp = 0, mp = tmpaddrs.m_next; mp; mp = np) + for (grp = false, mp = tmpaddrs.m_next; mp; mp = np) if (mp->m_nohost) { /* also used to test (hdr->flags & HTRY) */ /* The address doesn't include a host, so it might be an alias. */ pp = akvalue (mp->m_mbox); /* do mh alias substitution */ @@ -829,7 +993,7 @@ putfmt (char *name, char *str, FILE *out) : (hdr->set & MSND)) { strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); sender[sizeof(sender) - 1] = '\0'; - seensender++; + seensender = true; } /* @@ -845,9 +1009,8 @@ putfmt (char *name, char *str, FILE *out) 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); + else if (mp->m_gname) + putgrp (namep, mp->m_gname, out, hdr->flags); if (mp->m_ingrp) { if (sm_mts == MTS_SENDMAIL_PIPE) { /* Catch this before sendmail chokes with: @@ -857,14 +1020,14 @@ putfmt (char *name, char *str, FILE *out) aliases and put them in Bcc:, but then they'd have the Blind-Carbon-Copy indication. */ - adios (NULL, - "blind lists not compatible with" + die( "blind lists not compatible with" " sendmail/pipe"); } - grp++; + grp = true; } - if (putadr (namep, qp, mp, out, hdr->flags)) + if (putadr (namep, qp, mp, out, hdr->flags, savehdr, + savehdrlen)) msgflags |= (hdr->set & (MVIS | MINV)); else mnfree (mp); @@ -895,7 +1058,7 @@ putfmt (char *name, char *str, FILE *out) : (hdr->set & MSND)) { strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); sender[sizeof(sender) - 1] = '\0'; - seensender++; + seensender = true; } /* @@ -912,8 +1075,8 @@ putfmt (char *name, char *str, FILE *out) if (mp->m_gname) putgrp (namep, mp->m_gname, out, hdr->flags); if (mp->m_ingrp) - grp++; - keep = putadr (namep, "", mp, out, hdr->flags); + grp = true; + keep = putadr (namep, "", mp, out, hdr->flags, savehdr, savehdrlen); np = mp->m_next; if (keep) { mp->m_next = NULL; @@ -924,25 +1087,19 @@ putfmt (char *name, char *str, FILE *out) } /* - * If this is a From:/Resent-From: header, save the full thing for - * later in case we need it for use when constructing a Bcc draft message + * If it was a From header, strip off any trailing newlines from + * the alias-expanded From line. */ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { - strncpy(fullfrom, str, sizeof(fullfrom)); - fullfrom[sizeof(fullfrom) - 1] = 0; - /* - * Strip off any trailing newlines - */ - - while (strlen(fullfrom) > 0 && fullfrom[strlen(fullfrom) - 1] == '\n') { + while (*fullfrom && fullfrom[strlen(fullfrom) - 1] == '\n') { fullfrom[strlen(fullfrom) - 1] = '\0'; } } - if (grp > 0 && (hdr->flags & HNGR)) { - advise (NULL, "%s: field does not allow groups", name); - badmsg++; + if (grp && (hdr->flags & HNGR)) { + inform("%s: field does not allow groups", name); + badmsg = true; } if (linepos) { putc ('\n', out); @@ -981,16 +1138,16 @@ finish_headers (FILE *out) /* * A From: header is now required in the draft. */ - advise (NULL, "message has no From: header"); - advise (NULL, "See default components files for examples"); - badmsg++; + inform("message has no From: header"); + inform("See default components files for examples"); + badmsg = true; break; } - if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { - advise (NULL, "A Sender: or Envelope-From: header is required " + if (fromcount > 1 && (!seensender && !(msgflags & MEFM))) { + inform("A Sender: or Envelope-From: header is required " "with multiple\nFrom: addresses"); - badmsg++; + badmsg = true; break; } @@ -1006,12 +1163,12 @@ finish_headers (FILE *out) * from Envelope-From: (which in this case, cannot be blank) */ - if (fromcount > 1 && seensender == 0) { + if (fromcount > 1 && !seensender) { if (efrom[0] == '\0') { - advise (NULL, "Envelope-From cannot be blank when there " + inform("Envelope-From cannot be blank when there " "is multiple From: addresses\nand no Sender: " "header"); - badmsg++; + badmsg = true; } else { fprintf (out, "Sender: %s\n", efrom); } @@ -1023,23 +1180,23 @@ finish_headers (FILE *out) case RESENT: if (!(msgflags & MDAT)) { - advise (NULL, "message has no Date: header"); - badmsg++; + inform("message has no Date: header"); + badmsg = true; } if (!(msgflags & MFRM)) { - advise (NULL, "message has no From: header"); - badmsg++; + inform("message has no From: header"); + badmsg = true; } if (!(msgflags & MRFM)) { - advise (NULL, "message has no Resent-From: header"); - advise (NULL, "See default components files for examples"); - badmsg++; + inform("message has no Resent-From: header"); + inform("See default components files for examples"); + badmsg = true; break; } - if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { - advise (NULL, "A Resent-Sender: or Envelope-From: header is " + if (fromcount > 1 && (!seensender && !(msgflags & MEFM))) { + inform("A Resent-Sender: or Envelope-From: header is " "required with multiple\nResent-From: addresses"); - badmsg++; + badmsg = true; break; } @@ -1056,12 +1213,12 @@ finish_headers (FILE *out) * from Envelope-From (which in this case, cannot be blank) */ - if (fromcount > 1 && seensender == 0) { + if (fromcount > 1 && !seensender) { if (efrom[0] == '\0') { - advise (NULL, "Envelope-From cannot be blank when there " + inform("Envelope-From cannot be blank when there " "is multiple Resent-From: addresses and no " "Resent-Sender: header"); - badmsg++; + badmsg = true; } else { fprintf (out, "Resent-Sender: %s\n", efrom); } @@ -1073,9 +1230,9 @@ finish_headers (FILE *out) } if (badmsg) - adios (NULL, "re-format message and try again"); + die("re-format message and try again"); if (!recipients) - adios (NULL, "no addressees"); + die("no addressees"); } @@ -1084,18 +1241,22 @@ get_header (char *header, struct headers *table) { struct headers *h; + header = FENDNULL(header); for (h = table; h->value; h++) - if (!strcasecmp (header ? header : "", h->value ? h->value : "")) - return (h - table); + if (!strcasecmp(FENDNULL(h->value), header)) + return h - table; return NOTOK; } static int -putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flags) +putadr (char *name, char *aka, struct mailname *mp, FILE *out, + unsigned int flags, char *savehdr, unsigned int savehdrsize) { int len; + bool saveappend = false; + unsigned int shlen; char *cp; char buffer[BUFSIZ]; @@ -1110,8 +1271,13 @@ putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flag linepos += (nameoutput = strlen (name) + 2); } + if (savehdr) { + shlen = strlen(savehdr); + saveappend = true; + } + if (*aka && mp->m_type != UUCPHOST && !mp->m_pers) - mp->m_pers = getcpy (aka); + mp->m_pers = mh_xstrdup(aka); if (format) { if (mp->m_gname) { snprintf (buffer, sizeof(buffer), "%s;", mp->m_gname); @@ -1125,18 +1291,37 @@ putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flag len = strlen (cp); if (linepos != nameoutput) { - if (len + linepos + 2 > outputlinelen) + if (len + linepos + 2 > outputlinelen) { fprintf (out, ",\n%*s", linepos = nameoutput, ""); - else { + if (saveappend) { + if (shlen + 2 + nameoutput + len >= savehdrsize) { + saveappend = false; + } else { + snprintf(savehdr + shlen, savehdrsize - shlen, ",\n%*s", + linepos, ""); + } + } + } else { fputs (", ", out); linepos += 2; + if (saveappend) { + if (shlen + 2 + len >= savehdrsize) { + saveappend = false; + } else { + strncat(savehdr, ", ", savehdrsize - shlen); + } + } } } fputs (cp, out); + + if (saveappend && shlen + len < savehdrsize) + strncat(savehdr, cp, savehdrsize - shlen + len); + linepos += len; - return (flags & HTRY); + return flags & HTRY; } @@ -1186,15 +1371,15 @@ insert (struct mailname *np) : &netaddrs; mp->m_next; mp = mp->m_next) - if (!strcasecmp (np->m_host ? np->m_host : "", - mp->m_next->m_host ? mp->m_next->m_host : "") && - !strcasecmp (np->m_mbox ? np->m_mbox : "", - mp->m_next->m_mbox ? mp->m_next->m_mbox : "") && + if (!strcasecmp (FENDNULL(np->m_host), + FENDNULL(mp->m_next->m_host)) && + !strcasecmp (FENDNULL(np->m_mbox), + FENDNULL(mp->m_next->m_mbox)) && np->m_bcc == mp->m_next->m_bcc) return 0; mp->m_next = np; - recipients++; + recipients = true; return 1; } @@ -1205,29 +1390,29 @@ pl (void) int i; struct mailname *mp; - printf ("-------\n\t-- Addresses --\nlocal:\t"); + fputs("-------\n\t-- Addresses --\nlocal:\t", stdout); 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"); + fputs("\nnet:\t", stdout); for (mp = netaddrs.m_next; mp; mp = mp->m_next) - printf ("%s%s@%s%s%s", mp->m_path ? mp->m_path : "", + printf ("%s%s@%s%s%s", FENDNULL(mp->m_path), mp->m_mbox, mp->m_host, mp->m_bcc ? "[BCC]" : "", mp->m_next ? ",\n\t" : ""); - printf ("\nuucp:\t"); + fputs("\nuucp:\t", stdout); for (mp = uuaddrs.m_next; mp; mp = mp->m_next) printf ("%s!%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"); + fputs("\n\t-- Folder Copies --\nfcc:\t", stdout); for (i = 0; i < fccind; i++) printf ("%s%s", fccfold[i], i + 1 < fccind ? ",\n\t" : ""); - printf ("\n"); + putchar('\n'); } @@ -1263,7 +1448,7 @@ annoaux (struct mailname *mp) snprintf (buffer, sizeof(buffer), "%s\n", adrformat (mp)); i = strlen (buffer); - return (write (pfd, buffer, i) == i ? OK : NOTOK); + return write(pfd, buffer, i) == i ? OK : NOTOK; } @@ -1282,8 +1467,8 @@ insert_fcc (struct headers *hdr, char *pp) return; if (fccind >= FCCS) - adios (NULL, "too many %ss", hdr->value); - fccfold[fccind++] = getcpy (cp); + die("too many %ss", hdr->value); + fccfold[fccind++] = mh_xstrdup(cp); } /* @@ -1300,7 +1485,7 @@ make_bcc_file (int dashstuff) char *tfile = NULL, *program; if ((tfile = m_mktemp2(NULL, "bccs", NULL, &out)) == NULL) { - adios(NULL, "unable to create temporary file in %s", get_temp_dir()); + die("unable to create temporary file in %s", get_temp_dir()); } strncpy (bccfil, tfile, sizeof(bccfil)); @@ -1325,15 +1510,14 @@ make_bcc_file (int dashstuff) * prefix and check again. */ if ((cp = strchr(prefix, 'a')) == NULL) - adios (NULL, "lost prefix start"); + die("lost prefix start"); while (find_prefix () == NOTOK) { if (*cp < 'z') (*cp)++; - else - if (*++cp == 0) - adios (NULL, "can't find a unique delimiter string"); - else - (*cp)++; + else if (*++cp == 0) + die("can't find a unique delimiter string"); + else + (*cp)++; } fprintf (out, "%s: %s\n%s: multipart/digest; boundary=\"", @@ -1350,8 +1534,7 @@ make_bcc_file (int dashstuff) * of MIME encapsulation. */ if (filter != NULL) { - for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) - sleep (5); + child_id = fork(); switch (child_id) { case NOTOK: adios ("fork", "unable to"); @@ -1375,7 +1558,7 @@ make_bcc_file (int dashstuff) execvp (program, vec); fprintf (stderr, "unable to exec "); perror (mhlproc); - _exit (-1); + _exit(1); default: pidXwait (child_id, mhlproc); @@ -1421,7 +1604,7 @@ find_prefix (void) if ((in = fopen (tmpfil, "r")) == NULL) adios (tmpfil, "unable to re-open"); - while (fgets (buffer, sizeof(buffer) - 1, in)) + while (fgets (buffer, sizeof buffer, in)) if (buffer[0] == '-' && buffer[1] == '-') { char *cp; @@ -1440,18 +1623,16 @@ find_prefix (void) } -#define plural(x) (x == 1 ? "" : "s") - static void chkadr (void) { if (badadr && unkadr) - die (NULL, "%d address%s unparsable, %d addressee%s undeliverable", - badadr, plural (badadr), unkadr, plural (badadr)); + fatal (NULL, "%d address%s unparsable, %d addressee%s undeliverable", + badadr, PLURALS(badadr), unkadr, PLURALS(badadr)); if (badadr) - die (NULL, "%d address%s unparsable", badadr, plural (badadr)); + fatal (NULL, "%d address%s unparsable", badadr, PLURALS(badadr)); if (unkadr) - die (NULL, "%d addressee%s undeliverable", unkadr, plural (unkadr)); + fatal (NULL, "%d addressee%s undeliverable", unkadr, PLURALS(unkadr)); } @@ -1466,7 +1647,7 @@ do_addresses (int bccque, int talk) for (lp = localaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) - printf (" -- Local Recipients --\n"); + puts(" -- Local Recipients --"); do_an_address (lp, talk); state++; } @@ -1475,7 +1656,7 @@ do_addresses (int bccque, int talk) for (lp = uuaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) - printf (" -- UUCP Recipients --\n"); + puts(" -- UUCP Recipients --"); do_an_address (lp, talk); state++; } @@ -1484,7 +1665,7 @@ do_addresses (int bccque, int talk) for (lp = netaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) - printf (" -- Network Recipients --\n"); + puts(" -- Network Recipients --"); do_an_address (lp, talk); state++; } @@ -1492,7 +1673,7 @@ do_addresses (int bccque, int talk) chkadr (); if (rp_isbad (retval = sm_waend ())) - die (NULL, "problem ending addresses; %s", rp_string (retval)); + fatal (NULL, "problem ending addresses; %s", rp_string (retval)); } @@ -1506,10 +1687,10 @@ do_addresses (int bccque, int talk) */ static void -post (char *file, int bccque, int talk, char *envelope) +post (char *file, int bccque, int talk, int eai, char *envelope, + int oauth_flag, char *auth_svc) { - int fd; - int retval, i; + int retval; pid_t child_id; if (verbose) { @@ -1517,7 +1698,7 @@ post (char *file, int bccque, int talk, char *envelope) printf (" -- Posting for %s Recipients --\n", bccque ? "Blind" : "Sighted"); else - printf (" -- Posting for All Recipients --\n"); + puts(" -- Posting for All Recipients --"); } sigon (); @@ -1526,8 +1707,7 @@ post (char *file, int bccque, int talk, char *envelope) char **argp, *program; int argc; - for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) - sleep (5); + child_id = fork(); switch (child_id) { case NOTOK: adios ("fork", "unable to"); @@ -1554,15 +1734,33 @@ post (char *file, int bccque, int talk, char *envelope) break; } } else { - if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, - verbose, snoop, sasl, saslssf, - saslmech, user, tls)) || - rp_isbad (retval = sm_winit (envelope))) - die (NULL, "problem initializing server; %s", rp_string (retval)); + const int fd = open (file, O_RDONLY); + int eightbit = 0; + + if (fd == NOTOK) { + fatal (file, "unable to re-open"); + } + + if (msgflags & MMIM && cte != UNKNOWN) { + /* MIME message with C-T-E header. (BINARYMIME isn't + supported, use 8BITMIME instead for binary.) */ + eightbit = cte != SEVENBIT; + } else { + if (scan_input (fd, &eightbit) == NOTOK) { + close (fd); + fatal (file, "problem reading from"); + } + } + + if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, + verbose, snoop, sasl, saslmech, user, + oauth_flag ? auth_svc : NULL, tlsflag)) + || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) { + close (fd); + fatal (NULL, "problem initializing server; %s", rp_string (retval)); + } do_addresses (bccque, talk && verbose); - if ((fd = open (file, O_RDONLY)) == NOTOK) - die (file, "unable to re-open"); do_text (file, fd); close (fd); fflush (stdout); @@ -1575,7 +1773,7 @@ post (char *file, int bccque, int talk, char *envelope) printf (" -- %s Recipient Copies Posted --\n", bccque ? "Blind" : "Sighted"); else - printf (" -- Recipient Copies Posted --\n"); + puts(" -- Recipient Copies Posted --"); } fflush (stdout); @@ -1586,43 +1784,49 @@ post (char *file, int bccque, int talk, char *envelope) /* Address Verification */ static void -verify_all_addresses (int talk, char *envelope) +verify_all_addresses (int talk, int eai, char *envelope, int oauth_flag, + char *auth_svc) { int retval; struct mailname *lp; sigon (); - if (!whomsw || checksw) + if (!whomsw || checksw) { + /* Not sending message body, so don't need to use 8BITMIME. */ + const int eightbit = 0; + if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, - verbose, snoop, sasl, saslssf, - saslmech, user, tls)) - || rp_isbad (retval = sm_winit (envelope))) - die (NULL, "problem initializing server; %s", rp_string (retval)); + verbose, snoop, sasl, saslmech, user, + oauth_flag ? auth_svc : NULL, tlsflag)) + || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) { + fatal (NULL, "problem initializing server; %s", rp_string (retval)); + } + } if (talk && !whomsw) - printf (" -- Address Verification --\n"); + puts(" -- Address Verification --"); if (talk && localaddrs.m_next) - printf (" -- Local Recipients --\n"); + puts(" -- Local Recipients --"); for (lp = localaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); if (talk && uuaddrs.m_next) - printf (" -- UUCP Recipients --\n"); + puts(" -- UUCP Recipients --"); for (lp = uuaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); if (talk && netaddrs.m_next) - printf (" -- Network Recipients --\n"); + puts(" -- Network Recipients --"); for (lp = netaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); chkadr (); if (talk && !whomsw) - printf (" -- Address Verification Successful --\n"); + puts(" -- Address Verification Successful --"); if (!whomsw || checksw) - sm_end (DONE); + sm_end (whomsw ? OK : DONE); fflush (stdout); sigoff (); @@ -1664,14 +1868,14 @@ do_an_address (struct mailname *lp, int talk) return; } if (talk) - printf (": "); + fputs(": ", stdout); fflush (stdout); switch (retval = sm_wadr (mbox, host, lp->m_type != UUCPHOST ? lp->m_path : NULL)) { case RP_OK: if (talk) - printf ("address ok\n"); + puts("address ok"); break; case RP_NO: @@ -1686,7 +1890,7 @@ do_an_address (struct mailname *lp, int talk) default: if (!talk) fprintf (stderr, " %s: ", addr); - die (NULL, "unexpected response; %s", rp_string (retval)); + fatal (NULL, "unexpected response; %s", rp_string (retval)); } fflush (stdout); @@ -1699,15 +1903,15 @@ do_text (char *file, int fd) int retval, state; char buf[BUFSIZ]; - lseek (fd, (off_t) 0, SEEK_SET); + lseek(fd, 0, SEEK_SET); while ((state = read (fd, buf, sizeof(buf))) > 0) { if (rp_isbad (retval = sm_wtxt (buf, state))) - die (NULL, "problem writing text; %s\n", rp_string (retval)); + fatal (NULL, "problem writing text; %s\n", rp_string (retval)); } if (state == NOTOK) - die (file, "problem reading from"); + fatal (file, "problem reading from"); switch (retval = sm_wtend ()) { case RP_OK: @@ -1715,10 +1919,11 @@ do_text (char *file, int fd) case RP_NO: case RP_NDEL: - die (NULL, "posting failed; %s", rp_string (retval)); + fatal (NULL, "posting failed; %s", rp_string (retval)); + break; default: - die (NULL, "unexpected response; %s", rp_string (retval)); + fatal (NULL, "unexpected response; %s", rp_string (retval)); } } @@ -1781,11 +1986,11 @@ p_refile (char *file) return; if (verbose) - printf (" -- Filing Folder Copies --\n"); + puts(" -- Filing Folder Copies --"); for (i = 0; i < fccind; i++) fcc (file, fccfold[i]); if (verbose) - printf (" -- Folder Copies Filed --\n"); + puts(" -- Folder Copies Filed --"); } @@ -1797,7 +2002,7 @@ static void fcc (char *file, char *folder) { pid_t child_id; - int i, status, argp; + int status, argp; char fold[BUFSIZ]; char **arglist, *program; @@ -1805,9 +2010,7 @@ fcc (char *file, char *folder) printf (" %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder); fflush (stdout); - for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) - sleep (5); - + child_id = fork(); switch (child_id) { case NOTOK: if (!verbose) @@ -1830,17 +2033,17 @@ fcc (char *file, char *folder) arglist[argp++] = fold; arglist[argp] = NULL; execvp (program, arglist); - _exit (-1); + _exit(1); default: if ((status = pidwait (child_id, OK))) { if (!verbose) fprintf (stderr, " %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder); - pidstatus (status, verbose ? stdout : stderr, NULL); + pidstatus (status, verbose ? stdout : stderr, fileproc); } else { if (verbose) - printf ("folder ok\n"); + puts("folder ok"); } } @@ -1852,10 +2055,13 @@ fcc (char *file, char *folder) */ static void -die (char *what, char *fmt, ...) +fatal (char *what, char *fmt, ...) { + int err; va_list ap; + err = errno; + (void) m_unlink (tmpfil); if (msgflags & MINV) (void) m_unlink (bccfil); @@ -1864,6 +2070,7 @@ die (char *what, char *fmt, ...) sm_end (NOTOK); va_start(ap, fmt); + errno = err; advertise (what, NULL, fmt, ap); va_end(ap); done (1);