]> diplodocus.org Git - nmh/commitdiff
Moving closer to fixing mhshow completely. Includes fix from David Levine
authorKen Hornstein <kenh@pobox.com>
Thu, 3 Apr 2014 22:12:56 +0000 (18:12 -0400)
committerKen Hornstein <kenh@pobox.com>
Thu, 3 Apr 2014 22:12:56 +0000 (18:12 -0400)
for a slight bug in charset conversion.

Makefile.am
h/mhparse.h
h/prototypes.h
sbr/m_popen.c [new file with mode: 0644]
test/mhshow/test-charset
test/mhshow/test-textcharset
uip/mhlsbr.c
uip/mhmisc.c
uip/mhshow.c
uip/mhshowsbr.c

index f0670b3..71ab0e0 100644 (file)
@@ -575,7 +575,7 @@ sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr/ambigsw.c sbr/atooi.c sbr/arglist.c \
                      sbr/fmt_rfc2047.c sbr/fmt_scan.c sbr/lock_file.c \
                      sbr/m_atoi.c sbr/m_backup.c sbr/m_convert.c \
                      sbr/m_draft.c sbr/m_getfld.c sbr/m_gmprot.c \
-                     sbr/m_maildir.c sbr/m_name.c sbr/m_rand.c \
+                     sbr/m_maildir.c sbr/m_name.c sbr/m_popen.c sbr/m_rand.c \
                      sbr/makedir.c sbr/message_id.c sbr/mime_type.c sbr/mts.c \
                      sbr/norm_charmap.c sbr/path.c \
                      sbr/peekc.c sbr/pidwait.c sbr/pidstatus.c \
index cfa1e53..c2ba18a 100644 (file)
@@ -343,11 +343,21 @@ const struct str2init *get_ce_method (const char *);
 char *content_charset (CT);
 int convert_charset (CT, char *, int *);
 
+/*
+ * Given a content structure, return true if the content has a disposition
+ * of "inline".
+ *
+ * Arguments are:
+ *
+ * ct          - Content structure to examine
+ */
+int is_inline(CT ct);
+
 /*
  * Given a list of messages, display information about them on standard
  * output.
  *
- * Argumens are:
+ * Arguments are:
  *
  * cts         - An array of CT elements of messages that need to be
  *               displayed.  Array is terminated by a NULL.
index f8adbac..7a4f8a3 100644 (file)
@@ -207,6 +207,23 @@ char *m_mktemp(const char *, int *, FILE **);
 char *m_mktemp2(const char *, const char *, int *, FILE **);
 char *m_mktemps(const char *pfx, const char *suffix, int *, FILE **);
 char *get_temp_dir();
+
+/*
+ * Create a subprocess and redirect our standard output to it.
+ *
+ * Arguments are:
+ *
+ * name                - Name of process to create
+ * savestdout  - If true, will save the current stdout file descriptor and
+ *               m_pclose() will close it at the appropriate time.
+ */
+void m_popen(char *name, int savestdout);
+
+/*
+ * Wait for the last process opened by m_popen().
+ */
+void m_pclose(void);
+
 void m_unknown(m_getfld_state_t *, FILE *);
 int makedir (char *);
 char *message_id (time_t, int);
diff --git a/sbr/m_popen.c b/sbr/m_popen.c
new file mode 100644 (file)
index 0000000..8a3bae6
--- /dev/null
@@ -0,0 +1,83 @@
+
+/*
+ * m_popen.c -- Interface for a popen() call that redirects the current
+ *             process standard output to the popen()d process.
+ *
+ * This code is Copyright (c) 2014, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/signals.h>
+
+static int m_pid = NOTOK;      /* Process we're waiting for */
+static  int sd = NOTOK;                /* Original standard output */
+
+/*
+ * Fork a process and redirect our standard output to that process
+ */
+
+void
+m_popen (char *name, int savestdout)
+{
+    int pd[2];
+    char *file;
+    char **arglist;
+
+    if (savestdout && (sd = dup (fileno (stdout))) == NOTOK)
+       adios ("standard output", "unable to dup()");
+
+    if (pipe (pd) == NOTOK)
+       adios ("pipe", "unable to");
+
+    switch (m_pid = fork()) {
+       case NOTOK: 
+           adios ("fork", "unable to");
+
+       case OK: 
+           SIGNAL (SIGINT, SIG_DFL);
+           SIGNAL (SIGQUIT, SIG_DFL);
+
+           close (pd[1]);
+           if (pd[0] != fileno (stdin)) {
+               dup2 (pd[0], fileno (stdin));
+               close (pd[0]);
+           }
+           arglist = argsplit(name, &file, NULL);
+           execvp (file, arglist);
+           fprintf (stderr, "unable to exec ");
+           perror (name);
+           _exit (-1);
+
+       default: 
+           close (pd[0]);
+           if (pd[1] != fileno (stdout)) {
+               dup2 (pd[1], fileno (stdout));
+               close (pd[1]);
+           }
+    }
+}
+
+
+void
+m_pclose (void)
+{
+    if (m_pid == NOTOK)
+       return;
+
+    if (sd != NOTOK) {
+       fflush (stdout);
+       if (dup2 (sd, fileno (stdout)) == NOTOK)
+           adios ("standard output", "unable to dup2()");
+
+       clearerr (stdout);
+       close (sd);
+       sd = NOTOK;
+    }
+    else
+       fclose (stdout);
+
+    pidwait (m_pid, OK);
+    m_pid = NOTOK;
+}
index 974442c..0f3a53c 100755 (executable)
@@ -46,7 +46,7 @@ Subject: test
 
 MIME-Version: 1.0
 
