-
-/*
- * mshcmds.c -- command handlers in msh
- *
- * 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 <h/signals.h>
-#include <h/dropsbr.h>
-#include <h/fmt_scan.h>
-#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>
-
-
-static char delim3[] = "-------"; /* from burst.c */
-
-static int mhlnum;
-static FILE *mhlfp;
-
-/*
- * 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
- */
-static int burst (struct Msg *, int, int, int, int);
-static void forw (char *, char *, int, char **);
-static void rmm (void);
-static void show (int);
-static int eom_action (int);
-static FILE *mhl_action (char *);
-static int ask (int);
-static int is_nontext (int);
-static int get_fields (char *, char *, int, struct Msg *);
-static int msgsort (struct Msg *, struct Msg *);
-static int subsort (struct Msg *, struct Msg *);
-static char *sosmash (char *, char *);
-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 *(*)());
-
-void
-forkcmd (char **args, char *pgm)
-{
- int child_id;
- char *vec[MAXARGS];
-
- vec[0] = r1bindex (pgm, '/');
- copyip (args, vec + 1, MAXARGS - 1);
-
- if (fmsh) {
- context_del (pfolder);
- context_replace (pfolder, fmsh);/* update current folder */
- seq_save (mp);
- context_save (); /* save the context file */
- }
- fflush (stdout);
- switch (child_id = fork ()) {
- case NOTOK:
- advise ("fork", "unable to");
- return;
-
- case OK:
- closefds (3);
- SIGNAL (SIGINT, istat);
- SIGNAL (SIGQUIT, qstat);
-
- execvp (pgm, vec);
- fprintf (stderr, "unable to exec ");
- perror (cmd_name);
- _exit (1);
-
- default:
- pidXwait (child_id, NULL);
- break;
- }
- if (fmsh) { /* assume the worst case */
- mp->msgflags |= MODIFIED;
- modified++;
- }
-}
-
-
-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 }
-};
-
-
-void
-distcmd (char **args)
-{
- int vecp = 1;
- char *cp, *msg = NULL;
- char buf[BUFSIZ], *vec[MAXARGS];
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, distswit)) {
- case AMBIGSW:
- ambigsw (cp, distswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case DIHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, distswit, 1);
- return;
-
- case DIANSW: /* not implemented */
- case DINANSW:
- case DIINSW:
- case DININSW:
- continue;
-
- case DINDFSW:
- case DINEDSW:
- case DINWTSW:
- vec[vecp++] = --cp;
- continue;
-
- case DIEDTSW:
- case DIFRMSW:
- case DIDFSW:
- case DIDMSW:
- case DIWHTSW:
- vec[vecp++] = --cp;
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- if (msg) {
- advise (NULL, "only one message at a time!");
- return;
- }
- else
- msg = cp;
- }
-
- vec[0] = cmd_name;
- vec[vecp++] = "-file";
- vec[vecp] = NULL;
- if (!msg)
- msg = "cur";
- if (!m_convert (mp, msg))
- return;
- seq_setprev (mp);
-
- if (mp->numsel > 1) {
- advise (NULL, "only one message at a time!");
- return;
- }
- process (mp->hghsel, cmd_name, vecp, vec);
- seq_setcur (mp, mp->hghsel);
-}
-
-
-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 }
-};
-
-
-void
-explcmd (char **args)
-{
- int inplace = 0, quietsw = 0, verbosw = 0;
- int msgp = 0, hi, msgnum;
- char *cp, buf[BUFSIZ], *msgs[MAXARGS];
- struct Msg *smsgs;
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, explswit)) {
- case AMBIGSW:
- ambigsw (cp, explswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case EXHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, explswit, 1);
- return;
-
- case EXINSW:
- inplace++;
- continue;
- case EXNINSW:
- inplace = 0;
- continue;
- case EXQISW:
- quietsw++;
- continue;
- case EXNQISW:
- quietsw = 0;
- continue;
- case EXVBSW:
- verbosw++;
- continue;
- case EXNVBSW:
- verbosw = 0;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- if (!msgp)
- msgs[msgp++] = "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- smsgs = (struct Msg *)
- calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
- if (smsgs == NULL)
- adios (NULL, "unable to allocate folder storage");
-
- hi = mp->hghmsg + 1;
- interrupted = 0;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum))
- if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
- break;
-
- free ((char *) smsgs);
-
- if (inplace)
- seq_setcur (mp, mp->lowsel);
- else
- if (hi <= mp->hghmsg)
- seq_setcur (mp, hi);
-
- mp->msgflags |= MODIFIED;
- modified++;
-}
-
-
-static int
-burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
-{
- int i, j, ld3, wasdlm, msgp;
- long pos;
- char c, buffer[BUFSIZ];
- register FILE *zp;
-
- ld3 = strlen (delim3);
-
- if (Msgs[msgnum].m_scanl) {
- free (Msgs[msgnum].m_scanl);
- Msgs[msgnum].m_scanl = NULL;
- }
-
- pos = ftell (zp = msh_ready (msgnum, 1));
- for (msgp = 0; msgp <= MAXFOLDER;) {
- while (fgets (buffer, sizeof buffer, zp) != NULL
- && buffer[0] == '\n'
- && pos < Msgs[msgnum].m_stop)
- pos += (long) strlen (buffer);
- if (feof (zp) || pos >= Msgs[msgnum].m_stop)
- break;
- fseek (zp, pos, SEEK_SET);
- smsgs[msgp].m_start = pos;
-
- for (c = 0;
- pos < Msgs[msgnum].m_stop
- && fgets (buffer, sizeof buffer, zp) != NULL;
- c = buffer[0])
- if (strncmp (buffer, delim3, ld3) == 0
- && (msgp == 1 || c == '\n')
- && peekc (zp) == '\n')
- break;
- else
- pos += (long) strlen (buffer);
-
- wasdlm = strncmp (buffer, delim3, ld3) == 0;
- if (smsgs[msgp].m_start != pos)
- smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
- if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
- if (wasdlm)
- smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
- break;
- }
- pos += (long) strlen (buffer);
- }
-
- switch (msgp--) { /* toss "End of XXX Digest" */
- case 0:
- adios (NULL, "burst() botch -- you lose big");
-
- case 1:
- if (!quietsw)
- printf ("message %d not in digest format\n", msgnum);
- return OK;
-
- default:
- if (verbosw)
- printf ("%d message%s exploded from digest %d\n",
- msgp, msgp != 1 ? "s" : "", msgnum);
- break;
- }
-
- if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
- advise (NULL, "more than %d messages", MAXFOLDER);
- return NOTOK;
- }
- if (!(mp = folder_realloc (mp, mp->lowoff, i)))
- adios (NULL, "unable to allocate folder storage");
-
- j = mp->hghmsg;
- mp->hghmsg += msgp;
- mp->nummsg += msgp;
- if (mp->hghsel > msgnum)
- mp->hghsel += msgp;
-
- if (inplace)
- for (i = mp->hghmsg; j > msgnum; i--, j--) {
- if (verbosw)
- printf ("message %d becomes message %d\n", j, i);
-
- Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
- Msgs[i].m_top = Msgs[j].m_top;
- Msgs[i].m_start = Msgs[j].m_start;
- Msgs[i].m_stop = Msgs[j].m_stop;
- Msgs[i].m_scanl = NULL;
- if (Msgs[j].m_scanl) {
- free (Msgs[j].m_scanl);
- Msgs[j].m_scanl = NULL;
- }
- copy_msg_flags (mp, i, j);
- }
-
- if (Msgs[msgnum].m_bboard_id == 0)
- readid (msgnum);
-
- unset_selected (mp, msgnum);
- i = inplace ? msgnum + msgp : mp->hghmsg;
- for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
- if (verbosw && i != msgnum)
- printf ("message %d of digest %d becomes message %d\n",
- j, msgnum, i);
-
- Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
- Msgs[i].m_top = Msgs[j].m_top;
- Msgs[i].m_start = smsgs[j].m_start;
- Msgs[i].m_stop = smsgs[j].m_stop;
- Msgs[i].m_scanl = NULL;
- copy_msg_flags (mp, i, msgnum);
- }
-
- return OK;
-}
-
-
-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 }
-};
-
-
-void
-filecmd (char **args)
-{
- int linksw = 0, msgp = 0;
- int vecp = 1, i, msgnum;
- char *cp, buf[BUFSIZ];
- char *msgs[MAXARGS], *vec[MAXARGS];
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (i = smatch (++cp, fileswit)) {
- case AMBIGSW:
- ambigsw (cp, fileswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case FIHELP:
- snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
- print_help (buf, fileswit, 1);
- return;
-
- case FILINK:
- linksw++;
- continue;
- case FINLINK:
- linksw = 0;
- continue;
-
- case FIPRES:
- case FINPRES:
- continue;
-
- case FISRC:
- case FIDRFT:
- case FIFILE:
- case FIPROC:
- case FINPRC:
- advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
- return;
- }
- if (*cp == '+' || *cp == '@')
- vec[vecp++] = cp;
- else
- msgs[msgp++] = cp;
- }
-
- vec[0] = cmd_name;
- vec[vecp++] = "-file";
- vec[vecp] = NULL;
- if (!msgp)
- msgs[msgp++] = "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- interrupted = 0;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum))
- if (process (msgnum, fileproc, vecp, vec)) {
- unset_selected (mp, msgnum);
- mp->numsel--;
- }
-
- if (mp->numsel != mp->nummsg || linksw)
- seq_setcur (mp, mp->hghsel);
- if (!linksw)
- rmm ();
-}
-
-
-int
-filehak (char **args)
-{
- int result, vecp = 0;
- char *cp, *cwd, *vec[MAXARGS];
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, fileswit)) {
- case AMBIGSW:
- case UNKWNSW:
- case FIHELP:
- return NOTOK;
-
- case FILINK:
- case FINLINK:
- case FIPRES:
- case FINPRES:
- continue;
-
- case FISRC:
- case FIDRFT:
- case FIFILE:
- return NOTOK;
- }
- if (*cp == '+' || *cp == '@')
- vec[vecp++] = cp;
- }
- vec[vecp] = NULL;
-
- result = NOTOK;
- cwd = NULL;
- for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
- if (cwd == NULL)
- cwd = getcpy (pwd ());
- chdir (m_maildir (""));
- cp = pluspath (cp);
- if (access (m_maildir (cp), F_OK) == NOTOK)
- result = OK;
- free (cp);
- }
- if (cwd)
- chdir (cwd);
-
- return result;
-}
-
-
-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 }
-};
-
-
-void
-foldcmd (char **args)
-{
- int fastsw = 0, headersw = 0, packsw = 0;
- int hole, msgnum;
- char *cp, *folder = NULL, *msg = NULL;
- char buf[BUFSIZ], **vec = args;
-
- if (args == NULL)
- goto fast;
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, foldswit)) {
- case AMBIGSW:
- ambigsw (cp, foldswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case FLHELP:
- snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
- print_help (buf, foldswit, 1);
- return;
-
- case FLALSW: /* not implemented */
- case FLRCSW:
- case FLNRCSW:
- case FLTLSW:
- case FLNTLSW:
- case FLPRSW:
- case FLPUSW:
- case FLPOSW:
- case FLLISW:
- continue;
-
- case FLFASW:
- fastsw++;
- continue;
- case FLNFASW:
- fastsw = 0;
- continue;
- case FLHDSW:
- headersw++;
- continue;
- case FLNHDSW:
- headersw = 0;
- continue;
- case FLPKSW:
- packsw++;
- continue;
- case FLNPKSW:
- packsw = 0;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- if (folder) {
- advise (NULL, "only one folder at a time!\n");
- return;
- }
- else
- folder = fmsh ? pluspath (cp)
- : cp + 1;
- }
- else
- if (msg) {
- advise (NULL, "only one message at a time!\n");
- return;
- }
- else
- msg = cp;
- }
-
- if (folder) {
- if (*folder == 0) {
- advise (NULL, "null folder names are not permitted");
- return;
- }
- if (fmsh) {
- if (access (m_maildir (folder), R_OK) == NOTOK) {
- advise (folder, "unable to read");
- return;
- }
- }
- else {
- strncpy (buf, folder, sizeof(buf));
- if (expand (buf) == NOTOK)
- return;
- folder = buf;
- if (access (folder, R_OK) == NOTOK) {
- advise (folder, "unable to read");
- return;
- }
- }
- m_reset ();
-
- if (fmsh)
- fsetup (folder);
- else
- setup (folder);
- readids (0);
- display_info (0);
- }
-
- if (msg) {
- if (!m_convert (mp, msg))
- return;
- seq_setprev (mp);
-
- if (mp->numsel > 1) {
- advise (NULL, "only one message at a time!");
- return;
- }
- seq_setcur (mp, mp->hghsel);
- }
-
- if (packsw) {
- if (fmsh) {
- forkcmd (vec, cmd_name);
- return;
- }
-
- if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
- adios (NULL, "unable to allocate folder storage");
-
- for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
- if (does_exist (mp, msgnum)) {
- if (msgnum != hole) {
- Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
- Msgs[hole].m_top = Msgs[msgnum].m_top;
- Msgs[hole].m_start = Msgs[msgnum].m_start;
- Msgs[hole].m_stop = Msgs[msgnum].m_stop;
- Msgs[hole].m_scanl = NULL;
- if (Msgs[msgnum].m_scanl) {
- free (Msgs[msgnum].m_scanl);
- Msgs[msgnum].m_scanl = NULL;
- }
- copy_msg_flags (mp, hole, msgnum);
- if (mp->curmsg == msgnum)
- seq_setcur (mp, hole);
- }
- hole++;
- }
- if (mp->nummsg > 0) {
- mp->lowmsg = 1;
- mp->hghmsg = hole - 1;
- }
- mp->msgflags |= MODIFIED;
- modified++;
- }
-
-fast: ;
- if (fastsw)
- printf ("%s\n", fmsh ? fmsh : mp->foldpath);
- else {
- if (headersw)
- printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
- DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
- DMAXFOLDER - 2, "");
- printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
-
- /* check for empty folder */
- if (mp->nummsg == 0) {
- printf ("has no messages%*s",
- mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
- } else {
- printf ("has %*d message%s (%*d-%*d)",
- DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
- DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
- if (mp->curmsg >= mp->lowmsg
- && mp->curmsg <= mp->hghmsg)
- printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
- }
- printf (".\n");
- }
-}
-
-
-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 }
-};
-
-
-void
-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);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, forwswit)) {
- case AMBIGSW:
- ambigsw (cp, forwswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case FOHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, forwswit, 1);
- return;
-
- case FOANSW: /* not implemented */
- case FONANSW:
- case FOINSW:
- case FONINSW:
- case FOMISW:
- case FONMISW:
- continue;
-
- case FONDFSW:
- case FONEDSW:
- case FONWTSW:
- vec[vecp++] = --cp;
- continue;
-
- case FOEDTSW:
- case FOFRMSW:
- case FODFSW:
- case FODMSW:
- case FOWHTSW:
- vec[vecp++] = --cp;
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- case FOFTRSW:
- if (!(filter = *args++) || *filter == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- continue;
- case FOFTSW:
- if (access (filter = myfilter, R_OK) == NOTOK) {
- advise (filter, "unable to read default filter file");
- return;
- }
- continue;
- case FONFTSW:
- filter = NULL;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- /* foil search of .mh_profile */
- snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
-
- 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)
- msgs[msgp++] = "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- if (filter) {
- strncpy (buf, filter, sizeof(buf));
- if (expand (buf) == NOTOK)
- return;
- if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
- advise (filter, "unable to read");
- free (filter);
- return;
- }
- }
- forw (cmd_name, filter, vecp, vec);
- seq_setcur (mp, mp->hghsel);
- if (filter)
- free (filter);
-}
-
-
-static void
-forw (char *proc, char *filter, int vecp, char **vec)
-{
- int i, child_id, msgnum, msgcnt;
- 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));
-
- interrupted = 0;
- if (filter)
- switch (child_id = fork ()) {
- case NOTOK:
- advise ("fork", "unable to");
- return;
-
- case OK: /* "trust me" */
- if (freopen (tmpfil, "w", stdout) == NULL) {
- fprintf (stderr, "unable to create ");
- perror (tmpfil);
- _exit (1);
- }
- args[0] = r1bindex (mhlproc, '/');
- i = 1;
- args[i++] = "-forwall";
- args[i++] = "-form";
- args[i++] = filter;
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum))
- args[i++] = getcpy (m_name (msgnum));
- args[i] = NULL;
- mhlsbr (i, args, mhl_action);
- m_eomsbr ((int (*) ()) 0);
- fclose (stdout);
- _exit (0);
-
- default:
- if (pidXwait (child_id, NULL))
- interrupted++;
- break;
- }
- else {
- if ((out = fopen (tmpfil, "w")) == NULL) {
- advise (tmpfil, "unable to create temporary file");
- return;
- }
-
- msgcnt = 1;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum)) {
- fprintf (out, "\n\n-------");
- if (msgnum == mp->lowsel)
- fprintf (out, " Forwarded Message%s",
- mp->numsel > 1 ? "s" : "");
- else
- fprintf (out, " Message %d", msgcnt);
- fprintf (out, "\n\n");
- copy_digest (msgnum, out);
- msgcnt++;
- }
-
- fprintf (out, "\n\n------- End of Forwarded Message%s\n",
- mp->numsel > 1 ? "s" : "");
- fclose (out);
- }
-
- fflush (stdout);
- if (!interrupted)
- switch (child_id = fork ()) {
- case NOTOK:
- advise ("fork", "unable to");
- break;
-
- case OK:
- closefds (3);
- SIGNAL (SIGINT, istat);
- SIGNAL (SIGQUIT, qstat);
-
- vec[vecp++] = tmpfil;
- vec[vecp] = NULL;
-
- execvp (proc, vec);
- fprintf (stderr, "unable to exec ");
- perror (proc);
- _exit (1);
-
- default:
- pidXwait (child_id, NULL);
- break;
- }
-
- unlink (tmpfil);
-}
-
-
-static char *hlpmsg[] = {
- "The %s program emulates many of the commands found in the nmh",
- "system. Instead of operating on nmh folders, commands to %s concern",
- "a single file.",
- "",
- "To see the list of commands available, just type a ``?'' followed by",
- "the RETURN key. To find out what switches each command takes, type",
- "the name of the command followed by ``-help''. To leave %s, use the",
- "``quit'' command.",
- "",
- "Although a lot of nmh commands are found in %s, not all are fully",
- "implemented. %s will always recognize all legal switches for a",
- "given command though, and will let you know when you ask for an",
- "option that it is unable to perform.",
- "",
- "Running %s is fun, but using nmh from your shell is far superior.",
- "After you have familiarized yourself with the nmh style by using %s,",
- "you should try using nmh from the shell. You can still use %s for",
- "message files that aren't in nmh format, such as BBoard files.",
- NULL
-};
-
-
-void
-helpcmd (char **args)
-{
- int i;
-
- for (i = 0; hlpmsg[i]; i++) {
- printf (hlpmsg[i], invo_name);
- putchar ('\n');
- }
-}
-
-
-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 }
-};
-
-
-void
-markcmd (char **args)
-{
- int addsw = 0, deletesw = 0, debugsw = 0;
- int listsw = 0, zerosw = 0, seqp = 0;
- int msgp = 0, msgnum;
- char *cp, buf[BUFSIZ];
- char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
-
- while ((cp = *args++)) {
- if (*cp == '-') {
- switch (smatch (++cp, markswit)) {
- case AMBIGSW:
- ambigsw (cp, markswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case MHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, markswit, 1);
- return;
-
- case MADDSW:
- addsw++;
- deletesw = listsw = 0;
- continue;
- case MDELSW:
- deletesw++;
- addsw = listsw = 0;
- continue;
- case MLSTSW:
- listsw++;
- addsw = deletesw = 0;
- continue;
-
- case MSEQSW:
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- if (seqp < NUMATTRS)
- seqs[seqp++] = cp;
- else {
- advise (NULL, "only %d sequences allowed!", NUMATTRS);
- return;
- }
- continue;
-
- case MPUBSW: /* not implemented */
- case MNPUBSW:
- continue;
-
- case MDBUGSW:
- debugsw++;
- continue;
-
- case MZERSW:
- zerosw++;
- continue;
- case MNZERSW:
- zerosw = 0;
- continue;
- }
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- } else {
- msgs[msgp++] = cp;
- }
- }
-
- if (!addsw && !deletesw && !listsw) {
- if (seqp)
- addsw++;
- else
- if (debugsw)
- listsw++;
- else {
- seqs[seqp++] = "unseen";
- deletesw++;
- zerosw = 0;
- if (!msgp)
- msgs[msgp++] = "all";
- }
- }
-
- if (!msgp)
- msgs[msgp++] = listsw ? "all" :"cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
-
- if (debugsw) {
- printf ("invo_name=%s mypath=%s defpath=%s\n",
- invo_name, mypath, defpath);
- printf ("ctxpath=%s context flags=%s\n",
- ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
- printf ("foldpath=%s flags=%s\n",
- mp->foldpath,
- snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
- printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
- mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
- printf ("lowsel=%d hghsel=%d numsel=%d\n",
- mp->lowsel, mp->hghsel, mp->numsel);
- printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
- }
-
- if (seqp == 0 && (addsw || deletesw)) {
- advise (NULL, "-%s requires at least one -sequence argument",
- addsw ? "add" : "delete");
- return;
- }
- seqs[seqp] = NULL;
-
- if (addsw) {
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
- return;
- }
-
- if (deletesw) {
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
- return;
- }
-
- /* Listing messages in sequences */
- if (listsw) {
- if (seqp) {
- /* list the given sequences */
- for (seqp = 0; seqs[seqp]; seqp++)
- seq_print (mp, seqs[seqp]);
- } else {
- /* else list them all */
- seq_printall (mp);
- }
-
- interrupted = 0;
- if (debugsw)
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum)) {
- printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
- DMAXFOLDER,
- msgnum,
- Msgs[msgnum].m_bboard_id,
- Msgs[msgnum].m_top,
- (long) Msgs[msgnum].m_start,
- (long) Msgs[msgnum].m_stop,
- snprintb (buf, sizeof(buf),
- (unsigned) mp->msgstats[msgnum - mp->lowoff],
- seq_bits (mp)));
- if (Msgs[msgnum].m_scanl)
- printf ("%s", Msgs[msgnum].m_scanl);
- }
- }
-}
-
-
-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 }
-};
-
-
-void
-mhncmd (char **args)
-{
- int msgp = 0, vecp = 1;
- int msgnum;
- char *cp, buf[BUFSIZ];
- char *msgs[MAXARGS], *vec[MAXARGS];
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
- while ((cp = *args++)) {
- if (*cp == '-') {
- switch (smatch (++cp, mhnswit)) {
- case AMBIGSW:
- ambigsw (cp, mhnswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case MHNHELPSW:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, mhnswit, 1);
- return;
-
- case MHNAUTOSW:
- case MHNNAUTOSW:
- case MHNDEBUGSW:
- case MHNEBCDICSW:
- case MHNNEBCDICSW:
- case MHNHEADSW:
- case MHNNHEADSW:
- case MHNLISTSW:
- case MHNNLISTSW:
- case MHNSIZESW:
- case MHNNSIZESW:
- case MHNRFC934SW:
- case MHNNRFC934SW:
- case MHNSERIALSW:
- case MHNNSERIALSW:
- case MHNSHOWSW:
- case MHNNSHOWSW:
- case MHNSTORESW:
- case MHNNSTORESW:
- case MHNVERBSW:
- case MHNNVERBSW:
- case MHNNPROGSW:
- vec[vecp++] = --cp;
- continue;
-
- case MHNFORMSW:
- case MHNPARTSW:
- case MHNTYPESW:
- case MHNPROGSW:
- case MHNLENSW:
- case MHNWIDSW:
- vec[vecp++] = --cp;
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- }
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- } else {
- msgs[msgp++] = cp;
- }
- }
-
- vec[0] = cmd_name;
- vec[vecp++] = "-file";
- vec[vecp] = NULL;
- if (!msgp)
- msgs[msgp++] = "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- interrupted = 0;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum))
- if (process (msgnum, cmd_name, vecp, vec)) {
- unset_selected (mp, msgnum);
- mp->numsel--;
- }
-
- seq_setcur (mp, mp->hghsel);
-}
-
-
-static struct swit packswit[] = {
-#define PAFISW 0
- { "file name", 0 },
-#define PAHELP 1
- { "help", 0 },
- { NULL, 0 }
-};
-
-static int mbx_style = MMDF_FORMAT;
-
-void
-packcmd (char **args)
-{
- int msgp = 0, md, msgnum;
- char *cp, *file = NULL;
- char buf[BUFSIZ], *msgs[MAXARGS];
- struct stat st;
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, packswit)) {
- case AMBIGSW:
- ambigsw (cp, packswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case PAHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, packswit, 1);
- return;
-
- case PAFISW:
- if (!(file = *args++) || *file == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- if (!file)
- file = "./msgbox";
- file = path (file, TFILE);
- if (stat (file, &st) == NOTOK) {
- if (errno != ENOENT) {
- advise (file, "error on file");
- goto done_pack;
- }
- md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
- free (cp);
- if (!md)
- goto done_pack;
- }
-
- if (!msgp)
- msgs[msgp++] = "all";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- goto done_pack;
- seq_setprev (mp);
-
- if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
- advise (file, "unable to open");
- goto done_pack;
- }
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum))
- if (pack (file, md, msgnum) == NOTOK)
- break;
- mbx_close (file, md);
-
- if (mp->hghsel != mp->curmsg)
- seq_setcur (mp, mp->lowsel);
-
-done_pack: ;
- free (file);
-}
-
-
-int
-pack (char *mailbox, int md, int msgnum)
-{
- register FILE *zp;
-
- if (Msgs[msgnum].m_bboard_id == 0)
- readid (msgnum);
-
- zp = msh_ready (msgnum, 1);
- return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
- 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
-}
-
-
-int
-packhak (char **args)
-{
- int result;
- char *cp, *file = NULL;
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, packswit)) {
- case AMBIGSW:
- case UNKWNSW:
- case PAHELP:
- return NOTOK;
-
- case PAFISW:
- if (!(file = *args++) || *file == '-')
- return NOTOK;
- continue;
- }
- if (*cp == '+' || *cp == '@')
- return NOTOK;
- }
-
- file = path (file ? file : "./msgbox", TFILE);
- result = access (file, F_OK) == NOTOK ? OK : NOTOK;
- free (file);
-
- return result;
-}
-
-
-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 }
-};
-
-
-void
-pickcmd (char **args)
-{
- int zerosw = 1, msgp = 0, seqp = 0;
- int vecp = 0, hi, lo, msgnum;
- char *cp, buf[BUFSIZ], *msgs[MAXARGS];
- char *seqs[NUMATTRS], *vec[MAXARGS];
- register FILE *zp;
-
- while ((cp = *args++)) {
- if (*cp == '-') {
- if (*++cp == '-') {
- vec[vecp++] = --cp;
- goto pattern;
- }
- switch (smatch (cp, pickswit)) {
- case AMBIGSW:
- ambigsw (cp, pickswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case PIHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, pickswit, 1);
- return;
-
- case PICCSW:
- case PIDASW:
- case PIFRSW:
- case PISUSW:
- case PITOSW:
- case PIDFSW:
- case PIAFSW:
- case PIBFSW:
- case PISESW:
- vec[vecp++] = --cp;
-pattern: ;
- if (!(cp = *args++)) {/* allow -xyz arguments */
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- case PIOTSW:
- advise (NULL, "internal error!");
- return;
- case PIANSW:
- case PIORSW:
- case PINTSW:
- case PILBSW:
- case PIRBSW:
- vec[vecp++] = --cp;
- continue;
-
- case PISQSW:
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- if (seqp < NUMATTRS)
- seqs[seqp++] = cp;
- else {
- advise (NULL, "only %d sequences allowed!", NUMATTRS);
- return;
- }
- continue;
- case PIZRSW:
- zerosw++;
- continue;
- case PINZRSW:
- zerosw = 0;
- continue;
-
- case PIPUSW: /* not implemented */
- case PINPUSW:
- case PILISW:
- case PINLISW:
- continue;
- }
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
- vec[vecp] = NULL;
-
- if (!msgp)
- msgs[msgp++] = "all";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- interrupted = 0;
- if (!pcompile (vec, NULL))
- return;
-
- lo = mp->lowsel;
- hi = mp->hghsel;
-
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum)) {
- zp = msh_ready (msgnum, 1);
- if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
- fmsh ? 0L : Msgs[msgnum].m_stop)) {
- if (msgnum < lo)
- lo = msgnum;
- if (msgnum > hi)
- hi = msgnum;
- }
- else {
- unset_selected (mp, msgnum);
- mp->numsel--;
- }
- }
-
- if (interrupted)
- return;
-
- mp->lowsel = lo;
- mp->hghsel = hi;
-
- if (mp->numsel <= 0) {
- advise (NULL, "no messages match specification");
- return;
- }
-
- seqs[seqp] = NULL;
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
- return;
-
- printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
-}
-
-
-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 }
-};
-
-
-void
-replcmd (char **args)
-{
- int vecp = 1;
- char *cp, *msg = NULL;
- char buf[BUFSIZ], *vec[MAXARGS];
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, replswit)) {
- case AMBIGSW:
- ambigsw (cp, replswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case REHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, replswit, 1);
- return;
-
- case REANSW: /* not implemented */
- case RENANSW:
- case REINSW:
- case RENINSW:
- continue;
-
- case REQUSW:
- case RENQUSW:
- case RENDFSW:
- case RENEDSW:
- case RENWTSW:
- vec[vecp++] = --cp;
- continue;
-
- case RECCSW:
- case RENCCSW:
- case REEDTSW:
- case REFCCSW:
- case REFLTSW:
- case REFRMSW:
- case REWIDSW:
- case REDFSW:
- case REDMSW:
- case REWHTSW:
- vec[vecp++] = --cp;
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- if (msg) {
- advise (NULL, "only one message at a time!");
- return;
- }
- else
- msg = cp;
- }
-
- vec[0] = cmd_name;
- vec[vecp++] = "-file";
- vec[vecp] = NULL;
- if (!msg)
- msg = "cur";
- if (!m_convert (mp, msg))
- return;
- seq_setprev (mp);
-
- if (mp->numsel > 1) {
- advise (NULL, "only one message at a time!");
- return;
- }
- process (mp->hghsel, cmd_name, vecp, vec);
- seq_setcur (mp, mp->hghsel);
-}
-
-
-static struct swit rmmswit[] = {
-#define RMHELP 0
- { "help", 0 },
- { NULL, 0 }
-};
-
-
-void
-rmmcmd (char **args)
-{
- int msgp = 0, msgnum;
- char *cp, buf[BUFSIZ], *msgs[MAXARGS];
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, rmmswit)) {
- case AMBIGSW:
- ambigsw (cp, rmmswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case RMHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, rmmswit, 1);
- return;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- if (!msgp)
- msgs[msgp++] = "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- rmm ();
-}
-
-
-static void
-rmm (void)
-{
- register int msgnum, vecp;
- register char *cp;
- char buffer[BUFSIZ], *vec[MAXARGS];
-
- if (fmsh) {
- if (rmmproc) {
- if (mp->numsel > MAXARGS - 1) {
- advise (NULL, "more than %d messages for %s exec",
- MAXARGS - 1, rmmproc);
- return;
- }
- vecp = 0;
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum))
- vec[vecp++] = getcpy (m_name (msgnum));
- vec[vecp] = NULL;
- forkcmd (vec, rmmproc);
- for (vecp = 0; vec[vecp]; vecp++)
- free (vec[vecp]);
- }
- else
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum)) {
- strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
- if (rename (cp, buffer) == NOTOK)
- admonish (buffer, "unable to rename %s to", cp);
- }
- }
-
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum)) {
- set_deleted (mp, msgnum);
- unset_exists (mp, msgnum);
- }
-
- if ((mp->nummsg -= mp->numsel) <= 0) {
- if (fmsh)
- admonish (NULL, "no messages remaining in +%s", fmsh);
- else
- admonish (NULL, "no messages remaining in %s", mp->foldpath);
- mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
- }
- if (mp->lowsel == mp->lowmsg) {
- for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
- if (does_exist (mp, msgnum))
- break;
- mp->lowmsg = msgnum;
- }
- if (mp->hghsel == mp->hghmsg) {
- for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
- if (does_exist (mp, msgnum))
- break;
- mp->hghmsg = msgnum;
- }
-
- mp->msgflags |= MODIFIED;
- modified++;
-}
-
-
-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 }
-};
-
-
-void
-scancmd (char **args)
-{
-#define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
-
- int clearsw = 0, headersw = 0, width = 0, msgp = 0;
- int msgnum, optim, state;
- char *cp, *form = NULL, *format = NULL;
- char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
- register FILE *zp;
- static int s_optim = 0;
- static char *s_form = NULL, *s_format = NULL;
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, scanswit)) {
- case AMBIGSW:
- ambigsw (cp, scanswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case SCHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, scanswit, 1);
- return;
-
- case SCCLR:
- clearsw++;
- continue;
- case SCNCLR:
- clearsw = 0;
- continue;
- case SCHEAD:
- headersw++;
- continue;
- case SCNHEAD:
- headersw = 0;
- continue;
- case SCFORM:
- if (!(form = *args++) || *form == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- format = NULL;
- continue;
- case SCFMT:
- if (!(format = *args++) || *format == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- form = NULL;
- continue;
- case SCWID:
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- width = atoi (cp);
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- if (!msgp)
- msgs[msgp++] = "all";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- /* Get new format string */
- nfs = new_fs (form, format, FORMAT);
-
- /* force scansbr to (re)compile format */
- if (scanl) {
- free (scanl);
- scanl = NULL;
- }
-
- if (s_optim == 0) {
- s_optim = optim = 1;
- s_form = form ? getcpy (form) : NULL;
- s_format = format ? getcpy (format) : NULL;
-
- }
- else
- optim = equiv (s_form, form) && equiv (s_format, format);
-
- interrupted = 0;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum)) {
- if (optim && Msgs[msgnum].m_scanl)
- printf ("%s", Msgs[msgnum].m_scanl);
- else {
-
- zp = msh_ready (msgnum, 0);
- switch (state = scan (zp, msgnum, 0, nfs, width,
- msgnum == mp->curmsg,
- is_unseen (mp, msgnum),
- headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
- fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
- 1)) {
- case SCNMSG:
- case SCNENC:
- case SCNERR:
- if (optim)
- Msgs[msgnum].m_scanl = getcpy (scanl);
- break;
-
- default:
- advise (NULL, "scan() botch (%d)", state);
- return;
-
- case SCNEOF:
- printf ("%*d empty\n", DMAXFOLDER, msgnum);
- break;
- }
- }
- headersw = 0;
- }
-
- if (clearsw)
- clear_screen ();
-}
-
-
-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 }
-};
-
-
-void
-showcmd (char **args)
-{
- int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
- int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
- char *cp, *proc = showproc, buf[BUFSIZ];
- char *msgs[MAXARGS], *vec[MAXARGS];
-
- if (!mh_strcasecmp (cmd_name, "next"))
- mode = 1;
- else
- if (!mh_strcasecmp (cmd_name, "prev"))
- mode = -1;
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (i = smatch (++cp, showswit)) {
- case AMBIGSW:
- ambigsw (cp, showswit);
- return;
- case UNKWNSW:
- case SHNPROG:
- vec[vecp++] = --cp;
- continue;
- case SHHELP:
- snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
- cmd_name, mode ? NULL : "[msgs] ");
- print_help (buf, showswit, 1);
- return;
-
- case SHFORM:
- case SHPROG:
- case SHLEN:
- case SHWID:
- vec[vecp++] = --cp;
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- vec[vecp++] = cp;
- continue;
- case SHHEAD:
- headersw++;
- continue;
- case SHNHEAD:
- headersw = 0;
- continue;
- case SHSHOW:
- if (!(proc = *args++) || *proc == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- nshow = 0;
- continue;
- case SHNSHOW:
- nshow++;
- continue;
-
- case SHDRAFT:
- advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
- return;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- if (mode) {
- fprintf (stderr,
- "usage: %s [switches] [switches for showproc]\n",
- cmd_name);
- return;
- }
- else
- msgs[msgp++] = cp;
- }
- vec[vecp] = NULL;
-
- if (!msgp)
- msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- if (!nshow && !getenv ("NOMHNPROC"))
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
- proc = showmimeproc;
- vec[vecp++] = "-file";
- vec[vecp] = NULL;
- goto finish;
- }
-
- if (nshow)
- proc = catproc;
- else
- if (strcmp (showproc, "mhl") == 0) {
- proc = mhlproc;
- mhl++;
- }
-
-finish: ;
- seqnum = seq_getnum (mp, "unseen");
- vec[0] = r1bindex (proc, '/');
- if (mhl) {
- msgp = vecp;
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
- if (is_selected (mp, msgnum)) {
- vec[vecp++] = getcpy (m_name (msgnum));
- if (seqnum != -1)
- seq_delmsg (mp, "unseen", msgnum);
- }
- vec[vecp] = NULL;
- if (mp->numsel == 1 && headersw)
- show (mp->lowsel);
- mhlsbr (vecp, vec, mhl_action);
- m_eomsbr ((int (*)()) 0);
- while (msgp < vecp)
- free (vec[msgp++]);
- } else {
- interrupted = 0;
- for (msgnum = mp->lowsel;
- msgnum <= mp->hghsel && !interrupted;
- msgnum++)
- if (is_selected (mp, msgnum)) {
- switch (ask (msgnum)) {
- case NOTOK: /* QUIT */
- break;
-
- case OK: /* INTR */
- continue;
-
- default:
- if (mp->numsel == 1 && headersw)
- show (msgnum);
- if (nshow)
- copy_message (msgnum, stdout);
- else
- process (msgnum, proc, vecp, vec);
-
- if (seqnum != -1)
- seq_delmsg (mp, "unseen", msgnum);
- continue;
- }
- break;
- }
- }
-
- seq_setcur (mp, mp->hghsel);
-}
-
-
-static void
-show (int msgnum)
-{
- if (Msgs[msgnum].m_bboard_id == 0)
- readid (msgnum);
-
- printf ("(Message %d", msgnum);
- if (Msgs[msgnum].m_bboard_id > 0)
- printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
- printf (")\n");
-}
-
-
-
-static int
-eom_action (int c)
-{
- return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
-}
-
-
-static FILE *
-mhl_action (char *name)
-{
- int msgnum;
-
- if ((msgnum = m_atoi (name)) < mp->lowmsg
- || msgnum > mp->hghmsg
- || !does_exist (mp, msgnum))
- return NULL;
- mhlnum = msgnum;
-
- mhlfp = msh_ready (msgnum, 1);
- if (!fmsh)
- m_eomsbr (eom_action);
-
- return mhlfp;
-}
-
-
-
-static int
-ask (int msgnum)
-{
- char buf[BUFSIZ];
-
- if (mp->numsel == 1 || !interactive || redirected)
- return DONE;
-
- if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
- if (mp->lowsel != msgnum)
- printf ("\n\n\n");
- printf ("Press <return> to list \"%d\"...", 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');
-
- if (told_to_quit) {
- told_to_quit = interrupted = 0;
- return NOTOK;
- }
- if (interrupted) {
- interrupted = 0;
- return OK;
- }
-
- return DONE;
-}
-
-
-#include <h/mime.h>
-
-static int
-is_nontext (int msgnum)
-{
- int result, state;
- unsigned char *bp, *dp;
- char *cp;
- char buf[BUFSIZ], name[NAMESZ];
- FILE *fp;
-
- if (Msgs[msgnum].m_flags & MHNCHK)
- return (Msgs[msgnum].m_flags & MHNYES);
- Msgs[msgnum].m_flags |= MHNCHK;
-
- fp = msh_ready (msgnum, 1);
-
- for (state = FLD;;)
- switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
- case FLD:
- case FLDPLUS:
- case FLDEOF:
- /*
- * Check Content-Type field
- */
- if (!mh_strcasecmp (name, TYPE_FIELD)) {
- int passno;
- char c;
-
- cp = add (buf, NULL);
- while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, fp);
- cp = add (buf, cp);
- }
- bp = cp;
- passno = 1;
-
-again:
- for (; isspace (*bp); bp++)
- continue;
- if (*bp == '(') {
- int i;
-
- for (bp++, i = 0;;) {
- switch (*bp++) {
- case '\0':
-invalid:
- result = 0;
- goto out;
- case '\\':
- if (*bp++ == '\0')
- goto invalid;
- continue;
- case '(':
- i++;
- /* and fall... */
- default:
- continue;
- case ')':
- if (--i < 0)
- break;
- continue;
- }
- break;
- }
- }
- if (passno == 2) {
- if (*bp != '/')
- goto invalid;
- bp++;
- passno = 3;
- goto again;
- }
- for (dp = bp; istoken (*dp); dp++)
- continue;
- c = *dp;
- *dp = '\0';
- if (!*bp)
- goto invalid;
- if (passno > 1) {
- if ((result = (mh_strcasecmp (bp, "plain") != 0)))
- goto out;
- *dp = c;
- for (dp++; isspace (*dp); dp++)
- continue;
- if (*dp) {
- if ((result = !uprf (dp, "charset")))
- goto out;
- dp += sizeof "charset" - 1;
- while (isspace (*dp))
- dp++;
- if (*dp++ != '=')
- goto invalid;
- while (isspace (*dp))
- dp++;
- if (*dp == '"') {
- if ((bp = strchr(++dp, '"')))
- *bp = '\0';
- } else {
- for (bp = dp; *bp; bp++)
- if (isspace (*bp)) {
- *bp = '\0';
- break;
- }
- }
- } else {
- /* Default character set */
- dp = "US-ASCII";
- }
- /* Check the character set */
- result = !check_charset (dp, strlen (dp));
- } else {
- if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
- *dp = c;
- bp = dp;
- passno = 2;
- goto again;
- }
- }
-out:
- free (cp);
- if (result) {
- Msgs[msgnum].m_flags |= MHNYES;
- return result;
- }
- break;
- }
-
- /*
- * Check Content-Transfer-Encoding field
- */
- if (!mh_strcasecmp (name, ENCODING_FIELD)) {
- cp = add (buf, NULL);
- while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, fp);
- cp = add (buf, cp);
- }
- for (bp = cp; isspace (*bp); bp++)
- continue;
- for (dp = bp; istoken (*dp); dp++)
- continue;
- *dp = '\0';
- result = (mh_strcasecmp (bp, "7bit")
- && mh_strcasecmp (bp, "8bit")
- && mh_strcasecmp (bp, "binary"));
-
- free (cp);
- if (result) {
- Msgs[msgnum].m_flags |= MHNYES;
- return result;
- }
- break;
- }
-
- /*
- * 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);
- break;
-
- /*
- * We've passed the message header,
- * so message is just text.
- */
- 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 }
-};
-
-
-void
-sortcmd (char **args)
-{
- int msgp = 0, msgnum;
- char *cp, *datesw = NULL, *subjsw = NULL;
- char buf[BUFSIZ], *msgs[MAXARGS];
- struct tws tb;
-
- if (fmsh) {
- forkcmd (args, cmd_name);
- return;
- }
-
- while ((cp = *args++)) {
- if (*cp == '-')
- switch (smatch (++cp, sortswit)) {
- case AMBIGSW:
- ambigsw (cp, sortswit);
- return;
- case UNKWNSW:
- fprintf (stderr, "-%s unknown\n", cp);
- return;
- case SOHELP:
- snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
- print_help (buf, sortswit, 1);
- return;
-
- case SODATE:
- if (datesw) {
- advise (NULL, "only one date field at a time!");
- return;
- }
- if (!(datesw = *args++) || *datesw == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- continue;
-
- case SOSUBJ:
- if (subjsw) {
- advise (NULL, "only one text field at a time!");
- return;
- }
- if (!(subjsw = *args++) || *subjsw == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- continue;
- case SONSUBJ:
- subjsw = (char *)0;
- continue;
-
- case SOLIMT: /* too hard */
- if (!(cp = *args++) || *cp == '-') {
- advise (NULL, "missing argument to %s", args[-2]);
- return;
- }
- case SONLIMT:
- case SOVERB: /* not implemented */
- case SONVERB:
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- advise (NULL, "sorry, no folders allowed!");
- return;
- }
- else
- msgs[msgp++] = cp;
- }
-
- if (!msgp)
- msgs[msgp++] = "all";
- if (!datesw)
- datesw = "Date";
- for (msgnum = 0; msgnum < msgp; msgnum++)
- if (!m_convert (mp, msgs[msgnum]))
- return;
- seq_setprev (mp);
-
- twscopy (&tb, dlocaltimenow ());
-
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
- if (Msgs[msgnum].m_scanl) {
- free (Msgs[msgnum].m_scanl);
- Msgs[msgnum].m_scanl = NULL;
- }
- if (is_selected (mp, msgnum)) {
- if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
- twscopy (&Msgs[msgnum].m_tb,
- msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
- }
- else /* m_scaln is already NULL */
- twscopy (&Msgs[msgnum].m_tb, &tb);
- Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
- if (mp->curmsg == msgnum)
- Msgs[msgnum].m_stats |= CUR;
- }
-
- qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
- sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
-
- for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
- if (subjsw && Msgs[msgnum].m_scanl) {
- 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)
- seq_setcur (mp, msgnum);
- }
-
- mp->msgflags |= MODIFIED;
- modified++;
-}
-
-
-/*
- * get_fields - parse message, and get date and subject if needed.
- * We'll use the msgp->m_tb tws struct for the date, and overload
- * the msgp->m_scanl field with our subject string.
- */
-static int
-get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
-{
- int state, gotdate = 0;
- char *bp, buf[BUFSIZ], name[NAMESZ];
- struct tws *tw = (struct tws *) 0;
- register FILE *zp;
-
- zp = msh_ready (msgnum, 0);
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
- case FLD:
- case FLDEOF:
- case FLDPLUS:
- if (!mh_strcasecmp (name, datesw)) {
- bp = getcpy (buf);
- while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, zp);
- bp = add (buf, bp);
- }
- if ((tw = dparsetime (bp)) == NULL)
- admonish (NULL,
- "unable to parse %s field in message %d",
- datesw, msgnum);
- else
- twscopy (&(msgp->m_tb), tw);
- free (bp);
- if (!subjsw) /* not using this, or already done */
- break; /* all done! */
- gotdate++;
- }
- else if (subjsw && !mh_strcasecmp(name, subjsw)) {
- bp = getcpy (buf);
- while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, zp);
- bp = add (buf, bp);
- }
- msgp->m_scanl = sosmash(subjsw, bp);
- if (gotdate)
- break; /* date done so we're done */
- else
- subjsw = (char *)0;/* subject done, need date */
- } else {
- while (state == FLDPLUS) /* flush this one */
- state = m_getfld (state, name, buf, sizeof buf, zp);
- }
- continue;
-
- case BODY:
- case BODYEOF:
- case FILEEOF:
- break;
-
- case LENERR:
- case FMTERR:
- admonish (NULL, "format error in message %d", msgnum);
- if (msgp->m_scanl) { /* this might need free'd */
- free (msgp->m_scanl); /* probably can't use subj anyway */
- msgp->m_scanl = NULL;
- }
- return NOTOK;
-
- default:
- adios (NULL, "internal error -- you lose");
- }
- break;
- }
- if (tw)
- return OK; /* not an error if subj not found */
-
- admonish (NULL, "no %s field in message %d", datesw, msgnum);
- return NOTOK; /* NOTOK means use some other date */
-}
-
-
-/*
- * sort routines
- */
-
-static int
-msgsort (struct Msg *a, struct Msg *b)
-{
- return twsort (&a->m_tb, &b->m_tb);
-}
-
-
-static int
-subsort (struct Msg *a, struct Msg *b)
-{
- register int i;
-
- if (a->m_scanl && b->m_scanl)
- if ((i = strcmp (a->m_scanl, b->m_scanl)))
- return (i);
-
- return twsort (&a->m_tb, &b->m_tb);
-}
-
-
-/*
- * try to make the subject "canonical": delete leading "re:", everything
- * but letters & smash letters to lower case.
- */
-static char *
-sosmash (char *subj, char *s)
-{
- register char *cp, *dp;
- register unsigned char c;
-
- if (s) {
- cp = s;
- dp = s; /* dst pointer */
- if (!mh_strcasecmp (subj, "subject"))
- while ((c = *cp)) {
- if (! isspace(c)) {
- if(uprf(cp, "re:"))
- cp += 2;
- else {
- if (isalnum(c))
- *dp++ = isupper(c) ? tolower(c) : c;
- break;
- }
- }
- cp++;
- }
- while ((c = *cp++)) {
- if (isalnum(c))
- *dp++ = isupper(c) ? tolower(c) : c;
-
- }
- *dp = '\0';
- }
- return s;
-}
-
-
-static int
-process (int msgnum, char *proc, int vecp, char **vec)
-{
- int child_id, status;
- char tmpfil[BUFSIZ];
- FILE *out;
- char *cp;
-
- if (fmsh) {
- strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
- context_del (pfolder);
- context_replace (pfolder, fmsh);/* update current folder */
- seq_save (mp);
- context_save (); /* save the context file */
- goto ready;
- }
-
- 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 (NULL, "unable to create temporary file");
- return NOTOK;
- }
- }
- copy_message (msgnum, out);
- fclose (out);
- strncpy(tmpfil, cp, sizeof(tmpfil));
-
-ready: ;
- fflush (stdout);
- switch (child_id = fork ()) {
- case NOTOK:
- advise ("fork", "unable to");
- status = NOTOK;
- break;
-
- case OK:
- closefds (3);
- SIGNAL (SIGINT, istat);
- SIGNAL (SIGQUIT, qstat);
-
- vec[vecp++] = tmpfil;
- vec[vecp] = NULL;
-
- execvp (proc, vec);
- fprintf (stderr, "unable to exec ");
- perror (proc);
- _exit (1);
-
- default:
- status = pidXwait (child_id, NULL);
- break;
- }
-
- if (!fmsh)
- unlink (tmpfil);
- return status;
-}
-
-
-static void
-copy_message (int msgnum, FILE *out)
-{
- long pos;
- static char buffer[BUFSIZ];
- register FILE *zp;
-
- zp = msh_ready (msgnum, 1);
- if (fmsh) {
- while (fgets (buffer, sizeof buffer, zp) != NULL) {
- fputs (buffer, out);
- if (interrupted && out == stdout)
- break;
- }
- }
- else {
- pos = ftell (zp);
- while (fgets (buffer, sizeof buffer, zp) != NULL
- && pos < Msgs[msgnum].m_stop) {
- fputs (buffer, out);
- pos += (long) strlen (buffer);
- if (interrupted && out == stdout)
- break;
- }
- }
-}
-
-
-static void
-copy_digest (int msgnum, FILE *out)
-{
- char c;
- long pos = 0L;
- static char buffer[BUFSIZ];
- register FILE *zp;
-
- c = '\n';
- zp = msh_ready (msgnum, 1);
- if (!fmsh)
- pos = ftell (zp);
- while (fgets (buffer, sizeof buffer, zp) != NULL
- && !fmsh && pos < Msgs[msgnum].m_stop) {
- if (c == '\n' && *buffer == '-')
- fputc (' ', out);
- fputs (buffer, out);
- c = buffer[strlen (buffer) - 1];
- if (!fmsh)
- pos += (long) strlen (buffer);
- if (interrupted && out == stdout)
- break;
- }
-}