From a587df65eafb93bea5cc74053823fd07bc13ea8b Mon Sep 17 00:00:00 2001 From: Philipp Takacs Date: Sat, 5 Feb 2022 12:21:35 +0100 Subject: [PATCH 1/2] repl: pipe mail through mhshow When reply to a MIME message the mhshow will decode the mime message before mhl will get it to create a reply draft. This makes it more convinient to reply to a MIME message. Problems: * mhshow can be configured to display parts in a graphical programm. This can lead to unexpected behavior on repl (i.e. start plaing musik). * mhshow display string can contain '%l' which leads to a listing prior to displaying content. This listing is contained in the draft. --- man/repl.man | 22 ++++++++ uip/repl.c | 11 +++- uip/replsbr.c | 137 +++++++++++++++++++++++++++++++++++++------------- uip/replsbr.h | 2 +- 4 files changed, 134 insertions(+), 38 deletions(-) diff --git a/man/repl.man b/man/repl.man index 790e19b5..fc1935fc 100644 --- a/man/repl.man +++ b/man/repl.man @@ -51,6 +51,7 @@ all/to/cc/me] .RB [ \-build ] .RB [ \-file .IR msgfile ] +.RB [ \-fixmime " | " \-nofixmime ] .ad .SH DESCRIPTION .B repl @@ -71,6 +72,14 @@ format file (see .IR mh\-format (5) for details). .PP +To decode MIME messages +.B repl +pipe the message through +.IR showmimeproc . +This can be disabled with the +.B \-nofixmime +switch. +.PP If the switch .B \-nogroup is given (it is on by default), then @@ -516,6 +525,7 @@ is checked. ^Editor:~^To override the default editor ^Msg\-Protect:~^To set mode when creating a new message (draft) ^fileproc:~^Program to refile the message +^showmimeproc:~^Program to show non-text (MIME) messages ^mhlproc:~^Program to filter message being replied-to ^whatnowproc:~^Program to ask the \*(lqWhat now?\*(rq questions .fi @@ -542,6 +552,7 @@ is checked. .RB ` \-noquery ' .RB ` \-noatfile ' .RB ` "\-width\ 72" ' +.RB ` \-fixmime ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The message @@ -578,3 +589,14 @@ don't call it since .B repl won't run it. +.PP +The +.RB \-fixmime +switch causes repl to pipe the message through +.IR showmimeproc . +If the +.IR showmimeproc +is configured to display listing prior a mime part, these listing will end up in the draft. +There might also be some unexpected behaviors, when the +.IR showmimeproc +is configured to display the content externel (i.e. open a browser to display html). diff --git a/uip/repl.c b/uip/repl.c index b1ceb1f6..8ed22709 100644 --- a/uip/repl.c +++ b/uip/repl.c @@ -72,6 +72,8 @@ X("noatfile", 0, NOATFILESW) \ X("fmtproc program", 0, FMTPROCSW) \ X("nofmtproc", 0, NFMTPROCSW) \ + X("fixmime", 0, FIXMIMESW) \ + X("nofixmime", 0, NFIXMIMESW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(REPL); @@ -143,6 +145,7 @@ main (int argc, char **argv) bool nedit = false; bool nwhat = false; bool atfile = false; + bool fixmime = true; int fmtproc = -1; char *cp, *cwd, *dp, *maildir, *file = NULL; char *folder = NULL, *msg = NULL, *dfolder = NULL; @@ -354,6 +357,12 @@ main (int argc, char **argv) case NFMTPROCSW: fmtproc = 0; continue; + case FIXMIMESW: + fixmime = true; + continue; + case NFIXMIMESW: + fixmime = false; + continue; } } if (*cp == '+' || *cp == '@') { @@ -469,7 +478,7 @@ try_it_again: } replout (in, msg, drft, mp, outputlinelen, mime, form, filter, - fcc, fmtproc); + fcc, fmtproc, fixmime); fclose (in); { diff --git a/uip/replsbr.c b/uip/replsbr.c index ef4925ae..d2bab72f 100644 --- a/uip/replsbr.c +++ b/uip/replsbr.c @@ -61,7 +61,7 @@ static char *addrcomps[] = { * static prototypes */ static int insert (struct mailname *); -static void replfilter (FILE *, FILE *, char *, int); +static void replfilter (FILE *, FILE *, char *, int, bool); static char *replformataddr(char *, char *); static char *replconcataddr(char *, char *); static char *fix_addresses (char *); @@ -69,7 +69,7 @@ static char *fix_addresses (char *); void replout (FILE *inb, char *msg, char *drft, struct msgs *mp, int outputlinelen, - int mime, char *form, char *filter, char *fcc, int fmtproc) + int mime, char *form, char *filter, char *fcc, int fmtproc, bool fixmime) { int state, i; struct comp *cptr; @@ -241,7 +241,7 @@ finished: if (ferror (out)) adios (drft, "error writing"); - replfilter (inb, out, filter, fmtproc); + replfilter (inb, out, filter, fmtproc, fixmime); } else if (mime && mp) { fprintf (out, "#forw [original message] +%s %s\n", mp->foldpath, m_name (mp->lowsel)); @@ -421,21 +421,63 @@ insert (struct mailname *np) return 1; } +static void +execmhl(char *mhl, char **arglist, int argnum, char *filter, int fmtproc) +{ + char *errstr; + + /* + * We're not allocating the memory for the extra arguments, + * because we never call arglist_free(). But if we ever change + * that be sure to use getcpy() for the extra arguments. + */ + arglist[argnum++] = "-nomoreproc"; + arglist[argnum++] = "-form"; + arglist[argnum++] = filter; + arglist[argnum++] = "-noclear"; + + switch (fmtproc) { + case 1: + arglist[argnum++] = "-fmtproc"; + arglist[argnum++] = formatproc; + break; + case 0: + arglist[argnum++] = "-nofmtproc"; + break; + } + + arglist[argnum++] = NULL; + + execvp (mhl, arglist); + errstr = strerror(errno); + if (write(2, "unable to exec ", 15) < 0 || + write(2, mhlproc, strlen(mhlproc)) < 0 || + write(2, ": ", 2) < 0 || + write(2, errstr, strlen(errstr)) < 0 || + write(2, "\n", 1) < 0) { + advise ("stderr", "write"); + } + _exit(1); +} /* - * Call the mhlproc + * Start the filter pipeline * * This function expects that argument out has been fflushed by the caller. */ static void -replfilter (FILE *in, FILE *out, char *filter, int fmtproc) +replfilter (FILE *in, FILE *out, char *filter, int fmtproc, bool fixmime) { int pid; char *mhl; char *errstr; char **arglist; int argnum; + int mailpipe[2]; + char *mhshow; + char **mhshowargs; + int mshowargnum; if (filter == NULL) return; @@ -447,48 +489,71 @@ replfilter (FILE *in, FILE *out, char *filter, int fmtproc) lseek(fileno(in), 0, SEEK_SET); arglist = argsplit(mhlproc, &mhl, &argnum); + mhshowargs = argsplit(showmimeproc, &mhshow, &mshowargnum); switch (pid = fork()) { case NOTOK: adios ("fork", "unable to"); case OK: - dup2 (fileno (in), fileno (stdin)); - dup2 (fileno (out), fileno (stdout)); - - /* - * We're not allocating the memory for the extra arguments, - * because we never call arglist_free(). But if we ever change - * that be sure to use getcpy() for the extra arguments. - */ - arglist[argnum++] = "-form"; - arglist[argnum++] = filter; - arglist[argnum++] = "-noclear"; - - switch (fmtproc) { - case 1: - arglist[argnum++] = "-fmtproc"; - arglist[argnum++] = formatproc; - break; - case 0: - arglist[argnum++] = "-nofmtproc"; - break; - } - arglist[argnum++] = NULL; + if (fixmime) { + if (pipe(mailpipe) == -1) { + adios("pipe", "can't create pipe"); + } - execvp (mhl, arglist); - errstr = strerror(errno); - if (write(2, "unable to exec ", 15) < 0 || - write(2, mhlproc, strlen(mhlproc)) < 0 || - write(2, ": ", 2) < 0 || - write(2, errstr, strlen(errstr)) < 0 || - write(2, "\n", 1) < 0) { - advise ("stderr", "write"); + switch (pid = fork()) { + case NOTOK: + adios ("fork", "unable to"); + + case OK: + dup2 (fileno (in), fileno (stdin)); + dup2 (mailpipe[1], fileno (stdout)); + close(fileno(in)); + close(fileno(out)); + close(mailpipe[0]); + close(mailpipe[1]); + + /* + * We're not allocating the memory for the extra arguments, + * because we never call arglist_free(). But if we ever change + * that be sure to use getcpy() for the extra arguments. + */ + mhshowargs[argnum++] = "-file"; + mhshowargs[argnum++] = "-"; + mhshowargs[argnum++] = "-concat"; + mhshowargs[argnum++] = NULL; + + execvp (mhshow, mhshowargs); + errstr = strerror(errno); + if (write(2, "unable to exec ", 15) < 0 || + write(2, mhshow, strlen(mhshow)) < 0 || + write(2, ": ", 2) < 0 || + write(2, errstr, strlen(errstr)) < 0 || + write(2, "\n", 1) < 0) { + advise ("stderr", "write"); + } + _exit(1); + default: + dup2 (mailpipe[0], fileno (stdin)); + dup2 (fileno (out), fileno (stdout)); + close(fileno (in)); + close(fileno (out)); + close(mailpipe[0]); + close(mailpipe[1]); + execmhl(mhl, arglist, argnum, filter, fmtproc); + } + } else { + dup2(fileno (in), fileno (stdin)); + dup2(fileno (out), fileno (stdout)); + close(fileno (in)); + close(fileno (out)); + execmhl(mhl, arglist, argnum, filter, fmtproc); } - _exit(1); default: + close(fileno(in)); + close(fileno(out)); if (pidXwait (pid, mhl)) done (1); fseek (out, 0L, SEEK_END); diff --git a/uip/replsbr.h b/uip/replsbr.h index 2379962a..22423ed1 100644 --- a/uip/replsbr.h +++ b/uip/replsbr.h @@ -7,7 +7,7 @@ void replout(FILE *inb, char *msg, char *drft, struct msgs *mp, int outputlinelen, int mime, char *form, char *filter, char *fcc, - int fmtproc); + int fmtproc, bool fixmime); extern short ccto; extern short cccc; -- 2.30.2