From: David Levine Date: Sun, 16 Feb 2014 17:30:41 +0000 (-0600) Subject: Factored out duplicate code into parse_display_string() function. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/dda00b6407c616678ab0e3fcaf6e0e577a7bf867?ds=sidebyside;hp=b62a02a47bef30c4d5d052b5a0dcc582ce9d784e Factored out duplicate code into parse_display_string() function. --- diff --git a/uip/mhshowsbr.c b/uip/mhshowsbr.c index 4bab75ca..0a970179 100644 --- a/uip/mhshowsbr.c +++ b/uip/mhshowsbr.c @@ -61,7 +61,8 @@ static void show_single_message (CT, char *); static void DisplayMsgHeader (CT, char *); static int show_switch (CT, int, int); static int show_content (CT, int, int); -static int show_content_aux2 (CT, int, int, char *, char *, int, int, int, int, int); +static int show_content_aux2 (CT, int, int, char *, char *, int, int, int, int, + int); static int show_text (CT, int, int); static int show_multi (CT, int, int); static int show_multi_internal (CT, int, int); @@ -69,6 +70,8 @@ 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 int parse_display_string (CT, char *, int *, int *, int *, int *, char *, + char *, size_t, int multipart); static int convert_content_charset (CT, char **); static void intrser (int); @@ -297,10 +300,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, quoted; - int xstdin, xlist, xpause, xtty; - char *bp, *pp, *file, buffer[BUFSIZ]; - CI ci = &ct->c_ctinfo; + int fd; + int xstdin = 0, xlist = 0, xpause = 0, xtty = 0; + char *file, buffer[BUFSIZ]; if (!ct->c_ceopenfnx) { if (!alternate) @@ -329,167 +331,17 @@ show_content_aux (CT ct, int serial, int alternate, char *cp, char *cracked) } } - xlist = 0; - xpause = 0; - xstdin = 0; - xtty = 0; - if (cracked) { strncpy (buffer, cp, sizeof(buffer)); goto got_command; } - /* get buffer ready to go */ - bp = buffer; - buflen = sizeof(buffer) - 1; - bp[0] = bp[buflen] = '\0'; - quoted = 0; - - /* Now parse display string */ - for ( ; *cp && buflen > 0; cp++) { - if (*cp == '%') { - pp = bp; - - switch (*++cp) { - case 'a': - /* insert parameters from Content-Type field */ - { - char **ap, **ep; - char *s = ""; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - snprintf (bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); - len = strlen (bp); - bp += len; - buflen -= len; - s = " "; - } - } - break; - - case 'd': - /* insert content description */ - if (ct->c_descr) { - char *s; - - s = trimcpy (ct->c_descr); - strncpy (bp, s, buflen); - free (s); - } - break; - - case 'e': - /* exclusive execution */ - xtty = 1; - break; - - case 'F': - /* %e, %f, and stdin is terminal not content */ - xstdin = 1; - xtty = 1; - /* and fall... */ - - case 'f': - /* insert filename containing content */ - 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': - /* %l, and pause prior to displaying content */ - xpause = pausesw; - /* and fall... */ - - case 'l': - /* display listing prior to displaying content */ - xlist = !nolist; - break; - - case 's': - /* insert subtype of content */ - strncpy (bp, ci->ci_subtype, buflen); - break; - - case '%': - /* insert character % */ - goto raw; - - default: - *bp++ = *--cp; - *bp = '\0'; - buflen--; - continue; - } - 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--; - - 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"); + if (parse_display_string (ct, cp, &xstdin, &xlist, &xpause, &xtty, file, + buffer, sizeof(buffer) - 1, 0)) { + admonish (NULL, "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, serial, alternate, cracked, buffer, fd, xlist, xpause, xstdin, xtty); @@ -812,12 +664,12 @@ out: static int show_multi_aux (CT ct, int serial, int alternate, char *cp) { - int len, buflen, quoted; - int xlist, xpause, xtty; - char *bp, *pp, *file, buffer[BUFSIZ]; + /* xstdin is only used in the call to parse_display_string(): + its value is ignored in the function. */ + int xstdin = 0, xlist = 0, xpause = 0, xtty = 0; + char *file, buffer[BUFSIZ]; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; - CI ci = &ct->c_ctinfo; CT p; for (part = m->mp_parts; part; part = part->mp_next) { @@ -843,20 +695,104 @@ show_multi_aux (CT ct, int serial, int alternate, char *cp) } } - xlist = 0; - xpause = 0; - xtty = 0; + if (parse_display_string (ct, cp, &xstdin, &xlist, &xpause, &xtty, file, + buffer, sizeof(buffer) - 1, 1)) { + admonish (NULL, "Buffer overflow constructing show command!\n"); + return NOTOK; + } + + return show_content_aux2 (ct, serial, alternate, NULL, buffer, + NOTOK, xlist, xpause, 0, xtty); +} + + +/* + * show content of type "message/rfc822" + */ + +static int +show_message_rfc822 (CT ct, int serial, int alternate) +{ + char *cp, buffer[BUFSIZ]; + CI ci = &ct->c_ctinfo; + + /* Check for invo_name-show-type/subtype */ + snprintf (buffer, sizeof(buffer), "%s-show-%s/%s", + invo_name, ci->ci_type, ci->ci_subtype); + if ((cp = context_find (buffer)) && *cp != '\0') + return show_content_aux (ct, serial, alternate, cp, NULL); + + /* Check for invo_name-show-type */ + snprintf (buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type); + if ((cp = context_find (buffer)) && *cp != '\0') + return show_content_aux (ct, serial, alternate, cp, NULL); + + if ((cp = ct->c_showproc)) + return show_content_aux (ct, serial, alternate, cp, NULL); + + /* default method for message/rfc822 */ + if (ct->c_subtype == MESSAGE_RFC822) { + cp = (ct->c_showproc = add ("%pshow -file '%F'", NULL)); + return show_content_aux (ct, serial, 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 NOTOK; +} + + +/* + * Show content of type "message/partial". + */ + +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; +} + + +/* + * Show content of type "message/external". + * + * THE ERROR CHECKING IN THIS ONE IS NOT DONE YET. + */ + +static int +show_external (CT ct, int serial, 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, serial, alternate); +} + + +static int +parse_display_string (CT ct, char *cp, int *xstdin, int *xlist, int *xpause, + int *xtty, char *file, char *buffer, size_t buflen, + int multipart) { + int len, quoted = 0; + char *bp = buffer, *pp; + CI ci = &ct->c_ctinfo; - /* get buffer ready to go */ - bp = buffer; - buflen = sizeof(buffer) - 1; bp[0] = bp[buflen] = '\0'; - quoted = 0; - /* Now parse display string */ for ( ; *cp && buflen > 0; cp++) { if (*cp == '%') { pp = bp; + switch (*++cp) { case 'a': /* insert parameters from Content-Type field */ @@ -887,43 +823,59 @@ show_multi_aux (CT ct, int serial, int alternate, char *cp) case 'e': /* exclusive execution */ - xtty = 1; + *xtty = 1; break; case 'F': - /* %e and %f */ - xtty = 1; + /* %e, %f, and stdin is terminal not content */ + *xstdin = 1; + *xtty = 1; /* and fall... */ case 'f': - /* insert filename(s) containing content */ - { - char *s = ""; - - for (part = m->mp_parts; part; part = part->mp_next) { - p = part->mp_part; - - snprintf (bp, buflen, "%s'%s'", s, p->c_storage); - len = strlen (bp); - bp += len; - buflen -= len; - s = " "; - } - /* set our starting pointer back to bp, to avoid - * requoting the filenames we just added - */ - pp = bp; - } - break; + if (multipart) { + /* insert filename(s) containing content */ + struct multipart *m = (struct multipart *) ct->c_ctparams; + struct part *part; + char *s = ""; + CT p; + + for (part = m->mp_parts; part; part = part->mp_next) { + p = part->mp_part; + + snprintf (bp, buflen, "%s'%s'", s, p->c_storage); + len = strlen (bp); + bp += len; + buflen -= len; + s = " "; + } + /* set our starting pointer back to bp, to avoid + * requoting the filenames we just added + */ + pp = bp; + } else { + /* insert filename containing content */ + 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': /* %l, and pause prior to displaying content */ - xpause = pausesw; + *xpause = pausesw; /* and fall... */ case 'l': /* display listing prior to displaying content */ - xlist = !nolist; + *xlist = !nolist; break; case 's': @@ -986,12 +938,11 @@ raw: } if (buflen <= 0 || - (ct->c_termproc && buflen <= (ssize_t) strlen(ct->c_termproc))) { + (ct->c_termproc && 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; } @@ -1000,84 +951,10 @@ raw: char term[BUFSIZ]; strncpy (term, buffer, sizeof(term)); - snprintf (buffer, sizeof(buffer), ct->c_termproc, term); - } - - return show_content_aux2 (ct, serial, alternate, NULL, buffer, - NOTOK, xlist, xpause, 0, xtty); -} - - -/* - * show content of type "message/rfc822" - */ - -static int -show_message_rfc822 (CT ct, int serial, int alternate) -{ - char *cp, buffer[BUFSIZ]; - CI ci = &ct->c_ctinfo; - - /* Check for invo_name-show-type/subtype */ - snprintf (buffer, sizeof(buffer), "%s-show-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - if ((cp = context_find (buffer)) && *cp != '\0') - return show_content_aux (ct, serial, alternate, cp, NULL); - - /* Check for invo_name-show-type */ - snprintf (buffer, sizeof(buffer), "%s-show-%s", invo_name, ci->ci_type); - if ((cp = context_find (buffer)) && *cp != '\0') - return show_content_aux (ct, serial, alternate, cp, NULL); - - if ((cp = ct->c_showproc)) - return show_content_aux (ct, serial, alternate, cp, NULL); - - /* default method for message/rfc822 */ - if (ct->c_subtype == MESSAGE_RFC822) { - cp = (ct->c_showproc = add ("%pshow -file '%F'", NULL)); - return show_content_aux (ct, serial, alternate, cp, NULL); + snprintf (buffer, buflen, ct->c_termproc, term); } - /* 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 NOTOK; -} - - -/* - * Show content of type "message/partial". - */ - -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; -} - - -/* - * Show content of type "message/external". - * - * THE ERROR CHECKING IN THIS ONE IS NOT DONE YET. - */ - -static int -show_external (CT ct, int serial, 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, serial, alternate); + return OK; }