+++ /dev/null
-
-/*
- * msh.c -- The nmh shell
- *
- * 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.
- */
-
-/*
- * TODO:
- * Keep more status information in maildrop map
- */
-
-#include <h/mh.h>
-#include <fcntl.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 <h/utils.h>
-
-#include <termios.h>
-
-#include <pwd.h>
-#include <setjmp.h>
-#include <h/msh.h>
-#include <h/vmhsbr.h>
-
-#define QUOTE '\\' /* sigh */
-
-#define MSH_SWITCHES \
- X("idstart number", -7, IDSW) /* interface from bbc */ \
- X("idstop number", -6, FDSW) /* .. */ \
- X("idquit number", -6, QDSW) /* .. */ \
- X("idname BBoard", -6, NMSW) /* .. */ \
- X("prompt string", 0, PRMPTSW) \
- X("scan", 0, SCANSW) \
- X("noscan", 0, NSCANSW) \
- X("vmhread fd", -7, READSW) \
- X("vmhwrite fd", -8, WRITESW) \
- X("popread fd", -7, PREADSW) \
- X("popwrite fd", -8, PWRITSW) \
- X("topcur", 0, TCURSW) \
- X("notopcur", 0, NTCURSW) \
- X("version", 0, VERSIONSW) \
- X("help", 0, HELPSW) \
-
-#define X(sw, minchars, id) id,
-DEFINE_SWITCH_ENUM(MSH);
-#undef X
-
-#define X(sw, minchars, id) { sw, minchars, id },
-DEFINE_SWITCH_ARRAY(MSH, switches);
-#undef X
-
-static int mbx_style = MMDF_FORMAT;
-
-/*
- * FOLDER
- */
-char*fmsh = NULL; /* folder instead of file */
-int modified; /* command modified folder */
-struct msgs *mp; /* used a lot */
-static int nMsgs = 0;
-struct Msg *Msgs = NULL; /* Msgs[0] not used */
-static FILE *fp; /* input file */
-static FILE *yp = NULL; /* temporary file */
-static int mode; /* mode of file */
-static int numfds = 0; /* number of files cached */
-static int maxfds = 0; /* number of files cached to be cached */
-static time_t mtime = (time_t) 0; /* mtime of file */
-
-/*
- * VMH
- */
-#define ALARM ((unsigned int) 10)
-#define ttyN(c) ttyNaux ((c), NULL)
-
-static int vmh = 0;
-
-static int vmhpid = OK;
-static int vmhfd0;
-static int vmhfd1;
-static int vmhfd2;
-
-static int vmhtty = NOTOK;
-
-#define SCAN 1
-#define STATUS 2
-#define DISPLAY 3
-#define NWIN DISPLAY
-
-static int topcur = 0;
-
-static int numwins = 0;
-static int windows[NWIN + 1];
-
-static jmp_buf peerenv;
-
-/*
- * PARENT
- */
-static int pfd = NOTOK; /* fd parent is reading from */
-static int ppid = 0; /* pid of parent */
-
-/*
- * COMMAND
- */
-int interactive; /* running from a /dev/tty */
-int redirected; /* re-directing output */
-FILE *sp = NULL; /* original stdout */
-
-char *cmd_name; /* command being run */
-char myfilter[BUFSIZ]; /* path to mhl.forward */
-
-static char *myprompt = "(%s) ";/* prompting string */
-
-/*
- * BBOARDS
- */
-static int gap; /* gap in BBoard-ID:s */
-static char *myname = NULL; /* BBoard name */
-char *BBoard_ID = "BBoard-ID"; /* BBoard-ID constant */
-
-/*
- * SIGNALS
- */
-SIGNAL_HANDLER istat; /* original SIGINT */
-static SIGNAL_HANDLER pstat; /* current SIGPIPE */
-SIGNAL_HANDLER qstat; /* original SIGQUIT */
-
-#ifdef SIGTSTP
-SIGNAL_HANDLER tstat; /* original SIGTSTP */
-#endif
-
-int interrupted; /* SIGINT detected */
-int broken_pipe; /* SIGPIPE detected */
-int told_to_quit; /* SIGQUIT detected */
-
-/*
- * prototypes
- */
-void fsetup (char *);
-void setup (char *);
-void readids (int);
-int readid (int);
-void display_info (int);
-int expand (char *);
-void m_reset (void);
-void seq_setcur (struct msgs *, int);
-void padios (char *, char *, ...);
-void padvise (char *, char *, ...);
-
-extern m_getfld_state_t gstate; /* use the gstate in scansbr.c */
-
-
-/*
- * static prototypes
- */
-static void msh (int);
-static int read_map (char *, long);
-static int read_file (long, int);
-
-static void m_gMsgs (int);
-static int check_folder (int);
-static void scanrange (int, int);
-static void scanstring (char *);
-static void write_ids (void);
-static void quit (void);
-static int getargs (char *, struct swit *, struct Cmd *);
-static int getcmds (struct swit *, struct Cmd *, int);
-static int parse (char *, struct Cmd *);
-static int init_io (struct Cmd *, int);
-static int initaux_io (struct Cmd *);
-static void fin_io (struct Cmd *, int);
-static void finaux_io (struct Cmd *);
-static void m_init (void);
-static void intrser (int);
-static void pipeser (int);
-static void quitser (int);
-static void alrmser (int);
-static int pINI (void);
-static int pQRY (char *, int);
-static int pQRY1 (int);
-static int pQRY2 (void);
-static int pCMD (char *, struct swit *, struct Cmd *);
-static int pFIN (void);
-static int peerwait (void);
-static int ttyNaux (struct Cmd *, char *);
-static int ttyR (struct Cmd *);
-static int winN (struct Cmd *, int, int);
-static int winR (struct Cmd *);
-static int winX (int);
-
-
-int
-main (int argc, char **argv)
-{
- int id = 0, scansw = 0, vmh1 = 0, vmh2 = 0;
- char *cp, *file = NULL, *folder = NULL;
- char **argp, **arguments, buf[BUFSIZ];
-
- if (nmh_init(argv[0], 1)) { return 1; }
-
- mts_init (invo_name);
- arguments = getarguments (invo_name, argc,argv, 1);
- argp = arguments;
-
- while ((cp = *argp++)) {
- if (*cp == '-')
- switch (smatch (++cp, switches)) {
- case AMBIGSW:
- ambigsw (cp, switches);
- done (1);
- case UNKWNSW:
- adios (NULL, "-%s unknown", cp);
-
- case HELPSW:
- snprintf (buf, sizeof(buf), "%s [switches] file", invo_name);
- print_help (buf, switches, 1);
- done (0);
- case VERSIONSW:
- print_version(invo_name);
- done (0);
-
- case IDSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- if ((id = atoi (cp)) < 1)
- adios (NULL, "bad argument %s %s", argp[-2], cp);
- continue;
- case FDSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- if ((pfd = atoi (cp)) <= 1)
- adios (NULL, "bad argument %s %s", argp[-2], cp);
- continue;
- case QDSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- if ((ppid = atoi (cp)) <= 1)
- adios (NULL, "bad argument %s %s", argp[-2], cp);
- continue;
- case NMSW:
- if (!(myname = *argp++) || *myname == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- continue;
-
- case SCANSW:
- scansw++;
- continue;
- case NSCANSW:
- scansw = 0;
- continue;
-
- case PRMPTSW:
- if (!(myprompt = *argp++) || *myprompt == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- continue;
-
- case READSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- if ((vmh1 = atoi (cp)) < 1)
- adios (NULL, "bad argument %s %s", argp[-2], cp);
- continue;
- case WRITESW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- if ((vmh2 = atoi (cp)) < 1)
- adios (NULL, "bad argument %s %s", argp[-2], cp);
- continue;
-
- case PREADSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- continue;
- case PWRITSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- continue;
-
- case TCURSW:
- topcur++;
- continue;
- case NTCURSW:
- topcur = 0;
- continue;
- }
- if (*cp == '+' || *cp == '@') {
- if (folder)
- adios (NULL, "only one folder at a time!");
- else
- folder = pluspath (cp);
- }
- else
- if (file)
- adios (NULL, "only one file at a time!");
- else
- file = cp;
- }
-
- if (!file && !folder)
- file = "./msgbox";
- if (file && folder)
- adios (NULL, "use a file or a folder, not both");
- strncpy (myfilter, etcpath (mhlforward), sizeof(myfilter));
-#ifdef FIOCLEX
- if (pfd > 1)
- ioctl (pfd, FIOCLEX, NULL);
-#endif /* FIOCLEX */
-
- istat = SIGNAL2 (SIGINT, intrser);
- qstat = SIGNAL2 (SIGQUIT, quitser);
-
- sc_width (); /* MAGIC... */
-
- if ((vmh = vmh1 && vmh2)) {
- rcinit (vmh1, vmh2);
- pINI ();
- SIGNAL (SIGINT, SIG_IGN);
- SIGNAL (SIGQUIT, SIG_IGN);
-#ifdef SIGTSTP
- tstat = SIGNAL (SIGTSTP, SIG_IGN);
-#endif /* SIGTSTP */
- }
-
- if (folder)
- fsetup (folder);
- else
- setup (file);
- readids (id);
- display_info (id > 0 ? scansw : 0);
-
- msh (id > 0 ? scansw : 0);
- scan_finished ();
-
- m_reset ();
-
- done (0);
- return 1;
-}
-
-
-#define MSHCMDS_SWITCHES \
- X("advance", -7, ADVCMD) \
- X("ali", 0, ALICMD) \
- X("burst", 0, EXPLCMD) \
- X("comp", 0, COMPCMD) \
- X("dist", 0, DISTCMD) \
- X("exit", 0, EXITCMD) \
- X("folder", 0, FOLDCMD) \
- X("forw", 0, FORWCMD) \
- X("help", 0, HELPCMD) \
- X("inc", 0, INCMD) \
- X("mark", 0, MARKCMD) \
- X("mhmail", 0, MAILCMD) \
- X("mhn", 0, MHNCMD) \
- X("msgchk", 0, MSGKCMD) \
- X("next", 0, NEXTCMD) \
- X("packf", 0, PACKCMD) \
- X("pick", 0, PICKCMD) \
- X("prev", 0, PREVCMD) \
- X("quit", 0, QUITCMD) \
- X("refile", 0, FILECMD) \
- X("repl", 0, REPLCMD) \
- X("rmm", 0, RMMCMD) \
- X("scan", 0, SCANCMD) \
- X("send", 0, SENDCMD) \
- X("show", 0, SHOWCMD) \
- X("sortm", 0, SORTCMD) \
- X("whatnow", 0, WHATCMD) \
- X("whom", 0, WHOMCMD) \
-
-#define X(sw, minchars, id) id,
-DEFINE_SWITCH_ENUM(MSHCMDS);
-#undef X
-
-#define X(sw, minchars, id) { sw, minchars, id },
-DEFINE_SWITCH_ARRAY(MSHCMDS, mshcmds);
-#undef X
-
-
-static void
-msh (int scansw)
-{
- int i;
- register char *cp, **ap;
- char prompt[BUFSIZ], *vec[MAXARGS];
- struct Cmd typein;
- register struct Cmd *cmdp;
- static int once_only = ADVCMD;
-
- snprintf (prompt, sizeof(prompt), myprompt, invo_name);
- cmdp = &typein;
-
- for (;;) {
- if (yp) {
- fclose (yp);
- yp = NULL;
- }
- if (vmh) {
- if ((i = getcmds (mshcmds, cmdp, scansw)) == EOF) {
- rcdone ();
- return;
- }
- } else {
- check_folder (scansw);
- if ((i = getargs (prompt, mshcmds, cmdp)) == EOF) {
- putchar ('\n');
- return;
- }
- }
- cmd_name = mshcmds[i].sw;
-
- switch (i) {
- case QUITCMD:
- quit ();
- return;
-
- case ADVCMD:
- if (once_only == ADVCMD)
- once_only = i = SHOWCMD;
- else
- i = mp->curmsg != mp->hghmsg ? NEXTCMD : EXITCMD;
- cmd_name = mshcmds[i].sw;
- /* and fall... */
-
- case EXITCMD:
- case EXPLCMD:
- case FOLDCMD:
- case FORWCMD: /* sigh */
- case MARKCMD:
- case NEXTCMD:
- case PACKCMD:
- case PICKCMD:
- case PREVCMD:
- case RMMCMD:
- case SHOWCMD:
- case SCANCMD:
- case SORTCMD:
- if ((cp = context_find (cmd_name))) {
- cp = getcpy (cp);
- ap = brkstring (cp, " ", "\n");
- ap = copyip (ap, vec, MAXARGS);
- } else {
- ap = vec;
- }
- break;
-
- default:
- cp = NULL;
- ap = vec;
- break;
- }
- copyip (cmdp->args + 1, ap, MAXARGS);
-
- m_init ();
-
- if (!vmh && init_io (cmdp, vmh) == NOTOK) {
- if (cp != NULL)
- free (cp);
- continue;
- }
- modified = 0;
- redirected = vmh || cmdp->direction != STDIO;
-
- switch (i) {
- case ALICMD:
- case COMPCMD:
- case INCMD:
- case MAILCMD:
- case MSGKCMD:
- case SENDCMD:
- case WHATCMD:
- case WHOMCMD:
- if (!vmh || ttyN (cmdp) != NOTOK)
- forkcmd (vec, cmd_name);
- break;
-
- case DISTCMD:
- if (!vmh || ttyN (cmdp) != NOTOK)
- distcmd (vec);
- break;
-
- case EXPLCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- explcmd (vec);
- break;
-
- case FILECMD:
- if (!vmh
- || (filehak (vec) == OK ? ttyN (cmdp)
- : winN (cmdp, DISPLAY, 1)) != NOTOK)
- filecmd (vec);
- break;
-
- case FOLDCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- foldcmd (vec);
- break;
-
- case FORWCMD:
- if (!vmh || ttyN (cmdp) != NOTOK)
- forwcmd (vec);
- break;
-
- case HELPCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- helpcmd (vec);
- break;
-
- case EXITCMD:
- case MARKCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- markcmd (vec);
- break;
-
- case MHNCMD:
- if (!vmh || ttyN (cmdp) != NOTOK)
- mhncmd (vec);
- break;
-
- case NEXTCMD:
- case PREVCMD:
- case SHOWCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- showcmd (vec);
- break;
-
- case PACKCMD:
- if (!vmh
- || (packhak (vec) == OK ? ttyN (cmdp)
- : winN (cmdp, DISPLAY, 1)) != NOTOK)
- packcmd (vec);
- break;
-
- case PICKCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- pickcmd (vec);
- break;
-
- case REPLCMD:
- if (!vmh || ttyN (cmdp) != NOTOK)
- replcmd (vec);
- break;
-
- case RMMCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- rmmcmd (vec);
- break;
-
- case SCANCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- scancmd (vec);
- break;
-
- case SORTCMD:
- if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
- sortcmd (vec);
- break;
-
- default:
- padios (NULL, "no dispatch for %s", cmd_name);
- }
-
- if (vmh) {
- if (vmhtty != NOTOK)
- ttyR (cmdp);
- if (vmhpid > OK)
- winR (cmdp);
- }
- else
- fin_io (cmdp, vmh);
- if (cp != NULL)
- free (cp);
- if (i == EXITCMD) {
- quit ();
- return;
- }
- }
-}
-
-
-void
-fsetup (char *folder)
-{
- register int msgnum;
- char *maildir;
- struct stat st;
-
- maildir = m_maildir (folder);
- if (chdir (maildir) == NOTOK)
- padios (maildir, "unable to change directory to");
-
- /* read folder and create message structure */
- if (!(mp = folder_read (folder, 0)))
- padios (NULL, "unable to read folder %s", folder);
-
- /* check for empty folder */
- if (mp->nummsg == 0)
- padios (NULL, "no messages in %s", folder);
-
- mode = m_gmprot ();
- mtime = stat (mp->foldpath, &st) != NOTOK ? st.st_mtime : 0;
-
- m_gMsgs (mp->hghmsg);
-
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) {
- Msgs[msgnum].m_bboard_id = 0;
- Msgs[msgnum].m_top = NOTOK;
- Msgs[msgnum].m_start = Msgs[msgnum].m_stop = 0L;
- Msgs[msgnum].m_scanl = NULL;
- }
-
- m_init ();
-
- fmsh = getcpy (folder);
-
- maxfds = OPEN_MAX / 2;
-
- if ((maxfds -= 2) < 1)
- maxfds = 1;
-}
-
-
-void
-setup (char *file)
-{
- int i, msgp;
- struct stat st;
- if ((fp = fopen (file, "r")) == NULL)
- padios (file, "unable to read");
-#ifdef FIOCLEX
- ioctl (fileno (fp), FIOCLEX, NULL);
-#endif /* FIOCLEX */
- if (fstat (fileno (fp), &st) != NOTOK) {
- mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
- msgp = read_map (file, (long) st.st_size);
- }
- else {
- mode = m_gmprot (), mtime = 0;
- msgp = 0;
- }
-
- if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
- padios (NULL, "no messages in %s", myname ? myname : file);
-
- if (!(mp = (struct msgs *) calloc ((size_t) 1, sizeof(*mp))))
- padios (NULL, "unable to allocate folder storage");
-
- if (!(mp->msgstats = calloc ((size_t) msgp + 3, sizeof(*(mp->msgstats)))))
- padios (NULL, "unable to allocate message status storage");
-
- mp->hghmsg = msgp;
- mp->nummsg = msgp;
- mp->lowmsg = 1;
- mp->curmsg = 0;
- mp->foldpath = getcpy (myname ? myname : file);
- clear_folder_flags (mp);
-
- stat (file, &st);
- if (st.st_uid != getuid () || access (file, W_OK) == NOTOK)
- set_readonly (mp);
-
- mp->lowoff = 1;
- mp->hghoff = mp->hghmsg + 1;
-
- for (i = mp->lowmsg; i <= mp->hghmsg; i++) {
- clear_msg_flags (mp, i);
- set_exists (mp, i);
- }
- m_init ();
-
- svector_push_back (mp->msgattrs, getcpy ("unseen"));
-
- scan_detect_mbox_style (fp); /* the MAGIC invocation */
- if (fmsh) {
- free (fmsh);
- fmsh = NULL;
- }
-}
-
-
-static int
-read_map (char *file, long size)
-{
- register int i, msgp;
- register struct drop *dp, *mp;
- struct drop *rp;
-
- if ((i = map_read (file, size, &rp, 1)) == 0)
- return 0;
-
- m_gMsgs (i);
-
- msgp = 1;
- for (dp = rp + 1; i-- > 0; msgp++, dp++) {
- mp = &Msgs[msgp].m_drop;
- mp->d_id = dp->d_id;
- mp->d_size = dp->d_size;
- mp->d_start = dp->d_start;
- mp->d_stop = dp->d_stop;
- Msgs[msgp].m_scanl = NULL;
- }
- free ((char *) rp);
-
- return (msgp - 1);
-}
-
-
-static int
-read_file (long pos, int msgp)
-{
- register int i;
- register struct drop *dp, *mp;
- struct drop *rp;
-
- if ((i = mbx_read (fp, pos, &rp, 1)) <= 0)
- return (msgp - 1);
-
- m_gMsgs ((msgp - 1) + i);
-
- for (dp = rp; i-- > 0; msgp++, dp++) {
- mp = &Msgs[msgp].m_drop;
- mp->d_id = 0;
- mp->d_size = dp->d_size;
- mp->d_start = dp->d_start;
- mp->d_stop = dp->d_stop;
- Msgs[msgp].m_scanl = NULL;
- }
- free ((char *) rp);
-
- return (msgp - 1);
-}
-
-
-static void
-m_gMsgs (int n)
-{
- int nmsgs;
-
- if (Msgs == NULL) {
- nMsgs = n + MAXFOLDER / 2;
- Msgs = (struct Msg *) calloc ((size_t) (nMsgs + 2), sizeof *Msgs);
- if (Msgs == NULL)
- padios (NULL, "unable to allocate Msgs structure");
- return;
- }
-
- if (nMsgs >= n)
- return;
-
- nmsgs = nMsgs + n + MAXFOLDER / 2;
- Msgs = (struct Msg *) mh_xrealloc ((char *) Msgs, (size_t) (nmsgs + 2) * sizeof *Msgs);
- memset((char *) (Msgs + nMsgs + 2), 0, (size_t) ((nmsgs - nMsgs) * sizeof *Msgs));
-
- nMsgs = nmsgs;
-}
-
-
-FILE *
-msh_ready (int msgnum, int full)
-{
- register int msgp;
- int fd;
- char *cp;
- NMH_UNUSED (full);
-
- if (yp) {
- fclose (yp);
- yp = NULL;
- }
-
- if (fmsh) {
- if ((fd = Msgs[msgnum].m_top) == NOTOK) {
- if (numfds >= maxfds)
- for (msgp = mp->lowmsg; msgp <= mp->hghmsg; msgp++)
- if (Msgs[msgp].m_top != NOTOK) {
- close (Msgs[msgp].m_top);
- Msgs[msgp].m_top = NOTOK;
- numfds--;
- break;
- }
-
- if ((fd = open (cp = m_name (msgnum), O_RDONLY)) == NOTOK)
- padios (cp, "unable to open message");
- Msgs[msgnum].m_top = fd;
- numfds++;
- }
-
- if ((fd = dup (fd)) == NOTOK)
- padios ("cached message", "unable to dup");
- if ((yp = fdopen (fd, "r")) == NULL)
- padios (NULL, "unable to fdopen cached message");
- fseek (yp, 0L, SEEK_SET);
- return yp;
- }
-
- scan_reset_m_getfld_state ();
- scan_eom_action ((int (*)()) 0); /* XXX */
- fseek (fp, Msgs[msgnum].m_start, SEEK_SET);
- return fp;
-}
-
-
-static int
-check_folder (int scansw)
-{
- int seqnum, i, low, hgh, msgp;
- struct stat st;
-
- if (fmsh) {
- if (stat (mp->foldpath, &st) == NOTOK)
- padios (mp->foldpath, "unable to stat");
- if (mtime == st.st_mtime)
- return 0;
- mtime = st.st_mtime;
-
- low = mp->hghmsg + 1;
- folder_free (mp); /* free folder/message structure */
-
- if (!(mp = folder_read (fmsh, 0)))
- padios (NULL, "unable to re-read folder %s", fmsh);
-
- hgh = mp->hghmsg;
-
- for (msgp = mp->lowmsg; msgp <= mp->hghmsg; msgp++) {
- if (Msgs[msgp].m_top != NOTOK) {
- close (Msgs[msgp].m_top);
- Msgs[msgp].m_top = NOTOK;
- numfds--;
- }
- if (Msgs[msgp].m_scanl) {
- free (Msgs[msgp].m_scanl);
- Msgs[msgp].m_scanl = NULL;
- }
- }
-
- m_init ();
-
- if (modified || low > hgh)
- return 1;
- goto check_vmh;
- }
- if (fstat (fileno (fp), &st) == NOTOK)
- padios (mp->foldpath, "unable to fstat");
- if (mtime == st.st_mtime)
- return 0;
- mode = (int) (st.st_mode & 0777);
- mtime = st.st_mtime;
-
- if ((msgp = read_file (Msgs[mp->hghmsg].m_stop, mp->hghmsg + 1)) < 1)
- padios (NULL, "no messages in %s", mp->foldpath); /* XXX */
- if (msgp >= MAXFOLDER)
- padios (NULL, "more than %d messages in %s", MAXFOLDER,
- mp->foldpath);
- if (msgp <= mp->hghmsg)
- return 0; /* XXX */
-
- if (!(mp = folder_realloc (mp, mp->lowoff, msgp)))
- padios (NULL, "unable to allocate folder storage");
-
- low = mp->hghmsg + 1, hgh = msgp;
- seqnum = scansw ? seq_getnum (mp, "unseen") : -1;
- for (i = mp->hghmsg + 1; i <= msgp; i++) {
- set_exists(mp, i);
- if (seqnum != -1)
- add_sequence(mp, seqnum, i);
- mp->nummsg++;
- }
- mp->hghmsg = msgp;
- m_init ();
-
-check_vmh: ;
- if (vmh)
- return 1;
-
- advise (NULL, "new messages have arrived!\007");
- if (scansw)
- scanrange (low, hgh);
-
- return 1;
-}
-
-
-static void
-scanrange (int low, int hgh)
-{
- char buffer[BUFSIZ];
-
- snprintf (buffer, sizeof(buffer), "%d-%d", low, hgh);
- scanstring (buffer);
-}
-
-
-static void
-scanstring (char *arg)
-{
- char *cp, **ap, *vec[MAXARGS];
-
- /*
- * This should be replace with a call to getarguments()
- */
- if ((cp = context_find (cmd_name = "scan"))) {
- cp = getcpy (cp);
- ap = brkstring (cp, " ", "\n");
- ap = copyip (ap, vec, MAXARGS);
- } else {
- ap = vec;
- }
- *ap++ = arg;
- *ap = NULL;
- m_init ();
- scancmd (vec);
- if (cp != NULL)
- free (cp);
-}
-
-
-void
-readids (int id)
-{
- register int cur, seqnum, i=0, msgnum;
-
- if (mp->curmsg == 0)
- seq_setcur (mp, mp->lowmsg);
- if (id <= 0 || (seqnum = seq_getnum (mp, "unseen")) == -1)
- return;
-
- for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--)
- add_sequence(mp, seqnum, msgnum);
-
- if (id != 1) {
- cur = mp->curmsg;
-
- for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--)
- if (does_exist(mp, msgnum)) /* FIX */
- if ((i = readid (msgnum)) > 0 && i < id) {
- cur = msgnum + 1;
- clear_sequence(mp, seqnum, msgnum);
- break;
- }
- for (i = mp->lowmsg; i < msgnum; i++)
- clear_sequence(mp, seqnum, i);
-
- if (cur > mp->hghmsg)
- cur = mp->hghmsg;
-
- seq_setcur (mp, cur);
- }
-
- if ((gap = 1 < id && id < (i = readid (mp->lowmsg)) ? id : 0) && !vmh)
- advise (NULL, "gap in ID:s, last seen %d, lowest present %d\n",
- id - 1, i);
-}
-
-
-int
-readid (int msgnum)
-{
- int i, state;
- char *bp, buf[BUFSIZ], name[NAMESZ];
- register FILE *zp;
-
- if (Msgs[msgnum].m_bboard_id)
- return Msgs[msgnum].m_bboard_id;
-
- zp = msh_ready (msgnum, 0);
- for (;;) {
- int bufsz = sizeof buf;
- switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) {
- case FLD:
- case FLDPLUS:
- if (!strcasecmp (name, BBoard_ID)) {
- bp = getcpy (buf);
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, zp);
- bp = add (buf, bp);
- }
- i = atoi (bp);
- free (bp);
- if (i > 0)
- return (Msgs[msgnum].m_bboard_id = i);
- else
- continue;
- }
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, zp);
- }
- continue;
-
- default:
- return 0;
- }
- }
-}
-
-
-void
-display_info (int scansw)
-{
- int seqnum, sd;
-
- interactive = isatty (fileno (stdout));
- if (sp == NULL) {
- if ((sd = dup (fileno (stdout))) == NOTOK)
- padios ("standard output", "unable to dup");
-#ifdef FIOCLEX
- ioctl (sd, FIOCLEX, NULL);
-#endif /* FIOCLEX */
- if ((sp = fdopen (sd, "w")) == NULL)
- padios ("standard output", "unable to fdopen");
- }
-
- m_putenv ("mhfolder", mp->foldpath);
- if (vmh)
- return;
-
- if (myname) {
- printf ("Reading ");
- if (SOprintf ("%s", myname))
- printf ("%s", myname);
- printf (", currently at message %d of %d\n",
- mp->curmsg, mp->hghmsg);
- }
- else {
- printf ("Reading ");
- if (fmsh)
- printf ("+%s", fmsh);
- else
- printf ("%s", mp->foldpath);
- printf (", currently at message %d of %d\n",
- mp->curmsg, mp->hghmsg);
- }
-
- if (((seqnum = seq_getnum (mp, "unseen")) != -1)
- && scansw
- && in_sequence(mp, seqnum, mp->hghmsg))
- scanstring ("unseen");
-}
-
-
-static void
-write_ids (void)
-{
- int i = 0, seqnum, msgnum;
- char buffer[80];
-
- if (pfd <= 1)
- return;
-
- if ((seqnum = seq_getnum (mp, "unseen")) != -1)
- for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--)
- if (!in_sequence(mp, seqnum, msgnum)) {
- if (Msgs[msgnum].m_bboard_id == 0)
- readid (msgnum);
- if ((i = Msgs[msgnum].m_bboard_id) > 0)
- break;
- }
-
- snprintf (buffer, sizeof(buffer), "%d %d\n", i, Msgs[mp->hghmsg].m_bboard_id);
- write (pfd, buffer, sizeof(buffer));
- close (pfd);
- pfd = NOTOK;
-}
-
-
-static void
-quit (void)
-{
- int i, md, msgnum;
- char *cp, tmpfil[BUFSIZ];
- char map1[BUFSIZ], map2[BUFSIZ];
- struct stat st;
- FILE *dp;
- int failed_to_lock = 0;
-
- if (!(mp->msgflags & MODIFIED) || is_readonly(mp) || fmsh) {
- if (vmh)
- rc2peer (RC_FIN, 0, NULL);
- return;
- }
-
- if (vmh)
- ttyNaux (NULLCMD, "FAST");
- cp = NULL;
- if ((dp = lkfopendata (mp->foldpath, "r", &failed_to_lock)) == NULL) {
- advise (mp->foldpath, "unable to lock");
- if (vmh) {
- ttyR (NULLCMD);
- pFIN ();
- }
- return;
- }
- if (fstat (fileno (dp), &st) == NOTOK) {
- advise (mp->foldpath, "unable to stat");
- goto release;
- }
- if (mtime != st.st_mtime) {
- advise (NULL, "new messages have arrived, no update");
- goto release;
- }
- mode = (int) (st.st_mode & 0777);
-
- if (mp->nummsg == 0) {
- cp = concat ("Zero file \"", mp->foldpath, "\"? ", NULL);
- if (getanswer (cp)) {
- if ((i = creat (mp->foldpath, mode)) != NOTOK)
- close (i);
- else
- advise (mp->foldpath, "error zero'ing");
- (void) m_unlink (map_name (mp->foldpath));/* XXX */
- }
- goto release;
- }
-
- cp = concat ("Update file \"", mp->foldpath, "\"? ", NULL);
- if (!getanswer (cp))
- goto release;
- strncpy (tmpfil, m_backup (mp->foldpath), sizeof(tmpfil));
- if ((md = mbx_open (tmpfil, mbx_style, st.st_uid, st.st_gid, mode)) == NOTOK) {
- advise (tmpfil, "unable to open");
- goto release;
- }
-
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
- if (does_exist(mp, msgnum) && pack (tmpfil, md, msgnum) == NOTOK) {
- mbx_close (tmpfil, md);
- (void) m_unlink (tmpfil);
- (void) m_unlink (map_name (tmpfil));
- goto release;
- }
- mbx_close (tmpfil, md);
-
- if (rename (tmpfil, mp->foldpath) == NOTOK)
- admonish (mp->foldpath, "unable to rename %s to", tmpfil);
- else {
- strncpy (map1, map_name (tmpfil), sizeof(map1));
- strncpy (map2, map_name (mp->foldpath), sizeof(map2));
-
- if (rename (map1, map2) == NOTOK) {
- admonish (map2, "unable to rename %s to", map1);
- (void) m_unlink (map1);
- (void) m_unlink (map2);
- }
- }
-
-release: ;
- if (cp)
- free (cp);
- lkfclosedata (dp, mp->foldpath);
- if (vmh) {
- ttyR (NULLCMD);
- pFIN ();
- }
-}
-
-
-static int
-getargs (char *prompt, struct swit *sw, struct Cmd *cmdp)
-{
- int i;
- char *cp;
- static char buffer[BUFSIZ];
-
- told_to_quit = 0;
- for (;;) {
- interrupted = 0;
- if (interactive) {
- printf ("%s", prompt);
- fflush (stdout);
- }
- for (cp = buffer; (i = getchar ()) != '\n';) {
- if (interrupted && !told_to_quit) {
- buffer[0] = '\0';
- putchar ('\n');
- break;
- }
- if (told_to_quit || i == EOF) {
- if (ppid > 0)
-#ifdef SIGEMT
- kill (ppid, SIGEMT);
-#else
- kill (ppid, SIGTERM);
-#endif
- return EOF;
- }
- if (cp < &buffer[sizeof buffer - 2])
- *cp++ = i;
- }
- *cp = 0;
-
- if (buffer[0] == 0)
- continue;
- if (buffer[0] == '?') {
- printf ("commands:\n");
- print_sw (ALL, sw, "", stdout);
- printf ("type CTRL-D or use ``quit'' to leave %s\n",
- invo_name);
- continue;
- }
-
- if (parse (buffer, cmdp) == NOTOK)
- continue;
-
- switch (i = smatch (cmdp->args[0], sw)) {
- case AMBIGSW:
- ambigsw (cmdp->args[0], sw);
- continue;
- case UNKWNSW:
- printf ("say what: ``%s'' -- type ? (or help) for help\n",
- cmdp->args[0]);
- continue;
- default:
- return i;
- }
- }
-}
-
-
-static int
-getcmds (struct swit *sw, struct Cmd *cmdp, int scansw)
-{
- int i;
- struct record rcs, *rc;
-
- rc = &rcs;
- initrc (rc);
-
- for (;;)
- switch (peer2rc (rc)) {
- case RC_QRY:
- pQRY (rc->rc_data, scansw);
- break;
-
- case RC_CMD:
- if ((i = pCMD (rc->rc_data, sw, cmdp)) != NOTOK)
- return i;
- break;
-
- case RC_FIN:
- if (ppid > 0)
-#ifdef SIGEMT
- kill (ppid, SIGEMT);
-#else
- kill (ppid, SIGTERM);
-#endif
- return EOF;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pLOOP protocol screw-up");
- done (1);
- }
-}
-
-
-static int
-parse (char *buffer, struct Cmd *cmdp)
-{
- int argp = 0;
- char c, *cp, *pp;
-
- cmdp->line[0] = 0;
- pp = cmdp->args[argp++] = cmdp->line;
- cmdp->redirect = NULL;
- cmdp->direction = STDIO;
- cmdp->stream = NULL;
-
- for (cp = buffer; (c = *cp); cp++) {
- if (!isspace ((unsigned char) c))
- break;
- }
- if (c == '\0') {
- if (vmh)
- fmt2peer (RC_EOF, "null command");
- return NOTOK;
- }
-
- while ((c = *cp++)) {
- if (isspace ((unsigned char) c)) {
- while (isspace ((unsigned char) c))
- c = *cp++;
- if (c == 0)
- break;
- *pp++ = 0;
- cmdp->args[argp++] = pp;
- *pp = 0;
- }
-
- switch (c) {
- case '"':
- for (;;) {
- switch (c = *cp++) {
- case 0:
- padvise (NULL, "unmatched \"");
- return NOTOK;
- case '"':
- break;
- case QUOTE:
- if ((c = *cp++) == 0)
- goto no_quoting;
- default:
- *pp++ = c;
- continue;
- }
- break;
- }
- continue;
-
- case QUOTE:
- if ((c = *cp++) == 0) {
- no_quoting: ;
- padvise (NULL, "the newline character can not be quoted");
- return NOTOK;
- }
-
- default: ;
- *pp++ = c;
- continue;
-
- case '>':
- case '|':
- if (pp == cmdp->line) {
- padvise (NULL, "invalid null command");
- return NOTOK;
- }
- if (*cmdp->args[argp - 1] == 0)
- argp--;
- cmdp->direction = c == '>' ? CRTIO : PIPIO;
- if (cmdp->direction == CRTIO && (c = *cp) == '>') {
- cmdp->direction = APPIO;
- cp++;
- }
- cmdp->redirect = pp + 1;/* sigh */
- for (; (c = *cp); cp++)
- if (!isspace ((unsigned char) c))
- break;
- if (c == 0) {
- padvise (NULL, cmdp->direction != PIPIO
- ? "missing name for redirect"
- : "invalid null command");
- return NOTOK;
- }
- strcpy (cmdp->redirect, cp);
- if (cmdp->direction != PIPIO) {
- for (; *cp; cp++)
- if (isspace ((unsigned char) *cp)) {
- padvise (NULL, "bad name for redirect");
- return NOTOK;
- }
- if (expand (cmdp->redirect) == NOTOK)
- return NOTOK;
- }
- break;
- }
- break;
- }
-
- *pp++ = 0;
- cmdp->args[argp] = NULL;
-
- return OK;
-}
-
-
-int
-expand (char *redirect)
-{
- char *cp, *pp;
- char path[BUFSIZ];
- struct passwd *pw;
-
- if (*redirect != '~')
- return OK;
-
- if ((cp = strchr(pp = redirect + 1, '/')))
- *cp++ = 0;
- if (*pp == 0)
- pp = mypath;
- else
- if ((pw = getpwnam (pp)))
- pp = pw->pw_dir;
- else {
- padvise (NULL, "unknown user: %s", pp);
- return NOTOK;
- }
-
- snprintf (path, sizeof(path), "%s/%s", pp, cp ? cp : "");
- strcpy (redirect, path);
- return OK;
-}
-
-
-static int
-init_io (struct Cmd *cmdp, int vio)
-{
- int io, result;
-
- io = vmh;
-
- vmh = vio;
- result = initaux_io (cmdp);
- vmh = io;
-
- return result;
-}
-
-
-static int
-initaux_io (struct Cmd *cmdp)
-{
- char *mode;
-
- switch (cmdp->direction) {
- case STDIO:
- return OK;
-
- case CRTIO:
- case APPIO:
- mode = cmdp->direction == CRTIO ? "write" : "append";
- if ((cmdp->stream = fopen (cmdp->redirect, mode)) == NULL) {
- padvise (cmdp->redirect, "unable to %s ", mode);
- cmdp->direction = STDIO;
- return NOTOK;
- }
- break;
-
- case PIPIO:
- if ((cmdp->stream = popen (cmdp->redirect, "w")) == NULL) {
- padvise (cmdp->redirect, "unable to pipe");
- cmdp->direction = STDIO;
- return NOTOK;
- }
- SIGNAL (SIGPIPE, pipeser);
- broken_pipe = 0;
- break;
-
- default:
- padios (NULL, "unknown redirection for command");
- }
-
- fflush (stdout);
- if (dup2 (fileno (cmdp->stream), fileno (stdout)) == NOTOK)
- padios ("standard output", "unable to dup2");
- clearerr (stdout);
-
- return OK;
-}
-
-
-static void
-fin_io (struct Cmd *cmdp, int vio)
-{
- int io;
-
- io = vmh;
- vmh = vio;
- finaux_io (cmdp);
- vmh = io;
-}
-
-
-static void
-finaux_io (struct Cmd *cmdp)
-{
- switch (cmdp->direction) {
- case STDIO:
- return;
-
- case CRTIO:
- case APPIO:
- fflush (stdout);
- close (fileno (stdout));
- if (ferror (stdout))
- padvise (NULL, "problems writing %s", cmdp->redirect);
- fclose (cmdp->stream);
- break;
-
- case PIPIO:
- fflush (stdout);
- close (fileno (stdout));
- pclose (cmdp->stream);
- SIGNAL (SIGPIPE, SIG_DFL);
- break;
-
- default:
- padios (NULL, "unknown redirection for command");
- }
-
- if (dup2 (fileno (sp), fileno (stdout)) == NOTOK)
- padios ("standard output", "unable to dup2");
- clearerr (stdout);
-
- cmdp->direction = STDIO;
-}
-
-
-static void
-m_init (void)
-{
- int msgnum;
-
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
- unset_selected (mp, msgnum);
- mp->lowsel = mp->hghsel = mp->numsel = 0;
-}
-
-
-void
-m_reset (void)
-{
- write_ids ();
- folder_free (mp); /* free folder/message structure */
- myname = NULL;
-}
-
-
-void
-seq_setcur (struct msgs *mp, int msgnum)
-{
- if (mp->curmsg == msgnum)
- return;
-
- if (mp->curmsg && Msgs[mp->curmsg].m_scanl) {
- free (Msgs[mp->curmsg].m_scanl);
- Msgs[mp->curmsg].m_scanl = NULL;
- }
- if (Msgs[msgnum].m_scanl) {
- free (Msgs[msgnum].m_scanl);
- Msgs[msgnum].m_scanl = NULL;
- }
-
- mp->curmsg = msgnum;
-}
-
-
-
-static void
-intrser (int i)
-{
- NMH_UNUSED (i);
- discard (stdout);
- interrupted++;
-}
-
-
-static void
-pipeser (int i)
-{
- NMH_UNUSED (i);
- if (broken_pipe++ == 0)
- fprintf (stderr, "broken pipe\n");
- told_to_quit++;
- interrupted++;
-}
-
-
-static void
-quitser (int i)
-{
- NMH_UNUSED (i);
- told_to_quit++;
- interrupted++;
-}
-
-
-static void
-alrmser (int i)
-{
- NMH_UNUSED (i);
- longjmp (peerenv, DONE);
-}
-
-
-static int
-pINI (void)
-{
- int i, vrsn;
- char *bp;
- struct record rcs, *rc;
-
- rc = &rcs;
- initrc (rc);
-
- switch (peer2rc (rc)) {
- case RC_INI:
- bp = rc->rc_data;
- while (isspace ((unsigned char) *bp))
- bp++;
- if (sscanf (bp, "%d", &vrsn) != 1) {
- bad_init: ;
- fmt2peer (RC_ERR, "bad init \"%s\"", rc->rc_data);
- done (1);
- }
- if (vrsn != RC_VRSN) {
- fmt2peer (RC_ERR, "version %d unsupported", vrsn);
- done (1);
- }
-
- while (*bp && !isspace ((unsigned char) *bp))
- bp++;
- while (isspace ((unsigned char) *bp))
- bp++;
- if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0)
- goto bad_init;
- if (numwins > NWIN)
- numwins = NWIN;
-
- for (i = 1; i <= numwins; i++) {
- while (*bp && !isspace ((unsigned char) *bp))
- bp++;
- while (isspace ((unsigned char) *bp))
- bp++;
- if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0)
- goto bad_init;
- }
- rc2peer (RC_ACK, 0, NULL);
- return OK;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pINI protocol screw-up");
- done (1); /* NOTREACHED */
- }
-
- return 1; /* dead code to satisfy the compiler */
-}
-
-
-static int
-pQRY (char *str, int scansw)
-{
- NMH_UNUSED (str);
- if (pQRY1 (scansw) == NOTOK || pQRY2 () == NOTOK)
- return NOTOK;
-
- rc2peer (RC_EOF, 0, NULL);
- return OK;
-}
-
-
-static int
-pQRY1 (int scansw)
-{
- int oldhgh;
- static int lastlow = 0,
- lastcur = 0,
- lasthgh = 0,
- lastnum = 0;
-
- oldhgh = mp->hghmsg;
- if (check_folder (scansw) && oldhgh < mp->hghmsg) {
- switch (winX (STATUS)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- printf ("new messages have arrived!");
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- lastlow = lastcur = lasthgh = lastnum = 0;
- break;
- }
-
- switch (winX (DISPLAY)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- scanrange (oldhgh + 1, mp->hghmsg);
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- break;
- }
- return OK;
- }
-
- if (gap)
- switch (winX (STATUS)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- printf ("%s: gap in ID:s, last seen %d, lowest present %d\n",
- myname ? myname : fmsh ? fmsh : mp->foldpath, gap - 1,
- readid (mp->lowmsg));
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- gap = 0;
- return OK;
- }
-
- if (mp->lowmsg != lastlow
- || mp->curmsg != lastcur
- || mp->hghmsg != lasthgh
- || mp->nummsg != lastnum)
- switch (winX (STATUS)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- foldcmd (NULL);
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- lastlow = mp->lowmsg;
- lastcur = mp->curmsg;
- lasthgh = mp->hghmsg;
- lastnum = mp->nummsg;
- return OK;
- }
-
- return OK;
-}
-
-
-static int
-pQRY2 (void)
-{
- int i, j, k, msgnum, n;
- static int cur = 0,
- num = 0,
- lo = 0,
- hi = 0;
-
- if (mp->nummsg == 0 && mp->nummsg != num)
- switch (winX (SCAN)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- printf ("empty!");
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- num = mp->nummsg;
- return OK;
- }
- num = mp->nummsg;
-
- i = 0;
- j = (k = windows[SCAN]) / 2;
- for (msgnum = mp->curmsg; msgnum <= mp->hghmsg; msgnum++)
- if (does_exist (mp, msgnum))
- i++;
- if (i-- > 0) {
- if (topcur)
- k = i >= k ? 1 : k - i;
- else
- k -= i > j ? j : i;
- }
-
- i = j = 0;
- n = 1;
- for (msgnum = mp->curmsg; msgnum >= mp->lowmsg; msgnum--)
- if (does_exist (mp, msgnum)) {
- i = msgnum;
- if (j == 0)
- j = msgnum;
- if (n++ >= k)
- break;
- }
- for (msgnum = mp->curmsg + 1; msgnum <= mp->hghmsg; msgnum++)
- if (does_exist (mp, msgnum)) {
- if (i == 0)
- i = msgnum;
- j = msgnum;
- if (n++ >= windows[SCAN])
- break;
- }
- if (!topcur
- && lo > 0
- && hi > 0
- && does_exist (mp, lo)
- && does_exist (mp, hi)
- && (lo < mp->curmsg
- || (lo == mp->curmsg && lo == mp->lowmsg))
- && (mp->curmsg < hi
- || (hi == mp->curmsg && hi == mp->hghmsg))
- && hi - lo == j - i)
- i = lo, j = hi;
-
- if (mp->curmsg != cur || modified)
- switch (winN (NULLCMD, SCAN, 0)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- return OK;
-
- default:
- scanrange (lo = i, hi = j);
- cur = mp->curmsg;
- winR (NULLCMD);
- return OK;
- }
-
- return OK;
-}
-
-
-static int
-pCMD (char *str, struct swit *sw, struct Cmd *cmdp)
-{
- int i;
-
- if (*str == '?')
- switch (winX (DISPLAY)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- printf ("commands:\n");
- print_sw (ALL, sw, "", stdout);
- printf ("type ``quit'' to leave %s\n", invo_name);
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- rc2peer (RC_EOF, 0, NULL);
- return NOTOK;
- }
-
- if (parse (str, cmdp) == NOTOK)
- return NOTOK;
-
- switch (i = smatch (cmdp->args[0], sw)) {
- case AMBIGSW:
- switch (winX (DISPLAY)) {
- case NOTOK:
- return NOTOK;
-
- case OK:
- ambigsw (cmdp->args[0], sw);
- fflush (stdout);
- fflush (stderr);
- _exit (0); /* NOTREACHED */
-
- default:
- rc2peer (RC_EOF, 0, NULL);
- return NOTOK;
- }
-
- case UNKWNSW:
- fmt2peer (RC_ERR,
- "say what: ``%s'' -- type ? (or help) for help",
- cmdp->args[0]);
- return NOTOK;
-
- default:
- return i;
- }
-}
-
-
-static int
-pFIN (void)
-{
- int status;
-
- switch (setjmp (peerenv)) {
- case OK:
- SIGNAL (SIGALRM, alrmser);
- alarm (ALARM);
-
- status = peerwait ();
-
- alarm (0);
- return status;
-
- default:
- return NOTOK;
- }
-}
-
-
-static int
-peerwait (void)
-{
- struct record rcs, *rc;
-
- rc = &rcs;
- initrc (rc);
-
- switch (peer2rc (rc)) {
- case RC_QRY:
- case RC_CMD:
- rc2peer (RC_FIN, 0, NULL);
- return OK;
-
- case RC_XXX:
- advise (NULL, "%s", rc->rc_data);
- return NOTOK;
-
- default:
- fmt2peer (RC_FIN, "pLOOP protocol screw-up");
- return NOTOK;
- }
-}
-
-
-static int
-ttyNaux (struct Cmd *cmdp, char *s)
-{
- struct record rcs, *rc;
-
- rc = &rcs;
- initrc (rc);
-
- if (cmdp && init_io (cmdp, vmh) == NOTOK)
- return NOTOK;
-
- /* XXX: fseek() too tricky for our own good */
- if (!fmsh)
- fseek (fp, 0L, SEEK_SET);
-
- vmhtty = NOTOK;
- switch (rc2rc (RC_TTY, s ? strlen (s) : 0, s, rc)) {
- case RC_ACK:
- vmhtty = OK; /* fall */
- case RC_ERR:
- break;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);/* NOTREACHED */
-
- default:
- fmt2peer (RC_ERR, "pTTY protocol screw-up");
- done (1); /* NOTREACHED */
- }
-
-#ifdef SIGTSTP
- SIGNAL (SIGTSTP, tstat);
-#endif
- return vmhtty;
-}
-
-
-static int
-ttyR (struct Cmd *cmdp)
-{
- struct record rcs, *rc;
-
- rc = &rcs;
-
-#ifdef SIGTSTP
- SIGNAL (SIGTSTP, SIG_IGN);
-#endif
-
- if (vmhtty != OK)
- return NOTOK;
-
- initrc (rc);
-
- if (cmdp)
- fin_io (cmdp, 0);
-
- vmhtty = NOTOK;
- switch (rc2rc (RC_EOF, 0, NULL, rc)) {
- case RC_ACK:
- rc2peer (RC_EOF, 0, NULL);
- return OK;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);/* NOTREACHED */
-
- default:
- fmt2peer (RC_ERR, "pTTY protocol screw-up");
- done (1); /* NOTREACHED */
- }
-
- return 1; /* dead code to satisfy compiler */
-}
-
-
-static int
-winN (struct Cmd *cmdp, int n, int eof)
-{
- int i, pd[2];
- char buffer[BUFSIZ];
- struct record rcs, *rc;
-
- rc = &rcs;
- if (vmhpid == NOTOK)
- return OK;
-
- initrc (rc);
-
- /* XXX: fseek() too tricky for our own good */
- if (!fmsh)
- fseek (fp, 0L, SEEK_SET);
-
- vmhpid = OK;
-
- snprintf (buffer, sizeof(buffer), "%d", n);
- switch (str2rc (RC_WIN, buffer, rc)) {
- case RC_ACK:
- break;
-
- case RC_ERR:
- return NOTOK;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- done (1);
- }
-
- if (pipe (pd) == NOTOK) {
- err2peer (RC_ERR, "pipe", "unable to");
- return NOTOK;
- }
-
- switch (vmhpid = fork()) {
- case NOTOK:
- err2peer (RC_ERR, "fork", "unable to");
- close (pd[0]);
- close (pd[1]);
- return NOTOK;
-
- case OK:
- close (pd[1]);
- SIGNAL (SIGPIPE, SIG_IGN);
- while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
- switch (rc2rc (RC_DATA, i, buffer, rc)) {
- case RC_ACK:
- break;
-
- case RC_ERR:
- _exit (1);
-
- case RC_XXX:
- advise (NULL, "%s", rc->rc_data);
- _exit (2);
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- _exit (2);
- }
- if (i == OK)
- switch (rc2rc (RC_EOF, 0, NULL, rc)) {
- case RC_ACK:
- if (eof)
- rc2peer (RC_EOF, 0, NULL);
- i = 0;
- break;
-
- case RC_XXX:
- advise (NULL, "%s", rc->rc_data);
- i = 2;
- break;
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- i = 2;
- break;
- }
- if (i == NOTOK)
- err2peer (RC_ERR, "pipe", "error reading from");
- close (pd[0]);
- _exit (i != NOTOK ? i : 1);
-
- default:
- if ((vmhfd0 = dup (fileno (stdin))) == NOTOK)
- padios ("standard input", "unable to dup");
- if ((vmhfd1 = dup (fileno (stdout))) == NOTOK)
- padios ("standard output", "unable to dup");
- if ((vmhfd2 = dup (fileno (stderr))) == NOTOK)
- padios ("diagnostic output", "unable to dup");
-
- close (0);
- if ((i = open ("/dev/null", O_RDONLY)) != NOTOK && i != fileno (stdin)) {
- dup2 (i, fileno (stdin));
- close (i);
- }
-
- fflush (stdout);
- if (dup2 (pd[1], fileno (stdout)) == NOTOK)
- padios ("standard output", "unable to dup2");
- clearerr (stdout);
-
- fflush (stderr);
- if (dup2 (pd[1], fileno (stderr)) == NOTOK)
- padios ("diagnostic output", "unable to dup2");
- clearerr (stderr);
-
- if (cmdp && init_io (cmdp, 0) == NOTOK)
- return NOTOK;
- pstat = SIGNAL (SIGPIPE, pipeser);
- broken_pipe = 1;
-
- close (pd[0]);
- close (pd[1]);
-
- return vmhpid;
- }
-}
-
-
-static int
-winR (struct Cmd *cmdp)
-{
- int status;
-
- if (vmhpid <= OK)
- return NOTOK;
-
- if (cmdp)
- fin_io (cmdp, 0);
-
- if (dup2 (vmhfd0, fileno (stdin)) == NOTOK)
- padios ("standard input", "unable to dup2");
- clearerr (stdin);
- close (vmhfd0);
-
- fflush (stdout);
- if (dup2 (vmhfd1, fileno (stdout)) == NOTOK)
- padios ("standard output", "unable to dup2");
- clearerr (stdout);
- close (vmhfd1);
-
- fflush (stderr);
- if (dup2 (vmhfd2, fileno (stderr)) == NOTOK)
- padios ("diagnostic output", "unable to dup2");
- clearerr (stderr);
- close (vmhfd2);
-
- SIGNAL (SIGPIPE, pstat);
-
- if ((status = pidwait (vmhpid, OK)) == 2)
- done (1);
-
- vmhpid = OK;
- return (status == 0 ? OK : NOTOK);
-}
-
-
-static int
-winX (int n)
-{
- int i, pid, pd[2];
- char buffer[BUFSIZ];
- struct record rcs, *rc;
-
- rc = &rcs;
- initrc (rc);
-
- /* XXX: fseek() too tricky for our own good */
- if (!fmsh)
- fseek (fp, 0L, SEEK_SET);
-
- snprintf (buffer, sizeof(buffer), "%d", n);
- switch (str2rc (RC_WIN, buffer, rc)) {
- case RC_ACK:
- break;
-
- case RC_ERR:
- return NOTOK;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- done (1);
- }
-
- if (pipe (pd) == NOTOK) {
- err2peer (RC_ERR, "pipe", "unable to");
- return NOTOK;
- }
-
- switch (pid = fork ()) {
- case NOTOK:
- err2peer (RC_ERR, "fork", "unable to");
- close (pd[0]);
- close (pd[1]);
- return NOTOK;
-
- case OK:
- close (fileno (stdin));
- if ((i = open ("/dev/null", O_RDONLY)) != NOTOK && i != fileno (stdin)) {
- dup2 (i, fileno (stdin));
- close (i);
- }
- dup2 (pd[1], fileno (stdout));
- dup2 (pd[1], fileno (stderr));
- close (pd[0]);
- close (pd[1]);
- vmhpid = NOTOK;
- return OK;
-
- default:
- close (pd[1]);
- while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
- switch (rc2rc (RC_DATA, i, buffer, rc)) {
- case RC_ACK:
- break;
-
- case RC_ERR:
- close (pd[0]);
- pidwait (pid, OK);
- return NOTOK;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- done (1);
- }
- if (i == OK)
- switch (rc2rc (RC_EOF, 0, NULL, rc)) {
- case RC_ACK:
- break;
-
- case RC_XXX:
- padios (NULL, "%s", rc->rc_data);
-
- default:
- fmt2peer (RC_ERR, "pWIN protocol screw-up");
- done (1);
- }
- if (i == NOTOK)
- err2peer (RC_ERR, "pipe", "error reading from");
-
- close (pd[0]);
- pidwait (pid, OK);
- return (i != NOTOK ? pid : NOTOK);
- }
-}
-
-
-void
-padios (char *what, char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- if (vmh) {
- verr2peer (RC_FIN, what, fmt, ap);
- rcdone ();
- } else {
- advertise (what, NULL, fmt, ap);
- }
- va_end(ap);
-
- done (1);
-}
-
-
-void
-padvise (char *what, char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- if (vmh) {
- verr2peer (RC_ERR, what, fmt, ap);
- } else {
- advertise (what, NULL, fmt, ap);
- }
- va_end(ap);
-}
+++ /dev/null
-
-/*
- * 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 <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 *);
-
-/*
- * 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 *);
-
-extern m_getfld_state_t gstate; /* use the gstate in scansbr.c */
-
-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++;
- }
-}
-
-
-#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
-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);
-}
-
-
-#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
-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;
-}
-
-
-#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
-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;
-}
-
-
-#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
-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");
- }
-}
-
-
-#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
-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);
- scan_eom_action ((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;
- }
-
- (void) m_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;
- NMH_UNUSED (args);
-
- for (i = 0; hlpmsg[i]; i++) {
- printf (hlpmsg[i], invo_name);
- putchar ('\n');
- }
-}
-
-
-#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;
- size_t 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) *bvector_bits (msgstat (mp,
- msgnum)),
- seq_bits (mp)));
- if (Msgs[msgnum].m_scanl)
- printf ("%s", Msgs[msgnum].m_scanl);
- }
- }
-}
-
-
-#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
-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 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);
-}
-
-
-#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;
-
-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;
-}
-
-
-#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;
- size_t 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");
-}
-
-
-#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
-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);
-}
-
-
-#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
-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++;
-}
-
-
-#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
-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)
- nmh_clear_screen ();
-}
-
-
-#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
-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 (!strcasecmp (cmd_name, "next"))
- mode = 1;
- else
- if (!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)
- 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);
- scan_eom_action ((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)
-{
- NMH_UNUSED (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)
- scan_eom_action (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;
-
- read (fileno (stdout), buf, sizeof buf);
-
- 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;
- char *bp, *dp, *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 (;;) {
- int bufsz = sizeof buf;
- switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
- case FLD:
- case FLDPLUS:
- /*
- * Check Content-Type field
- */
- if (!strcasecmp (name, TYPE_FIELD)) {
- int passno;
- char c;
-
- cp = add (buf, NULL);
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, fp);
- cp = add (buf, cp);
- }
- bp = cp;
- passno = 1;
-
-again:
- for (; isspace ((unsigned char) *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 = (strcasecmp (bp, "plain") != 0)))
- goto out;
- *dp = c;
- for (dp++; isspace ((unsigned char) *dp); dp++)
- continue;
- if (*dp) {
- if ((result = !uprf (dp, "charset")))
- goto out;
- dp += sizeof "charset" - 1;
- while (isspace ((unsigned char) *dp))
- dp++;
- if (*dp++ != '=')
- goto invalid;
- while (isspace ((unsigned char) *dp))
- dp++;
- if (*dp == '"') {
- if ((bp = strchr(++dp, '"')))
- *bp = '\0';
- } else {
- for (bp = dp; *bp; bp++)
- if (isspace ((unsigned char) *bp)) {
- *bp = '\0';
- break;
- }
- }
- } else {
- /* Default character set */
- dp = "US-ASCII";
- }
- /* Check the character set */
- result = !check_charset (dp, strlen (dp));
- } else {
- if (!(result = (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 (!strcasecmp (name, ENCODING_FIELD)) {
- cp = add (buf, NULL);
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, fp);
- cp = add (buf, cp);
- }
- for (bp = cp; isspace ((unsigned char) *bp); bp++)
- continue;
- for (dp = bp; istoken (*dp); dp++)
- continue;
- *dp = '\0';
- result = (strcasecmp (bp, "7bit")
- && strcasecmp (bp, "8bit")
- && 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) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, fp);
- }
- break;
-
- /*
- * We've passed the message header,
- * so message is just text.
- */
- default:
- return 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
-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 = bvector_create (0);
- bvector_copy (Msgs[msgnum].m_stats, msgstat (mp, msgnum));
- if (mp->curmsg == msgnum)
- bvector_set (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;
- }
- 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);
- }
-
- 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 (;;) {
- int bufsz = sizeof buf;
- switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) {
- case FLD:
- case FLDPLUS:
- if (!strcasecmp (name, datesw)) {
- bp = getcpy (buf);
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, 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 && !strcasecmp(name, subjsw)) {
- bp = getcpy (buf);
- while (state == FLDPLUS) {
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, 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 */
- bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, zp);
- }
- }
- continue;
-
- case BODY:
- 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 (!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)
- (void) m_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;
- }
-}