for a slight bug in charset conversion.
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 \
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.
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);
--- /dev/null
+
+/*
+ * 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;
+}
MIME-Version: 1.0
-part text/plain 10
+part text/plain 11
This is a test
EOF
MIME-Version: 1.0
-part text/plain 10
+part text/plain 11
4 รท 2 = 2
EOF
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 *);
SIGNAL2 (SIGQUIT, quitser);
}
SIGNAL2 (SIGPIPE, pipeser);
- m_popen (moreproc);
+ m_popen (moreproc, mhl_action != NULL);
ontty = PITTY;
} else {
SIGNAL (SIGINT, SIG_IGN);
}
-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.
}
+/*
+ * 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)
{
context_save (); /* save the context file */
}
+ if (concat)
+ m_popen(moreproc, 0);
+
/*
* Show the message content
*/
free ((char *) cts);
cts = NULL;
+ if (concat)
+ m_pclose();
+
done (0);
return 1;
}
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 *);
sigaddset (&set, SIGTERM);
sigprocmask (SIG_BLOCK, &set, &oset);
- while (wait (&status) != NOTOK) {
+ while (!concat && wait (&status) != NOTOK) {
pidcheck (status);
continue;
}
}
case CT_TEXT:
- return show_text (ct, alternate);
+ return show_text (ct, alternate, concat);
case CT_AUDIO:
case CT_IMAGE:
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 : "",
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;
*/
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;
* 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);
}
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,
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);