]> diplodocus.org Git - nmh/blobdiff - uip/mshcmds.c
Disable assertions by default.
[nmh] / uip / mshcmds.c
index 3548b7ec355df13713f8c96437f2a1e084fe88b2..f91f277afdabd7a615fa5f22d153325901427180 100644 (file)
@@ -2,8 +2,6 @@
 /*
  * mshcmds.c -- command handlers in msh
  *
- * $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/scansbr.h>
 #include <h/tws.h>
 #include <h/mts.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <signal.h>
 #include <h/msh.h>
 #include <h/picksbr.h>
+#include <h/utils.h>
 
-extern int errno;
 
 static char delim3[] = "-------";      /* from burst.c */
 
 static int mhlnum;
 static FILE *mhlfp;
 
-#if defined(NNTP) && defined(MPOP)
-# undef        MPOP
-#endif
-
-#ifdef MPOP
-# ifdef BPOP
-extern int pmsh;
-extern char response[];
-# endif
-#endif /* MPOP */
-
 /*
  * Type for a compare function for qsort.  This keeps
  * the compiler happy.
  */
 typedef int (*qsort_comp) (const void *, const void *);
 
-/*
- * prototypes
- */
-void clear_screen (void);   /* from termsbr.c */
-int SOprintf (char *, ...); /* from termsbr.c */
-int sc_width (void);        /* from termsbr.c */
-
 /*
  * static prototypes
  */
@@ -72,8 +49,7 @@ static int process (int, char *, int, char **);
 static void copy_message (int, FILE *);
 static void copy_digest (int, FILE *);
 
-/* from mhlsbr.c */
-int mhlsbr (int, char **, FILE *(*)());
+extern m_getfld_state_t gstate;        /* use the gstate in scansbr.c */
 
 void
 forkcmd (char **args, char *pgm)
@@ -117,35 +93,28 @@ forkcmd (char **args, char *pgm)
 }
 
 
-static struct swit distswit[] = {
-#define        DIANSW                    0
-    { "annotate", 0 },
-#define        DINANSW                   1
-    { "noannotate", 0 },
-#define        DIDFSW                    2
-    { "draftfolder +folder", 0 },
-#define        DIDMSW                    3
-    { "draftmessage msg", 0 },
-#define        DINDFSW                   4
-    { "nodraftfolder", 0 },
-#define        DIEDTSW                   5
-    { "editor editor", 0 },
-#define        DINEDSW                   6
-    { "noedit", 0 },
-#define        DIFRMSW                   7
-    { "form formfile", 0 },
-#define        DIINSW                    8
-    { "inplace", 0 },
-#define        DININSW                   9
-    { "noinplace", 0 },
-#define        DIWHTSW                  10
-    { "whatnowproc program", 0 },
-#define        DINWTSW                  11
-    { "nowhatnowproc", 0 },
-#define        DIHELP                   12
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define DIST_SWITCHES \
+    X("annotate", 0, DIANSW) \
+    X("noannotate", 0, DINANSW) \
+    X("draftfolder +folder", 0, DIDFSW) \
+    X("draftmessage msg", 0, DIDMSW) \
+    X("nodraftfolder", 0, DINDFSW) \
+    X("editor editor", 0, DIEDTSW) \
+    X("noedit", 0, DINEDSW) \
+    X("form formfile", 0, DIFRMSW) \
+    X("inplace", 0, DIINSW) \
+    X("noinplace", 0, DININSW) \
+    X("whatnowproc program", 0, DIWHTSW) \
+    X("nowhatnowproc", 0, DINWTSW) \
+    X("help", 0, DIHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DIST, distswit);
+#undef X
 
 
 void
@@ -230,23 +199,22 @@ distcmd (char **args)
 }
 
 
