Removed some dead code, all inside #if 0's. I tried to not remove
[mmh] / uip / mhshowsbr.c
index e76dbaa..3b91eeb 100644 (file)
@@ -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 <h/mh.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <signal.h>
-#include <zotnet/mts/mts.h>
-#include <zotnet/tws/tws.h>
+#include <h/mts.h>
+#include <h/tws.h>
 #include <h/mime.h>
 #include <h/mhparse.h>
+#include <h/utils.h>
+#include <sys/wait.h>
 
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#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 <return> to show content..."))
-           printf ("Press <return> to show content...");
-
-       if (xpause) {
+       if (xpause && isatty (fileno (stdout))) {
            int intr;
            SIGNAL_HANDLER istat;
 
+           if (SOprintf ("Press <return> to show content..."))
+               printf ("Press <return> 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);