X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/8bf4e8784aa2a0438ba09b1a0eb9207d3baf6bd9..04ee0c3f6ad7e4177cc43a0c57f046013a4fbac9:/uip/send.c diff --git a/uip/send.c b/uip/send.c index 626593ef..d5ac70e5 100644 --- a/uip/send.c +++ b/uip/send.c @@ -1,17 +1,25 @@ - -/* - * send.c -- send a composed message +/* send.c -- send a composed message * * 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/push.h" +#include "sbr/path.h" +#include "sbr/print_version.h" +#include "sbr/print_help.h" +#include "sbr/arglist.h" +#include "sbr/error.h" #include -#include -#include - +#include "h/done.h" +#include "h/utils.h" +#ifdef OAUTH_SUPPORT +#include "h/oauth.h" +#endif +#include "sbr/m_maildir.h" +#include "sbr/m_mktemp.h" #ifndef CYRUS_SASL # define SASLminc(a) (a) @@ -60,17 +68,17 @@ X("server host", 6, SERVSW) \ X("snoop", 5, SNOOPSW) \ X("sasl", SASLminc(4), SASLSW) \ - X("nosasl", SASLminc(-6), NOSASLSW) \ - X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ - X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \ + X("nosasl", SASLminc(6), NOSASLSW) \ + X("saslmech mechanism", SASLminc(6), SASLMECHSW) \ + X("authservice", SASLminc(0), AUTHSERVICESW) \ X("user username", SASLminc(-4), USERSW) \ - X("attach", 6, ATTACHSW) \ - X("noattach", 0, NOATTACHSW) \ - X("attachformat", 7, ATTACHFORMATSW) \ X("port server-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("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ @@ -96,12 +104,12 @@ DEFINE_SWITCH_ARRAY(USE, anyl); #undef X extern int debugsw; /* from sendsbr.c */ -extern int forwsw; +extern bool forwsw; extern int inplace; -extern int pushsw; +extern bool pushsw; extern int splitsw; -extern int unique; -extern int verbsw; +extern bool unique; +extern bool verbsw; extern char *altmsg; /* .. */ extern char *annotext; @@ -111,24 +119,18 @@ extern char *distfile; int main (int argc, char **argv) { - int msgp = 0, distsw = 0, vecp; - int isdf = 0, mime = 0; + int msgp = 0, vecp; + int isdf = 0; int msgnum, status; char *cp, *dfolder = NULL, *maildir = NULL; char buf[BUFSIZ], **ap, **argp, **arguments, *program; char *msgs[MAXARGS], **vec; + const char *user = NULL, *saslmech = NULL; struct msgs *mp; struct stat st; - char *attach = NMH_ATTACH_HEADER; /* header field name for attachments */ - int attachformat = 1; /* mhbuild format specifier for attachments */ - -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); + char *auth_svc = NULL; - /* read user profile/context */ - context_read(); + if (nmh_init(argv[0], true, true)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -136,16 +138,22 @@ main (int argc, char **argv) vec = argsplit(postproc, &program, &vecp); vec[vecp++] = "-library"; - vec[vecp++] = getcpy (m_maildir ("")); + vec[vecp++] = mh_xstrdup(m_maildir("")); if ((cp = context_find ("fileproc"))) { - vec[vecp++] = "-fileproc"; - vec[vecp++] = cp; + vec[vecp++] = "-fileproc"; + vec[vecp++] = cp; } if ((cp = context_find ("mhlproc"))) { - vec[vecp++] = "-mhlproc"; - vec[vecp++] = cp; + vec[vecp++] = "-mhlproc"; + vec[vecp++] = cp; + } + + if ((cp = context_find ("credentials"))) { + /* post doesn't read context so need to pass credentials. */ + vec[vecp++] = "-credentials"; + vec[vecp++] = cp; } while ((cp = *argp++)) { @@ -155,7 +163,7 @@ main (int argc, char **argv) ambigsw (cp, switches); done (1); case UNKWNSW: - adios (NULL, "-%s unknown\n", cp); + die("-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [file] [switches]", invo_name); @@ -171,15 +179,15 @@ main (int argc, char **argv) case DFOLDSW: if (dfolder) - adios (NULL, "only one draft folder at a time!"); + die("only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); msgs[msgp++] = cp; continue; case NDFLDSW: @@ -188,51 +196,54 @@ main (int argc, char **argv) continue; case PUSHSW: - pushsw++; + pushsw = true; continue; case NPUSHSW: - pushsw = 0; + pushsw = false; continue; case SPLITSW: if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case UNIQSW: - unique++; + unique = true; continue; case NUNIQSW: - unique = 0; + unique = false; continue; case FORWSW: - forwsw++; + forwsw = true; continue; case NFORWSW: - forwsw = 0; + forwsw = false; continue; case VERBSW: - verbsw++; + verbsw = true; vec[vecp++] = --cp; continue; case NVERBSW: - verbsw = 0; + verbsw = false; vec[vecp++] = --cp; continue; case MIMESW: - mime++; vec[vecp++] = --cp; continue; case NMIMESW: - mime = 0; + vec[vecp++] = --cp; + continue; + + case SNOOPSW: vec[vecp++] = --cp; continue; case DEBUGSW: - debugsw++; /* fall */ + debugsw++; + /* FALLTHRU */ case NFILTSW: case FRMTSW: case NFRMTSW: @@ -242,54 +253,52 @@ main (int argc, char **argv) case NMSGDSW: case WATCSW: case NWATCSW: - case SNOOPSW: case SASLSW: case NOSASLSW: case TLSSW: case INITTLSSW: case NTLSSW: + case CERTVERSW: + case NOCERTVERSW: vec[vecp++] = --cp; continue; + case USERSW: + vec[vecp++] = --cp; + if (!(cp = *argp++) || *cp == '-') + die("missing argument to %s", argp[-2]); + vec[vecp++] = cp; + user = cp; + continue; + + case AUTHSERVICESW: +#ifdef OAUTH_SUPPORT + if (!(auth_svc = *argp++) || *auth_svc == '-') + die("missing argument to %s", argp[-2]); +#else + die("not built with OAuth support"); +#endif + continue; + + case SASLMECHSW: + if (!(saslmech = *argp) || *saslmech == '-') + die("missing argument to %s", argp[-1]); + /* FALLTHRU */ + case ALIASW: case FILTSW: case WIDTHSW: case CLIESW: case SERVSW: - case SASLMECHSW: - case SASLMXSSFSW: - case USERSW: case PORTSW: + case MTSSM: case MTSSW: case MESSAGEIDSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); vec[vecp++] = cp; continue; - - case ATTACHSW: - if (!(attach = *argp++) || *attach == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - case NOATTACHSW: - attach = NULL; - continue; - - case ATTACHFORMATSW: - if (! *argp || **argp == '-') - adios (NULL, "missing argument to %s", argp[-1]); - else { - attachformat = atoi (*argp); - if (attachformat < 0 || - attachformat > ATTACHFORMATS - 1) { - advise (NULL, "unsupported attachformat %d", - attachformat); - continue; - } - } - ++argp; - continue; } } else { msgs[msgp++] = cp; @@ -302,7 +311,7 @@ main (int argc, char **argv) if ((cp = context_find ("Aliasfile"))) { char *dp = NULL; - for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) { + for (ap = brkstring(dp = mh_xstrdup(cp), " ", "\n"); ap && *ap; ap++) { vec[vecp++] = "-alias"; vec[vecp++] = *ap; } @@ -310,18 +319,12 @@ main (int argc, char **argv) if (dfolder == NULL) { if (msgp == 0) { -#ifdef WHATNOW - if ((cp = getenv ("mhdraft")) && *cp) { - msgs[msgp++] = cp; - goto go_to_it; - } -#endif /* WHATNOW */ - msgs[msgp++] = getcpy (m_draft (NULL, NULL, 1, &isdf)); + msgs[msgp++] = mh_xstrdup(m_draft(NULL, NULL, 1, &isdf)); if (stat (msgs[0], &st) == NOTOK) adios (msgs[0], "unable to stat draft file"); cp = concat ("Use \"", msgs[0], "\"? ", NULL); for (status = LISTDSW; status != YESW;) { - if (!(argp = getans (cp, anyl))) + if (!(argp = read_switch_multiword (cp, anyl))) done (1); switch (status = smatch (*argp, anyl)) { case NOSW: @@ -332,13 +335,13 @@ main (int argc, char **argv) showfile (++argp, msgs[0]); break; default: - advise (NULL, "say what?"); + inform("say what?"); break; } } } else { for (msgnum = 0; msgnum < msgp; msgnum++) - msgs[msgnum] = getcpy (m_maildir (msgs[msgnum])); + msgs[msgnum] = mh_xstrdup(m_maildir(msgs[msgnum])); } } else { if (!context_find ("path")) @@ -353,11 +356,11 @@ main (int argc, char **argv) /* read folder and create message structure */ if (!(mp = folder_read (dfolder, 1))) - adios (NULL, "unable to read folder %s", dfolder); + die("unable to read folder %s", dfolder); /* check for empty folder */ if (mp->nummsg == 0) - adios (NULL, "no messages in %s", dfolder); + die("no messages in %s", dfolder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgp; msgnum++) @@ -367,7 +370,7 @@ main (int argc, char **argv) for (msgp = 0, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { - msgs[msgp++] = getcpy (m_name (msgnum)); + msgs[msgp++] = mh_xstrdup(m_name (msgnum)); unset_exists (mp, msgnum); } } @@ -382,7 +385,7 @@ go_to_it: if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0) if ((cp = context_find ("signature")) && *cp) - m_putenv ("SIGNATURE", cp); + setenv("SIGNATURE", cp, 1); for (msgnum = 0; msgnum < msgp; msgnum++) if (stat (msgs[msgnum], &st) == NOTOK) @@ -397,11 +400,14 @@ go_to_it: if ((cp = getenv ("mhdist")) && *cp - && (distsw = atoi (cp)) + && atoi(cp) && altmsg) { vec[vecp++] = "-dist"; - distfile = getcpy (m_mktemp2 (altmsg, invo_name, NULL, NULL)); - unlink(distfile); + if ((cp = m_mktemp2(altmsg, invo_name, NULL, NULL)) == NULL) { + die("unable to create temporary file"); + } + distfile = mh_xstrdup(cp); + (void) m_unlink(distfile); if (link (altmsg, distfile) == NOTOK) { /* Cygwin with FAT32 filesystem produces EPERM. */ if (errno != EXDEV && errno != EPERM @@ -411,7 +417,11 @@ go_to_it: ) adios (distfile, "unable to link %s to", altmsg); free (distfile); - distfile = getcpy (m_mktemp2(NULL, invo_name, NULL, NULL)); + if ((cp = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { + die("unable to create temporary file in %s", + get_temp_dir()); + } + distfile = mh_xstrdup(cp); { int in, out; struct stat st; @@ -430,6 +440,22 @@ go_to_it: distfile = NULL; } +#ifdef OAUTH_SUPPORT + if (auth_svc == NULL) { + if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { + die("must specify -authservice with -saslmech xoauth2"); + } + } else { + if (user == NULL) { + die("must specify -user with -saslmech xoauth2"); + } + } +#else + NMH_UNUSED(auth_svc); + NMH_UNUSED(user); + NMH_UNUSED(saslmech); +#endif /* OAUTH_SUPPORT */ + if (altmsg == NULL || stat (altmsg, &st) == NOTOK) { st.st_mtime = 0; st.st_dev = 0; @@ -442,12 +468,13 @@ go_to_it: closefds (3); for (msgnum = 0; msgnum < msgp; msgnum++) { - switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1, attach, - attachformat)) { + switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1, auth_svc)) { case DONE: done (++status); + /* FALLTHRU */ case NOTOK: - status++; /* fall */ + status++; + /* FALLTHRU */ case OK: break; }