X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fwhatnowsbr.c;h=a5dbb2b008e0db8cdd0d41932c5974843b88c8d6;hb=374ece2e88368afd6e0a29c4ee4b75ffa9e28b39;hp=854a97258db4eedac03f85e0f948789275add19d;hpb=3c9700d8d045f3ff26ce5dd2a174454dafc14822;p=mmh diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index 854a972..a5dbb2b 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -2,13 +2,47 @@ /* * 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. + * + * Several options have been added to ease the inclusion of attachments + * using the header field name mechanism added to anno and send. The + * -attach option is used to specify the header field name for attachments. + * + * Several commands have been added at the whatnow prompt: + * + * cd [ directory ] This option works just like the shell's + * cd command and lets the user change the + * directory from which attachments are + * taken so that long path names are not + * needed with every file. + * + * ls [ ls-options ] This option works just like the normal + * ls command and exists to allow the user + * to verify file names in the directory. + * + * pwd This option works just like the normal + * pwd command and exists to allow the user + * to verify the directory. + * + * attach files This option attaches the named files to + * the draft. + * + * alist [-ln] This option lists the attachments on the + * draft. -l gets long listings, -n gets + * numbered listings. + * + * detach files This option removes attachments from the + * detach -n numbers draft. This can be done by file name or + * by attachment number. */ #include #include #include #include +#include static struct swit whatnowswitches[] = { #define DFOLDSW 0 @@ -26,7 +60,11 @@ static struct swit whatnowswitches[] = { #define VERSIONSW 6 { "version", 0 }, #define HELPSW 7 - { "help", 4 }, + { "help", 0 }, +#define ATTACHSW 8 + { "attach header-field-name", 0 }, +#define NOATTACHSW 9 + { "noattach", 0 }, { NULL, 0 } }; @@ -54,6 +92,18 @@ static struct swit aleqs[] = { { "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 } }; @@ -63,13 +113,18 @@ 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 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 *); @@ -79,12 +134,19 @@ static int copyf (char *, char *); 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 = 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 */ invo_name = r1bindex (argv[0], '/'); @@ -94,24 +156,32 @@ WhatNow (int argc, char **argv) arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; + /* + * Get the initial current working directory. + */ + + if (getcwd(cwd, sizeof (cwd)) == (char *)0) { + adios("getcwd", "could not get working directory"); + } + while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, whatnowswitches)) { - case AMBIGSW: + case AMBIGSW: ambigsw (cp, whatnowswitches); done (1); - case UNKWNSW: + case UNKWNSW: adios (NULL, "-%s unknown", cp); - case HELPSW: + 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: + case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') @@ -119,23 +189,23 @@ WhatNow (int argc, char **argv) dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; - case DMSGSW: + case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; - case NDFLDSW: + case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; - case EDITRSW: + case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; - case NEDITSW: + case NEDITSW: nedit++; continue; @@ -143,6 +213,15 @@ WhatNow (int argc, char **argv) if (!(myprompt = *argp++) || *myprompt == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; + + case ATTACHSW: + if (!(attach = *argp++) || *attach == '-') + adios (NULL, "missing argument to %s", argp[-2]); + continue; + + case NOATTACHSW: + attach = NULL; + continue; } } if (drft) @@ -156,6 +235,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); @@ -165,12 +247,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); } @@ -192,11 +279,12 @@ 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; - case LISTSW: + case LISTSW: /* display the draft file */ showfile (++argp, drft); break; @@ -228,18 +316,224 @@ WhatNow (int argc, char **argv) done (1); break; - case SENDSW: + case SENDSW: /* Send draft */ sendfile (++argp, drft, 0); break; - case REFILEOPT: + case REFILEOPT: /* Refile the draft */ if (refile (++argp, drft) == 0) done (0); break; - default: + case CDCMDSW: + /* Change the working directory for attachments + * + * Run the directory through the user's shell so that + * we can take advantage of any syntax that the user + * is accustomed to. Read back the absolute path. + */ + + if (*(argp+1) == (char *)0) { + (void)sprintf(buf, "$SHELL -c \"cd;pwd\""); + } + else { + writesomecmd(buf, BUFSIZ, "cd", "pwd", argp); + } + if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { + fgets(cwd, sizeof (cwd), f); + + if (strchr(cwd, '\n') != (char *)0) + *strchr(cwd, '\n') = '\0'; + + pclose(f); + } + else { + advise("popen", "could not get directory"); + } + + break; + + case PWDCMDSW: + /* Print the working directory for attachments */ + printf("%s\n", cwd); + break; + + case LSCMDSW: + /* List files in the current attachment working directory + * + * 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); + (void)system_in_dir(cwd, buf); + break; + + case ALISTCMDSW: + /* + * List attachments on current draft. Options are: + * + * -l long listing (full path names) + * -n numbers listing + */ + + if (attach == (char *)0) { + advise((char *)0, "can't list because no header field name was given."); + break; + } + + l = (char *)0; + n = 0; + + while (*++argp != (char *)0) { + if (strcmp(*argp, "-l") == 0) + l = "/"; + + else if (strcmp(*argp, "-n") == 0) + n = 1; + + else if (strcmp(*argp, "-ln") == 0 || strcmp(*argp, "-nl") == 0) { + l = "/"; + n = 1; + } + + else { + n = -1; + break; + } + } + + if (n == -1) + advise((char *)0, "usage is alist [-ln]."); + + else + annolist(drft, attach, l, n); + + break; + + case ATTACHCMDSW: + /* + * Attach files to current draft. + */ + + if (attach == (char *)0) { + advise((char *)0, "can't attach because no header field name was given."); + 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); + + /* + * Read back the response from the shell, which contains a number of lines + * with one file name per line. Remove off the newline. Determine whether + * we have an absolute or relative path name. Prepend the current working + * directory to relative path names. Add the attachment annotation to the + * draft. + */ + + if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { + while (fgets(shell, sizeof (shell), f) != (char *)0) { + *(strchr(shell, '\n')) = '\0'; + + if (*shell == '/') + (void)annotate(drft, attach, shell, 1, 0, -2, 1); + else { + (void)sprintf(file, "%s/%s", cwd, shell); + (void)annotate(drft, attach, file, 1, 0, -2, 1); + } + } + + pclose(f); + } + else { + advise("popen", "could not get file from shell"); + } + + break; + + case DETACHCMDSW: + /* + * Detach files from current draft. + */ + + if (attach == (char *)0) { + advise((char *)0, "can't detach because no header field name was given."); + break; + } + + /* + * Scan the arguments for a -n. Mixed file names and numbers aren't allowed, + * so this catches a -n anywhere in the argument list. + */ + + for (n = 0, arguments = argp + 1; *arguments != (char *)0; arguments++) { + if (strcmp(*arguments, "-n") == 0) { + n = 1; + break; + } + } + + /* + * A -n was found so interpret the arguments as attachment numbers. + * Decrement any remaining argument number that is greater than the one + * just processed after processing each one so that the numbering stays + * correct. + */ + + if (n == 1) { + for (arguments = argp + 1; *arguments != (char *)0; arguments++) { + if (strcmp(*arguments, "-n") == 0) + continue; + + if (**arguments != '\0') { + n = atoi(*arguments); + (void)annotate(drft, attach, (char *)0, 1, 0, n, 1); + + for (argp = arguments + 1; *argp != (char *)0; argp++) { + if (atoi(*argp) > n) { + if (atoi(*argp) == 1) + *argp = ""; + else + (void)sprintf(*argp, "%d", atoi(*argp) - 1); + } + } + } + } + } + + /* + * The arguments are interpreted as file names. Run them through the + * user's shell for wildcard expansion and other goodies. Do this from + * the current working directory if the argument is not an absolute path + * name (does not begin with a /). + * + * 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); + if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { + while (fgets(shell, sizeof (shell), f) != (char *)0) { + *(strchr(shell, '\n')) = '\0'; + (void)annotate(drft, attach, shell, 1, 0, 0, 1); + } + pclose(f); + } else { + advise("popen", "could not get file from shell"); + } + + break; + + default: /* Unknown command */ advise (NULL, "say what?"); break; @@ -248,6 +542,96 @@ WhatNow (int argc, char **argv) /*NOTREACHED*/ } + + +/* Build a command line of the form $SHELL -c "cd 'cwd'; cmd argp ... ; trailcmd". */ +static void +writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) +{ + char *cp; + /* Note that we do not quote -- the argp from the user + * is assumed to be quoted as they desire. (We can't treat + * it as pure literal as that would prevent them using ~, + * wildcards, etc.) The buffer produced by this function + * should be given to popen_in_dir() or system_in_dir() so + * that the current working directory is set correctly. + */ + int ln = snprintf(buf, bufsz, "$SHELL -c \"%s", cmd); + /* NB that some snprintf() return -1 on overflow rather than the + * 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 + */ + int trailln = strlen(trailcmd) + 3; + if (ln < 0 || ln + trailln > bufsz) + adios((char *)0, "arguments too long"); + + cp = buf + ln; + + while (*++argp != (char *)0) { + ln = strlen(*argp); + /* +1 for leading space */ + if (ln + trailln + 1 > bufsz - (cp-buf)) + adios((char *)0, "arguments too long"); + *cp++ = ' '; + memcpy(cp, *argp, ln+1); + cp += ln; + } + if (*trailcmd) { + *cp++ = ';'; + strcpy(cp, trailcmd); + cp += trailln - 3; + } + *cp++ = '"'; + *cp = 0; +} + +/* + * Build a command line that causes the user's shell to list the file name + * arguments. This handles and wildcard expansion, tilde expansion, etc. + */ +static void +writelscmd(char *buf, int bufsz, char **argp) +{ + writesomecmd(buf, bufsz, "ls", "", argp); +} + +/* Like system(), but run the command in directory dir. + * This assumes the program is single-threaded! + */ +static int +system_in_dir(const char *dir, const char *cmd) +{ + char olddir[BUFSIZ]; + int r; + if (getcwd(olddir, sizeof(olddir)) == 0) + adios("getcwd", "could not get working directory"); + if (chdir(dir) != 0) + adios("chdir", "could not change working directory"); + r = system(cmd); + if (chdir(olddir) != 0) + adios("chdir", "could not change working directory"); + return r; +} + +/* ditto for popen() */ +static FILE* +popen_in_dir(const char *dir, const char *cmd, const char *type) +{ + char olddir[BUFSIZ]; + FILE *f; + if (getcwd(olddir, sizeof(olddir)) == 0) + adios("getcwd", "could not get working directory"); + if (chdir(dir) != 0) + adios("chdir", "could not change working directory"); + f = popen(cmd, type); + if (chdir(olddir) != 0) + adios("chdir", "could not change working directory"); + return f; +} + + /* * EDIT */ @@ -258,7 +642,7 @@ 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]; @@ -266,10 +650,7 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, struct stat st; #ifdef HAVE_LSTAT - int slinked; -#if 0 - int oumask; /* PJS: for setting permissions on symlinks. */ -#endif + int slinked = 0; #endif /* HAVE_LSTAT */ /* Was there a previous edit session? */ @@ -290,7 +671,7 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, *ed = defaulteditor; } - if (altmsg) { + if (altmsg && atfile) { if (mp == NULL || *altmsg == '/' || cwd == NULL) strncpy (altpath, altmsg, sizeof(altpath)); else @@ -299,20 +680,11 @@ 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; @@ -325,13 +697,13 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, context_save (); /* save the context file */ fflush (stdout); - switch (pid = vfork ()) { - case NOTOK: + switch (pid = vfork()) { + case NOTOK: advise ("fork", "unable to"); status = NOTOK; break; - case OK: + case OK: if (cwd) chdir (cwd); if (altmsg) { @@ -353,15 +725,8 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, perror (*ed); _exit (-1); - default: + 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) && @@ -373,9 +738,6 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, } status = -2; /* maybe "reedit ? -2 : -1"? */ break; -#ifdef ATTVIBUG - } -#endif } reedit++; @@ -409,7 +771,7 @@ 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; @@ -459,16 +821,14 @@ sendfile (char **arg, char *file, int pushsw) /* 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; /* @@ -488,9 +848,9 @@ sendfile (char **arg, char *file, int pushsw) for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { - case NOTOK: + case NOTOK: advise (NULL, "unable to fork, so sending directly..."); - case OK: + case OK: vecp = 0; vec[vecp++] = invo_name; if (pushsw) @@ -506,7 +866,7 @@ sendfile (char **arg, char *file, int pushsw) perror (sendproc); _exit (-1); - default: + default: if (pidwait(child_id, OK) == 0) done (0); return 1; @@ -532,8 +892,7 @@ buildfile (char **argp, char *file) while (argp[i]) i++; } - if ((args = (char **) malloc((i + 2) * sizeof(char *))) == NULL) - adios (NULL, "unable to malloc memory"); + args = (char **) mh_xmalloc((i + 2) * sizeof(char *)); /* * For backward compatibility, we need to add -build @@ -548,7 +907,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); @@ -607,6 +966,18 @@ check_draft (char *msgnam) } +#ifndef CYRUS_SASL +# define SASLminc(a) (a) +#else /* CYRUS_SASL */ +# define SASLminc(a) 0 +#endif /* CYRUS_SASL */ + +#ifndef TLS_SUPPORT +# define TLSminc(a) (a) +#else /* TLS_SUPPORT */ +# define TLSminc(a) 0 +#endif /* TLS_SUPPORT */ + static struct swit sendswitches[] = { #define ALIASW 0 { "alias aliasfile", 0 }, @@ -655,7 +1026,7 @@ static struct swit sendswitches[] = { #define SVERSIONSW 22 { "version", 0 }, #define SHELPSW 23 - { "help", 4 }, + { "help", 0 }, #define BITSTUFFSW 24 { "dashstuffing", -12 }, #define NBITSTUFFSW 25 @@ -671,7 +1042,7 @@ static struct swit sendswitches[] = { #define CLIESW 30 { "client host", -6 }, #define SERVSW 31 - { "server host", -6 }, + { "server host", 6 }, #define SNOOPSW 32 { "snoop", -5 }, #define SDRFSW 33 @@ -680,6 +1051,30 @@ static struct swit sendswitches[] = { { "draftmessage msg", -6 }, #define SNDRFSW 35 { "nodraftfolder", -3 }, +#define SASLSW 36 + { "sasl", SASLminc(-4) }, +#define NOSASLSW 37 + { "nosasl", SASLminc(-6) }, +#define SASLMXSSFSW 38 + { "saslmaxssf", SASLminc(-10) }, +#define SASLMECHSW 39 + { "saslmech", SASLminc(-5) }, +#define USERSW 40 + { "user", SASLminc(-4) }, +#define SNDATTACHSW 41 + { "attach file", 6 }, +#define SNDNOATTACHSW 42 + { "noattach", 0 }, +#define SNDATTACHFORMAT 43 + { "attachformat", 7 }, +#define PORTSW 44 + { "port server-port-name/number", 4 }, +#define TLSSW 45 + { "tls", TLSminc(-3) }, +#define NTLSSW 46 + { "notls", TLSminc(-5) }, +#define MTSSW 47 + { "mts smtp|sendmail/smtp|sendmail/pipe", 2 }, { NULL, 0 } }; @@ -704,13 +1099,13 @@ sendit (char *sp, char **arg, char *file, int pushed) char *cp, buf[BUFSIZ], **argp; char **arguments, *vec[MAXARGS]; struct stat st; + 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 @@ -758,17 +1153,27 @@ sendit (char *sp, char **arg, char *file, int pushed) 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; + } + while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, sendswitches)) { - case AMBIGSW: + case AMBIGSW: ambigsw (cp, sendswitches); return; - case UNKWNSW: + case UNKWNSW: advise (NULL, "-%s unknown\n", cp); return; - case SHELPSW: + case SHELPSW: snprintf (buf, sizeof(buf), "%s [switches]", sp); print_help (buf, sendswitches, 1); return; @@ -776,34 +1181,34 @@ sendit (char *sp, char **arg, char *file, int pushed) print_version (invo_name); return; - case SPSHSW: + case SPSHSW: pushed++; continue; - case NSPSHSW: + case NSPSHSW: pushed = 0; continue; - case SPLITSW: + case SPLITSW: if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) { advise (NULL, "missing argument to %s", argp[-2]); return; } continue; - case UNIQSW: + case UNIQSW: unique++; continue; - case NUNIQSW: + case NUNIQSW: unique = 0; continue; - case FORWSW: + case FORWSW: forwsw++; continue; - case NFORWSW: + case NFORWSW: forwsw = 0; continue; - case VERBSW: + case VERBSW: verbsw++; vec[vecp++] = --cp; continue; @@ -812,32 +1217,41 @@ sendit (char *sp, char **arg, char *file, int pushed) vec[vecp++] = --cp; continue; - case DEBUGSW: + case DEBUGSW: debugsw++; /* fall */ - case NFILTSW: - case FRMTSW: - case NFRMTSW: + case NFILTSW: + case FRMTSW: + case NFRMTSW: case BITSTUFFSW: case NBITSTUFFSW: - case MIMESW: - case NMIMESW: - case MSGDSW: - case NMSGDSW: - case WATCSW: - case NWATCSW: - case MAILSW: - case SAMLSW: - case SSNDSW: - case SOMLSW: - case SNOOPSW: + case MIMESW: + case NMIMESW: + case MSGDSW: + case NMSGDSW: + case WATCSW: + case NWATCSW: + case MAILSW: + case SAMLSW: + case SSNDSW: + case SOMLSW: + case SNOOPSW: + case SASLSW: + case NOSASLSW: + case TLSSW: + case NTLSSW: vec[vecp++] = --cp; continue; - case ALIASW: - case FILTSW: - case WIDTHSW: - case CLIESW: - case SERVSW: + case ALIASW: + case FILTSW: + case WIDTHSW: + case CLIESW: + case SERVSW: + case SASLMXSSFSW: + case SASLMECHSW: + case USERSW: + case PORTSW: + case MTSSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') { advise (NULL, "missing argument to %s", argp[-2]); @@ -846,13 +1260,38 @@ sendit (char *sp, char **arg, char *file, int pushed) vec[vecp++] = cp; continue; - case SDRFSW: - case SDRMSW: + case SDRFSW: + case SDRMSW: if (!(cp = *argp++) || *cp == '-') { advise (NULL, "missing argument to %s", argp[-2]); return; } - case SNDRFSW: + case SNDRFSW: + continue; + + case SNDATTACHSW: + if (!(attach = *argp++) || *attach == '-') { + advise (NULL, "missing argument to %s", argp[-2]); + return; + } + continue; + case SNDNOATTACHSW: + attach = NULL; + continue; + + case SNDATTACHFORMAT: + 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; } } @@ -874,18 +1313,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; @@ -901,7 +1328,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 { @@ -919,7 +1347,7 @@ sendit (char *sp, char **arg, char *file, int pushed) vec[0] = r1bindex (postproc, '/'); closefds (3); - if (sendsbr (vec, vecp, file, &st, 1) == OK) + if (sendsbr (vec, vecp, file, &st, 1, attach, attachformat) == OK) done (0); } @@ -937,12 +1365,12 @@ whomfile (char **arg, char *file) context_save (); /* save the context file */ fflush (stdout); - switch (pid = vfork ()) { - case NOTOK: + switch (pid = vfork()) { + case NOTOK: advise ("fork", "unable to"); return 1; - case OK: + case OK: vecp = 0; vec[vecp++] = r1bindex (whomproc, '/'); vec[vecp++] = file; @@ -956,7 +1384,7 @@ whomfile (char **arg, char *file) perror (whomproc); _exit (-1); /* NOTREACHED */ - default: + default: return (pidwait (pid, NOTOK) & 0377 ? 1 : 0); } }