-static struct swit explswit[] = {
-#define        EXINSW         0
-    { "inplace", 0 },
-#define        EXNINSW        1
-    { "noinplace", 0 },
-#define        EXQISW         2
-    { "quiet", 0 },
-#define        EXNQISW        3
-    { "noquiet", 0 },
-#define        EXVBSW         4
-    { "verbose", 0 },
-#define        EXNVBSW        5
-    { "noverbose", 0 },
-#define        EXHELP         6
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define EXPLODE_SWITCHES \
+    X("inplace", 0, EXINSW) \
+    X("noinplace", 0, EXNINSW) \
+    X("quiet", 0, EXQISW) \
+    X("noquiet", 0, EXNQISW) \
+    X("verbose", 0, EXVBSW) \
+    X("noverbose", 0, EXNVBSW) \
+    X("help", 0, EXHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(EXPLODE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(EXPLODE, explswit);
+#undef X
 
 
 void
@@ -453,29 +421,25 @@ burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
 }
 
 
-static struct swit fileswit[] = {
-#define        FIDRFT               0
-    { "draft", 0 },
-#define        FILINK               1
-    { "link", 0 },
-#define        FINLINK              2
-    { "nolink", 0 },
-#define        FIPRES               3
-    { "preserve", 0 },
-#define FINPRES              4
-    { "nopreserve", 0 },
-#define        FISRC                5
-    { "src +folder", 0 },
-#define        FIFILE               6
-    { "file file", 0 },
-#define        FIPROC               7
-    { "rmmproc program", 0 },
-#define        FINPRC               8
-    { "normmproc", 0 },
-#define        FIHELP               9
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define FILE_SWITCHES \
+    X("draft", 0, FIDRFT) \
+    X("link", 0, FILINK) \
+    X("nolink", 0, FINLINK) \
+    X("preserve", 0, FIPRES) \
+    X("nopreserve", 0, FINPRES) \
+    X("src +folder", 0, FISRC) \
+    X("file file", 0, FIFILE) \
+    X("rmmproc program", 0, FIPROC) \
+    X("normmproc", 0, FINPRC) \
+    X("help", 0, FIHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FILE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FILE, fileswit);
+#undef X
 
 
 void
@@ -593,7 +557,7 @@ filehak (char **args)
        if (cwd == NULL)
            cwd = getcpy (pwd ());
        chdir (m_maildir (""));
-       cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
+       cp = pluspath (cp);
        if (access (m_maildir (cp), F_OK) == NOTOK)
            result = OK;
        free (cp);
@@ -605,41 +569,31 @@ filehak (char **args)
 }
 
 
-static struct swit foldswit[] = {
-#define        FLALSW         0
-    { "all", 0 },
-#define        FLFASW         1
-    { "fast", 0 },
-#define        FLNFASW        2
-    { "nofast", 0 },
-#define        FLHDSW         3
-    { "header", 0 },
-#define        FLNHDSW        4
-    { "noheader", 0 },
-#define        FLPKSW         5
-    { "pack", 0 },
-#define        FLNPKSW        6
-    { "nopack", 0 },
-#define        FLRCSW         7
-    { "recurse", 0 },
-#define        FLNRCSW        8
-    { "norecurse", 0 },
-#define        FLTLSW         9
-    { "total", 0 },
-#define        FLNTLSW       10
-    { "nototal", 0 },
-#define        FLPRSW        11
-    { "print", 0 },
-#define        FLPUSW        12
-    { "push", 0 },
-#define        FLPOSW        13
-    { "pop", 0 },
-#define        FLLISW        14
-    { "list", 0 },
-#define        FLHELP        15
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define FOLDER_SWITCHES \
+    X("all", 0, FLALSW) \
+    X("fast", 0, FLFASW) \
+    X("nofast", 0, FLNFASW) \
+    X("header", 0, FLHDSW) \
+    X("noheader", 0, FLNHDSW) \
+    X("pack", 0, FLPKSW) \
+    X("nopack", 0, FLNPKSW) \
+    X("recurse", 0, FLRCSW) \
+    X("norecurse", 0, FLNRCSW) \
+    X("total", 0, FLTLSW) \
+    X("nototal", 0, FLNTLSW) \
+    X("print", 0, FLPRSW) \
+    X("push", 0, FLPUSW) \
+    X("pop", 0, FLPOSW) \
+    X("list", 0, FLLISW) \
+    X("help", 0, FLHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FOLDER);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FOLDER, foldswit);
+#undef X
 
 
 void
@@ -703,7 +657,7 @@ foldcmd (char **args)
                return;
            }
            else
-               folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
+               folder = fmsh ? pluspath (cp)
                            : cp + 1;
        }
        else
@@ -820,45 +774,33 @@ fast: ;
 }
 
 
