X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/7b98850d3b8b2453b473fdfb6db52f4aa3fe39b6..b4f2851d:/uip/whatnowsbr.c?ds=sidebyside diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index 42e0d61a..85ba4b90 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -2,8 +2,6 @@ /* * whatnowsbr.c -- the WhatNow shell * - * $Id$ - * * 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. @@ -42,70 +40,57 @@ #include #include -#include #include #include -static struct swit whatnowswitches[] = { -#define DFOLDSW 0 - { "draftfolder +folder", 0 }, -#define DMSGSW 1 - { "draftmessage msg", 0 }, -#define NDFLDSW 2 - { "nodraftfolder", 0 }, -#define EDITRSW 3 - { "editor editor", 0 }, -#define NEDITSW 4 - { "noedit", 0 }, -#define PRMPTSW 5 - { "prompt string", 4 }, -#define VERSIONSW 6 - { "version", 0 }, -#define HELPSW 7 - { "help", 0 }, -#define ATTACHSW 8 - { "attach header-field-name", 0 }, - { NULL, 0 } -}; +#define WHATNOW_SWITCHES \ + X("draftfolder +folder", 0, DFOLDSW) \ + X("draftmessage msg", 0, DMSGSW) \ + X("nodraftfolder", 0, NDFLDSW) \ + X("editor editor", 0, EDITRSW) \ + X("noedit", 0, NEDITSW) \ + X("prompt string", 4, PRMPTSW) \ + X("version", 0, VERSIONSW) \ + X("help", 0, HELPSW) \ + X("attach header-field-name", 0, ATTACHSW) \ + X("noattach", 0, NOATTACHSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(WHATNOW); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(WHATNOW, whatnowswitches); +#undef X /* * Options at the "whatnow" prompt */ -static struct swit aleqs[] = { -#define EDITSW 0 - { "edit [ ]", 0 }, -#define REFILEOPT 1 - { "refile [] +folder", 0 }, -#define BUILDMIMESW 2 - { "mime []", 0 }, -#define DISPSW 3 - { "display []", 0 }, -#define LISTSW 4 - { "list []", 0 }, -#define SENDSW 5 - { "send []", 0 }, -#define PUSHSW 6 - { "push []", 0 }, -#define WHOMSW 7 - { "whom []", 0 }, -#define QUITSW 8 - { "quit [-delete]", 0 }, -#define DELETESW 9 - { "delete", 0 }, -#define CDCMDSW 10 - { "cd [directory]", 0 }, -#define PWDCMDSW 11 - { "pwd", 0 }, -#define LSCMDSW 12 - { "ls", 0 }, -#define ATTACHCMDSW 13 - { "attach", 0 }, -#define DETACHCMDSW 14 - { "detach [-n]", 2 }, -#define ALISTCMDSW 15 - { "alist [-ln] ", 2 }, - { NULL, 0 } -}; +#define PROMPT_SWITCHES \ + X("edit [ ]", 0, EDITSW) \ + X("refile [] +folder", 0, REFILEOPT) \ + X("mime []", 0, BUILDMIMESW) \ + X("display []", 0, DISPSW) \ + X("list []", 0, LISTSW) \ + X("send []", 0, SENDSW) \ + X("push []", 0, PUSHSW) \ + X("whom []", 0, WHOMSW) \ + X("quit [-delete]", 0, QUITSW) \ + X("delete", 0, DELETESW) \ + X("cd [directory]", 0, CDCMDSW) \ + X("pwd", 0, PWDCMDSW) \ + X("ls", 2, LSCMDSW) \ + X("attach", 0, ATTACHCMDSW) \ + X("detach [-n]", 0, DETACHCMDSW) \ + X("alist [-ln] ", 2, ALISTCMDSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(PROMPT); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(PROMPT, aleqs); +#undef X static char *myprompt = "\nWhat now? "; @@ -113,37 +98,33 @@ static char *myprompt = "\nWhat now? "; * static prototypes */ static int editfile (char **, char **, char *, int, struct msgs *, - char *, char *, int); + char *, char *, int, int); static int sendfile (char **, char *, int); static void sendit (char *, char **, char *, int); static int buildfile (char **, char *); static int check_draft (char *); static int whomfile (char **, char *); static int removefile (char *); -static void writelscmd(char *, int, char **); +static void writelscmd(char *, int, char *, char **); static void writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp); static FILE* popen_in_dir(const char *dir, const char *cmd, const char *type); static int system_in_dir(const char *dir, const char *cmd); - - -#ifdef HAVE_LSTAT static int copyf (char *, char *); -#endif int WhatNow (int argc, char **argv) { - int isdf = 0, nedit = 0, use = 0; + int isdf = 0, nedit = 0, use = 0, atfile = 1; char *cp, *dfolder = NULL, *dmsg = NULL; char *ed = NULL, *drft = NULL, *msgnam = NULL; char buf[BUFSIZ], prompt[BUFSIZ]; char **argp, **arguments; struct stat st; - char *attach = (char *)0; /* attachment header field name */ - char cwd[MAXPATHLEN + 1]; /* current working directory */ - char file[MAXPATHLEN + 1]; /* file name buffer */ - char shell[MAXPATHLEN + 1]; /* shell response buffer */ + char *attach = NMH_ATTACH_HEADER;/* attachment header field name */ + char cwd[PATH_MAX + 1]; /* current working directory */ + char file[PATH_MAX + 1]; /* file name buffer */ + char shell[PATH_MAX + 1]; /* shell response buffer */ FILE *f; /* read pointer for bgnd proc */ char *l; /* set on -l to alist command */ int n; /* set on -n to alist command */ @@ -176,10 +157,10 @@ WhatNow (int argc, char **argv) case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [file]", invo_name); print_help (buf, whatnowswitches, 1); - done (1); + done (0); case VERSIONSW: print_version(invo_name); - done (1); + done (0); case DFOLDSW: if (dfolder) @@ -215,11 +196,13 @@ WhatNow (int argc, char **argv) continue; case ATTACHSW: - if (attach != (char *)0) - adios(NULL, "only one attachment header field name at a time!"); if (!(attach = *argp++) || *attach == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; + + case NOATTACHSW: + attach = NULL; + continue; } } if (drft) @@ -233,6 +216,9 @@ WhatNow (int argc, char **argv) msgnam = (cp = getenv ("mhaltmsg")) && *cp ? getcpy (cp) : NULL; + if ((cp = getenv ("mhatfile")) && *cp) + atfile = atoi(cp); + if ((cp = getenv ("mhuse")) && *cp) use = atoi (cp); @@ -242,12 +228,17 @@ WhatNow (int argc, char **argv) } /* start editing the draft, unless -noedit was given */ - if (!nedit && editfile (&ed, NULL, drft, use, NULL, msgnam, NULL, 1) < 0) + if (!nedit && editfile (&ed, NULL, drft, use, NULL, msgnam, + NULL, 1, atfile) < 0) done (1); snprintf (prompt, sizeof(prompt), myprompt, invo_name); for (;;) { +#ifdef READLINE_SUPPORT + if (!(argp = getans_via_readline (prompt, aleqs))) { +#else /* ! READLINE_SUPPORT */ if (!(argp = getans (prompt, aleqs))) { +#endif /* READLINE_SUPPORT */ unlink (LINK); done (1); } @@ -269,7 +260,8 @@ WhatNow (int argc, char **argv) /* Call an editor on the draft file */ if (*++argp) ed = *argp++; - if (editfile (&ed, argp, drft, NOUSE, NULL, msgnam, NULL, 1) == NOTOK) + if (editfile (&ed, argp, drft, NOUSE, NULL, msgnam, + NULL, 1, atfile) == NOTOK) done (1); break; @@ -325,7 +317,7 @@ WhatNow (int argc, char **argv) */ if (*(argp+1) == (char *)0) { - (void)sprintf(buf, "$SHELL -c \"cd;pwd\""); + (void)sprintf(buf, "$SHELL -c \"cd&&pwd\""); } else { writesomecmd(buf, BUFSIZ, "cd", "pwd", argp); @@ -355,7 +347,7 @@ WhatNow (int argc, char **argv) * Use the user's shell so that we can take advantage of any * syntax that the user is accustomed to. */ - writelscmd(buf, sizeof(buf), argp); + writelscmd(buf, sizeof(buf), "", argp); (void)system_in_dir(cwd, buf); break; @@ -411,11 +403,16 @@ WhatNow (int argc, char **argv) break; } + if (*(argp+1) == (char *)0) { + advise((char *)0, "attach command requires file argument(s)."); + break; + } + /* * Build a command line that causes the user's shell to list the file name * arguments. This handles and wildcard expansion, tilde expansion, etc. */ - writelscmd(buf, sizeof(buf), argp); + writelscmd(buf, sizeof(buf), "-d --", argp); /* * Read back the response from the shell, which contains a number of lines @@ -504,7 +501,7 @@ WhatNow (int argc, char **argv) * We feed all the file names to the shell at once, otherwise you can't * provide a file name with a space in it. */ - writelscmd(buf, sizeof(buf), argp); + writelscmd(buf, sizeof(buf), "-d --", argp); if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { while (fgets(shell, sizeof (shell), f) != (char *)0) { *(strchr(shell, '\n')) = '\0'; @@ -545,15 +542,15 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) * new C99 mandated 'number of chars that would have been written' */ /* length checks here and inside the loop allow for the - * trailing ';', trailcmd, '"' and NUL + * trailing "&&", trailcmd, '"' and NUL */ - int trailln = strlen(trailcmd) + 3; + int trailln = strlen(trailcmd) + 4; if (ln < 0 || ln + trailln > bufsz) adios((char *)0, "arguments too long"); - + cp = buf + ln; - - while (*++argp != (char *)0) { + + while (*argp && *++argp) { ln = strlen(*argp); /* +1 for leading space */ if (ln + trailln + 1 > bufsz - (cp-buf)) @@ -563,9 +560,9 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) cp += ln; } if (*trailcmd) { - *cp++ = ';'; + *cp++ = '&'; *cp++ = '&'; strcpy(cp, trailcmd); - cp += trailln - 3; + cp += trailln - 4; } *cp++ = '"'; *cp = 0; @@ -576,9 +573,11 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) * arguments. This handles and wildcard expansion, tilde expansion, etc. */ static void -writelscmd(char *buf, int bufsz, char **argp) +writelscmd(char *buf, int bufsz, char *lsoptions, char **argp) { - writesomecmd(buf, bufsz, "ls", "", argp); + char *lscmd = concat ("ls ", lsoptions, NULL); + writesomecmd(buf, bufsz, lscmd, "", argp); + free (lscmd); } /* Like system(), but run the command in directory dir. @@ -589,6 +588,11 @@ system_in_dir(const char *dir, const char *cmd) { char olddir[BUFSIZ]; int r; + + /* ensure that $SHELL exists, as the cmd was written relying on + a non-blank $SHELL... */ + setenv("SHELL","/bin/sh",0); /* don't overwrite */ + if (getcwd(olddir, sizeof(olddir)) == 0) adios("getcwd", "could not get working directory"); if (chdir(dir) != 0) @@ -605,6 +609,11 @@ popen_in_dir(const char *dir, const char *cmd, const char *type) { char olddir[BUFSIZ]; FILE *f; + + /* ensure that $SHELL exists, as the cmd was written relying on + a non-blank $SHELL... */ + setenv("SHELL","/bin/sh",0); /* don't overwrite */ + if (getcwd(olddir, sizeof(olddir)) == 0) adios("getcwd", "could not get working directory"); if (chdir(dir) != 0) @@ -626,19 +635,14 @@ static char *edsave = NULL; /* the editor we used previously */ static int editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, - char *altmsg, char *cwd, int save_editor) + char *altmsg, char *cwd, int save_editor, int atfile) { int pid, status, vecp; char altpath[BUFSIZ], linkpath[BUFSIZ]; - char *cp, *vec[MAXARGS]; + char *cp, *prog, **vec; struct stat st; -#ifdef HAVE_LSTAT - int slinked; -#if 0 - int oumask; /* PJS: for setting permissions on symlinks. */ -#endif -#endif /* HAVE_LSTAT */ + int slinked = 0; /* Was there a previous edit session? */ if (reedit) { @@ -654,8 +658,8 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, } } else { /* set initial editor */ - if (*ed == NULL && (*ed = context_find ("editor")) == NULL) - *ed = defaulteditor; + if (*ed == NULL) + *ed = get_default_editor(); } if (altmsg) { @@ -667,33 +671,22 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, strncpy (linkpath, LINK, sizeof(linkpath)); else snprintf (linkpath, sizeof(linkpath), "%s/%s", cwd, LINK); - } - if (altmsg) { - unlink (linkpath); -#ifdef HAVE_LSTAT - if (link (altpath, linkpath) == NOTOK) { -#if 0 - /* I don't think permission on symlinks matters /JLR */ - oumask = umask(0044); /* PJS: else symlinks are world 'r' */ -#endif - symlink (altpath, linkpath); -#if 0 - umask(oumask); /* PJS: else symlinks are world 'r' */ -#endif - slinked = 1; - } else { - slinked = 0; + if (atfile) { + unlink (linkpath); + if (link (altpath, linkpath) == NOTOK) { + symlink (altpath, linkpath); + slinked = 1; + } else { + slinked = 0; + } } -#else /* not HAVE_LSTAT */ - link (altpath, linkpath); -#endif /* not HAVE_LSTAT */ } context_save (); /* save the context file */ fflush (stdout); - switch (pid = vfork ()) { + switch (pid = fork()) { case NOTOK: advise ("fork", "unable to"); status = NOTOK; @@ -708,28 +701,21 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, m_putenv ("editalt", altpath); } - vecp = 0; - vec[vecp++] = r1bindex (*ed, '/'); + vec = argsplit(*ed, &prog, &vecp); + if (arg) while (*arg) vec[vecp++] = *arg++; vec[vecp++] = file; vec[vecp] = NULL; - execvp (*ed, vec); + execvp (prog, vec); fprintf (stderr, "unable to exec "); perror (*ed); _exit (-1); default: if ((status = pidwait (pid, NOTOK))) { -#ifdef ATTVIBUG - if ((cp = r1bindex (*ed, '/')) - && strcmp (cp, "vi") == 0 - && (status & 0x00ff) == 0) - status = 0; - else { -#endif if (((status & 0xff00) != 0xff00) && (!reedit || (status & 0x00ff))) { if (!use && (status & 0xff00) && @@ -741,13 +727,9 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, } status = -2; /* maybe "reedit ? -2 : -1"? */ break; -#ifdef ATTVIBUG - } -#endif } reedit++; -#ifdef HAVE_LSTAT if (altmsg && mp && !is_readonly(mp) @@ -760,16 +742,6 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, && (unlink (altpath) == NOTOK || link (linkpath, altpath) == NOTOK))) advise (linkpath, "unable to update %s from", altmsg); -#else /* HAVE_LSTAT */ - if (altmsg - && mp - && !is_readonly(mp) - && stat (linkpath, &st) != NOTOK - && st.st_nlink == 1 - && (unlink (altpath) == NOTOK - || link (linkpath, altpath) == NOTOK)) - advise (linkpath, "unable to update %s from", altmsg); -#endif /* HAVE_LSTAT */ } /* normally, we remember which editor we used */ @@ -777,14 +749,13 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, edsave = getcpy (*ed); *ed = NULL; - if (altmsg) + if (altmsg && atfile) unlink (linkpath); return status; } -#ifdef HAVE_LSTAT static int copyf (char *ifile, char *ofile) { @@ -810,7 +781,6 @@ copyf (char *ifile, char *ofile) close (out); return i; } -#endif /* HAVE_LSTAT */ /* @@ -822,21 +792,19 @@ sendfile (char **arg, char *file, int pushsw) { pid_t child_id; int i, vecp; - char *cp, *sp, *vec[MAXARGS]; + char *cp, *sp, **vec, *program; /* Translate MIME composition file, if necessary */ if ((cp = context_find ("automimeproc")) && (!strcmp (cp, "1")) - && !getenv ("NOMHNPROC") && check_draft (file) && (buildfile (NULL, file) == NOTOK)) return 0; /* For backwards compatibility */ if ((cp = context_find ("automhnproc")) - && !getenv ("NOMHNPROC") && check_draft (file) - && (i = editfile (&cp, NULL, file, NOUSE, NULL, NULL, NULL, 0))) + && (i = editfile (&cp, NULL, file, NOUSE, NULL, NULL, NULL, 0, 0))) return 0; /* @@ -853,14 +821,13 @@ sendfile (char **arg, char *file, int pushsw) context_save (); /* save the context file */ fflush (stdout); - for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++) + for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: advise (NULL, "unable to fork, so sending directly..."); case OK: - vecp = 0; - vec[vecp++] = invo_name; + vec = argsplit(sendproc, &program, &vecp); if (pushsw) vec[vecp++] = "-push"; if (arg) @@ -869,7 +836,7 @@ sendfile (char **arg, char *file, int pushsw) vec[vecp++] = file; vec[vecp] = NULL; - execvp (sendproc, vec); + execvp (program, vec); fprintf (stderr, "unable to exec "); perror (sendproc); _exit (-1); @@ -915,7 +882,7 @@ buildfile (char **argp, char *file) args[i++] = *argp++; args[i] = NULL; - i = editfile (&ed, args, file, NOUSE, NULL, NULL, NULL, 0); + i = editfile (&ed, args, file, NOUSE, NULL, NULL, NULL, 0, 0); free (args); return (i ? NOTOK : OK); @@ -932,14 +899,15 @@ check_draft (char *msgnam) int state; char buf[BUFSIZ], name[NAMESZ]; FILE *fp; + m_getfld_state_t gstate = 0; if ((fp = fopen (msgnam, "r")) == NULL) return 0; - for (state = FLD;;) - switch (state = m_getfld (state, name, buf, sizeof(buf), fp)) { + for (;;) { + int bufsz = sizeof buf; + switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { case FLD: case FLDPLUS: - case FLDEOF: /* * If draft already contains any of the * Content-XXX fields, then assume it already @@ -947,10 +915,13 @@ check_draft (char *msgnam) */ if (uprf (name, XXX_FIELD_PRF)) { fclose (fp); + m_getfld_state_destroy (&gstate); return 0; } - while (state == FLDPLUS) - state = m_getfld (state, name, buf, sizeof(buf), fp); + while (state == FLDPLUS) { + bufsz = sizeof buf; + state = m_getfld (&gstate, name, buf, &bufsz, fp); + } break; case BODY: @@ -960,17 +931,21 @@ check_draft (char *msgnam) for (bp = buf; *bp; bp++) if (*bp != ' ' && *bp != '\t' && *bp != '\n') { fclose (fp); + m_getfld_state_destroy (&gstate); return 1; } - state = m_getfld (state, name, buf, sizeof(buf), fp); + bufsz = sizeof buf; + state = m_getfld (&gstate, name, buf, &bufsz, fp); } while (state == BODY); /* and fall... */ default: fclose (fp); + m_getfld_state_destroy (&gstate); return 0; } + } } @@ -980,93 +955,67 @@ check_draft (char *msgnam) # define SASLminc(a) 0 #endif /* CYRUS_SASL */ -static struct swit sendswitches[] = { -#define ALIASW 0 - { "alias aliasfile", 0 }, -#define DEBUGSW 1 - { "debug", -5 }, -#define FILTSW 2 - { "filter filterfile", 0 }, -#define NFILTSW 3 - { "nofilter", 0 }, -#define FRMTSW 4 - { "format", 0 }, -#define NFRMTSW 5 - { "noformat", 0 }, -#define FORWSW 6 - { "forward", 0 }, -#define NFORWSW 7 - { "noforward", 0 }, -#define MIMESW 8 - { "mime", 0 }, -#define NMIMESW 9 - { "nomime", 0 }, -#define MSGDSW 10 - { "msgid", 0 }, -#define NMSGDSW 11 - { "nomsgid", 0 }, -#define SPSHSW 12 - { "push", 0 }, -#define NSPSHSW 13 - { "nopush", 0 }, -#define SPLITSW 14 - { "split seconds", 0 }, -#define UNIQSW 15 - { "unique", -6 }, -#define NUNIQSW 16 - { "nounique", -8 }, -#define VERBSW 17 - { "verbose", 0 }, -#define NVERBSW 18 - { "noverbose", 0 }, -#define WATCSW 19 - { "watch", 0 }, -#define NWATCSW 20 - { "nowatch", 0 }, -#define WIDTHSW 21 - { "width columns", 0 }, -#define SVERSIONSW 22 - { "version", 0 }, -#define SHELPSW 23 - { "help", 0 }, -#define BITSTUFFSW 24 - { "dashstuffing", -12 }, -#define NBITSTUFFSW 25 - { "nodashstuffing", -14 }, -#define MAILSW 26 - { "mail", -4 }, -#define SAMLSW 27 - { "saml", -4 }, -#define SSNDSW 28 - { "send", -4 }, -#define SOMLSW 29 - { "soml", -4 }, -#define CLIESW 30 - { "client host", -6 }, -#define SERVSW 31 - { "server host", 6 }, -#define SNOOPSW 32 - { "snoop", -5 }, -#define SDRFSW 33 - { "draftfolder +folder", -6 }, -#define SDRMSW 34 - { "draftmessage msg", -6 }, -#define SNDRFSW 35 - { "nodraftfolder", -3 }, -#define SASLSW 36 - { "sasl", SASLminc(-4) }, -#define SASLMECHSW 37 - { "saslmech", SASLminc(-5) }, -#define USERSW 38 - { "user", SASLminc(4) }, -#define SNDATTACHSW 39 - { "attach file", 6 }, -#define SNDATTACHFORMAT 40 - { "attachformat", 7 }, -#define PORTSW 41 - { "port server-port-name/number", 4 }, - { NULL, 0 } -}; +#ifndef TLS_SUPPORT +# define TLSminc(a) (a) +#else /* TLS_SUPPORT */ +# define TLSminc(a) 0 +#endif /* TLS_SUPPORT */ + +#define SEND_SWITCHES \ + X("alias aliasfile", 0, ALIASW) \ + X("debug", -5, DEBUGSW) \ + 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, SPSHSW) \ + X("nopush", 0, NSPSHSW) \ + 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, SVERSIONSW) \ + X("help", 0, SHELPSW) \ + X("dashstuffing", -12, BITSTUFFSW) \ + X("nodashstuffing", -14, NBITSTUFFSW) \ + X("client host", -6, CLIESW) \ + X("server host", 6, SERVSW) \ + X("snoop", -5, SNOOPSW) \ + X("draftfolder +folder", -6, SDRFSW) \ + X("draftmessage msg", -6, SDRMSW) \ + X("nodraftfolder", -3, SNDRFSW) \ + X("sasl", SASLminc(-4), SASLSW) \ + X("nosasl", SASLminc(-6), NOSASLSW) \ + X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ + X("saslmech", SASLminc(-5), SASLMECHSW) \ + X("user", SASLminc(-4), USERSW) \ + X("attach fieldname", 6, SNDATTACHSW) \ + X("noattach", 0, SNDNOATTACHSW) \ + X("attachformat", 7, SNDATTACHFORMAT) \ + X("port server-port-name/number", 4, PORTSW) \ + X("tls", TLSminc(-3), TLSSW) \ + X("initialtls", TLSminc(-10), INITTLSSW) \ + X("notls", TLSminc(-5), NTLSSW) \ + 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, sendswitches); +#undef X extern int debugsw; /* from sendsbr.c */ @@ -1086,33 +1035,30 @@ static void sendit (char *sp, char **arg, char *file, int pushed) { int vecp, n = 1; - char *cp, buf[BUFSIZ], **argp; - char **arguments, *vec[MAXARGS]; + char *cp, buf[BUFSIZ], **argp, *program; + char **arguments, *savearg[MAXARGS], **vec; struct stat st; - char *attach = (char *)0; /* attachment header field name */ - int attachformat = 0; /* mhbuild format specifier for + char *attach = NMH_ATTACH_HEADER;/* attachment header field name */ + int attachformat = 1; /* mhbuild format specifier for attachments */ #ifndef lint int distsw = 0; #endif -#ifdef UCI - FILE *fp; -#endif /* * Make sure these are defined. In particular, we need - * vec[1] to be NULL, in case "arg" is NULL below. It - * doesn't matter what is the value of vec[0], but we + * savearg[1] to be NULL, in case "arg" is NULL below. It + * doesn't matter what is the value of savearg[0], but we * set it to NULL, to help catch "off-by-one" errors. */ - vec[0] = NULL; - vec[1] = NULL; + savearg[0] = NULL; + savearg[1] = NULL; /* - * Temporarily copy arg to vec, since the brkstring() call in + * Temporarily copy arg to savearg, since the brkstring() call in * getarguments() will wipe it out before it is merged in. - * Also, we skip the first element of vec, since getarguments() + * Also, we skip the first element of savearg, since getarguments() * skips it. Then we count the number of arguments * copied. The value of "n" will be one greater than * this in order to simulate the standard argc/argv. @@ -1120,17 +1066,17 @@ sendit (char *sp, char **arg, char *file, int pushed) if (arg) { char **bp; - copyip (arg, vec+1, MAXARGS-1); - bp = vec+1; + copyip (arg, savearg+1, MAXARGS-1); + bp = savearg+1; while (*bp++) n++; } /* - * Merge any arguments from command line (now in vec) + * Merge any arguments from command line (now in savearg) * and arguments from profile. */ - arguments = getarguments (sp, n, vec, 1); + arguments = getarguments (sp, n, savearg, 1); argp = arguments; debugsw = 0; @@ -1142,10 +1088,31 @@ sendit (char *sp, char **arg, char *file, int pushed) annotext = NULL; distfile = NULL; - vecp = 1; /* we'll get the zero'th element later */ + /* + * Get our initial arguments for postproc now + */ + + vec = argsplit(postproc, &program, &vecp); + vec[vecp++] = "-library"; vec[vecp++] = getcpy (m_maildir ("")); + if ((cp = context_find ("fileproc"))) { + vec[vecp++] = "-fileproc"; + vec[vecp++] = cp; + } + + if ((cp = context_find ("mhlproc"))) { + 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++)) { if (*cp == '-') { switch (smatch (++cp, sendswitches)) { @@ -1213,12 +1180,12 @@ sendit (char *sp, char **arg, char *file, int pushed) case NMSGDSW: case WATCSW: case NWATCSW: - case MAILSW: - case SAMLSW: - case SSNDSW: - case SOMLSW: case SNOOPSW: case SASLSW: + case NOSASLSW: + case TLSSW: + case INITTLSSW: + case NTLSSW: vec[vecp++] = --cp; continue; @@ -1227,8 +1194,12 @@ sendit (char *sp, char **arg, char *file, int pushed) case WIDTHSW: case CLIESW: case SERVSW: + case SASLMXSSFSW: case SASLMECHSW: case USERSW: + case PORTSW: + case MTSSW: + case MESSAGEIDSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') { advise (NULL, "missing argument to %s", argp[-2]); @@ -1252,6 +1223,9 @@ sendit (char *sp, char **arg, char *file, int pushed) return; } continue; + case SNDNOATTACHSW: + attach = NULL; + continue; case SNDATTACHFORMAT: if (! *argp || **argp == '-') @@ -1287,18 +1261,6 @@ sendit (char *sp, char **arg, char *file, int pushed) if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0) if ((cp = context_find ("signature")) && *cp) m_putenv ("SIGNATURE", cp); -#ifdef UCI - else { - snprintf (buf, sizeof(buf), "%s/.signature", mypath); - if ((fp = fopen (buf, "r")) != NULL - && fgets (buf, sizeof(buf), fp) != NULL) { - fclose (fp); - if (cp = strchr (buf, '\n')) - *cp = 0; - m_putenv ("SIGNATURE", buf); - } - } -#endif /* UCI */ if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0) annotext = NULL; @@ -1314,7 +1276,8 @@ sendit (char *sp, char **arg, char *file, int pushed) #endif /* not lint */ && altmsg) { vec[vecp++] = "-dist"; - distfile = getcpy (m_scratch (altmsg, invo_name)); + distfile = getcpy (m_mktemp2(altmsg, invo_name, NULL, NULL)); + unlink(distfile); if (link (altmsg, distfile) == NOTOK) adios (distfile, "unable to link %s to", altmsg); } else { @@ -1329,10 +1292,9 @@ sendit (char *sp, char **arg, char *file, int pushed) if ((pushsw = pushed)) push (); - vec[0] = r1bindex (postproc, '/'); closefds (3); - if (sendsbr (vec, vecp, file, &st, 1, attach, attachformat) == OK) + if (sendsbr (vec, vecp, program, file, &st, 1, attach, attachformat) == OK) done (0); } @@ -1345,26 +1307,25 @@ whomfile (char **arg, char *file) { pid_t pid; int vecp; - char *vec[MAXARGS]; + char **vec, *program; context_save (); /* save the context file */ fflush (stdout); - switch (pid = vfork ()) { + switch (pid = fork()) { case NOTOK: advise ("fork", "unable to"); return 1; case OK: - vecp = 0; - vec[vecp++] = r1bindex (whomproc, '/'); + vec = argsplit(whomproc, &program, &vecp); vec[vecp++] = file; if (arg) while (*arg) vec[vecp++] = *arg++; vec[vecp] = NULL; - execvp (whomproc, vec); + execvp (program, vec); fprintf (stderr, "unable to exec "); perror (whomproc); _exit (-1); /* NOTREACHED */