X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fmsh.c;fp=uip%2Fmsh.c;h=0000000000000000000000000000000000000000;hp=c2d4e1a64b197c2801acf00d5e3e989909d7816b;hb=916690191222433a6923a4be54b0d8f6ac01bd02;hpb=ecc90fb56b43863f4c33ed62da4abe898b17d7fb diff --git a/uip/msh.c b/uip/msh.c deleted file mode 100644 index c2d4e1a..0000000 --- a/uip/msh.c +++ /dev/null @@ -1,2395 +0,0 @@ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_TERMIOS_H -# include -#else -# ifdef HAVE_TERMIO_H -# include -# else -# include -# endif -#endif - -#include -#include -#include -#include -#include - -#define QUOTE '\\' /* sigh */ - -static struct swit switches[] = { -#define IDSW 0 - { "idstart number", -7 }, /* interface from bbc */ -#define FDSW 1 - { "idstop number", -6 }, /* .. */ -#define QDSW 2 - { "idquit number", -6 }, /* .. */ -#define NMSW 3 - { "idname BBoard", -6 }, /* .. */ -#define PRMPTSW 4 - { "prompt string", 0 }, -#define SCANSW 5 - { "scan", 0 }, -#define NSCANSW 6 - { "noscan", 0 }, -#define READSW 7 - { "vmhread fd", -7 }, -#define WRITESW 8 - { "vmhwrite fd", -8 }, -#define PREADSW 9 - { "popread fd", -7 }, -#define PWRITSW 10 - { "popwrite fd", -8 }, -#define TCURSW 11 - { "topcur", 0 }, -#define NTCURSW 12 - { "notopcur", 0 }, -#define VERSIONSW 13 - { "version", 0 }, -#define HELPSW 14 - { "help", 0 }, - { NULL, 0 } -}; - -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 */ - -#ifdef BSD42 -int should_intr; /* signal handler should interrupt call */ -jmp_buf sigenv; /* the environment pointer */ -#endif - -/* - * prototypes - */ -int SOprintf (char *, ...); /* from termsbr.c */ -int sc_width (void); /* from termsbr.c */ -void fsetup (char *); -void setup (char *); -FILE *msh_ready (int, int); -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 *, ...); - - -/* - * static prototypes - */ -static void msh (int); -static int read_map (char *, long); -static int read_file (long, int); - -static void m_gMsgs (int); -FILE *msh_ready (int, 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 RETSIGTYPE intrser (int); -static RETSIGTYPE pipeser (int); -static RETSIGTYPE quitser (int); -static RETSIGTYPE 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]; - -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); - - /* read user profile/context */ - context_read(); - - 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 (1); - case VERSIONSW: - print_version(invo_name); - done (1); - - 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 */ - -#ifdef BSD42 - should_intr = 0; -#endif /* BSD42 */ - 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); - - m_reset (); - - done (0); - return 1; -} - - -static struct swit mshcmds[] = { -#define ADVCMD 0 - { "advance", -7 }, -#define ALICMD 1 - { "ali", 0 }, -#define EXPLCMD 2 - { "burst", 0 }, -#define COMPCMD 3 - { "comp", 0 }, -#define DISTCMD 4 - { "dist", 0 }, -#define EXITCMD 5 - { "exit", 0 }, -#define FOLDCMD 6 - { "folder", 0 }, -#define FORWCMD 7 - { "forw", 0 }, -#define HELPCMD 8 - { "help", 0 }, -#define INCMD 9 - { "inc", 0 }, -#define MARKCMD 10 - { "mark", 0 }, -#define MAILCMD 11 - { "mhmail", 0 }, -#define MHNCMD 12 - { "mhn", 0 }, -#define MSGKCMD 13 - { "msgchk", 0 }, -#define NEXTCMD 14 - { "next", 0 }, -#define PACKCMD 15 - { "packf", 0 }, -#define PICKCMD 16 - { "pick", 0 }, -#define PREVCMD 17 - { "prev", 0 }, -#define QUITCMD 18 - { "quit", 0 }, -#define FILECMD 19 - { "refile", 0 }, -#define REPLCMD 20 - { "repl", 0 }, -#define RMMCMD 21 - { "rmm", 0 }, -#define SCANCMD 22 - { "scan", 0 }, -#define SENDCMD 23 - { "send", 0 }, -#define SHOWCMD 24 - { "show", 0 }, -#define SORTCMD 25 - { "sortm", 0 }, -#define WHATCMD 26 - { "whatnow", 0 }, -#define WHOMCMD 27 - { "whom", 0 }, - { NULL, 0 } -}; - - -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))) - 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 (); - - mp->msgattrs[0] = getcpy ("unseen"); - mp->msgattrs[1] = NULL; - - m_unknown (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; - - 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; - } - - m_eomsbr ((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))) - 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 (state = FLD;;) - switch (state = m_getfld (state, name, buf, sizeof(buf), zp)) { - case FLD: - case FLDEOF: - case FLDPLUS: - if (!mh_strcasecmp (name, BBoard_ID)) { - bp = getcpy (buf); - while (state == FLDPLUS) { - state = m_getfld (state, name, buf, sizeof(buf), 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) - state = m_getfld (state, name, buf, sizeof(buf), zp); - if (state != FLDEOF) - 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"); -#ifndef BSD42 /* XXX */ -#ifdef FIOCLEX - ioctl (sd, FIOCLEX, NULL); -#endif /* FIOCLEX */ -#endif /* not BSD42 */ - 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; - - 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 = lkfopen (mp->foldpath, "r")) == 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"); - 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); - unlink (tmpfil); - 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); - unlink (map1); - unlink (map2); - } - } - -release: ; - if (cp) - free (cp); - lkfclose (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; -#ifdef BSD42 - switch (setjmp (sigenv)) { - case OK: - should_intr = 1; - break; - - default: - should_intr = 0; - if (interrupted && !told_to_quit) { - putchar ('\n'); - continue; - } - if (ppid > 0) -#ifdef SIGEMT - kill (ppid, SIGEMT); -#else - kill (ppid, SIGTERM); -#endif - return EOF; - } -#endif /* BSD42 */ - if (interactive) { - printf ("%s", prompt); - fflush (stdout); - } - for (cp = buffer; (i = getchar ()) != '\n';) { -#ifndef BSD42 - 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; - } -#else /* BSD42 */ - if (i == EOF) - longjmp (sigenv, DONE); -#endif /* BSD42 */ - 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: -#ifdef BSD42 - should_intr = 0; -#endif /* BSD42 */ - 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; - unsigned char c, *cp; - char *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 (c)) - break; - } - if (c == '\0') { - if (vmh) - fmt2peer (RC_EOF, "null command"); - return NOTOK; - } - - while ((c = *cp++)) { - if (isspace (c)) { - while (isspace (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 (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 (*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 RETSIGTYPE -intrser (int i) -{ -#ifndef RELIABLE_SIGNALS - SIGNAL (SIGINT, intrser); -#endif - - discard (stdout); - interrupted++; - -#ifdef BSD42 - if (should_intr) - longjmp (sigenv, NOTOK); -#endif -} - - -static RETSIGTYPE -pipeser (int i) -{ -#ifndef RELIABLE_SIGNALS - SIGNAL (SIGPIPE, pipeser); -#endif - - if (broken_pipe++ == 0) - fprintf (stderr, "broken pipe\n"); - told_to_quit++; - interrupted++; - -#ifdef BSD42 - if (should_intr) - longjmp (sigenv, NOTOK); -#endif -} - - -static RETSIGTYPE -quitser (int i) -{ -#ifndef RELIABLE_SIGNALS - SIGNAL (SIGQUIT, quitser); -#endif - - told_to_quit++; - interrupted++; - -#ifdef BSD42 - if (should_intr) - longjmp (sigenv, NOTOK); -#endif -} - - -static RETSIGTYPE -alrmser (int i) -{ - longjmp (peerenv, DONE); -} - - -static int -pINI (void) -{ - int i, vrsn; - unsigned char *bp; - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - switch (peer2rc (rc)) { - case RC_INI: - bp = rc->rc_data; - while (isspace (*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 (*bp)) - bp++; - while (isspace (*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 (*bp)) - bp++; - while (isspace (*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) -{ - 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); -}