-static struct swit forwswit[] = {
-#define        FOANSW                   0
-    { "annotate", 0 },
-#define        FONANSW                  1
-    { "noannotate", 0 },
-#define        FODFSW                   2
-    { "draftfolder +folder", 0 },
-#define        FODMSW                   3
-    { "draftmessage msg", 0 },
-#define        FONDFSW                  4
-    { "nodraftfolder", 0 },
-#define        FOEDTSW                  5
-    { "editor editor", 0 },
-#define        FONEDSW                  6
-    { "noedit", 0 },
-#define        FOFTRSW                  7
-    { "filter filterfile", 0 },
-#define        FOFRMSW                  8
-    { "form formfile", 0 },
-#define        FOFTSW                   9
-    { "format", 5 },
-#define        FONFTSW                 10
-    { "noformat", 7 },
-#define        FOINSW                  11
-    { "inplace", 0 },
-#define        FONINSW                 12
-    { "noinplace", 0 },
-#define        FOMISW                  13
-    { "mime", 0 },
-#define        FONMISW                 14
-    { "nomime", 0 },
-#define        FOWHTSW                 15
-    { "whatnowproc program", 0 },
-#define        FONWTSW                 16
-    { "nowhatnow", 0 },
-#define        FOHELP                  17
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define FORW_SWITCHES \
+    X("annotate", 0, FOANSW) \
+    X("noannotate", 0, FONANSW) \
+    X("draftfolder +folder", 0, FODFSW) \
+    X("draftmessage msg", 0, FODMSW) \
+    X("nodraftfolder", 0, FONDFSW) \
+    X("editor editor", 0, FOEDTSW) \
+    X("noedit", 0, FONEDSW) \
+    X("filter filterfile", 0, FOFTRSW) \
+    X("form formfile", 0, FOFRMSW) \
+    X("format", 5, FOFTSW) \
+    X("noformat", 7, FONFTSW) \
+    X("inplace", 0, FOINSW) \
+    X("noinplace", 0, FONINSW) \
+    X("mime", 0, FOMISW) \
+    X("nomime", 0, FONMISW) \
+    X("whatnowproc program", 0, FOWHTSW) \
+    X("nowhatnow", 0, FONWTSW) \
+    X("help", 0, FOHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FORW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FORW, forwswit);
+#undef X
 
 
 void
@@ -867,6 +809,8 @@ forwcmd (char **args)
     int        msgp = 0, vecp = 1, msgnum;
     char *cp, *filter = NULL, buf[BUFSIZ];
     char *msgs[MAXARGS], *vec[MAXARGS];
+    char *tfile = NULL;
+    char tmpfil[BUFSIZ];
 
     if (fmsh) {
        forkcmd (args, cmd_name);
@@ -939,16 +883,12 @@ forwcmd (char **args)
 
                                        /* foil search of .mh_profile */
     snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
-/*
-  Mkstemp work postponed until later -Doug
-#ifdef HAVE_MKSTEMP
-    vec[0] = (char *)mkstemp (buf);
-#else
-*/
-    vec[0] = (char *)mktemp (buf);
-/*
-#endif
-*/
+
+    tfile = m_mktemp(buf, NULL, NULL);
+    if (tfile == NULL) adios("forwcmd", "unable to create temporary file");
+    strncpy (tmpfil, tfile, sizeof(tmpfil));
+    vec[0] = tmpfil;
+
     vec[vecp++] = "-file";
     vec[vecp] = NULL;
     if (!msgp)
@@ -979,10 +919,14 @@ static void
 forw (char *proc, char *filter, int vecp, char **vec)
 {
     int i, child_id, msgnum, msgcnt;
-    char tmpfil[80], *args[MAXARGS];
+    char tmpfil[BUFSIZ], *args[MAXARGS];
     FILE *out;
+    char *tfile = NULL;
+
+    tfile = m_mktemp2(NULL, invo_name, NULL, NULL);
+    if (tfile == NULL) adios("forw", "unable to create temporary file");
+    strncpy (tmpfil, tfile, sizeof(tmpfil));
 
-    strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
     interrupted = 0;
     if (filter)
        switch (child_id = fork ()) {
@@ -1006,7 +950,7 @@ forw (char *proc, char *filter, int vecp, char **vec)
                        args[i++] = getcpy (m_name (msgnum));
                args[i] = NULL;
                mhlsbr (i, args, mhl_action);
-               m_eomsbr ((int (*) ()) 0);
+               scan_eom_action ((int (*) ()) 0);
                fclose (stdout);
                _exit (0);
 
@@ -1098,6 +1042,7 @@ void
 helpcmd (char **args)
 {
     int i;
+    NMH_UNUSED (args);
 
     for (i = 0; hlpmsg[i]; i++) {
        printf (hlpmsg[i], invo_name);
@@ -1106,36 +1051,33 @@ helpcmd (char **args)
 }
 
 
-static struct swit markswit[] = {
-#define        MADDSW             0
-    { "add", 0 },
-#define        MDELSW             1
-    { "delete", 0 },
-#define        MLSTSW             2
-    { "list", 0 },
-#define        MSEQSW             3
-    { "sequence name", 0 },
-#define        MPUBSW             4
-    { "public", 0 },
-#define        MNPUBSW            5
-    { "nopublic", 0 },
-#define        MZERSW             6
-    { "zero", 0 },
-#define        MNZERSW            7
-    { "nozero", 0 },
-#define        MHELP              8
-    { "help", 0 },
-#define        MDBUGSW            9
-    { "debug", -5 },
-    { NULL, 0 }
-};
+#define MARK_SWITCHES \
+    X("add", 0, MADDSW) \
+    X("delete", 0, MDELSW) \
+    X("list", 0, MLSTSW) \
+    X("sequence name", 0, MSEQSW) \
+    X("public", 0, MPUBSW) \
+    X("nopublic", 0, MNPUBSW) \
+    X("zero", 0, MZERSW) \
+    X("nozero", 0, MNZERSW) \
+    X("help", 0, MHELP) \
+    X("debug", -5, MDBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MARK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MARK, markswit);
+#undef X
 
 
 void
 markcmd (char **args)
 {
     int addsw = 0, deletesw = 0, debugsw = 0;
-    int listsw = 0, zerosw = 0, seqp = 0;
+    int listsw = 0, zerosw = 0;
+    size_t seqp = 0;
     int msgp = 0, msgnum;
     char *cp, buf[BUFSIZ];
     char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
@@ -1284,8 +1226,9 @@ markcmd (char **args)
                        (long) Msgs[msgnum].m_start,
                        (long) Msgs[msgnum].m_stop,
                        snprintb (buf, sizeof(buf),
-                               (unsigned) mp->msgstats[msgnum - mp->lowoff],
-                               seq_bits (mp)));
+                                 (unsigned) *bvector_bits (msgstat (mp,
+                                                                     msgnum)),
+                                 seq_bits (mp)));
                    if (Msgs[msgnum].m_scanl)
                        printf ("%s", Msgs[msgnum].m_scanl);
                }                           
@@ -1293,67 +1236,42 @@ markcmd (char **args)
 }
 
 
-static struct swit mhnswit[] = {
-#define        MHNAUTOSW           0
-    { "auto", 0 },
-#define        MHNNAUTOSW          1
-    { "noauto", 0 },
-#define        MHNDEBUGSW          2
-    { "debug", -5 },
-#define        MHNEBCDICSW         3
-    { "ebcdicsafe", 0 },
-#define        MHNNEBCDICSW        4
-    { "noebcdicsafe", 0 },
-#define        MHNFORMSW           5
-    { "form formfile", 4 },
-#define        MHNHEADSW           6
-    { "headers", 0 },
-#define        MHNNHEADSW          7
-    { "noheaders", 0 },
-#define        MHNLISTSW           8
-    { "list", 0 },
-#define        MHNNLISTSW          9
-    { "nolist", 0 },
-#define        MHNPARTSW          10
-    { "part number", 0 },
-#define        MHNSIZESW          11
-    { "realsize", 0 },
-#define        MHNNSIZESW         12
-    { "norealsize", 0 },
-#define        MHNRFC934SW        13
-    { "rfc934mode", 0 },
-#define        MHNNRFC934SW       14
-    { "norfc934mode", 0 },
-#define        MHNSERIALSW        15
-    { "serialonly", 0 },
-#define        MHNNSERIALSW       16
-    { "noserialonly", 0 },
-#define        MHNSHOWSW          17
-    { "show", 0 },
-#define        MHNNSHOWSW         18
-    { "noshow", 0 },
-#define        MHNSTORESW         19
-    { "store", 0 },
-#define        MHNNSTORESW        20
-    { "nostore", 0 },
-#define        MHNTYPESW          21
-    { "type content", 0 },
-#define        MHNVERBSW          22
-    { "verbose", 0 },
-#define        MHNNVERBSW         23
-    { "noverbose", 0 },
-#define        MHNHELPSW          24
-    { "help", 0 },
-#define        MHNPROGSW          25
-    { "moreproc program", -4 },
-#define        MHNNPROGSW         26
-    { "nomoreproc", -3 },
-#define        MHNLENSW           27
-    { "length lines", -4 },
-#define        MHNWIDSW           28
-    { "width columns", -4 },
-    { NULL, 0 }
-};
+#define MHN_SWITCHES \
+    X("auto", 0, MHNAUTOSW) \
+    X("noauto", 0, MHNNAUTOSW) \
+    X("debug", -5, MHNDEBUGSW) \
+    X("form formfile", 4, MHNFORMSW) \
+    X("headers", 0, MHNHEADSW) \
+    X("noheaders", 0, MHNNHEADSW) \
+    X("list", 0, MHNLISTSW) \
+    X("nolist", 0, MHNNLISTSW) \
+    X("part number", 0, MHNPARTSW) \
+    X("realsize", 0, MHNSIZESW) \
+    X("norealsize", 0, MHNNSIZESW) \
+    X("rfc934mode", 0, MHNRFC934SW) \
+    X("norfc934mode", 0, MHNNRFC934SW) \
+    X("serialonly", 0, MHNSERIALSW) \
+    X("noserialonly", 0, MHNNSERIALSW) \
+    X("show", 0, MHNSHOWSW) \
+    X("noshow", 0, MHNNSHOWSW) \
+    X("store", 0, MHNSTORESW) \
+    X("nostore", 0, MHNNSTORESW) \
+    X("type content", 0, MHNTYPESW) \
+    X("verbose", 0, MHNVERBSW) \
+    X("noverbose", 0, MHNNVERBSW) \
+    X("help", 0, MHNHELPSW) \
+    X("moreproc program", -4, MHNPROGSW) \
+    X("nomoreproc", -3, MHNNPROGSW) \
+    X("length lines", -4, MHNLENSW) \
+    X("width columns", -4, MHNWIDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHN);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHN, mhnswit);
+#undef X
 
 
 void
