BSD 4_3 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 6 Nov 1985 17:46:37 +0000 (09:46 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 6 Nov 1985 17:46:37 +0000 (09:46 -0800)
Work on file usr/contrib/mh/uip/prompter.c
Work on file usr/contrib/mh/uip/sortm.c
Work on file usr/contrib/mh/uip/distsbr.c

Synthesized-from: CSRG/cd1/4.3

usr/contrib/mh/uip/distsbr.c [new file with mode: 0644]
usr/contrib/mh/uip/prompter.c [new file with mode: 0644]
usr/contrib/mh/uip/sortm.c [new file with mode: 0644]

diff --git a/usr/contrib/mh/uip/distsbr.c b/usr/contrib/mh/uip/distsbr.c
new file mode 100644 (file)
index 0000000..b90d9cb
--- /dev/null
@@ -0,0 +1,213 @@
+/* distsbr.c - routines to do additional "dist-style" processing */
+
+#include "../h/mh.h"
+#include <ctype.h>
+#include <stdio.h>
+
+
+static int  hdrfd = NOTOK;
+static int  txtfd = NOTOK;
+
+
+long   lseek ();
+
+/* \f */
+
+#define        BADHDR  "please re-edit %s to remove the ``%s'' header!"
+#define        BADTXT  "please re-edit %s to consist of headers only!"
+#define        BADMSG  "please re-edit %s to include a ``Resent-To:''!"
+#define        BADRFT  "please re-edit %s and fix that header!"
+
+int    distout (drft, msgnam, backup)
+register char   *drft,
+       *msgnam,
+       *backup;
+{
+    int     state;
+    register char  *dp,
+                   *resent;
+    char    name[NAMESZ],
+            buffer[BUFSIZ];
+    register    FILE *ifp,
+                    *ofp;
+
+    if (rename (drft, strcpy (backup, m_backup (drft))) == NOTOK)
+       adios (backup, "unable to rename %s to",drft);
+    if ((ifp = fopen (backup, "r")) == NULL)
+       adios (backup, "unable to read");
+
+    if ((ofp = fopen (drft, "w")) == NULL)
+       adios (drft, "unable to create temporary file");
+    (void) chmod (drft, m_gmprot ());
+
+    ready_msg (msgnam);
+    (void) lseek (hdrfd, 0L, 0);       /* msgnam not accurate */
+    cpydata (hdrfd, fileno (ofp), msgnam, drft);
+
+/* \f */
+
+    for (state = FLD, resent = NULL;;)
+       switch (state =
+               m_getfld (state, name, buffer, sizeof buffer, ifp)) {
+           case FLD: 
+           case FLDPLUS: 
+           case FLDEOF: 
+               if (uprf (name, "distribute-"))
+                   (void) sprintf (name, "%s%s", "Resent", &name[10]);
+               if (uprf (name, "distribution-"))
+                   (void) sprintf (name, "%s%s", "Resent", &name[12]);
+               if (!uprf (name, "resent")) {
+                   advise (NULLCP, BADHDR, "draft", name);
+                   goto leave_bad;
+               }
+               if (state == FLD)
+                   resent = add (":", add (name, resent));
+               resent = add (buffer, resent);
+               fprintf (ofp, "%s: %s", name, buffer);
+               while (state == FLDPLUS) {
+                   state = m_getfld (state, name,
+                           buffer, sizeof buffer, ifp);
+                   resent = add (buffer, resent);
+                   fputs (buffer, ofp);
+               }
+               if (state == FLDEOF)
+                   goto process;
+               break;
+
+           case BODY: 
+           case BODYEOF: 
+               for (dp = buffer; *dp; dp++)
+                   if (!isspace (*dp)) {
+                       advise (NULLCP, BADTXT, "draft");
+                       goto leave_bad;
+                   }
+
+           case FILEEOF: 
+               goto process;
+
+           case LENERR: 
+           case FMTERR: 
+               advise (NULLCP, BADRFT, "draft");
+       leave_bad: ;
+               (void) fclose (ifp);
+               (void) fclose (ofp);
+               (void) unlink (drft);
+               if (rename (backup, drft) == NOTOK)
+                   adios (drft, "unable to rename %s to", backup);
+               return NOTOK;
+
+           default: 
+               adios (NULLCP, "getfld() returned %d", state);
+       }
+process: ;
+    (void) fclose (ifp);
+    (void) fflush (ofp);
+
+/* \f */
+
+    if (!resent) {
+       advise (NULLCP, BADMSG, "draft");
+       (void) fclose (ofp);
+       (void) unlink (drft);
+       if (rename (backup, drft) == NOTOK)
+           adios (drft, "unable to rename %s to", backup);
+       return NOTOK;
+    }
+    free (resent);
+
+    if (txtfd != NOTOK) {
+       (void) lseek (txtfd, 0L, 0);    /* msgnam not accurate */
+       cpydata (txtfd, fileno (ofp), msgnam, drft);
+    }
+
+    (void) fclose (ofp);
+
+    return OK;
+}
+
+/* \f */
+
+static ready_msg (msgnam)
+register char   *msgnam;
+{
+    int     state,
+            out;
+    char    name[NAMESZ],
+            buffer[BUFSIZ],
+            tmpfil[BUFSIZ];
+    register    FILE *ifp,
+                    *ofp;
+
+    if (hdrfd != NOTOK)
+       (void) close (hdrfd), hdrfd = NOTOK;
+    if (txtfd != NOTOK)
+       (void) close (txtfd), txtfd = NOTOK;
+
+    if ((ifp = fopen (msgnam, "r")) == NULL)
+       adios (msgnam, "unable to open message");
+
+    (void) strcpy (tmpfil, m_tmpfil ("dist"));
+    if ((hdrfd = creat (tmpfil, 0600)) == NOTOK)
+       adios (tmpfil, "unable to create temporary file");
+    (void) close (hdrfd);
+    if ((hdrfd = open (tmpfil, 2)) == NOTOK)
+       adios (tmpfil, "unable to re-open temporary file");
+    if ((out = dup (hdrfd)) == NOTOK
+           || (ofp = fdopen (out, "w")) == NULL)
+       adios (NULLCP, "no file descriptors -- you lose big");
+    (void) unlink (tmpfil);
+
+/* \f */
+
+    for (state = FLD;;)
+       switch (state =
+               m_getfld (state, name, buffer, sizeof buffer, ifp)) {
+           case FLD: 
+           case FLDPLUS: 
+           case FLDEOF: 
+               if (uprf (name, "resent"))
+                   fprintf (ofp, "Prev-");
+               fprintf (ofp, "%s: %s", name, buffer);
+               while (state == FLDPLUS) {
+                   state = m_getfld (state, name,
+                           buffer, sizeof buffer, ifp);
+                   fputs (buffer, ofp);
+               }
+               if (state == FLDEOF)
+                   goto process;
+               break;
+
+           case BODY: 
+           case BODYEOF: 
+               (void) fclose (ofp);
+
+               (void) strcpy (tmpfil, m_tmpfil ("dist"));
+               if ((txtfd = creat (tmpfil, 0600)) == NOTOK)
+                   adios (tmpfil, "unable to create temporary file");
+               (void) close (txtfd);
+               if ((txtfd = open (tmpfil, 2)) == NOTOK)
+                   adios (tmpfil, "unable to re-open temporary file");
+               if ((out = dup (txtfd)) == NOTOK
+                       || (ofp = fdopen (out, "w")) == NULL)
+                   adios (NULLCP, "no file descriptors -- you lose big");
+               (void) unlink (tmpfil);
+               fprintf (ofp, "\n%s", buffer);
+               while (state == BODY) {
+                   state = m_getfld (state, name,
+                           buffer, sizeof buffer, ifp);
+                   fputs (buffer, ofp);
+               }
+           case FILEEOF: 
+               goto process;
+
+           case LENERR: 
+           case FMTERR: 
+               adios (NULLCP, "format error in message %s", msgnam);
+
+           default: 
+               adios (NULLCP, "getfld() returned %d", state);
+       }
+process: ;
+    (void) fclose (ifp);
+    (void) fclose (ofp);
+}
diff --git a/usr/contrib/mh/uip/prompter.c b/usr/contrib/mh/uip/prompter.c
new file mode 100644 (file)
index 0000000..6c8c939
--- /dev/null
@@ -0,0 +1,449 @@
+/* prompter.c - prompting editor front-end */
+
+#include "../h/mh.h"
+#include <stdio.h>
+#include <errno.h>
+#ifndef        SYS5
+#include <sgtty.h>
+#else  SYS5
+#include <sys/types.h>
+#include <termio.h>
+#include <sys/ioctl.h>
+#endif SYS5
+#ifdef BSD42
+#include <setjmp.h>
+#endif BSD42
+#include <signal.h>
+
+
+#define        QUOTE   '\\'
+#ifndef        CKILL
+#define CKILL   '@'
+#endif not CKILL
+#ifndef        CERASE
+#define CERASE  '#'
+#endif not CERASE
+
+/* \f */
+
+static struct swit switches[] = {
+#define        ERASESW 0
+    "erase chr", 0,
+#define        KILLSW  1
+    "kill chr", 0,
+
+#define        PREPSW  2
+    "prepend", 0,      
+#define        NPREPSW 3
+    "noprepend", 0,    
+
+#define        RAPDSW  4
+    "rapid", 0,        
+#define        NRAPDSW 5
+    "norapid", 0,      
+
+#define        BODYSW  6
+    "body", -4,
+#define        NBODYSW 7
+    "nobody", -6,
+
+#define        HELPSW  8
+    "help", 4,         
+
+    NULL, NULL
+};
+
+/* \f */
+
+extern int  errno;
+
+
+#ifndef        SYS5
+#define        ERASE   sg.sg_erase
+#define        KILL    sg.sg_kill
+static struct sgttyb    sg;
+
+#define        INTR    tc.t_intrc
+static struct tchars    tc;
+#else  SYS5
+#define        ERASE   sg.c_cc[VERASE]
+#define        KILL    sg.c_cc[VKILL]
+#define        INTR    sg.c_cc[VINTR]
+static struct termio    sg;
+#endif SYS5
+
+
+int    intrser ();
+
+static int  wtuser = 0;
+static int  sigint = 0;
+
+#ifdef BSD42
+static jmp_buf sigenv;
+#endif BSD42
+
+/* \f */
+
+/* ARGSUSED */
+
+main (argc, argv)
+int     argc;
+char   *argv[];
+{
+    int     body = 1,
+           prepend = 1,
+           rapid = 0,
+           fdi,
+           fdo,
+            i,
+            state;
+    char   *cp,
+           *drft = NULL,
+           *erasep = NULL,
+           *killp = NULL,
+            name[NAMESZ],
+            field[BUFSIZ],
+            buffer[BUFSIZ],
+            tmpfil[BUFSIZ],
+          **ap,
+           *arguments[MAXARGS],
+          **argp;
+    FILE *in, *out;
+
+    invo_name = r1bindex (argv[0], '/');
+    if ((cp = m_find (invo_name)) != NULL) {
+       ap = brkstring (cp = getcpy (cp), " ", "\n");
+       ap = copyip (ap, arguments);
+    }
+    else
+       ap = arguments;
+    (void) copyip (argv + 1, ap);
+    argp = arguments;
+
+/* \f */
+
+    while (cp = *argp++)
+       if (*cp == '-')
+           switch (smatch (++cp, switches)) {
+               case AMBIGSW: 
+                   ambigsw (cp, switches);
+                   done (1);
+               case UNKWNSW: 
+                   adios (NULLCP, "-%s unknown", cp);
+               case HELPSW: 
+                   (void) sprintf (buffer, "%s [switches] file", invo_name);
+                   help (buffer, switches);
+                   done (1);
+
+               case ERASESW: 
+                   if (!(erasep = *argp++) || *erasep == '-')
+                       adios (NULLCP, "missing argument to %s", argp[-2]);
+                   continue;
+               case KILLSW: 
+                   if (!(killp = *argp++) || *killp == '-')
+                       adios (NULLCP, "missing argument to %s", argp[-2]);
+                   continue;
+
+               case PREPSW: 
+                   prepend++;
+                   continue;
+               case NPREPSW: 
+                   prepend = 0;
+                   continue;
+
+               case RAPDSW: 
+                   rapid++;
+                   continue;
+               case NRAPDSW: 
+                   rapid = 0;
+                   continue;
+
+               case BODYSW: 
+                   body++;
+                   continue;
+               case NBODYSW: 
+                   body = 0;
+                   continue;
+           }
+       else
+           if (!drft)
+               drft = cp;
+
+/* \f */
+
+    if (!drft)
+       adios (NULLCP, "usage: %s [switches] file", invo_name);
+    if ((in = fopen (drft, "r")) == NULL)
+       adios (drft, "unable to open");
+
+    (void) strcpy (tmpfil, m_tmpfil (invo_name));
+    if ((out = fopen (tmpfil, "w")) == NULL)
+       adios (tmpfil, "unable to create");
+    (void) chmod (tmpfil, 0600);
+
+    if (killp || erasep) {
+#ifndef        SYS5
+       int    serase,
+              skill;
+#else  SYS5
+       char   serase,
+              skill;
+#endif SYS5
+
+#ifndef        SYS5
+       (void) ioctl (0, TIOCGETP, (char *) &sg);
+       (void) ioctl (0, TIOCGETC, (char *) &tc);
+#else  SYS5
+       (void) ioctl(0, TCGETA, &sg);
+#endif SYS5
+       skill = KILL;
+       serase = ERASE;
+       KILL = killp ? chrcnv (killp) : skill;
+       ERASE = erasep ? chrcnv (erasep) : serase;
+#ifndef        SYS5
+       (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else  SYS5
+       (void) ioctl(0, TCSETAW, &sg);
+#endif SYS5
+
+       chrdsp ("erase", ERASE);
+       chrdsp (", kill", KILL);
+       chrdsp (", intr", INTR);
+       (void) putchar ('\n');
+       (void) fflush (stdout);
+
+       KILL = skill;
+       ERASE = serase;
+    }
+
+/* \f */
+
+    sigint = 0;
+    setsig (SIGINT, intrser);
+
+    for (state = FLD;;) {
+       switch (state = m_getfld (state, name, field, sizeof field, in)) {
+           case FLD: 
+           case FLDEOF: 
+           case FLDPLUS: 
+               for (cp = field; *cp; cp++)
+                   if (*cp != ' ' && *cp != '\t')
+                       break;
+               if (*cp++ != '\n' || *cp != NULL) {
+                   printf ("%s:%s", name, field);
+                   fprintf (out, "%s:%s", name, field);
+                   while (state == FLDPLUS) {
+                       state =
+                           m_getfld (state, name, field, sizeof field, in);
+                       printf ("%s", field);
+                       fprintf (out, "%s", field);
+                   }
+               }
+               else {
+                   printf ("%s: ", name);
+                   (void) fflush (stdout);
+                   i = getln (field, sizeof field);
+                   if (i == -1) {
+abort: ;
+                       if (killp || erasep)
+#ifndef        SYS5
+                           (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else  SYS5
+                           (void) ioctl (0, TCSETA, &sg);
+#endif SYS5
+                       (void) unlink (tmpfil);
+                       done (1);
+                   }
+                   if (i != 0 || (field[0] != '\n' && field[0] != NULL)) {
+                       fprintf (out, "%s:", name);
+                       do {
+                           if (field[0] != ' ' && field[0] != '\t')
+                               (void) putc (' ', out);
+                           fprintf (out, "%s", field);
+                       } while (i == 1
+                                   && (i = getln (field, sizeof field)) >= 0);
+                       if (i == -1)
+                           goto abort;
+                   }
+               }
+               if (state == FLDEOF) {/* moby hack */
+                   fprintf (out, "--------\n");
+                   printf ("--------\n");
+                   if (!body)
+                       break;
+                   goto no_body;
+               }
+               continue;
+
+           case BODY: 
+           case BODYEOF:
+           case FILEEOF: 
+               fprintf (out, "--------\n");
+               if (field[0] == NULL || !prepend)
+                   printf ("--------\n");
+               if (field[0]) {
+                   if (prepend && body) {
+                       printf ("\n--------Enter initial text\n\n");
+                       (void) fflush (stdout);
+                       for (;;) {
+                           (void) getln (buffer, sizeof buffer);
+                           if (buffer[0] == NULL)
+                               break;
+                           fprintf (out, "%s", buffer);
+                       }
+                   }
+
+                   do {
+                       fprintf (out, "%s", field);
+                       if (!rapid && !sigint)
+                           printf ("%s", field);
+                   } while (state == BODY &&
+                           (state = m_getfld (state, name, field, sizeof field, in)));
+                   if (prepend || !body)
+                       break;
+                   else
+                       printf ("\n--------Enter additional text\n\n");
+               }
+no_body: ;
+               (void) fflush (stdout);
+               for (;;) {
+                   (void) getln (field, sizeof field);
+                   if (field[0] == NULL)
+                       break;
+                   fprintf (out, "%s", field);
+               }
+               break;
+
+           default: 
+               adios (NULLCP, "skeleton is poorly formatted");
+       }
+       break;
+    }
+
+    if (body)
+       printf ("--------\n");
+    (void) fflush (stdout);
+
+    (void) fclose (in);
+    (void) fclose (out);
+
+    (void) signal (SIGINT, SIG_IGN);
+
+/* \f */
+
+    if (killp || erasep)
+#ifndef        SYS5
+       (void) ioctl (0, TIOCSETN, (char *) &sg);
+#else  SYS5
+       (void) ioctl (0, TCSETAW, &sg);
+#endif SYS5
+
+    if ((fdi = open (tmpfil, 0)) == NOTOK)
+       adios (tmpfil, "unable to re-open");
+    if ((fdo = creat (drft, m_gmprot ())) == NOTOK)
+       adios (drft, "unable to write");
+    cpydata (fdi, fdo, tmpfil, drft);
+    (void) close (fdi);
+    (void) close (fdo);
+    (void) unlink (tmpfil);
+
+    m_update ();
+
+    done (0);
+}
+
+/* \f */
+
+getln (buffer, n)
+register char   *buffer;
+register int     n;
+{
+    int     c;
+    char   *cp;
+
+    cp = buffer;
+    *cp = NULL;
+
+#ifndef        BSD42
+    wtuser = 1;
+#else  BSD42
+    switch (setjmp (sigenv)) {
+       case OK: 
+           wtuser = 1;
+           break;
+
+       case DONE: 
+           wtuser = 0;
+           return 0;
+
+       default: 
+           wtuser = 0;
+           return NOTOK;
+    }
+#endif BSD42
+
+    for (;;)
+       switch (c = getchar ()) {
+           case EOF: 
+#ifndef BSD42
+               wtuser = 0;
+               return (errno != EINTR ? 0 : NOTOK);
+#else  BSD42
+               clearerr (stdin);
+               longjmp (sigenv, DONE);
+#endif BSD42
+
+           case '\n': 
+               if (cp[-1] == QUOTE) {
+                   cp[-1] = c;
+                   wtuser = 0;
+                   return 1;
+               }
+               *cp++ = c;
+               *cp = NULL;
+               wtuser = 0;
+               return 0;
+
+           default: 
+               if (cp < buffer + n)
+                   *cp++ = c;
+               *cp = NULL;
+       }
+}
+
+/* \f */
+
+/* ARGSUSED */
+
+static int intrser (i)
+int    i;
+{
+#ifndef        BSD42
+    (void) signal (SIGINT, intrser);
+    if (!wtuser)
+       sigint++;
+#else  BSD42
+    if (wtuser)
+       longjmp (sigenv, NOTOK);
+    sigint++;
+#endif BSD42
+}
+
+
+chrcnv (cp)
+register char   *cp;
+{
+    return (*cp != QUOTE ? *cp : m_atoi (++cp));
+}
+
+
+chrdsp (s, c)
+char   *s,
+       c;
+{
+    printf ("%s ", s);
+    if (c < ' ' || c == 0177)
+       printf ("^%c", c ^ 0100);
+    else
+       printf ("%c", c);
+}
diff --git a/usr/contrib/mh/uip/sortm.c b/usr/contrib/mh/uip/sortm.c
new file mode 100644 (file)
index 0000000..a38dd4b
--- /dev/null
@@ -0,0 +1,335 @@
+/* sortm.c - sort messages in a folder by date/time */
+
+#include "../h/mh.h"
+#include "../zotnet/tws.h"
+#include <stdio.h>
+
+/* \f */
+
+static struct swit switches[] = {
+#define        DATESW  0
+    "datefield field", 0,
+
+#define        VERBSW  1
+    "verbose", 0,
+#define NVERBSW        2
+    "noverbose", 0,
+
+#define        HELPSW  3
+    "help", 4,
+
+    NULL, NULL
+};
+
+/* \f */
+
+struct smsg {
+    int     s_msg;
+    struct tws  s_tws;
+};
+
+static struct smsg *smsgs;
+
+
+int     msgsort ();
+
+struct tws *getws ();
+
+
+long   time ();
+
+/* \f */
+
+/* ARGSUSED */
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    int     verbosw = 0,
+            msgp = 0,
+           i,
+            msgnum;
+    char   *cp,
+           *maildir,
+           *datesw = NULL,
+           *folder = NULL,
+            buf[100],
+          **ap,
+          **argp,
+           *arguments[MAXARGS],
+           *msgs[MAXARGS];
+    struct msgs *mp;
+
+    invo_name = r1bindex (argv[0], '/');
+    if ((cp = m_find (invo_name)) != NULL) {
+       ap = brkstring (cp = getcpy (cp), " ", "\n");
+       ap = copyip (ap, arguments);
+    }
+    else
+       ap = arguments;
+    (void) copyip (argv + 1, ap);
+    argp = arguments;
+
+/* \f */
+
+    while (cp = *argp++) {
+       if (*cp == '-')
+           switch (smatch (++cp, switches)) {
+               case AMBIGSW: 
+                   ambigsw (cp, switches);
+                   done (1);
+               case UNKWNSW: 
+                   adios (NULLCP, "-%s unknown", cp);
+               case HELPSW: 
+                   (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
+                           invo_name);
+                   help (buf, switches);
+                   done (1);
+
+               case DATESW: 
+                   if (datesw)
+                       adios (NULLCP, "only one date field at a time!");
+                   if (!(datesw = *argp++) || *datesw == '-')
+                       adios (NULLCP, "missing argument to %s", argp[-2]);
+                   continue;
+
+               case VERBSW: 
+                   verbosw++;
+                   continue;
+               case NVERBSW: 
+                   verbosw = 0;
+                   continue;
+           }
+       if (*cp == '+' || *cp == '@') {
+           if (folder)
+               adios (NULLCP, "only one folder at a time!");
+           else
+               folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
+       }
+       else
+           msgs[msgp++] = cp;
+    }
+
+/* \f */
+
+    if (!m_find ("path"))
+       free (path ("./", TFOLDER));
+    if (!msgp)
+       msgs[msgp++] = "all";
+    if (!datesw)
+       datesw = "Date";
+    if (!folder)
+       folder = m_getfolder ();
+    maildir = m_maildir (folder);
+
+    if (chdir (maildir) == NOTOK)
+       adios (maildir, "unable to change directory to");
+    if (!(mp = m_gmsg (folder)))
+       adios (NULLCP, "unable to read folder %s", folder);
+    if (mp -> hghmsg == 0)
+       adios (NULLCP, "no messages in %s", folder);
+
+    for (msgnum = 0; msgnum < msgp; msgnum++)
+       if (!m_convert (mp, msgs[msgnum]))
+           done (1);
+    m_setseq (mp);
+
+    if ((i = read_dates (mp, datesw)) <= 0)
+       adios (NULLCP, "no messages to sort");
+    qsort ((char *) smsgs, i, sizeof *smsgs, msgsort);
+    file_dates (mp, verbosw);
+
+    m_replace (pfolder, folder);
+    m_sync (mp);
+    m_update ();
+
+    done (0);
+}
+
+/* \f */
+
+static int  read_dates (mp, datesw)
+register struct  msgs *mp;
+register char   *datesw;
+{
+    int     msgnum;
+    struct tws  tb;
+    register struct smsg *s;
+    register struct tws *tw;
+
+    twscopy (&tb, dtwstime ());
+
+    smsgs = (struct smsg   *)
+               calloc ((unsigned) (mp -> hghsel - mp -> lowsel + 2),
+                       sizeof *smsgs);
+    if (smsgs == NULL)
+       adios (NULLCP, "unable to allocate sort storage");
+
+    s = smsgs;
+    for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
+       tw = NULL;
+       if (mp -> msgstats[msgnum] & SELECTED) {
+           if ((tw = getws (datesw, msgnum)) == NULL)
+               tw = msgnum != mp -> lowsel ? &((s - 1) -> s_tws) : &tb;
+       }
+       else
+           if (mp -> msgstats[msgnum] & EXISTS)
+               tw = &tb;
+
+       if (tw) {
+           s -> s_msg = msgnum;
+           twscopy (&s -> s_tws, tw);
+           s++;
+       }
+    }
+
+    s -> s_msg = 0;
+    return (s - smsgs);
+}
+
+/* \f */
+
+static struct tws  *getws (datesw, msg)
+register char   *datesw;
+int     msg;
+{
+    int     compnum,
+            state;
+    register char  *hp,
+                   *msgnam;
+    char    buf[BUFSIZ],
+            nam[NAMESZ];
+    register struct tws *tw;
+    register    FILE *in;
+
+    if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
+       admonish (msgnam, "unable to read message");
+       return NULL;
+    }
+
+/* \f */
+
+    for (compnum = 1, state = FLD, hp = NULL;;) {
+       switch (state = m_getfld (state, nam, buf, sizeof buf, in)) {
+           case FLD: 
+           case FLDEOF: 
+           case FLDPLUS: 
+               compnum++;
+               if (hp != NULL)
+                   free (hp), hp = NULL;
+               hp = add (buf, NULLCP);
+               while (state == FLDPLUS) {
+                   state = m_getfld (state, nam, buf, sizeof buf, in);
+                   hp = add (buf, hp);
+               }
+               if (uleq (nam, datesw))
+                   break;
+               if (state != FLDEOF)
+                   continue;
+
+           case BODY: 
+           case BODYEOF: 
+           case FILEEOF: 
+               admonish (NULLCP, "no %s field in message %d", datesw, msg);
+
+           case LENERR: 
+           case FMTERR: 
+               if (state == LENERR || state == FMTERR)
+                   admonish (NULLCP,
+                           "format error in message %d(header #%d)",
+                           msg, compnum);
+               if (hp != NULL)
+                   free (hp);
+               (void) fclose (in);
+               return NULL;
+
+           default: 
+               adios (NULLCP, "internal error -- you lose");
+       }
+       break;
+    }
+
+    if ((tw = dparsetime (hp)) == NULL)
+       admonish (NULLCP, "unable to parse %s field in message %d",
+               datesw, msg);
+
+    if (hp != NULL)
+       free (hp);
+    (void) fclose (in);
+    return tw;
+}
+
+/* \f */
+
+static int  msgsort (a, b)
+register struct smsg *a,
+                    *b;
+{
+    return twsort (&a -> s_tws, &b -> s_tws);
+}
+
+/* \f */
+
+static  file_dates (mp, verbosw)
+register struct  msgs *mp;
+int     verbosw;
+{
+    register int    i,
+                    j,
+                    k;
+    short   stats;
+    char    f1[BUFSIZ],
+            f2[BUFSIZ],
+            tmpfil[BUFSIZ];
+
+    (void) strcpy (tmpfil, m_scratch ("", invo_name));
+
+    for (i = 0; j = smsgs[i++].s_msg;)
+       if (i != j) {
+           (void) strcpy (f1, m_name (i));
+           (void) strcpy (f2, m_name (j));
+           if (mp -> msgstats[i] & EXISTS) {
+               if (verbosw)
+                   printf ("swap messages %s and %s\n", f2, f1);
+
+               if (rename (f1, tmpfil) == NOTOK) {
+                   admonish (tmpfil, "unable to rename %s to ", f1);
+                   continue;
+               }
+
+               if (rename (f2, f1) == NOTOK) {
+                   admonish (f1, "unable to rename %s to", f2);
+                   continue;
+               }
+
+               if (rename (tmpfil, f2) == NOTOK) {
+                   admonish (f2, "unable to rename %s to", tmpfil);
+                   continue;
+               }
+
+               for (k = i; smsgs[k].s_msg; k++)
+                   if (smsgs[k].s_msg == i) {
+                       smsgs[k].s_msg = j;
+                       break;
+                   }
+           }
+           else {
+               if (verbosw)
+                   printf ("message %s becomes message %s\n", f2, f1);
+
+               if (rename (f2, f1) == NOTOK) {
+                   admonish (f1, "unable to rename %s to ", f2);
+                   continue;
+               }
+           }
+
+           smsgs[i - 1].s_msg = i;
+           stats = mp -> msgstats[i];
+           mp -> msgstats[i] = mp -> msgstats[j];
+           mp -> msgstats[j] = stats;
+           if (mp -> curmsg == j)
+               m_setcur (mp, i);
+           mp -> msgflags |= SEQMOD;
+       }
+}