X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/8bf4e8784aa2a0438ba09b1a0eb9207d3baf6bd9..f1920d78123667716f2321d37ce37628603b2700:/uip/whatnowsbr.c diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index eb6106a7..d8862dc9 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -26,8 +26,9 @@ * pwd command and exists to allow the user * to verify the directory. * - * attach files This option attaches the named files to - * the draft. + * attach [-v] files This option attaches the named files to + * the draft. -v displays the mhbuild + * directive that send(1) will use. * * alist [-ln] This option lists the attachments on the * draft. -l gets long listings, -n gets @@ -40,7 +41,6 @@ #include #include -#include #include #include @@ -53,8 +53,9 @@ X("prompt string", 4, PRMPTSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ - X("attach header-field-name", 0, ATTACHSW) \ - X("noattach", 0, NOATTACHSW) \ + X("attach header-field-name", -6, ATTACHSW) \ + X("noattach", -8, NOATTACHSW) \ + #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(WHATNOW); @@ -81,8 +82,8 @@ DEFINE_SWITCH_ARRAY(WHATNOW, whatnowswitches); X("cd [directory]", 0, CDCMDSW) \ X("pwd", 0, PWDCMDSW) \ X("ls", 2, LSCMDSW) \ - X("attach", 0, ATTACHCMDSW) \ - X("detach [-n]", 2, DETACHCMDSW) \ + X("attach [-v]", 0, ATTACHCMDSW) \ + X("detach [-n]", 0, DETACHCMDSW) \ X("alist [-ln] ", 2, ALISTCMDSW) \ #define X(sw, minchars, id) id, @@ -103,18 +104,14 @@ static int editfile (char **, char **, char *, int, struct msgs *, 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 int checkmimeheader (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 @@ -126,7 +123,6 @@ WhatNow (int argc, char **argv) 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 */ @@ -134,11 +130,9 @@ WhatNow (int argc, char **argv) char *l; /* set on -l to alist command */ int n; /* set on -n to alist command */ + /* Need this if called from what_now(). */ invo_name = r1bindex (argv[0], '/'); - /* read user profile/context */ - context_read(); - arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -201,12 +195,11 @@ WhatNow (int argc, char **argv) continue; case ATTACHSW: - if (!(attach = *argp++) || *attach == '-') - adios (NULL, "missing argument to %s", argp[-2]); + advise(NULL, "The -attach switch is deprecated"); continue; case NOATTACHSW: - attach = NULL; + advise(NULL, "The -noattach switch is deprecated"); continue; } } @@ -244,7 +237,7 @@ WhatNow (int argc, char **argv) #else /* ! READLINE_SUPPORT */ if (!(argp = getans (prompt, aleqs))) { #endif /* READLINE_SUPPORT */ - unlink (LINK); + (void) m_unlink (LINK); done (1); } switch (smatch (*argp, aleqs)) { @@ -328,7 +321,9 @@ WhatNow (int argc, char **argv) writesomecmd(buf, BUFSIZ, "cd", "pwd", argp); } if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { - fgets(cwd, sizeof (cwd), f); + if (fgets(cwd, sizeof (cwd), f) == NULL) { + advise (buf, "fgets"); + } if (strchr(cwd, '\n') != (char *)0) *strchr(cwd, '\n') = '\0'; @@ -364,10 +359,8 @@ WhatNow (int argc, char **argv) * -n numbers listing */ - if (attach == (char *)0) { - advise((char *)0, "can't list because no header field name was given."); + if (checkmimeheader(drft)) break; - } l = (char *)0; n = 0; @@ -394,22 +387,32 @@ WhatNow (int argc, char **argv) advise((char *)0, "usage is alist [-ln]."); else - annolist(drft, attach, l, n); + annolist(drft, ATTACH_FIELD, l, n); break; - case ATTACHCMDSW: + case ATTACHCMDSW: { /* * Attach files to current draft. */ - if (attach == (char *)0) { - advise((char *)0, "can't attach because no header field name was given."); + int verbose = 0; + char **ap; + + if (checkmimeheader(drft)) break; + + for (ap = argp+1; *ap; ++ap) { + if (strcmp(*ap, "-v") == 0) { + ++argp; + verbose = 1; + } else if (*ap[0] != '-') { + break; + } } if (*(argp+1) == (char *)0) { - advise((char *)0, "attach command requires file argument(s)."); + advise(NULL, "attach command requires file argument(s)."); break; } @@ -417,7 +420,7 @@ WhatNow (int argc, char **argv) * 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), "-d", argp); + writelscmd(buf, sizeof(buf), "-d --", argp); /* * Read back the response from the shell, which contains a number of lines @@ -429,13 +432,22 @@ WhatNow (int argc, char **argv) if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { while (fgets(shell, sizeof (shell), f) != (char *)0) { + char *ctype; + *(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); + if (*shell == '/') { + strncpy(file, shell, sizeof(file)); + file[sizeof(file) - 1] = '\0'; + } else { + snprintf(file, sizeof(file), "%s/%s", cwd, shell); + } + + annotate(drft, ATTACH_FIELD, file, 1, 0, -2, 1); + if (verbose) { + ctype = mime_type(file); + printf ("Attaching %s as a %s\n", file, ctype); + free (ctype); } } @@ -446,22 +458,20 @@ WhatNow (int argc, char **argv) } 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. */ + if (checkmimeheader(drft)) + break; + for (n = 0, arguments = argp + 1; *arguments != (char *)0; arguments++) { if (strcmp(*arguments, "-n") == 0) { n = 1; @@ -483,7 +493,7 @@ WhatNow (int argc, char **argv) if (**arguments != '\0') { n = atoi(*arguments); - (void)annotate(drft, attach, (char *)0, 1, 0, n, 1); + annotate(drft, ATTACH_FIELD, (char *)0, 1, 0, n, 1); for (argp = arguments + 1; *argp != (char *)0; argp++) { if (atoi(*argp) > n) { @@ -506,11 +516,11 @@ 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), "-d", 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'; - (void)annotate(drft, attach, shell, 1, 0, 0, 1); + annotate(drft, ATTACH_FIELD, shell, 1, 0, 0, 1); } pclose(f); } else { @@ -580,7 +590,7 @@ writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) static void writelscmd(char *buf, int bufsz, char *lsoptions, char **argp) { - char *lscmd = concat ("ls ", lsoptions, " --", NULL); + char *lscmd = concat ("ls ", lsoptions, NULL); writesomecmd(buf, bufsz, lscmd, "", argp); free (lscmd); } @@ -647,12 +657,10 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, char *cp, *prog, **vec; struct stat st; -#ifdef HAVE_LSTAT int slinked = 0; -#endif /* HAVE_LSTAT */ /* Was there a previous edit session? */ - if (reedit) { + if (reedit && (*ed || edsave)) { if (!*ed) { /* no explicit editor */ *ed = edsave; /* so use the previous one */ if ((cp = r1bindex (*ed, '/')) == NULL) @@ -680,17 +688,15 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, snprintf (linkpath, sizeof(linkpath), "%s/%s", cwd, LINK); if (atfile) { - unlink (linkpath); -#ifdef HAVE_LSTAT + (void) m_unlink (linkpath); if (link (altpath, linkpath) == NOTOK) { - symlink (altpath, linkpath); + if (symlink (altpath, linkpath) < 0) { + adios (linkpath, "symlink"); + } slinked = 1; } else { slinked = 0; } -#else /* not HAVE_LSTAT */ - link (altpath, linkpath); -#endif /* not HAVE_LSTAT */ } } @@ -704,8 +710,11 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, break; case OK: - if (cwd) - chdir (cwd); + if (cwd) { + if (chdir (cwd) < 0) { + advise (cwd, "chdir"); + } + } if (altmsg) { if (mp) m_putenv ("mhfolder", mp->foldpath); @@ -741,7 +750,6 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, } reedit++; -#ifdef HAVE_LSTAT if (altmsg && mp && !is_readonly(mp) @@ -751,19 +759,9 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, && copyf (linkpath, altpath) == NOTOK : stat (linkpath, &st) != NOTOK && st.st_nlink == 1 - && (unlink (altpath) == NOTOK + && (m_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 */ @@ -772,13 +770,12 @@ editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, *ed = NULL; if (altmsg && atfile) - unlink (linkpath); + (void) m_unlink (linkpath); return status; } -#ifdef HAVE_LSTAT static int copyf (char *ifile, char *ofile) { @@ -804,7 +801,6 @@ copyf (char *ifile, char *ofile) close (out); return i; } -#endif /* HAVE_LSTAT */ /* @@ -818,19 +814,6 @@ sendfile (char **arg, char *file, int pushsw) int i, vecp; char *cp, *sp, **vec, *program; - /* Translate MIME composition file, if necessary */ - if ((cp = context_find ("automimeproc")) - && (!strcmp (cp, "1")) - && check_draft (file) - && (buildfile (NULL, file) == NOTOK)) - return 0; - - /* For backwards compatibility */ - if ((cp = context_find ("automhnproc")) - && check_draft (file) - && (i = editfile (&cp, NULL, file, NOUSE, NULL, NULL, NULL, 0, 0))) - return 0; - /* * If the sendproc is the nmh command `send', then we call * those routines directly rather than exec'ing the command. @@ -913,66 +896,6 @@ buildfile (char **argp, char *file) } -/* - * Check if draft is a mhbuild composition file - */ - -static int -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 (;;) { - int bufsz = sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { - case FLD: - case FLDPLUS: - /* - * If draft already contains any of the - * Content-XXX fields, then assume it already - * been converted. - */ - if (uprf (name, XXX_FIELD_PRF)) { - fclose (fp); - m_getfld_state_destroy (&gstate); - return 0; - } - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, fp); - } - break; - - case BODY: - do { - char *bp; - - for (bp = buf; *bp; bp++) - if (*bp != ' ' && *bp != '\t' && *bp != '\n') { - fclose (fp); - m_getfld_state_destroy (&gstate); - return 1; - } - - 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; - } - } -} - - #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ @@ -1023,13 +946,14 @@ check_draft (char *msgnam) X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ X("saslmech", SASLminc(-5), SASLMECHSW) \ X("user", SASLminc(-4), USERSW) \ - X("attach file", 6, SNDATTACHSW) \ + 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("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ @@ -1062,9 +986,6 @@ sendit (char *sp, char **arg, char *file, int pushed) char *cp, buf[BUFSIZ], **argp, *program; char **arguments, *savearg[MAXARGS], **vec; 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; @@ -1122,13 +1043,19 @@ sendit (char *sp, char **arg, char *file, int pushed) 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++)) { @@ -1216,6 +1143,7 @@ sendit (char *sp, char **arg, char *file, int pushed) case SASLMECHSW: case USERSW: case PORTSW: + case MTSSM: case MTSSW: case MESSAGEIDSW: vec[vecp++] = --cp; @@ -1236,28 +1164,14 @@ sendit (char *sp, char **arg, char *file, int pushed) continue; case SNDATTACHSW: - if (!(attach = *argp++) || *attach == '-') { - advise (NULL, "missing argument to %s", argp[-2]); - return; - } + advise(NULL, "The -attach switch is deprecated"); continue; case SNDNOATTACHSW: - attach = NULL; + advise(NULL, "The -noattach switch is deprecated"); 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; + advise(NULL, "The -attachformat switch is deprecated"); continue; } } @@ -1294,8 +1208,12 @@ sendit (char *sp, char **arg, char *file, int pushed) #endif /* not lint */ && 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 = getcpy (cp); + (void) m_unlink(distfile); if (link (altmsg, distfile) == NOTOK) adios (distfile, "unable to link %s to", altmsg); } else { @@ -1312,7 +1230,7 @@ sendit (char *sp, char **arg, char *file, int pushed) closefds (3); - if (sendsbr (vec, vecp, program, file, &st, 1, attach, attachformat) == OK) + if (sendsbr (vec, vecp, program, file, &st, 1) == OK) done (0); } @@ -1337,10 +1255,10 @@ whomfile (char **arg, char *file) case OK: vec = argsplit(whomproc, &program, &vecp); - vec[vecp++] = file; if (arg) while (*arg) vec[vecp++] = *arg++; + vec[vecp++] = file; vec[vecp] = NULL; execvp (program, vec); @@ -1361,8 +1279,50 @@ whomfile (char **arg, char *file) static int removefile (char *drft) { - if (unlink (drft) == NOTOK) + if (m_unlink (drft) == NOTOK) adios (drft, "unable to unlink"); return OK; } + + +/* + * Return 1 if we already have a MIME-Verson header, 0 otherwise. + */ + +static int +checkmimeheader (char *drft) +{ + FILE *f; + m_getfld_state_t gstate = 0; + char buf[BUFSIZ], name[NAMESZ]; + int state, retval = 0; + + if ((f = fopen(drft, "r")) == NULL) { + admonish(drft, "unable to read draft"); + return (0); + } + + for (;;) { + int bufsz = sizeof(buf); + switch (state = m_getfld(&gstate, name, buf, &bufsz, f)) { + case FLD: + case FLDPLUS: + if (strcasecmp(name, VRSN_FIELD) == 0) { + advise(NULL, "Cannot use attach commands with already-" + "formatted MIME message \"%s\"", drft); + retval = 1; + break; + } + continue; + default: + break; + } + break; + } + + m_getfld_state_destroy(&gstate); + fclose(f); + + return retval; +}