#include <fcntl.h>
#include <h/signals.h>
#include <errno.h>
-#include <setjmp.h>
#include <signal.h>
#include <h/tws.h>
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/utils.h>
#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sysexits.h>
extern int debugsw;
int nolist = 0;
char *formsw = NULL;
-pid_t xpid = 0;
/* mhparse.c */
void flush_errors(void);
/* mhlistsbr.c */
-int list_switch(CT, int, int, int, int);
-int list_content(CT, int, int, int, int);
+int list_switch(CT, int, int, int);
+int list_content(CT, int, int, int);
/*
** prototypes
static void DisplayMsgHeader(CT, char *);
static int show_switch(CT, int);
static int show_content(CT, int);
-static int show_content_aux2(CT, int, char *, char *, int, int, int, int);
+static int show_content_aux2(CT, int, char *, char *, int, int, int);
static int show_text(CT, int);
static int show_multi(CT, int);
static int show_multi_internal(CT, int);
for (ctp = cts; *ctp; ctp++) {
ct = *ctp;
- /* if top-level type is ok, then display message */
- if (type_ok(ct, 1))
- show_single_message(ct, formsw);
+ if (!type_ok(ct, 1)) { /* top-level type */
+ continue;
+ }
+ if (cts[1]) {
+ if (ctp != cts) {
+ printf("\n\n");
+ }
+ printf(">>> Message %s\n\n", ct->c_file);
+ }
+ show_single_message(ct, formsw);
}
}
static void
show_single_message(CT ct, char *form)
{
- sigset_t set, oset;
- int status;
-
/*
** Allow user executable bit so that temporary directories created by
** the viewer (e.g., lynx) are going to be accessible
*/
if (form)
DisplayMsgHeader(ct, form);
- else
- xpid = 0;
/* Show the body of the message */
show_switch(ct, 0);
if (ct->c_ceclosefnx)
(*ct->c_ceclosefnx) (ct);
- /* block a few signals */
- sigemptyset(&set);
- sigaddset(&set, SIGHUP);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGQUIT);
- sigaddset(&set, SIGTERM);
- sigprocmask(SIG_BLOCK, &set, &oset);
-
- while (wait(&status) != NOTOK) {
- pidcheck(status);
- continue;
- }
-
- /* reset the signal mask */
- sigprocmask(SIG_SETMASK, &oset, &set);
-
- xpid = 0;
flush_errors();
}
switch (child_id = fork()) {
case NOTOK:
- adios("fork", "unable to");
+ adios(EX_OSERR, "fork", "unable to");
/* NOTREACHED */
case OK:
execvp("mhl", vec);
fprintf(stderr, "unable to exec ");
perror("mhl");
- _exit(-1);
+ _exit(EX_OSERR);
/* NOTREACHED */
default:
- xpid = -child_id;
+ pidcheck(pidwait(child_id, NOTOK));
break;
}
}
break;
default:
- adios(NULL, "unknown content type %d", ct->c_type);
+ adios(EX_DATAERR, NULL, "unknown content type %d", ct->c_type);
break;
}
CI ci = &ct->c_ctinfo;
/* Check for mhshow-show-type/subtype */
- snprintf(buffer, sizeof(buffer), "%s-show-%s/%s",
- invo_name, ci->ci_type, ci->ci_subtype);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s/%s",
+ ci->ci_type, ci->ci_subtype);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
/* Check for mhshow-show-type */
- snprintf(buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s", ci->ci_type);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
/* complain if we are not a part of a multipart/alternative */
if (!alternate)
- content_error(NULL, ct, "don't know how to display content");
+ return show_content_aux(ct, alternate, "%l", NULL);
return NOTOK;
}
/*
** Parse the display string for displaying generic content
*/
-
int
show_content_aux(CT ct, int alternate, char *cp, char *cracked)
{
int fd, len, buflen, quoted;
- int xstdin, xlist, xtty;
+ int xstdin, xlist;
char *bp, *pp, *file, buffer[BUFSIZ];
CI ci = &ct->c_ctinfo;
xlist = 0;
xstdin = 0;
- xtty = 0;
if (cracked) {
strncpy(buffer, cp, sizeof(buffer));
}
break;
+ case 'c':
+ /* insert charset */
+ strncpy(bp, ct->c_charset ? ct->c_charset :
+ "US-ASCII", buflen);
+ break;
+
case 'd':
/* insert content description */
if (ct->c_descr) {
}
break;
- case 'e':
- /* exclusive execution */
- xtty = 1;
- break;
-
case 'F':
- /* %e, %f, and stdin is terminal not content */
+ /* %f, and stdin is terminal not content */
xstdin = 1;
- xtty = 1;
/* and fall... */
case 'f':
pp = bp;
break;
- case 'p':
case 'l':
/*
** display listing prior to displaying content
}
}
- if (buflen <= 0 || (ct->c_termproc &&
- (size_t)buflen <= strlen(ct->c_termproc))) {
- /*
- ** content_error would provide a more useful error message
- ** here, except that if we got overrun, it probably would
- ** too.
- */
- fprintf(stderr, "Buffer overflow constructing show command!\n");
- return NOTOK;
- }
-
- /* use charset string to modify display method */
- if (ct->c_termproc) {
- char term[BUFSIZ];
-
- strncpy(term, buffer, sizeof(term));
- snprintf(buffer, sizeof(buffer), ct->c_termproc, term);
- }
-
got_command:
return show_content_aux2(ct, alternate, cracked, buffer,
- fd, xlist, xstdin, xtty);
+ fd, xlist, xstdin);
}
/*
** Routine to actually display the content
*/
-
static int
show_content_aux2(CT ct, int alternate, char *cracked,
- char *buffer, int fd, int xlist, int xstdin, int xtty)
+ char *buffer, int fd, int xlist, int xstdin)
{
pid_t child_id;
- char *vec[4], exec[BUFSIZ + sizeof "exec "];
if (debugsw || cracked) {
fflush(stdout);
fprintf(stderr, " using command %s\n", buffer);
}
- if (xpid < 0 || (xtty && xpid)) {
- if (xpid < 0)
- xpid = -xpid;
- pidcheck(pidwait(xpid, NOTOK));
- xpid = 0;
- }
-
if (xlist) {
if (ct->c_type == CT_MULTIPART)
- list_content(ct, -1, 1, 0, 0);
+ list_content(ct, -1, 0, 0);
else
- list_switch(ct, -1, 1, 0, 0);
+ list_switch(ct, -1, 0, 0);
}
- snprintf(exec, sizeof(exec), "exec %s", buffer);
-
- vec[0] = "/bin/sh";
- vec[1] = "-c";
- vec[2] = exec;
- vec[3] = NULL;
-
fflush(stdout);
switch (child_id = fork()) {
if (!xstdin)
dup2(fd, 0);
close(fd);
- execvp("/bin/sh", vec);
+ execlp("/bin/sh", "/bin/sh", "-c", buffer, NULL);
fprintf(stderr, "unable to exec ");
perror("/bin/sh");
- _exit(-1);
+ _exit(EX_OSERR);
/* NOTREACHED */
default:
CI ci = &ct->c_ctinfo;
/* Check for mhshow-show-type/subtype */
- snprintf(buffer, sizeof(buffer), "%s-show-%s/%s",
- invo_name, ci->ci_type, ci->ci_subtype);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s/%s",
+ ci->ci_type, ci->ci_subtype);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
/* Check for mhshow-show-type */
- snprintf(buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s", ci->ci_type);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
** if it is not a text part of a multipart/alternative
*/
if (!alternate || ct->c_subtype == TEXT_PLAIN) {
- snprintf(buffer, sizeof(buffer), "%%p%s '%%F'", defaultpager);
- cp = (ct->c_showproc = getcpy(buffer));
- return show_content_aux(ct, alternate, cp, NULL);
+ if (ct->c_charset && !is_native_charset(ct->c_charset)) {
+ snprintf(buffer, sizeof(buffer), "%%liconv -f '%s'",
+ ct->c_charset);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%%lcat");
+ }
+ ct->c_showproc = getcpy(buffer);
+ return show_content_aux(ct, alternate, ct->c_showproc, NULL);
}
return NOTOK;
CI ci = &ct->c_ctinfo;
/* Check for mhshow-show-type/subtype */
- snprintf(buffer, sizeof(buffer), "%s-show-%s/%s",
- invo_name, ci->ci_type, ci->ci_subtype);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s/%s",
+ ci->ci_type, ci->ci_subtype);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_multi_aux(ct, alternate, cp);
/* Check for mhshow-show-type */
- snprintf(buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s", ci->ci_type);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_multi_aux(ct, alternate, cp);
show_multi_aux(CT ct, int alternate, char *cp)
{
int len, buflen, quoted;
- int xlist, xtty;
+ int xlist;
char *bp, *pp, *file, buffer[BUFSIZ];
struct multipart *m = (struct multipart *) ct->c_ctparams;
struct part *part;
}
xlist = 0;
- xtty = 0;
/* get buffer ready to go */
bp = buffer;
}
break;
+ case 'c':
+ /* insert charset */
+ strncpy(bp, ct->c_charset ? ct->c_charset :
+ "US-ASCII", buflen);
+ break;
+
case 'd':
/* insert content description */
if (ct->c_descr) {
}
break;
- case 'e':
- /* exclusive execution */
- xtty = 1;
- break;
-
case 'F':
- /* %e and %f */
- xtty = 1;
- /* and fall... */
-
case 'f':
/* insert filename(s) containing content */
{
}
break;
- case 'p':
case 'l':
/*
** display listing prior to displaying content
}
}
- if (buflen <= 0 || (ct->c_termproc &&
- (size_t)buflen <= strlen(ct->c_termproc))) {
- /*
- ** content_error would provide a more useful error message
- ** here, except that if we got overrun, it probably would
- ** too.
- */
- fprintf(stderr, "Buffer overflow constructing show command!\n");
- return NOTOK;
- }
-
- /* use charset string to modify display method */
- if (ct->c_termproc) {
- char term[BUFSIZ];
-
- strncpy(term, buffer, sizeof(term));
- snprintf(buffer, sizeof(buffer), ct->c_termproc, term);
- }
-
return show_content_aux2(ct, alternate, NULL, buffer,
- NOTOK, xlist, 0, xtty);
+ NOTOK, xlist, 0);
}
CI ci = &ct->c_ctinfo;
/* Check for mhshow-show-type/subtype */
- snprintf(buffer, sizeof(buffer), "%s-show-%s/%s",
- invo_name, ci->ci_type, ci->ci_subtype);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s/%s",
+ ci->ci_type, ci->ci_subtype);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
/* Check for mhshow-show-type */
- snprintf(buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type);
+ snprintf(buffer, sizeof(buffer), "mhshow-show-%s", ci->ci_type);
if ((cp = context_find(buffer)) && *cp != '\0')
return show_content_aux(ct, alternate, cp, NULL);
/* default method for message/rfc822 */
if (ct->c_subtype == MESSAGE_RFC822) {
- cp = (ct->c_showproc = getcpy("%pshow -file '%F'"));
+ cp = (ct->c_showproc = getcpy("%lshow -file %F"));
return show_content_aux(ct, alternate, cp, NULL);
}
/* complain if we are not a part of a multipart/alternative */
if (!alternate)
- content_error(NULL, ct, "don't know how to display content");
+ return show_content_aux(ct, alternate, "%l", NULL);
return NOTOK;
}
static int
show_partial(CT ct, int alternate)
{
- content_error(NULL, ct,
- "in order to display this message, you must reassemble it");
+ show_content_aux(ct, alternate, "%l", NULL);
+ puts("in order to display this message, you must reassemble it");
return NOTOK;
}
/*
-** Show content of type "message/external".
-**
-** THE ERROR CHECKING IN THIS ONE IS NOT DONE YET.
+** Show how to retrieve content of type "message/external".
*/
-
static int
show_external(CT ct, int alternate)
{
- struct exbody *e = (struct exbody *) ct->c_ctparams;
- CT p = e->eb_content;
-
- if (!type_ok(p, 0))
- return OK;
-
- return show_switch(p, alternate);
-
-#if 0
- content_error(NULL, p, "don't know how to display content");
- return NOTOK;
-#endif
+ char **ap, **ep;
+ char *msg;
+ FILE *fp;
+ char buf[BUFSIZ];
+
+ msg = add("You need to fetch the contents yourself:\n", NULL);
+ ap = ct->c_ctinfo.ci_attrs;
+ ep = ct->c_ctinfo.ci_values;
+ for (; *ap; ap++, ep++) {
+ msg = add(concat("\t", *ap, ": ", *ep, NULL), msg);
+ }
+ if (!(fp = fopen(ct->c_file, "r"))) {
+ adios(EX_IOERR, ct->c_file, "unable to open");
+ }
+ fseek(fp, ct->c_begin, SEEK_SET);
+ while (!feof(fp) && ftell(fp) < ct->c_end) {
+ if (!fgets(buf, sizeof buf, fp)) {
+ adios(EX_IOERR, ct->c_file, "unable to read");
+ }
+ *strchr(buf, '\n') = '\0';
+ if (!*buf) {
+ continue; /* skip empty lines */
+ }
+ msg = add(concat("\t", buf, "\n", NULL), msg);
+ }
+ fclose(fp);
+ show_content_aux(ct, alternate, "%l", NULL);
+ fputs(msg, stdout);
+ return OK;
}