X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/9f8f8b1e1d553774865f2c177191c359c3dc652c..e6c91771:/uip/send.c?ds=inline diff --git a/uip/send.c b/uip/send.c index 7f0529e7..297b8f04 100644 --- a/uip/send.c +++ b/uip/send.c @@ -1,6 +1,4 @@ - -/* - * 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 @@ -9,9 +7,12 @@ #include #include -#include -#include - +#include +#ifdef OAUTH_SUPPORT +# include +#endif +#include "../sbr/m_maildir.h" +#include "../sbr/m_mktemp.h" #ifndef CYRUS_SASL # define SASLminc(a) (a) @@ -25,119 +26,75 @@ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ -static struct swit switches[] = { -#define ALIASW 0 - { "alias aliasfile", 0 }, -#define DEBUGSW 1 - { "debug", -5 }, -#define DRAFTSW 2 - { "draft", 0 }, -#define DFOLDSW 3 - { "draftfolder +folder", 6 }, -#define DMSGSW 4 - { "draftmessage msg", 6 }, -#define NDFLDSW 5 - { "nodraftfolder", 0 }, -#define FILTSW 6 - { "filter filterfile", 0 }, -#define NFILTSW 7 - { "nofilter", 0 }, -#define FRMTSW 8 - { "format", 0 }, -#define NFRMTSW 9 - { "noformat", 0 }, -#define FORWSW 10 - { "forward", 0 }, -#define NFORWSW 11 - { "noforward", 0 }, -#define MIMESW 12 - { "mime", 0 }, -#define NMIMESW 13 - { "nomime", 0 }, -#define MSGDSW 14 - { "msgid", 0 }, -#define NMSGDSW 15 - { "nomsgid", 0 }, -#define PUSHSW 16 - { "push", 0 }, -#define NPUSHSW 17 - { "nopush", 0 }, -#define SPLITSW 18 - { "split seconds", 0 }, -#define UNIQSW 19 - { "unique", -6 }, -#define NUNIQSW 20 - { "nounique", -8 }, -#define VERBSW 21 - { "verbose", 0 }, -#define NVERBSW 22 - { "noverbose", 0 }, -#define WATCSW 23 - { "watch", 0 }, -#define NWATCSW 24 - { "nowatch", 0 }, -#define WIDTHSW 25 - { "width columns", 0 }, -#define VERSIONSW 26 - { "version", 0 }, -#define HELPSW 27 - { "help", 0 }, -#define BITSTUFFSW 28 - { "dashstuffing", -12 }, -#define NBITSTUFFSW 29 - { "nodashstuffing", -14 }, -#define MAILSW 30 - { "mail", -4 }, -#define SAMLSW 31 - { "saml", -4 }, -#define SENDSW 32 - { "send", -4 }, -#define SOMLSW 33 - { "soml", -4 }, -#define CLIESW 34 - { "client host", -6 }, -#define SERVSW 35 - { "server host", 6 }, -#define SNOOPSW 36 - { "snoop", 5 }, -#define SASLSW 37 - { "sasl", SASLminc(4) }, -#define NOSASLSW 38 - { "nosasl", SASLminc(-6) }, -#define SASLMXSSFSW 39 - { "saslmaxssf", SASLminc(-10) }, -#define SASLMECHSW 40 - { "saslmech mechanism", SASLminc(-5) }, -#define USERSW 41 - { "user username", SASLminc(-4) }, -#define ATTACHSW 42 - { "attach", 6 }, -#define NOATTACHSW 43 - { "noattach", 0 }, -#define ATTACHFORMATSW 44 - { "attachformat", 7 }, -#define PORTSW 45 - { "port server-port-name/number" , 4 }, -#define TLSSW 46 - { "tls", TLSminc(-3) }, -#define NTLSSW 47 - { "notls", TLSminc(-5) }, -#define MTSSW 48 - { "mts smtp|sendmail/smtp|sendmail/pipe", 2 }, -#define MESSAGEIDSW 49 - { "messageid localname|random", 2 }, - { NULL, 0 } -}; - -static struct swit anyl[] = { -#define NOSW 0 - { "no", 0 }, -#define YESW 1 - { "yes", 0 }, -#define LISTDSW 2 - { "list", 0 }, - { NULL, 0 } -}; +#define SEND_SWITCHES \ + X("alias aliasfile", 0, ALIASW) \ + X("debug", -5, DEBUGSW) \ + X("draft", 0, DRAFTSW) \ + X("draftfolder +folder", 6, DFOLDSW) \ + X("draftmessage msg", 6, DMSGSW) \ + X("nodraftfolder", 0, NDFLDSW) \ + X("filter filterfile", 0, FILTSW) \ + X("nofilter", 0, NFILTSW) \ + X("format", 0, FRMTSW) \ + X("noformat", 0, NFRMTSW) \ + X("forward", 0, FORWSW) \ + X("noforward", 0, NFORWSW) \ + X("mime", 0, MIMESW) \ + X("nomime", 0, NMIMESW) \ + X("msgid", 0, MSGDSW) \ + X("nomsgid", 0, NMSGDSW) \ + X("push", 0, PUSHSW) \ + X("nopush", 0, NPUSHSW) \ + X("split seconds", 0, SPLITSW) \ + X("unique", -6, UNIQSW) \ + X("nounique", -8, NUNIQSW) \ + X("verbose", 0, VERBSW) \ + X("noverbose", 0, NVERBSW) \ + X("watch", 0, WATCSW) \ + X("nowatch", 0, NWATCSW) \ + X("width columns", 0, WIDTHSW) \ + X("version", 0, VERSIONSW) \ + X("help", 0, HELPSW) \ + X("dashstuffing", -12, BITSTUFFSW) \ + X("nodashstuffing", -14, NBITSTUFFSW) \ + X("client host", -6, CLIESW) \ + X("server host", 6, SERVSW) \ + X("snoop", 5, SNOOPSW) \ + X("sasl", SASLminc(4), SASLSW) \ + X("nosasl", SASLminc(6), NOSASLSW) \ + X("saslmech mechanism", SASLminc(6), SASLMECHSW) \ + X("authservice", SASLminc(0), AUTHSERVICESW) \ + X("user username", SASLminc(-4), USERSW) \ + 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) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(SEND); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(SEND, switches); +#undef X + +#define USE_SWITCHES \ + X("no", 0, NOSW) \ + X("yes", 0, YESW) \ + X("list", 0, LISTDSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(USE); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(USE, anyl); +#undef X extern int debugsw; /* from sendsbr.c */ extern int forwsw; @@ -155,39 +112,42 @@ extern char *distfile; int main (int argc, char **argv) { - int msgp = 0, distsw = 0, vecp = 1; + int msgp = 0, distsw = 0, vecp; int isdf = 0, mime = 0; int msgnum, status; char *cp, *dfolder = NULL, *maildir = NULL; - char buf[BUFSIZ], **ap, **argp, **arguments; - char *msgs[MAXARGS], *vec[MAXARGS]; + 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 */ + int snoop = 0; + char *auth_svc = NULL; -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); - - /* read user profile/context */ - context_read(); + if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; + vec = argsplit(postproc, &program, &vecp); + vec[vecp++] = "-library"; vec[vecp++] = getcpy (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++)) { @@ -273,8 +233,14 @@ main (int argc, char **argv) vec[vecp++] = --cp; continue; + case SNOOPSW: + snoop++; + vec[vecp++] = --cp; + continue; + case DEBUGSW: - debugsw++; /* fall */ + debugsw++; + /* FALLTHRU */ case NFILTSW: case FRMTSW: case NFRMTSW: @@ -284,27 +250,45 @@ main (int argc, char **argv) case NMSGDSW: case WATCSW: case NWATCSW: - case MAILSW: - case SAMLSW: - case SENDSW: - case SOMLSW: - 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 == '-') + adios (NULL, "missing argument to %s", argp[-2]); + vec[vecp++] = cp; + user = cp; + continue; + + case AUTHSERVICESW: +#ifdef OAUTH_SUPPORT + if (!(auth_svc = *argp++) || *auth_svc == '-') + adios (NULL, "missing argument to %s", argp[-2]); +#else + adios (NULL, "not built with OAuth support"); +#endif + continue; + + case SASLMECHSW: + if (!(saslmech = *argp) || *saslmech == '-') + adios (NULL, "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; @@ -312,29 +296,6 @@ main (int argc, char **argv) adios (NULL, "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; @@ -347,7 +308,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; } @@ -355,18 +316,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)); 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: @@ -377,7 +332,7 @@ main (int argc, char **argv) showfile (++argp, msgs[0]); break; default: - advise (NULL, "say what?"); + inform("say what?"); break; } } @@ -397,7 +352,7 @@ main (int argc, char **argv) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ - if (!(mp = folder_read (dfolder))) + if (!(mp = folder_read (dfolder, 1))) adios (NULL, "unable to read folder %s", dfolder); /* check for empty folder */ @@ -412,7 +367,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); } } @@ -427,7 +382,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) @@ -445,8 +400,12 @@ go_to_it: && (distsw = 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) { + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); + } + distfile = mh_xstrdup(cp); + (void) m_unlink(distfile); if (link (altmsg, distfile) == NOTOK) { /* Cygwin with FAT32 filesystem produces EPERM. */ if (errno != EXDEV && errno != EPERM @@ -456,7 +415,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) { + adios(NULL, "unable to create temporary file in %s", + get_temp_dir()); + } + distfile = mh_xstrdup(cp); { int in, out; struct stat st; @@ -475,6 +438,22 @@ go_to_it: distfile = NULL; } +#ifdef OAUTH_SUPPORT + if (auth_svc == NULL) { + if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { + adios (NULL, "must specify -authservice with -saslmech xoauth2"); + } + } else { + if (user == NULL) { + adios (NULL, "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; @@ -484,16 +463,16 @@ go_to_it: push (); status = 0; - vec[0] = r1bindex (postproc, '/'); closefds (3); for (msgnum = 0; msgnum < msgp; msgnum++) { - switch (sendsbr (vec, vecp, 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; }