]> diplodocus.org Git - nmh/commitdiff
Factored out duplicate code into parse_display_string() function.
authorDavid Levine <levinedl@acm.org>
Sun, 16 Feb 2014 17:30:41 +0000 (11:30 -0600)
committerDavid Levine <levinedl@acm.org>
Sun, 16 Feb 2014 17:30:41 +0000 (11:30 -0600)
uip/mhshowsbr.c

index 4bab75cafeaf164ec1802d4672cb060877aaefe5..0a970179a25b54325c4e5f49a4f85b2963920995 100644 (file)
@@ -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 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);
 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 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);
 
 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
 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)
 
     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;
     }
 
     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;
     }
 
        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);
 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)
 {
 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;
     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) {
     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';
     bp[0] = bp[buflen] = '\0';
-    quoted = 0;
 
 
-    /* Now parse display string */
     for ( ; *cp && buflen > 0; cp++) {
        if (*cp == '%') {
            pp = bp;
     for ( ; *cp && buflen > 0; cp++) {
        if (*cp == '%') {
            pp = bp;
+
            switch (*++cp) {
            case 'a':
                /* insert parameters from Content-Type field */
            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 */
 
            case 'e':
                /* exclusive execution */
-               xtty = 1;
+               *xtty = 1;
                break;
 
            case 'F':
                break;
 
            case 'F':
-               /* %e and %f */
-               xtty = 1;
+               /* %e, %f, and stdin is terminal not content */
+               *xstdin = 1;
+               *xtty = 1;
                /* and fall... */
 
            case 'f':
                /* 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 */
 
            case 'p':
                /* %l, and pause prior to displaying content */
-               xpause = pausesw;
+               *xpause = pausesw;
                /* and fall... */
 
            case 'l':
                /* display listing prior to displaying content */
                /* and fall... */
 
            case 'l':
                /* display listing prior to displaying content */
-               xlist = !nolist;
+               *xlist = !nolist;
                break;
 
            case 's':
                break;
 
            case 's':
@@ -986,12 +938,11 @@ raw:
     }
 
     if (buflen <= 0 ||
     }
 
     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.
         */
        /* 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;
     }
 
        return NOTOK;
     }
 
@@ -1000,84 +951,10 @@ raw:
        char term[BUFSIZ];
 
        strncpy (term, buffer, sizeof(term));
        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;
 }
 
 
 }