X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fmhshowsbr.c;h=3b91eebf78ccb74ff46e044cea46e94c96189d51;hb=bfad64befb4d6696fdfb63b119666eec4bac6fb3;hp=e76dbaac92cbaaa10b64082346edd92fad48d323;hpb=794dab6aa5027ffaf024506140c258f6a0a9322d;p=mmh diff --git a/uip/mhshowsbr.c b/uip/mhshowsbr.c index e76dbaa..3b91eeb 100644 --- a/uip/mhshowsbr.c +++ b/uip/mhshowsbr.c @@ -2,7 +2,9 @@ /* * mhshowsbr.c -- routines to display the contents of MIME messages * - * $Id$ + * This code is Copyright (c) 2002, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. */ #include @@ -12,26 +14,13 @@ #include #include #include -#include -#include +#include +#include #include #include +#include +#include -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -/* - * Just use sigjmp/longjmp on older machines that - * don't have sigsetjmp/siglongjmp. - */ -#ifndef HAVE_SIGSETJMP -# define sigjmp_buf jmp_buf -# define sigsetjmp(env,mask) setjmp(env) -# define siglongjmp(env,val) longjmp(env,val) -#endif - -extern int errno; extern int debugsw; int pausesw = 1; @@ -49,12 +38,6 @@ pid_t xpid = 0; static sigjmp_buf intrenv; -/* termsbr.c */ -int SOprintf (char *, ...); - -/* mhparse.c */ -int pidcheck (int); - /* mhmisc.c */ int part_ok (CT, int); int type_ok (CT, int); @@ -86,7 +69,7 @@ static int show_multi_aux (CT, int, int, char *); static int show_message_rfc822 (CT, int, int); static int show_partial (CT, int, int); static int show_external (CT, int, int); -static RETSIGTYPE intrser (int); +static void intrser (int); /* @@ -115,7 +98,7 @@ show_all_messages (CT *cts) ct = *ctp; /* if top-level type is ok, then display message */ - if (type_ok (ct, 0)) + if (type_ok (ct, 1)) show_single_message (ct, formsw); } } @@ -130,13 +113,11 @@ show_single_message (CT ct, char *form) { sigset_t set, oset; -#ifdef WAITINT int status; -#else - union wait status; -#endif - umask (ct->c_umask); + /* Allow user executable bit so that temporary directories created by + * the viewer (e.g., lynx) are going to be accessible */ + umask (ct->c_umask & ~(0100)); /* * If you have a format file, then display @@ -163,19 +144,15 @@ show_single_message (CT ct, char *form) sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); - SIGPROCMASK (SIG_BLOCK, &set, &oset); + sigprocmask (SIG_BLOCK, &set, &oset); while (wait (&status) != NOTOK) { -#ifdef WAITINT pidcheck (status); -#else - pidcheck (status.w_status); -#endif continue; } /* reset the signal mask */ - SIGPROCMASK (SIG_SETMASK, &oset, &set); + sigprocmask (SIG_SETMASK, &oset, &set); xpid = 0; flush_errors (); @@ -325,9 +302,9 @@ show_content (CT ct, int serial, int alternate) int show_content_aux (CT ct, int serial, int alternate, char *cp, char *cracked) { - int fd, len, buflen; + int fd, len, buflen, quoted; int xstdin, xlist, xpause, xtty; - char *bp, *file, buffer[BUFSIZ]; + char *bp, *pp, *file, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; if (!ct->c_ceopenfnx) { @@ -355,12 +332,15 @@ show_content_aux (CT ct, int serial, int alternate, char *cp, char *cracked) /* get buffer ready to go */ bp = buffer; - bp[0] = '\0'; - buflen = sizeof(buffer); + buflen = sizeof(buffer) - 1; + bp[0] = bp[buflen] = '\0'; + quoted = 0; /* Now parse display string */ - for ( ; *cp; cp++) { + for ( ; *cp && buflen > 0; cp++) { if (*cp == '%') { + pp = bp; + switch (*++cp) { case 'a': /* insert parameters from Content-Type field */ @@ -402,7 +382,16 @@ show_content_aux (CT ct, int serial, int alternate, char *cp, char *cracked) case 'f': /* insert filename containing content */ - snprintf (bp, buflen, "%s", file); + snprintf (bp, buflen, "'%s'", file); + /* since we've quoted the file argument, set things up + * to look past it, to avoid problems with the quoting + * logic below. (I know, I should figure out what's + * broken with the quoting logic, but..) + */ + len = strlen(bp); + buflen -= len; + bp += len; + pp = bp; break; case 'p': @@ -433,14 +422,57 @@ show_content_aux (CT ct, int serial, int alternate, char *cp, char *cracked) len = strlen (bp); bp += len; buflen -= len; + + /* Did we actually insert something? */ + if (bp != pp) { + /* Insert single quote if not inside quotes already */ + if (!quoted && buflen) { + len = strlen (pp); + memmove (pp + 1, pp, len); + *pp++ = '\''; + buflen--; + bp++; + } + /* Escape existing quotes */ + while ((pp = strchr (pp, '\'')) && buflen > 3) { + len = strlen (pp++); + memmove (pp + 3, pp, len); + *pp++ = '\\'; + *pp++ = '\''; + *pp++ = '\''; + buflen -= 3; + bp += 3; + } + /* If pp is still set, that means we ran out of space. */ + if (pp) + buflen = 0; + if (!quoted && buflen) { + *bp++ = '\''; + *bp = '\0'; + buflen--; + } + } } else { raw: - *bp++ = *cp; - *bp = '\0'; - buflen--; + *bp++ = *cp; + *bp = '\0'; + buflen--; + + if (*cp == '\'') + quoted = !quoted; } } + 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]; @@ -495,13 +527,13 @@ show_content_aux2 (CT ct, int serial, int alternate, char *cracked, char *buffer else list_switch (ct, -1, 1, 0, 0); - if (xpause && SOprintf ("Press to show content...")) - printf ("Press to show content..."); - - if (xpause) { + if (xpause && isatty (fileno (stdout))) { int intr; SIGNAL_HANDLER istat; + if (SOprintf ("Press to show content...")) + printf ("Press to show content..."); + istat = SIGNAL (SIGINT, intrser); if ((intr = sigsetjmp (intrenv, 1)) == OK) { fflush (stdout); @@ -509,10 +541,11 @@ show_content_aux2 (CT ct, int serial, int alternate, char *cracked, char *buffer read (fileno (stdout), prompt, sizeof(prompt)); } SIGNAL (SIGINT, istat); - if (intr != OK) { + if (intr != OK || prompt[0] == 'n') { (*ct->c_ceclosefnx) (ct); return (alternate ? DONE : NOTOK); } + if (prompt[0] == 'q') done(OK); } } @@ -525,7 +558,7 @@ show_content_aux2 (CT ct, int serial, int alternate, char *cracked, char *buffer fflush (stdout); - for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++) + for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: @@ -622,14 +655,11 @@ show_multi (CT ct, int serial, int alternate) return show_multi_aux (ct, serial, alternate, cp); /* - * Use default method to display this multipart content - * if it is not a (nested) part of a multipart/alternative, - * or if it is one of the known subtypes of multipart. + * Use default method to display this multipart content. Even + * unknown types are displayable, since they're treated as mixed + * per RFC 2046. */ - if (!alternate || ct->c_subtype != MULTI_UNKNOWN) - return show_multi_internal (ct, serial, alternate); - - return NOTOK; + return show_multi_internal (ct, serial, alternate); } @@ -672,7 +702,7 @@ show_multi_internal (CT ct, int serial, int alternate) sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); - SIGPROCMASK (SIG_BLOCK, &set, &oset); + sigprocmask (SIG_BLOCK, &set, &oset); } /* @@ -685,7 +715,7 @@ show_multi_internal (CT ct, int serial, int alternate) for (part = m->mp_parts; part; part = part->mp_next) { p = part->mp_part; - if (part_ok (p, 0) && type_ok (p, 0)) { + if (part_ok (p, 1) && type_ok (p, 1)) { int inneresult; inneresult = show_switch (p, nowserial, nowalternate); @@ -724,11 +754,7 @@ show_multi_internal (CT ct, int serial, int alternate) if (serial && !nowserial) { pid_t pid; int kids; -#ifdef WAITINT int status; -#else - union wait status; -#endif kids = 0; for (part = m->mp_parts; part; part = part->mp_next) { @@ -743,11 +769,7 @@ show_multi_internal (CT ct, int serial, int alternate) } while (kids > 0 && (pid = wait (&status)) != NOTOK) { -#ifdef WAITINT pidcheck (status); -#else - pidcheck (status.w_status); -#endif for (part = m->mp_parts; part; part = part->mp_next) { p = part->mp_part; @@ -766,7 +788,7 @@ show_multi_internal (CT ct, int serial, int alternate) out: if (!nowserial) { /* reset the signal mask */ - SIGPROCMASK (SIG_SETMASK, &oset, &set); + sigprocmask (SIG_SETMASK, &oset, &set); } return result; @@ -781,9 +803,9 @@ out: static int show_multi_aux (CT ct, int serial, int alternate, char *cp) { - int len, buflen; + int len, buflen, quoted; int xlist, xpause, xtty; - char *bp, *file, buffer[BUFSIZ]; + char *bp, *pp, *file, buffer[BUFSIZ]; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; CI ci = &ct->c_ctinfo; @@ -818,12 +840,14 @@ show_multi_aux (CT ct, int serial, int alternate, char *cp) /* get buffer ready to go */ bp = buffer; - bp[0] = '\0'; - buflen = sizeof(buffer); + buflen = sizeof(buffer) - 1; + bp[0] = bp[buflen] = '\0'; + quoted = 0; /* Now parse display string */ - for ( ; *cp; cp++) { + for ( ; *cp && buflen > 0; cp++) { if (*cp == '%') { + pp = bp; switch (*++cp) { case 'a': /* insert parameters from Content-Type field */ @@ -876,6 +900,10 @@ show_multi_aux (CT ct, int serial, int alternate, char *cp) buflen -= len; s = " "; } + /* set our starting pointer back to bp, to avoid + * requoting the filenames we just added + */ + pp = bp; } break; @@ -907,14 +935,57 @@ show_multi_aux (CT ct, int serial, int alternate, char *cp) len = strlen (bp); bp += len; buflen -= len; + + /* Did we actually insert something? */ + if (bp != pp) { + /* Insert single quote if not inside quotes already */ + if (!quoted && buflen) { + len = strlen (pp); + memmove (pp + 1, pp, len); + *pp++ = '\''; + buflen--; + bp++; + } + /* Escape existing quotes */ + while ((pp = strchr (pp, '\'')) && buflen > 3) { + len = strlen (pp++); + memmove (pp + 3, pp, len); + *pp++ = '\\'; + *pp++ = '\''; + *pp++ = '\''; + buflen -= 3; + bp += 3; + } + /* If pp is still set, that means we ran out of space. */ + if (pp) + buflen = 0; + if (!quoted && buflen) { + *bp++ = '\''; + *bp = '\0'; + buflen--; + } + } } else { raw: - *bp++ = *cp; - *bp = '\0'; - buflen--; + *bp++ = *cp; + *bp = '\0'; + buflen--; + + if (*cp == '\'') + quoted = !quoted; } } + if (buflen <= 0 || + (ct->c_termproc && buflen <= (ssize_t) 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]; @@ -973,6 +1044,9 @@ show_message_rfc822 (CT ct, int serial, int alternate) static int show_partial (CT ct, int serial, int alternate) { + NMH_UNUSED (serial); + NMH_UNUSED (alternate); + content_error (NULL, ct, "in order to display this message, you must reassemble it"); return NOTOK; @@ -995,20 +1069,13 @@ show_external (CT ct, int serial, int alternate) return OK; return show_switch (p, serial, alternate); - -#if 0 - content_error (NULL, p, "don't know how to display content"); - return NOTOK; -#endif } -static RETSIGTYPE +static void intrser (int i) { -#ifndef RELIABLE_SIGNALS - SIGNAL (SIGINT, intrser); -#endif + NMH_UNUSED (i); putchar ('\n'); siglongjmp (intrenv, DONE);