@@ -1385,8 +1303,6 @@ mhncmd (char **args)
                case MHNAUTOSW:
                case MHNNAUTOSW:
                case MHNDEBUGSW:
-               case MHNEBCDICSW:
-               case MHNNEBCDICSW:
                case MHNHEADSW:
                case MHNNHEADSW:
                case MHNLISTSW:
@@ -1454,13 +1370,17 @@ mhncmd (char **args)
 }
 
 
-static struct swit packswit[] = {
-#define        PAFISW         0
-    { "file name", 0 },
-#define        PAHELP         1
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define PACK_SWITCHES \
+    X("file name", 0, PAFISW) \
+    X("help", 0, PAHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PACK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PACK, packswit);
+#undef X
 
 static int mbx_style = MMDF_FORMAT;
 
@@ -1590,61 +1510,45 @@ packhak (char **args)
 }
 
 
-static struct swit pickswit[] = {
-#define        PIANSW                0
-    { "and", 0 },
-#define        PIORSW                1
-    { "or", 0 },
-#define        PINTSW                2
-    { "not", 0 },
-#define        PILBSW                3
-    { "lbrace", 0 },
-#define        PIRBSW                4
-    { "rbrace", 0 },
-#define        PICCSW                5
-    { "cc  pattern", 0 },
-#define        PIDASW                6
-    { "date  pattern", 0 },
-#define        PIFRSW                7
-    { "from  pattern", 0 },
-#define        PISESW                8
-    { "search  pattern", 0 },
-#define        PISUSW                9
-    { "subject  pattern", 0 },
-#define        PITOSW               10
-    { "to  pattern", 0 },
-#define        PIOTSW               11
-    { "-othercomponent  pattern", 15 },
-#define        PIAFSW               12
-    { "after date", 0 },
-#define        PIBFSW               13
-    { "before date", 0 },
-#define        PIDFSW               14
-    { "datefield field", 5 },
-#define        PISQSW               15
-    { "sequence name", 0 },
-#define        PIPUSW               16
-    { "public", 0 },
-#define        PINPUSW              17
-    { "nopublic", 0 },
-#define        PIZRSW               18
-    { "zero", 0 },
-#define        PINZRSW              19
-    { "nozero", 0 },
-#define        PILISW               20
-    { "list", 0 },
-#define        PINLISW              21
-    { "nolist", 0 },
-#define        PIHELP               22
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define PICK_SWITCHES \
+    X("and", 0, PIANSW) \
+    X("or", 0, PIORSW) \
+    X("not", 0, PINTSW) \
+    X("lbrace", 0, PILBSW) \
+    X("rbrace", 0, PIRBSW) \
+    X("cc  pattern", 0, PICCSW) \
+    X("date  pattern", 0, PIDASW) \
+    X("from  pattern", 0, PIFRSW) \
+    X("search  pattern", 0, PISESW) \
+    X("subject  pattern", 0, PISUSW) \
+    X("to  pattern", 0, PITOSW) \
+    X("-othercomponent  pattern", 15, PIOTSW) \
+    X("after date", 0, PIAFSW) \
+    X("before date", 0, PIBFSW) \
+    X("datefield field", 5, PIDFSW) \
+    X("sequence name", 0, PISQSW) \
+    X("public", 0, PIPUSW) \
+    X("nopublic", 0, PINPUSW) \
+    X("zero", 0, PIZRSW) \
+    X("nozero", 0, PINZRSW) \
+    X("list", 0, PILISW) \
+    X("nolist", 0, PINLISW) \
+    X("help", 0, PIHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PICK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PICK, pickswit);
+#undef X
 
 
 void
 pickcmd (char **args)
 {
-    int zerosw = 1, msgp = 0, seqp = 0;
+    int zerosw = 1, msgp = 0;
+    size_t seqp = 0;
     int vecp = 0, hi, lo, msgnum;
     char *cp, buf[BUFSIZ], *msgs[MAXARGS];
     char *seqs[NUMATTRS], *vec[MAXARGS];
@@ -1783,49 +1687,35 @@ pattern: ;
 }
 
 
-static struct swit replswit[] = {
-#define        REANSW                  0
-    { "annotate", 0 },
-#define        RENANSW                 1
-    { "noannotate", 0 },
-#define        RECCSW                  2
-    { "cc type", 0 },
-#define        RENCCSW                 3
-    { "nocc type", 0 },
-#define        REDFSW                  4
-    { "draftfolder +folder", 0 },
-#define        REDMSW                  5
-    { "draftmessage msg", 0 },
-#define        RENDFSW                 6
-    { "nodraftfolder", 0 },
-#define        REEDTSW                 7
-    { "editor editor", 0 },
-#define        RENEDSW                 8
-    { "noedit", 0 },
-#define        REFCCSW                 9
-    { "fcc +folder", 0 },
-#define        REFLTSW                10
-    { "filter filterfile", 0 },
-#define        REFRMSW                11
-    { "form formfile", 0 },
-#define        REINSW                 12
-    { "inplace", 0 },
-#define        RENINSW                13
-    { "noinplace", 0 },
-#define        REQUSW                 14
-    { "query", 0 },
-#define        RENQUSW                15
-    { "noquery", 0 },
-#define        REWHTSW                16
-    { "whatnowproc program", 0 },
-#define        RENWTSW                17
-    { "nowhatnow", 0 },
-#define        REWIDSW                19
-    { "width columns", 0 },
-#define        REHELP                 20
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define REPL_SWITCHES \
+    X("annotate", 0, REANSW) \
+    X("noannotate", 0, RENANSW) \
+    X("cc type", 0, RECCSW) \
+    X("nocc type", 0, RENCCSW) \
+    X("draftfolder +folder", 0, REDFSW) \
+    X("draftmessage msg", 0, REDMSW) \
+    X("nodraftfolder", 0, RENDFSW) \
+    X("editor editor", 0, REEDTSW) \
+    X("noedit", 0, RENEDSW) \
+    X("fcc +folder", 0, REFCCSW) \
+    X("filter filterfile", 0, REFLTSW) \
+    X("form formfile", 0, REFRMSW) \
+    X("inplace", 0, REINSW) \
+    X("noinplace", 0, RENINSW) \
+    X("query", 0, REQUSW) \
+    X("noquery", 0, RENQUSW) \
+    X("whatnowproc program", 0, REWHTSW) \
+    X("nowhatnow", 0, RENWTSW) \
+    X("width columns", 0, REWIDSW) \
+    X("help", 0, REHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(REPL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(REPL, replswit);
+#undef X
 
 
 void
@@ -1917,11 +1807,16 @@ replcmd (char **args)
 }
 
 
-static struct swit rmmswit[] = {
-#define        RMHELP    0
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define RMM_SWITCHES \
+    X("help", 0, RMHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RMM);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RMM, rmmswit);
+#undef X
 
 
 void
@@ -1999,12 +1894,6 @@ rmm (void)
        if (is_selected (mp, msgnum)) {
            set_deleted (mp, msgnum);
            unset_exists (mp, msgnum);
-#ifdef MPOP
-#ifdef BPOP
-           if (pmsh && pop_dele (msgnum) != OK)
-               fprintf (stderr, "%s", response);
-#endif
-#endif /* MPOP */
        }
 
     if ((mp->nummsg -= mp->numsel) <= 0) {
@@ -2032,25 +1921,23 @@ rmm (void)
 }
 
 
-static struct swit scanswit[] = {
-#define        SCCLR              0
-    { "clear", 0 },
-#define        SCNCLR             1
-    { "noclear", 0 },
-#define        SCFORM             2
-    { "form formatfile", 0 },
-#define        SCFMT              3
-    { "format string", 5 },
-#define        SCHEAD             4
-    { "header", 0 },
-#define SCNHEAD            5
-    { "noheader", 0 },
-#define        SCWID              6
-    { "width columns", 0 },
-#define        SCHELP             7
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define SCAN_SWITCHES \
+    X("clear", 0, SCCLR) \
+    X("noclear", 0, SCNCLR) \
+    X("form formatfile", 0, SCFORM) \
+    X("format string", 5, SCFMT) \
+    X("header", 0, SCHEAD) \
+    X("noheader", 0, SCNHEAD) \
+    X("width columns", 0, SCWID) \
+    X("help", 0, SCHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SCAN);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SCAN, scanswit);
+#undef X
 
 
 void
@@ -2063,11 +1950,6 @@ scancmd (char **args)
     char *cp, *form = NULL, *format = NULL;
     char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
     register FILE *zp;
-#ifdef MPOP
-#ifdef BPOP
-    static int p_optim = 0;
-#endif
-#endif /* MPOP */
     static int s_optim = 0;
     static char *s_form = NULL, *s_format = NULL;
 
@@ -2148,80 +2030,10 @@ scancmd (char **args)
        s_form = form ? getcpy (form) : NULL;
        s_format = format ? getcpy (format) : NULL;
 
-#ifdef MPOP
-#ifdef BPOP
-       if (pmsh) {
-           int i;
-           char *dp, *ep, *fp;
-
-           if (width == 0)
-               width = sc_width ();
-
-           for (dp = nfs, i = 0; *dp; dp++, i++)
-               if (*dp == '\\' || *dp == '"' || *dp == '\n')
-                   i++;
-           i++;
-           if ((ep = malloc ((unsigned) i)) == NULL)
-               adios (NULL, "out of memory");
-           for (dp = nfs, fp = ep; *dp; dp++) {
-               if (*dp == '\n') {
-                   *fp++ = '\\', *fp++ = 'n';
-                   continue;
-               }
-               if (*dp == '"' || *dp == '\\')
-                   *fp++ = '\\';
-               *fp++ = *dp;
-           }
-           *fp = NULL;
-
-           if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
-               p_optim = 1;
-
-           free (ep);
-       }
-#endif
-#endif /* MPOP */
     }
     else
        optim = equiv (s_form, form) && equiv (s_format, format);
 
-#ifdef MPOP
-#ifdef BPOP
-    if (p_optim && optim) {
-       for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
-           if (!is_selected(mp, msgnum) || Msgs[msgnum].m_scanl)
-               break;
-       if (msgnum > mp->hghmsg && pop_command ("LIST") == OK) {
-           fprintf (stderr, "Stand-by...");
-           fflush (stderr);
-
-           for (;;) {
-               int     size;
-
-               switch (pop_multiline ()) {
-                   case NOTOK:
-                       fprintf (stderr, "%s", response);
-                       /* and fall... */
-                   case DONE:
-                       fprintf (stderr,"\n");
-                       break;
-
-                   case OK:
-                       if (sscanf (response, "%d %d", &msgnum, &size) == 2
-                               && mp->lowmsg <= msgnum
-                               && msgnum <= mp->hghmsg
-                               && (cp = strchr(response, '#'))
-                               && *++cp)
-                           Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
-                       continue;
-               }
-               break;
-           }
-       }
-    }
-#endif
-#endif /* MPOP */
-
     interrupted = 0;
     for (msgnum = mp->lowsel;
            msgnum <= mp->hghsel && !interrupted;
@@ -2230,20 +2042,6 @@ scancmd (char **args)
            if (optim && Msgs[msgnum].m_scanl)
                printf ("%s", Msgs[msgnum].m_scanl);
            else {
-#ifdef MPOP
-#ifdef BPOP
-               if (p_optim
-                       && optim
-                       && is_virtual (mp, msgnum)
-                       && pop_command ("LIST %d", msgnum) == OK
-                       && (cp = strchr(response, '#'))
-                       && *++cp) {
-                   Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
-                   printf ("%s", Msgs[msgnum].m_scanl);                    
-                   continue;
-               }
-#endif
-#endif /* MPOP */
 
                zp = msh_ready (msgnum, 0);
                switch (state = scan (zp, msgnum, 0, nfs, width,
@@ -2276,31 +2074,26 @@ scancmd (char **args)
 }
 
 
-static struct swit showswit[] = {
-#define        SHDRAFT               0
-    { "draft", 5 },
-#define        SHFORM                1
-    { "form formfile", 4 },
-#define        SHPROG                2
-    { "moreproc program", 4 },
-#define        SHNPROG               3
-    { "nomoreproc", 3 },
-#define        SHLEN                 4
-    { "length lines", 4 },
-#define        SHWID                 5
-    { "width columns", 4 },
-#define        SHSHOW                6
-    { "showproc program", 4 },
-#define        SHNSHOW               7
-    { "noshowproc", 3 },
-#define        SHHEAD                8
-    { "header", 4 },
-#define SHNHEAD               9
-    { "noheader", 3 },
-#define        SHHELP               10
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define SHOW_SWITCHES \
+    X("draft", 5, SHDRAFT) \
+    X("form formfile", 4, SHFORM) \
+    X("moreproc program", 4, SHPROG) \
+    X("nomoreproc", 3, SHNPROG) \
+    X("length lines", 4, SHLEN) \
+    X("width columns", 4, SHWID) \
+    X("showproc program", 4, SHSHOW) \
+    X("noshowproc", 3, SHNSHOW) \
+    X("header", 4, SHHEAD) \
+    X("noheader", 3, SHNHEAD) \
+    X("help", 0, SHHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SHOW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SHOW, showswit);
+#undef X
 
 
 void
@@ -2387,7 +2180,7 @@ showcmd (char **args)
            return;
     seq_setprev (mp);
 
-    if (!nshow && !getenv ("NOMHNPROC"))
+    if (!nshow)
        for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
            if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
                proc = showmimeproc;
@@ -2419,7 +2212,7 @@ finish: ;
        if (mp->numsel == 1 && headersw)
            show (mp->lowsel);
        mhlsbr (vecp, vec, mhl_action);
-       m_eomsbr ((int (*)()) 0);
+       scan_eom_action ((int (*)()) 0);
        while (msgp < vecp)
            free (vec[msgp++]);
     } else {
@@ -2472,6 +2265,8 @@ show (int msgnum)
 static int
 eom_action (int c)
 {
+    NMH_UNUSED (c);
+
     return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
 }
 
@@ -2489,7 +2284,7 @@ mhl_action (char *name)
 
     mhlfp = msh_ready (msgnum, 1);
     if (!fmsh)
-       m_eomsbr (eom_action);
+       scan_eom_action (eom_action);
 
     return mhlfp;
 }
@@ -2512,19 +2307,7 @@ ask (int msgnum)
     fflush (stdout);
     buf[0] = 0;
 
-#ifndef        BSD42
     read (fileno (stdout), buf, sizeof buf);
-#else /* BSD42 */
-    switch (setjmp (sigenv)) {
-       case OK: 
-           should_intr = 1;
-           read (fileno (stdout), buf, sizeof buf);/* fall... */
-
-       default: 
-           should_intr = 0;
-           break;
-    }
-#endif /* BSD42 */
 
     if (strchr(buf, '\n') == NULL)
        putchar ('\n');
@@ -2548,7 +2331,7 @@ static int
 is_nontext (int msgnum)
 {
     int        result, state;
-    char *bp, *cp, *dp;
+    char *bp, *dp, *cp;
     char buf[BUFSIZ], name[NAMESZ];
     FILE *fp;
 
@@ -2558,11 +2341,11 @@ is_nontext (int msgnum)
 
     fp = msh_ready (msgnum, 1);
 
-    for (state = FLD;;)
-       switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
+    for (;;) {
+       int bufsz = sizeof buf;
+       switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
        case FLD:
        case FLDPLUS:
-       case FLDEOF:
            /*
             * Check Content-Type field
             */
@@ -2572,14 +2355,15 @@ is_nontext (int msgnum)
 
                cp = add (buf, NULL);
                while (state == FLDPLUS) {
-                   state = m_getfld (state, name, buf, sizeof buf, fp);
+                   bufsz = sizeof buf;
+                   state = m_getfld (&gstate, name, buf, &bufsz, fp);
                    cp = add (buf, cp);
                }
                bp = cp;
                passno = 1;
 
 again:
-               for (; isspace (*bp); bp++)
+               for (; isspace ((unsigned char) *bp); bp++)
                    continue;
                if (*bp == '(') {
                    int i;
@@ -2624,24 +2408,24 @@ invalid:
                    if ((result = (strcasecmp (bp, "plain") != 0)))
                        goto out;
                    *dp = c;
-                   for (dp++; isspace (*dp); dp++)
+                   for (dp++; isspace ((unsigned char) *dp); dp++)
                        continue;
                    if (*dp) {
                        if ((result = !uprf (dp, "charset")))
                            goto out;
                        dp += sizeof "charset" - 1;
-                       while (isspace (*dp))
+                       while (isspace ((unsigned char) *dp))
                            dp++;
                        if (*dp++ != '=')
                            goto invalid;
-                       while (isspace (*dp))
+                       while (isspace ((unsigned char) *dp))
                            dp++;
                        if (*dp == '"') {
                            if ((bp = strchr(++dp, '"')))
                                *bp = '\0';
                        } else {
                            for (bp = dp; *bp; bp++)
-                               if (isspace (*bp)) {
+                               if (isspace ((unsigned char) *bp)) {
                                    *bp = '\0';
                                    break;
                                }
@@ -2675,10 +2459,11 @@ out:
            if (!strcasecmp (name, ENCODING_FIELD)) {
                cp = add (buf, NULL);
                while (state == FLDPLUS) {
-                   state = m_getfld (state, name, buf, sizeof buf, fp);
+                   bufsz = sizeof buf;
+                   state = m_getfld (&gstate, name, buf, &bufsz, fp);
                    cp = add (buf, cp);
                }
-               for (bp = cp; isspace (*bp); bp++)
+               for (bp = cp; isspace ((unsigned char) *bp); bp++)
                    continue;
                for (dp = bp; istoken (*dp); dp++)
                    continue;
@@ -2699,8 +2484,10 @@ out:
             * Just skip the rest of this header
             * field and go to next one.
             */
-           while (state == FLDPLUS)
-               state = m_getfld (state, name, buf, sizeof(buf), fp);
+           while (state == FLDPLUS) {
+               bufsz = sizeof buf;
+               state = m_getfld (&gstate, name, buf, &bufsz, fp);
+           }
            break;
 
            /*
@@ -2710,28 +2497,27 @@ out:
        default:
            return 0;
        }
+    }
 }
 
 
-static struct swit sortswit[] = {
-#define        SODATE               0
-    { "datefield field", 0 },
-#define        SOSUBJ               1
-    { "textfield field", 0 },
-#define        SONSUBJ              2
-    { "notextfield", 0 },
-#define        SOLIMT               3
-    { "limit days", 0 },
-#define        SONLIMT              4
-    { "nolimit", 0 },
-#define        SOVERB               5
-    { "verbose", 0 },
-#define        SONVERB              6
-    { "noverbose", 0 },
-#define        SOHELP               7
-    { "help", 0 },
-    { NULL, 0 }
-};
+#define SORT_SWITCHES \
+    X("datefield field", 0, SODATE) \
+    X("textfield field", 0, SOSUBJ) \
+    X("notextfield", 0, SONSUBJ) \
+    X("limit days", 0, SOLIMT) \
+    X("nolimit", 0, SONLIMT) \
+    X("verbose", 0, SOVERB) \
+    X("noverbose", 0, SONVERB) \
+    X("help", 0, SOHELP) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SORT);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SORT, sortswit);
+#undef X
 
 
 void
@@ -2827,9 +2613,10 @@ sortcmd (char **args)
        }
        else                    /* m_scaln is already NULL */
            twscopy (&Msgs[msgnum].m_tb, &tb);
-       Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
+       Msgs[msgnum].m_stats = bvector_create (0);
+       bvector_copy (Msgs[msgnum].m_stats, msgstat (mp, msgnum));
        if (mp->curmsg == msgnum)
-           Msgs[msgnum].m_stats |= CUR;
+            bvector_set (Msgs[msgnum].m_stats, CUR);
     }
 
     qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
@@ -2840,8 +2627,9 @@ sortcmd (char **args)
            free (Msgs[msgnum].m_scanl);        /* from subjsort */
            Msgs[msgnum].m_scanl = NULL;
        }
-       mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
-       if (Msgs[msgnum].m_stats & CUR)
+       bvector_clear (Msgs[msgnum].m_stats, CUR);
+       bvector_copy (msgstat (mp, msgnum), Msgs[msgnum].m_stats);
+       if (bvector_at (Msgs[msgnum].m_stats, CUR))
            seq_setcur (mp, msgnum);
     }
            
@@ -2864,15 +2652,17 @@ get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
     register FILE *zp;
 
     zp = msh_ready (msgnum, 0);
-    for (state = FLD;;) {
-       switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
+
+    for (;;) {
+       int bufsz = sizeof buf;
+       switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) {
            case FLD: 
-           case FLDEOF: 
            case FLDPLUS: 
                if (!strcasecmp (name, datesw)) {
                    bp = getcpy (buf);
                    while (state == FLDPLUS) {
-                       state = m_getfld (state, name, buf, sizeof buf, zp);
+                       bufsz = sizeof buf;
+                       state = m_getfld (&gstate, name, buf, &bufsz, zp);
                        bp = add (buf, bp);
                    }
                    if ((tw = dparsetime (bp)) == NULL)
@@ -2889,7 +2679,8 @@ get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
                else if (subjsw && !strcasecmp(name, subjsw)) {
                    bp = getcpy (buf);
                    while (state == FLDPLUS) {
-                       state = m_getfld (state, name, buf, sizeof buf, zp);
+                       bufsz = sizeof buf;
+                       state = m_getfld (&gstate, name, buf, &bufsz, zp);
                        bp = add (buf, bp);
                    }
                    msgp->m_scanl = sosmash(subjsw, bp);
@@ -2898,13 +2689,14 @@ get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
                    else
                        subjsw = (char *)0;/* subject done, need date */
                } else {
-                   while (state == FLDPLUS)    /* flush this one */
-                       state = m_getfld (state, name, buf, sizeof buf, zp);
+                   while (state == FLDPLUS) {  /* flush this one */
+                       bufsz = sizeof buf;
+                       state = m_getfld (&gstate, name, buf, &bufsz, zp);
+                   }
                }
                continue;
 
            case BODY: 
-           case BODYEOF: 
            case FILEEOF: 
                break;
 
@@ -2961,7 +2753,8 @@ subsort (struct Msg *a, struct Msg *b)
 static char *
 sosmash (char *subj, char *s)
 {
-    register char *cp, *dp, c;
+    register char *cp, *dp;
+    register unsigned char c;
 
     if (s) {
        cp = s;
@@ -2994,8 +2787,9 @@ static int
 process (int msgnum, char *proc, int vecp, char **vec)
 {
     int        child_id, status;
-    char tmpfil[80];
+    char tmpfil[BUFSIZ];
     FILE *out;
+    char *cp;
 
     if (fmsh) {
        strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
@@ -3006,24 +2800,20 @@ process (int msgnum, char *proc, int vecp, char **vec)
        goto ready;
     }
 
-    strncpy (tmpfil, m_scratch ("", invo_name), sizeof(tmpfil));
-    if ((out = fopen (tmpfil, "w")) == NULL) {
-       int olderr;
-       extern int errno;
-       char newfil[80];
-
-       olderr = errno;
-       strncpy (newfil, m_tmpfil (invo_name), sizeof(newfil));
-       if ((out = fopen (newfil, "w")) == NULL) {
+    cp = m_mktemp(invo_name, NULL, &out);
+    if (cp == NULL) {
+        /* Try again, but try to create under /tmp */
+       int olderr = errno;
+        cp = m_mktemp2(NULL, invo_name, NULL, &out);
+        if (cp == NULL) {
            errno = olderr;
-           advise (tmpfil, "unable to create temporary file");
+           advise (NULL, "unable to create temporary file");
            return NOTOK;
-       } else {
-           strncpy (tmpfil, newfil, sizeof(tmpfil));
        }
     }
     copy_message (msgnum, out);
     fclose (out);
+    strncpy(tmpfil, cp, sizeof(tmpfil));
 
 ready: ;
     fflush (stdout);
@@ -3089,7 +2879,7 @@ static void
 copy_digest (int msgnum, FILE *out)
 {
     char c;
-    long pos;
+    long pos = 0L;
     static char buffer[BUFSIZ];
     register FILE *zp;