-part       text/plain                  10
+part       text/plain                  11
 This is a test
 EOF
 
index 9fad5d8..5fc07e6 100755 (executable)
@@ -47,7 +47,7 @@ Subject: test display with charset conversion
 
 MIME-Version: 1.0
 
-part       text/plain                  10
+part       text/plain                  11
 4 รท 2 = 2
 EOF
 
index 3ebfa69..e9d4de8 100644 (file)
@@ -332,7 +332,6 @@ static void pipeser (int);
 static void quitser (int);
 static void mhladios (char *, char *, ...);
 static void mhldone (int);
-static void m_popen (char *);
 static void filterbody (struct mcomp *, char *, int, int, FILE *,
                         m_getfld_state_t);
 static void compile_formatfield(struct mcomp *);
@@ -482,7 +481,7 @@ mhl (int argc, char **argv)
                SIGNAL2 (SIGQUIT, quitser);
            }
            SIGNAL2 (SIGPIPE, pipeser);
-           m_popen (moreproc);
+           m_popen (moreproc, mhl_action != NULL);
            ontty = PITTY;
        } else {
            SIGNAL (SIGINT, SIG_IGN);
@@ -1644,74 +1643,6 @@ mhldone (int status)
 }
 
 
-static int m_pid = NOTOK;
-static  int sd = NOTOK;
-
-static void
-m_popen (char *name)
-{
-    int pd[2];
-    char *file;
-    char **arglist;
-
-    if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
-       adios ("standard output", "unable to dup()");
-
-    if (pipe (pd) == NOTOK)
-       adios ("pipe", "unable to");
-
-    switch (m_pid = fork()) {
-       case NOTOK: 
-           adios ("fork", "unable to");
-
-       case OK: 
-           SIGNAL (SIGINT, SIG_DFL);
-           SIGNAL (SIGQUIT, SIG_DFL);
-
-           close (pd[1]);
-           if (pd[0] != fileno (stdin)) {
-               dup2 (pd[0], fileno (stdin));
-               close (pd[0]);
-           }
-           arglist = argsplit(name, &file, NULL);
-           execvp (file, arglist);
-           fprintf (stderr, "unable to exec ");
-           perror (name);
-           _exit (-1);
-
-       default: 
-           close (pd[0]);
-           if (pd[1] != fileno (stdout)) {
-               dup2 (pd[1], fileno (stdout));
-               close (pd[1]);
-           }
-    }
-}
-
-
-void
-m_pclose (void)
-{
-    if (m_pid == NOTOK)
-       return;
-
-    if (sd != NOTOK) {
-       fflush (stdout);
-       if (dup2 (sd, fileno (stdout)) == NOTOK)
-           adios ("standard output", "unable to dup2()");
-
-       clearerr (stdout);
-       close (sd);
-       sd = NOTOK;
-    }
-    else
-       fclose (stdout);
-
-    pidwait (m_pid, OK);
-    m_pid = NOTOK;
-}
-
-
 /*
  * Compile a format string used by the formatfield option and save it
  * for later.
index 7d32023..f4b8916 100644 (file)
@@ -75,6 +75,29 @@ type_ok (CT ct, int sP)
 }
 
 
+/*
+ * Returns true if this content is marked as "inline".
+ *
+ * Technically we should check parent content to see if they have
+ * disposition to use as a default, but we don't right now.  Maybe
+ * later ....
+ */
+
+int
+is_inline(CT ct)
+{
+    /*
+     * If there isn't any disposition at all, it's "inline".  Obviously
+     * if it's "inline", then it's inline.  RFC 2183 says if it's an unknown
+     * disposition, treat it as 'attachment'.
+     */
+
+    if (! ct->c_dispo_type || strcasecmp(ct->c_dispo_type, "inline") == 0)
+       return 1;
+    else
+       return 0;
+}
+
 int
 make_intermediates (char *file)
 {
index edf3f1e..ab58955 100644 (file)
@@ -382,6 +382,9 @@ do_cache:
        context_save ();                  /* save the context file  */
     }
 
+    if (concat)
+       m_popen(moreproc, 0);
+
     /*
      * Show the message content
      */
@@ -394,6 +397,9 @@ do_cache:
     free ((char *) cts);
     cts = NULL;
 
+    if (concat)
+       m_pclose();
+
     done (0);
     return 1;
 }
index c418b21..9ca3419 100644 (file)
@@ -51,7 +51,7 @@ static void DisplayMsgHeader (CT, char *, int);
 static int show_switch (CT, int, int, int, int);
 static int show_content (CT, int);
 static int show_content_aux2 (CT, int, char *, char *, int, int, int);
-static int show_text (CT, int);
+static int show_text (CT, int, int);
 static int show_multi (CT, int, int, int, int);
 static int show_multi_internal (CT, int, int, int, int);
 static int show_multi_aux (CT, int, char *);
@@ -137,7 +137,7 @@ show_single_message (CT ct, char *form, int concat, int textonly,
     sigaddset (&set, SIGTERM);
     sigprocmask (SIG_BLOCK, &set, &oset);
 
-    while (wait (&status) != NOTOK) {
+    while (!concat && wait (&status) != NOTOK) {
        pidcheck (status);
        continue;
     }
@@ -232,7 +232,7 @@ show_switch (CT ct, int alternate, int concat, int textonly, int inlineonly)
            }
 
        case CT_TEXT:
-           return show_text (ct, alternate);
+           return show_text (ct, alternate, concat);
 
        case CT_AUDIO:
        case CT_IMAGE:
@@ -310,7 +310,11 @@ show_content_aux (CT ct, int alternate, char *cp, char *cracked)
            unfortunately the type checks are necessary without
            some code rearrangement.  And to make this really ugly,
            only do it in mhshow, not mhfixmsg, mhn, or mhstore. */
-        if (convert_content_charset (ct, &file) != OK) {
+        if (convert_content_charset (ct, &file) == OK) {
+            close_encoding (ct);
+            if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
+                return NOTOK;
+        } else {
             admonish (NULL, "unable to convert character set%s to %s",
                       ct->c_partno  ?  "of part "  :  "",
                       ct->c_partno  ?  ct->c_partno  :  "",
@@ -367,6 +371,33 @@ show_content_aux2 (CT ct, int alternate, char *cracked, char *buffer,
            list_switch (ct, -1, 1, 0, 0, 0);
     }
 
+    /*
+     * If the command is a zero-length string, just write the output on
+     * stdout.
+     */
+
+    if (buffer[0] == '\0') {
+       char readbuf[BUFSIZ];
+       ssize_t cc;
+
+       if (fd == NOTOK) {
+           advise(NULL, "Cannot use NULL command to display content-type "
+                  "%s/%s", ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype);
+           return NOTOK;
+       }
+
+       while ((cc = read(fd, readbuf, sizeof(readbuf))) > 0) {
+           fwrite(readbuf, sizeof(char), cc, stdout);
+       }
+
+       if (cc < 0) {
+           advise("read", "while reading text content");
+           return NOTOK;
+       }
+
+       return OK;
+    }
+
     vec = argsplit(buffer, &file, &vecp);
     vec[vecp++] = NULL;
 
@@ -409,7 +440,7 @@ show_content_aux2 (CT ct, int alternate, char *cracked, char *buffer,
  */
 
 static int
-show_text (CT ct, int alternate)
+show_text (CT ct, int alternate, int concat)
 {
     char *cp, buffer[BUFSIZ];
     CI ci = &ct->c_ctinfo;
@@ -430,8 +461,11 @@ show_text (CT ct, int alternate)
      * if it is not a text part of a multipart/alternative
      */
     if (!alternate || ct->c_subtype == TEXT_PLAIN) {
-       snprintf (buffer, sizeof(buffer), "%%l%s %%F", progsw ? progsw :
-               moreproc && *moreproc ? moreproc : DEFAULT_PAGER);
+       if (concat)
+           snprintf(buffer, sizeof(buffer), "%%l");
+       else
+           snprintf (buffer, sizeof(buffer), "%%l%s %%F", progsw ? progsw :
+                     moreproc && *moreproc ? moreproc : DEFAULT_PAGER);
        cp = (ct->c_showproc = add (buffer, NULL));
        return show_content_aux (ct, alternate, cp, NULL);
     }
@@ -505,7 +539,8 @@ show_multi_internal (CT ct, int alternate, int concat, int textonly,
     for (part = m->mp_parts; part; part = part->mp_next) {
        p = part->mp_part;
 
-       if (part_ok (p, 1) && type_ok (p, 1)) {
+       if (part_ok (p, 1) && type_ok (p, 1) &&
+                                       (!inlineonly || is_inline(ct))) {
            int inneresult;
 
            inneresult = show_switch (p, nowalternate, concat, textonly,
@@ -660,7 +695,7 @@ show_external (CT ct, int alternate, int concat, int textonly, int inlineonly)
     struct exbody *e = (struct exbody *) ct->c_ctparams;
     CT p = e->eb_content;
 
-    if (!type_ok (p, 0))
+    if (!type_ok (p, 0) || (inlineonly && !is_inline(p)))
        return OK;
 
     return show_switch (p, alternate, concat, textonly, inlineonly);