Annotation of 43BSDReno/contrib/mh/uip/msh.c, revision 1.1.1.1

1.1       root        1: /* msh.c - The MH shell (sigh) */
                      2: 
                      3: /* TODO:
                      4:        Keep more status information in maildrop map
                      5:  */
                      6: 
                      7: #include "../h/mh.h"
                      8: #include "../h/dropsbr.h"
                      9: #include "../h/formatsbr.h"
                     10: #include "../h/scansbr.h"
                     11: #include "../zotnet/tws.h"
                     12: #include <stdio.h>
                     13: #include "../zotnet/mts.h"
                     14: #include <ctype.h>
                     15: #include <sys/types.h>
                     16: #include <sys/stat.h>
                     17: #ifndef        SYS5
                     18: #include <sgtty.h>
                     19: #else  SYS5
                     20: #include <termio.h>
                     21: #include <sys/ioctl.h>
                     22: #endif SYS5
                     23: #include <pwd.h>
                     24: #include <setjmp.h>
                     25: #include <signal.h>
                     26: #include "../h/mshsbr.h"
                     27: #include "../h/vmhsbr.h"
                     28: 
                     29: 
                     30: #define        QUOTE   '\\'            /* sigh */
                     31: 
                     32: 
                     33: /*  */
                     34: 
                     35: static struct swit switches[] = {
                     36: #define        IDSW    0
                     37:     "idstart number", -7,      /* interface from bbc */
                     38: #define        FDSW    1
                     39:     "idstop number", -6,       /*  .. */
                     40: #define        QDSW    2
                     41:     "idquit number", -6,       /*  .. */
                     42: #define        NMSW    3
                     43:     "idname BBoard", -6,       /*  .. */
                     44: 
                     45: #define        PRMPTSW 4
                     46:     "prompt string", 0,
                     47: 
                     48: #define        SCANSW  5
                     49:     "scan", 0,
                     50: #define        NSCANSW 6
                     51:     "noscan", 0,
                     52: 
                     53: #define        READSW  7
                     54:     "vmhread fd", -7,
                     55: #define        WRITESW 8
                     56:     "vmhwrite fd", -8,
                     57: 
                     58: #define        PREADSW 9
                     59:     "popread fd", -7,
                     60: #define        PWRITSW 10
                     61:     "popwrite fd", -8,
                     62: 
                     63: #define        TCURSW  11
                     64:     "topcur", 0,
                     65: #define        NTCURSW 12
                     66:     "notopcur", 0,
                     67: 
                     68: #define        HELPSW  13
                     69:     "help", 4,
                     70: 
                     71:     NULL, NULL
                     72: };
                     73: 
                     74: /*  */
                     75:                                /* FOLDER */
                     76: char  *fmsh = NULL;            /* folder instead of file */
                     77: int    modified;               /* command modified folder */
                     78: struct msgs *mp;               /* used a lot */
                     79: static int   nMsgs = 0;
                     80: struct Msg  *Msgs = NULL;      /* Msgs[0] not used */
                     81: static FILE *fp;               /* input file */
                     82: static FILE *yp = NULL;                /* temporary file */
                     83: static int  mode;              /* mode of file */
                     84: static int  numfds = 0;                /* number of files cached */
                     85: static int  maxfds = 0;                /* number of files cached to be cached */
                     86: static time_t mtime = (time_t) 0;/* mtime of file */
                     87: 
                     88: 
                     89:                                /* VMH */
                     90: #define        ALARM   ((unsigned int) 10)
                     91: #define        ttyN(c) ttyNaux ((c), NULLCP)
                     92: 
                     93: static int  vmh = 0;
                     94: 
                     95: static int  vmhpid = OK;
                     96: static int  vmhfd0;
                     97: static int  vmhfd1;
                     98: static int  vmhfd2;
                     99: 
                    100: static int  vmhtty = NOTOK;
                    101: 
                    102: #define        SCAN    1
                    103: #define        STATUS  2
                    104: #define        DISPLAY 3
                    105: #define        NWIN    DISPLAY
                    106: 
                    107: static int  topcur = 0;
                    108: 
                    109: static int  numwins = 0;
                    110: static int  windows[NWIN + 1];
                    111: 
                    112: static jmp_buf peerenv;
                    113: 
                    114: 
                    115: #ifdef BPOP
                    116:                                /* POP */
                    117: 
                    118: static int pmsh = 0;           /* BPOP enabled */
                    119: 
                    120: extern char response[];
                    121: #endif BPOP
                    122: 
                    123: 
                    124:                                /* PARENT */
                    125: static int  pfd = NOTOK;       /* fd parent is reading from */
                    126: static int  ppid = 0;          /* pid of parent */
                    127: 
                    128: 
                    129:                                /* COMMAND */
                    130: int     interactive;           /* running from a /dev/tty */
                    131: int     redirected;            /* re-directing output */
                    132: FILE  *sp = NULL;              /* original stdout */
                    133: 
                    134: char   *cmd_name;              /* command being run */
                    135: 
                    136: char    myfilter[BUFSIZ];      /* path to mhl.forward */
                    137: 
                    138: static char *myprompt = "(%s) ";/* prompting string */
                    139: 
                    140: 
                    141:                                /* BBOARDS */
                    142: static int    gap;             /* gap in BBoard-ID:s */
                    143: 
                    144: static char *myname = NULL;    /* BBoard name */
                    145: 
                    146: char   *BBoard_ID = "BBoard-ID";/* BBoard-ID constant */
                    147: 
                    148:                                /* SIGNALS */
                    149: SIGDECL (*istat)();            /* original SIGINT */
                    150: static SIGDECL (*pstat)();     /* current SIGPIPE */
                    151: SIGDECL (*qstat)();            /* original SIGQUIT */
                    152: #ifdef SIGTSTP
                    153: static SIGDECL (*tstat)();     /* original SIGTSTP */
                    154: #endif SIGTSTP
                    155: int     interrupted;           /* SIGINT detected */
                    156: int     broken_pipe;           /* SIGPIPE detected */
                    157: int     told_to_quit;          /* SIGQUIT detected */
                    158: 
                    159: #ifdef BSD42
                    160: int    should_intr;            /* signal handler should interrupt call */
                    161: jmp_buf sigenv;                        /* the environment pointer */
                    162: #endif BSD42
                    163: 
                    164: void padios(), padvise();
                    165: 
                    166: static int read_map(), read_file(), check_folder(), getargs(), getcmds(),
                    167:     parse(), init_io(), initaux_io(), finaux_io(), pINI(), pQRY(), pQRY1(),
                    168:     pQRY2(), pCMD(), pFIN(), peerwait(), alrmser(), ttyNaux(), ttyR(),
                    169:     winN(), winR(), winX();
                    170: static void msh(), m_gMsgs(), scanrange(), scanstring(), quit(), fin_io(),
                    171:     m_init();
                    172: static SIGDECL intrser(), pipeser(), quitser();
                    173: 
                    174: 
                    175: #ifdef SYS5
                    176: struct passwd  *getpwnam ();
                    177: #endif SYS5
                    178: 
                    179: /*  */
                    180: 
                    181: /* ARGSUSED */
                    182: 
                    183: main (argc, argv)
                    184: int     argc;
                    185: char  **argv;
                    186: {
                    187:     int            id = 0,
                    188:             scansw = 0,
                    189:            vmh1 = 0,
                    190:             vmh2 = 0;
                    191: #ifdef BPOP
                    192:     int            pmsh1 = 0,
                    193:            pmsh2 = 0;
                    194: #endif BPOP
                    195:     char   *cp,
                    196:            *file = NULL,
                    197:            *folder = NULL,
                    198:           **ap,
                    199:           **argp,
                    200:             buf[80],
                    201:            *arguments[MAXARGS];
                    202: 
                    203:     invo_name = r1bindex (argv[0], '/');
                    204:     mts_init (invo_name);
                    205:     if ((cp = m_find (invo_name)) != NULL) {
                    206:        ap = brkstring (cp = getcpy (cp), " ", "\n");
                    207:        ap = copyip (ap, arguments);
                    208:     }
                    209:     else
                    210:        ap = arguments;
                    211:     (void) copyip (argv + 1, ap);
                    212:     argp = arguments;
                    213: 
                    214: /*  */
                    215: 
                    216:     while (cp = *argp++) {
                    217:        if (*cp == '-')
                    218:            switch (smatch (++cp, switches)) {
                    219:                case AMBIGSW:
                    220:                    ambigsw (cp, switches);
                    221:                    done (1);
                    222:                case UNKWNSW:
                    223:                    adios (NULLCP, "-%s unknown", cp);
                    224:                case HELPSW:
                    225:                    (void) sprintf (buf, "%s [switches] file", invo_name);
                    226:                    help (buf, switches);
                    227:                    done (1);
                    228: 
                    229:                case IDSW:
                    230:                    if (!(cp = *argp++) || *cp == '-')
                    231:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    232:                    if ((id = atoi (cp)) < 1)
                    233:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    234:                    continue;
                    235:                case FDSW:
                    236:                    if (!(cp = *argp++) || *cp == '-')
                    237:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    238:                    if ((pfd = atoi (cp)) <= 1)
                    239:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    240:                    continue;
                    241:                case QDSW:
                    242:                    if (!(cp = *argp++) || *cp == '-')
                    243:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    244:                    if ((ppid = atoi (cp)) <= 1)
                    245:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    246:                    continue;
                    247:                case NMSW:
                    248:                    if (!(myname = *argp++) || *myname == '-')
                    249:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    250:                    continue;
                    251: 
                    252:                case SCANSW:
                    253:                    scansw++;
                    254:                    continue;
                    255:                case NSCANSW:
                    256:                    scansw = 0;
                    257:                    continue;
                    258: 
                    259:                case PRMPTSW:
                    260:                    if (!(myprompt = *argp++) || *myprompt == '-')
                    261:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    262:                    continue;
                    263: 
                    264:                case READSW:
                    265:                    if (!(cp = *argp++) || *cp == '-')
                    266:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    267:                    if ((vmh1 = atoi (cp)) < 1)
                    268:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    269:                    continue;
                    270:                case WRITESW:
                    271:                    if (!(cp = *argp++) || *cp == '-')
                    272:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    273:                    if ((vmh2 = atoi (cp)) < 1)
                    274:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    275:                    continue;
                    276: 
                    277:                case PREADSW:
                    278:                    if (!(cp = *argp++) || *cp == '-')
                    279:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    280: #ifdef BPOP
                    281:                    if ((pmsh1 = atoi (cp)) < 1)
                    282:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    283: #endif BPOP
                    284:                    continue;
                    285:                case PWRITSW:
                    286:                    if (!(cp = *argp++) || *cp == '-')
                    287:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    288: #ifdef BPOP
                    289:                    if ((pmsh2 = atoi (cp)) < 1)
                    290:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    291: #endif BPOP
                    292:                    continue;
                    293: 
                    294:                case TCURSW:
                    295:                    topcur++;
                    296:                    continue;
                    297:                case NTCURSW:
                    298:                    topcur = 0;
                    299:                    continue;
                    300:            }
                    301:        if (*cp == '+' || *cp == '@') {
                    302:            if (folder)
                    303:                adios (NULLCP, "only one folder at a time!");
                    304:            else
                    305:                folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
                    306:        }
                    307:        else
                    308:            if (file)
                    309:                adios (NULLCP, "only one file at a time!");
                    310:            else
                    311:                file = cp;
                    312:     }
                    313: 
                    314: /*  */
                    315: 
                    316:     if (!file && !folder)
                    317:        file = "./msgbox";
                    318:     if (file && folder)
                    319:        adios (NULLCP, "use a file or a folder, not both");
                    320:     (void) strcpy (myfilter, libpath (mhlforward));
                    321: #ifdef FIOCLEX
                    322:     if (pfd > 1)
                    323:        (void) ioctl (pfd, FIOCLEX, NULLCP);
                    324: #endif FIOCLEX
                    325: 
                    326: #ifdef BSD42
                    327:     should_intr = 0;
                    328: #endif BSD42
                    329:     setsigx (istat, SIGINT, intrser);
                    330:     setsigx (qstat, SIGQUIT, quitser);
                    331: 
                    332:     (void) sc_width ();                /* MAGIC... */
                    333: 
                    334:     if (vmh = vmh1 && vmh2) {
                    335:        (void) rcinit (vmh1, vmh2);
                    336:        (void) pINI ();
                    337:        (void) signal (SIGINT, SIG_IGN);
                    338:        (void) signal (SIGQUIT, SIG_IGN);
                    339: #ifdef SIGTSTP
                    340:        tstat = signal (SIGTSTP, SIG_IGN);
                    341: #endif SIGTSTP
                    342:     }
                    343: 
                    344: #ifdef BPOP
                    345:     if (pmsh = pmsh1 && pmsh2) {
                    346:        cp = getenv ("MHPOPDEBUG");
                    347:        if (pop_set (pmsh1, pmsh2, cp && *cp) == NOTOK)
                    348:            padios (NULLCP, "%s", response);
                    349:        if (folder)
                    350:            file = folder, folder = NULL;
                    351:     }
                    352: #endif BPOP
                    353: 
                    354:     if (folder)
                    355:        fsetup (folder);
                    356:     else
                    357:        setup (file);
                    358:     readids (id);
                    359:     display_info (id > 0 ? scansw : 0);
                    360: 
                    361:     msh (id > 0 ? scansw : 0);
                    362: 
                    363:     m_reset ();
                    364: 
                    365:     done (0);
                    366: }
                    367: 
                    368: /*  */
                    369: 
                    370: static struct swit mshcmds[] = {
                    371: #define        ALICMD  0
                    372:     "ali", 0,
                    373: #define        EXPLCMD 1
                    374:     "burst", 0,
                    375: #define        COMPCMD 2
                    376:     "comp", 0,
                    377: #define        DISTCMD 3
                    378:     "dist", 0,
                    379: #define        EXITCMD 4
                    380:     "exit", 0,
                    381: #define        FOLDCMD 5
                    382:     "folder", 0,
                    383: #define        FORWCMD 6
                    384:     "forw", 0,
                    385: #define        HELPCMD 7
                    386:     "help", 0,
                    387: #define        INCMD   8
                    388:     "inc", 0,
                    389: #define        MARKCMD 9
                    390:     "mark", 0,
                    391: #define        MAILCMD 10
                    392:     "mhmail", 0,
                    393: #define        MSGKCMD 11
                    394:     "msgchk", 0,
                    395: #define        NEXTCMD 12
                    396:     "next", 0,
                    397: #define        PACKCMD 13
                    398:     "packf", 0,
                    399: #define        PICKCMD 14
                    400:     "pick", 0,
                    401: #define        PREVCMD 15
                    402:     "prev", 0,
                    403: #define        QUITCMD 16
                    404:     "quit", 0,
                    405: #define        FILECMD 17
                    406:     "refile", 0,
                    407: #define        REPLCMD 18
                    408:     "repl", 0,
                    409: #define        RMMCMD  19
                    410:     "rmm", 0,
                    411: #define        SCANCMD 20
                    412:     "scan", 0,
                    413: #define        SENDCMD 21
                    414:     "send", 0,
                    415: #define        SHOWCMD 22
                    416:     "show", 0,
                    417: #define        SORTCMD 23
                    418:     "sortm", 0,
                    419: #define        WHATCMD 24
                    420:     "whatnow", 0,
                    421: #define        WHOMCMD 25
                    422:     "whom", 0,
                    423: 
                    424:     NULL, NULL
                    425: };
                    426: 
                    427: /*  */
                    428: 
                    429: static void msh (scansw)
                    430: int     scansw;
                    431: {
                    432:     int     i;
                    433:     register char  *cp,
                    434:                   **ap;
                    435:     char    prompt[BUFSIZ],
                    436:            *vec[MAXARGS];
                    437:     struct Cmd  typein;
                    438:     register struct Cmd *cmdp;
                    439: 
                    440:     (void) sprintf (prompt, myprompt, invo_name);
                    441:     cmdp = &typein;
                    442: 
                    443:     for (;;) {
                    444:        if (yp) {
                    445:            (void) fclose (yp);
                    446:            yp = NULL;
                    447:        }
                    448:        if (vmh) {
                    449:            if ((i = getcmds (mshcmds, cmdp, scansw)) == EOF) {
                    450:                (void) rcdone ();
                    451:                return;
                    452:            }
                    453:        }
                    454:        else {
                    455:            (void) check_folder (scansw);
                    456:            if ((i = getargs (prompt, mshcmds, cmdp)) == EOF) {
                    457:                (void) putchar ('\n');
                    458:                return;
                    459:            }
                    460:        }
                    461:        cmd_name = mshcmds[i].sw;
                    462: 
                    463:        switch (i) {
                    464:            case QUITCMD:
                    465:                quit ();
                    466:                return;
                    467: 
                    468:            case EXITCMD:
                    469:            case EXPLCMD:
                    470:            case FOLDCMD:
                    471:            case FORWCMD:       /* sigh */
                    472:            case MARKCMD:
                    473:            case NEXTCMD:
                    474:            case PACKCMD:
                    475:            case PICKCMD:
                    476:            case PREVCMD:
                    477:            case RMMCMD:
                    478:            case SHOWCMD:
                    479:            case SCANCMD:
                    480:            case SORTCMD:
                    481:                if ((cp = m_find (cmd_name)) != NULL) {
                    482:                    ap = brkstring (cp = getcpy (cp), " ", "\n");
                    483:                    ap = copyip (ap, vec);
                    484:                }
                    485:                else
                    486:                    ap = vec;
                    487:                break;
                    488: 
                    489:            default:
                    490:                cp = NULL;
                    491:                ap = vec;
                    492:                break;
                    493:        }
                    494:        (void) copyip (cmdp -> args + 1, ap);
                    495: 
                    496:        m_init ();
                    497: 
                    498:        if (!vmh && init_io (cmdp, vmh) == NOTOK) {
                    499:            if (cp != NULL)
                    500:                free (cp);
                    501:            continue;
                    502:        }
                    503:        modified = 0;
                    504:        redirected = vmh || cmdp -> direction != STDIO;
                    505: 
                    506:        switch (i) {
                    507:            case ALICMD:
                    508:            case COMPCMD:
                    509:            case INCMD:
                    510:            case MAILCMD:
                    511:            case MSGKCMD:
                    512:            case SENDCMD:
                    513:            case WHATCMD:
                    514:            case WHOMCMD:
                    515:                if (!vmh || ttyN (cmdp) != NOTOK)
                    516:                    forkcmd (vec, cmd_name);
                    517:                break;
                    518: 
                    519:            case DISTCMD:
                    520:                if (!vmh || ttyN (cmdp) != NOTOK)
                    521:                    distcmd (vec);
                    522:                break;
                    523: 
                    524:            case EXPLCMD:
                    525:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    526:                    explcmd (vec);
                    527:                break;
                    528: 
                    529:            case FILECMD:
                    530:                if (!vmh
                    531:                        || (filehak (vec) == OK ? ttyN (cmdp)
                    532:                                        : winN (cmdp, DISPLAY, 1)) != NOTOK)
                    533:                    filecmd (vec);
                    534:                break;
                    535: 
                    536:            case FOLDCMD:
                    537:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    538:                    foldcmd (vec);
                    539:                break;
                    540: 
                    541:            case FORWCMD:
                    542:                if (!vmh || ttyN (cmdp) != NOTOK)
                    543:                    forwcmd (vec);
                    544:                break;
                    545: 
                    546:            case HELPCMD:
                    547:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    548:                    helpcmd (vec);
                    549:                break;
                    550: 
                    551:            case EXITCMD:
                    552:            case MARKCMD:
                    553:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    554:                    markcmd (vec);
                    555:                break;
                    556: 
                    557:            case NEXTCMD:
                    558:            case PREVCMD:
                    559:            case SHOWCMD:
                    560:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    561:                    showcmd (vec);
                    562:                break;
                    563: 
                    564:            case PACKCMD:
                    565:                if (!vmh
                    566:                        || (packhak (vec) == OK ? ttyN (cmdp)
                    567:                                        : winN (cmdp, DISPLAY, 1)) != NOTOK)
                    568:                    packcmd (vec);
                    569:                break;
                    570: 
                    571:            case PICKCMD:
                    572:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    573:                    pickcmd (vec);
                    574:                break;
                    575: 
                    576:            case REPLCMD:
                    577:                if (!vmh || ttyN (cmdp) != NOTOK)
                    578:                    replcmd (vec);
                    579:                break;
                    580: 
                    581:            case RMMCMD:
                    582:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    583:                    rmmcmd (vec);
                    584:                break;
                    585: 
                    586:            case SCANCMD:
                    587:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    588:                    scancmd (vec);
                    589:                break;
                    590: 
                    591:            case SORTCMD:
                    592:                if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK)
                    593:                    sortcmd (vec);
                    594:                break;
                    595: 
                    596:            default:
                    597:                padios (NULLCP, "no dispatch for %s", cmd_name);
                    598:        }
                    599: 
                    600:        if (vmh) {
                    601:            if (vmhtty != NOTOK)
                    602:                (void) ttyR (cmdp);
                    603:            if (vmhpid > OK)
                    604:                (void) winR (cmdp);
                    605:        }
                    606:        else
                    607:            fin_io (cmdp, vmh);
                    608:        if (cp != NULL)
                    609:            free (cp);
                    610:        if (i == EXITCMD) {
                    611:            quit ();
                    612:            return;
                    613:        }
                    614:     }
                    615: }
                    616: 
                    617: /*  */
                    618: 
                    619: fsetup (folder)
                    620: char   *folder;
                    621: {
                    622:     register int msgnum;
                    623:     char   *maildir;
                    624:     struct stat st;
                    625: 
                    626:     maildir = m_maildir (folder);
                    627:     if (chdir (maildir) == NOTOK)
                    628:        padios (maildir, "unable to change directory to");
                    629:     if (!(mp = m_gmsg (folder)))
                    630:        padios (NULLCP, "unable to read folder %s", folder);
                    631:     if (mp -> hghmsg == 0)
                    632:        padios (NULLCP, "no messages in %s", folder);
                    633: 
                    634:     mode = m_gmprot ();
                    635:     mtime = stat (mp -> foldpath, &st) != NOTOK ? st.st_mtime : 0;
                    636: 
                    637:     m_gMsgs (mp -> hghmsg);
                    638: 
                    639:     for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) {
                    640:        Msgs[msgnum].m_bboard_id = 0;
                    641:        Msgs[msgnum].m_top = NOTOK;
                    642:        Msgs[msgnum].m_start = Msgs[msgnum].m_stop = 0L;
                    643:        Msgs[msgnum].m_scanl = NULL;
                    644:     }
                    645: 
                    646:     m_init ();
                    647: 
                    648:     fmsh = getcpy (folder);
                    649: 
                    650: #ifndef        BSD42
                    651:     maxfds = _NFILE / 2;
                    652: #else  BSD42
                    653:     maxfds = getdtablesize () / 2;
                    654: #endif BSD42
                    655:     if ((maxfds -= 2) < 1)
                    656:        maxfds = 1;
                    657: }
                    658: 
                    659: /*  */
                    660: 
                    661: setup (file)
                    662: char   *file;
                    663: {
                    664:     int     i,
                    665:             msgp;
                    666: #ifdef BPOP
                    667:     char    tmpfil[BUFSIZ];
                    668: #endif BPOP
                    669:     struct stat st;
                    670: 
                    671: #ifdef BPOP
                    672:     if (pmsh) {
                    673:        (void) strcpy (tmpfil, m_tmpfil (invo_name));
                    674:        if ((fp = fopen (tmpfil, "w+")) == NULL)
                    675:            padios (tmpfil, "unable to create");
                    676:        (void) unlink (tmpfil);
                    677:     }
                    678:     else
                    679: #endif BPOP
                    680:     if ((fp = fopen (file, "r")) == NULL)
                    681:        padios (file, "unable to read");
                    682: #ifdef FIOCLEX
                    683:     (void) ioctl (fileno (fp), FIOCLEX, NULLCP);
                    684: #endif FIOCLEX
                    685:     if (fstat (fileno (fp), &st) != NOTOK) {
                    686:        mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
                    687:        msgp = read_map (file, (long) st.st_size);
                    688:     }
                    689:     else {
                    690:        mode = m_gmprot (), mtime = 0;
                    691:        msgp = 0;
                    692:     }
                    693: 
                    694:     if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
                    695:        padios (NULLCP, "no messages in %s", myname ? myname : file);
                    696: 
                    697:     mp = (struct msgs  *) calloc ((unsigned) 1, MSGSIZE (mp, 1, msgp + 1));
                    698:     if (mp == NULL)
                    699:        padios (NULLCP, "unable to allocate folder storage");
                    700: 
                    701:     mp -> hghmsg = msgp;
                    702:     mp -> nummsg = msgp;
                    703:     mp -> lowmsg = 1;
                    704:     mp -> curmsg = 0;
                    705: 
                    706:     mp -> foldpath = getcpy (myname ? myname : file);
                    707:     mp -> msgflags = NULL;
                    708: #ifdef BPOP
                    709:     if (pmsh)
                    710:        mp -> msgflags |= READONLY;
                    711:     else {
                    712: #endif BPOP
                    713:        (void) stat (file, &st);
                    714:        if (st.st_uid != getuid () || access (file, 02) == NOTOK)
                    715:            mp -> msgflags |= READONLY;
                    716: #ifdef BPOP
                    717:     }
                    718: #endif BPOP
                    719:     mp -> lowoff = 1;
                    720:     mp -> hghoff = mp -> hghmsg + 1;
                    721: 
                    722: #ifdef MTR
                    723:     mp -> msgstats = (short *)
                    724:                calloc ((unsigned) 1, MSGSIZEX(mp, mp -> lowmsg, mp -> hghmsg));
                    725:     if (mp -> msgstats == NULL)
                    726:        padios (NULLCP, "unable to allocate messages storage");
                    727:     mp -> msgstats = (mp -> msgbase = mp -> msgstats) - mp -> lowoff;
                    728:     if (mp -> msgstats < 0)
                    729:        padios (NULLCP, "setup() botch -- you lose big");
                    730: #endif MTR
                    731: #ifdef BPOP
                    732:     if (pmsh) {
                    733:        for (i = mp -> lowmsg; i <= mp -> hghmsg; i++) {
                    734:            Msgs[i].m_top = i;
                    735:            mp -> msgstats[i] = EXISTS | VIRTUAL;
                    736:        }
                    737:     }
                    738:     else
                    739: #endif BPOP
                    740:     for (i = mp -> lowmsg; i <= mp -> hghmsg; i++)
                    741:        mp -> msgstats[i] = EXISTS;
                    742:     m_init ();
                    743: 
                    744:     mp -> msgattrs[0] = getcpy ("unseen");
                    745:     mp -> msgattrs[1] = NULL;
                    746: 
                    747:     m_unknown (fp);            /* the MAGIC invocation */
                    748:     if (fmsh) {
                    749:        free (fmsh);
                    750:        fmsh = NULL;
                    751:     }
                    752: }
                    753: 
                    754: /*  */
                    755: 
                    756: static int  read_map (file, size)
                    757: char   *file;
                    758: long    size;
                    759: {
                    760:     register int    i,
                    761:                     msgp;
                    762:     register struct drop   *dp,
                    763:                            *mp;
                    764:     struct drop *rp;
                    765: 
                    766: #ifdef BPOP
                    767:     if (pmsh)
                    768:        return read_pop ();
                    769: #endif BPOP
                    770: 
                    771:     if ((i = map_read (file, size, &rp, 1)) == 0)
                    772:        return 0;
                    773: 
                    774:     m_gMsgs (i);
                    775: 
                    776:     msgp = 1;
                    777:     for (dp = rp; i-- > 0; msgp++, dp++) {
                    778:        mp = &Msgs[msgp].m_drop;
                    779:        mp -> d_id = dp -> d_id;
                    780:        mp -> d_size = dp -> d_size;
                    781:        mp -> d_start = dp -> d_start;
                    782:        mp -> d_stop = dp -> d_stop;
                    783:        Msgs[msgp].m_scanl = NULL;
                    784:     }
                    785:     free ((char *) rp);
                    786: 
                    787:     return (msgp - 1);
                    788: }
                    789: 
                    790: /*  */
                    791: 
                    792: static  int    read_file (pos, msgp)
                    793: register long  pos;
                    794: register int    msgp;
                    795: {
                    796:     register int    i;
                    797:     register struct drop   *dp,
                    798:                            *mp;
                    799:     struct drop *rp;
                    800: 
                    801: #ifdef BPOP
                    802:     if (pmsh)
                    803:        return (msgp - 1);
                    804: #endif BPOP
                    805: 
                    806:     if ((i = mbx_read (fp, pos, &rp, 1)) <= 0)
                    807:        return (msgp - 1);
                    808: 
                    809:     m_gMsgs ((msgp - 1) + i);
                    810: 
                    811:     for (dp = rp; i-- > 0; msgp++, dp++) {
                    812:        mp = &Msgs[msgp].m_drop;
                    813:        mp -> d_id = 0;
                    814:        mp -> d_size = dp -> d_size;
                    815:        mp -> d_start = dp -> d_start;
                    816:        mp -> d_stop = dp -> d_stop;
                    817:        Msgs[msgp].m_scanl = NULL;
                    818:     }
                    819:     free ((char *) rp);
                    820: 
                    821:     return (msgp - 1);
                    822: }
                    823: 
                    824: /*  */
                    825: 
                    826: #ifdef BPOP
                    827: static int  read_pop ()
                    828: {
                    829:     int            nmsgs,
                    830:             nbytes;
                    831: 
                    832:     if (pop_stat (&nmsgs, &nbytes) == NOTOK)
                    833:        padios (NULLCP, "%s", response);
                    834: 
                    835:     m_gMsgs (nmsgs);
                    836: 
                    837:     return nmsgs;
                    838: }
                    839: 
                    840: 
                    841: static int  pop_action (s)
                    842: register char  *s;
                    843: {
                    844:     fprintf (yp, "%s\n", s);
                    845: }
                    846: #endif BPOP
                    847: 
                    848: /*  */
                    849: 
                    850: static void m_gMsgs (n)
                    851: int    n;
                    852: {
                    853:     if (Msgs == NULL) {
                    854:        nMsgs = n + MAXFOLDER / 2;
                    855:        Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
                    856:        if (Msgs == NULL)
                    857:            padios (NULLCP, "unable to allocate Msgs structure");
                    858:        return;
                    859:     }
                    860: 
                    861:     if (nMsgs >= n)
                    862:        return;
                    863: 
                    864:     nMsgs = n + MAXFOLDER / 2;
                    865:     Msgs = (struct Msg *) realloc ((char *) Msgs,
                    866:                            (unsigned) (nMsgs + 2) * sizeof *Msgs);
                    867:     if (Msgs == NULL)
                    868:        padios (NULLCP, "unable to reallocate Msgs structure");
                    869: }
                    870: 
                    871: /*  */
                    872: 
                    873: FILE   *msh_ready (msgnum, full)
                    874: register int msgnum;
                    875: int    full;
                    876: {
                    877:     register int    msgp;
                    878:     int     fd;
                    879:     long    pos1,
                    880:             pos2;
                    881:     char   *cp,
                    882:             tmpfil[BUFSIZ];
                    883: 
                    884:     if (yp) {
                    885:        (void) fclose (yp);
                    886:        yp = NULL;
                    887:     }
                    888: 
                    889:     if (fmsh) {
                    890:        if ((fd = Msgs[msgnum].m_top) == NOTOK) {
                    891:            if (numfds >= maxfds)
                    892:                for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++)
                    893:                    if (Msgs[msgp].m_top != NOTOK) {
                    894:                        (void) close (Msgs[msgp].m_top);
                    895:                        Msgs[msgp].m_top = NOTOK;
                    896:                        numfds--;
                    897:                        break;
                    898:                    }
                    899: 
                    900:            if ((fd = open (cp = m_name (msgnum), 0)) == NOTOK)
                    901:                padios (cp, "unable to open message");
                    902:            Msgs[msgnum].m_top = fd;
                    903:            numfds++;
                    904:        }
                    905: 
                    906:        if ((fd = dup (fd)) == NOTOK)
                    907:            padios ("cached message", "unable to dup");
                    908:        if ((yp = fdopen (fd, "r")) == NULL)
                    909:            padios (NULLCP, "unable to fdopen cached message");
                    910:        (void) fseek (yp, 0L, 0);
                    911:        return yp;
                    912:     }
                    913: 
                    914: #ifdef BPOP
                    915:     if (pmsh && (mp -> msgstats[msgnum] & VIRTUAL)) {
                    916:        if (Msgs[msgnum].m_top == 0)
                    917:            padios (NULLCP, "msh_ready (%d, %d) botch", msgnum, full);
                    918:        if (!full) {
                    919:            (void) strcpy (tmpfil, m_tmpfil (invo_name));
                    920:            if ((yp = fopen (tmpfil, "w+")) == NULL)
                    921:                padios (tmpfil, "unable to create");
                    922:            (void) unlink (tmpfil);
                    923: 
                    924:            if (pop_top (Msgs[msgnum].m_top, 4, pop_action) == NOTOK)
                    925:                padios (NULLCP, "%s", response);
                    926: 
                    927:            m_eomsbr ((int (*)()) 0);   /* XXX */
                    928:            msg_style = MS_DEFAULT;     /*  .. */
                    929:            (void) fseek (yp, 0L, 0);
                    930:            return yp;
                    931:        }
                    932: 
                    933:        (void) fseek (fp, 0L, 2);
                    934:        (void) fwrite (mmdlm1, 1, strlen (mmdlm1), fp);
                    935:        if (fflush (fp))
                    936:            padios ("temporary file", "write error on");
                    937:        (void) fseek (fp, 0L, 2);
                    938:        pos1 = ftell (fp);
                    939: 
                    940:        yp = fp;
                    941:        if (pop_retr (Msgs[msgnum].m_top, pop_action) == NOTOK)
                    942:            padios (NULLCP, "%s", response);
                    943:        yp = NULL;
                    944: 
                    945:        (void) fseek (fp, 0L, 2);
                    946:        pos2 = ftell (fp);
                    947:        (void) fwrite (mmdlm2, 1, strlen (mmdlm2), fp);
                    948:        if (fflush (fp))
                    949:            padios ("temporary file", "write error on");
                    950: 
                    951:        Msgs[msgnum].m_start = pos1;
                    952:        Msgs[msgnum].m_stop = pos2;
                    953: 
                    954:        mp -> msgstats[msgnum] &= ~VIRTUAL;
                    955:     }
                    956: #endif BPOP
                    957: 
                    958:     m_eomsbr ((int (*)()) 0);  /* XXX */
                    959:     (void) fseek (fp, Msgs[msgnum].m_start, 0);
                    960:     return fp;
                    961: }
                    962: 
                    963: /*  */
                    964: 
                    965: static int check_folder (scansw)
                    966: int     scansw;
                    967: {
                    968:     int     flags,
                    969:             i,
                    970:             low,
                    971:             hgh,
                    972:             msgp;
                    973:     struct stat st;
                    974: 
                    975: #ifdef BPOP
                    976:     if (pmsh)
                    977:        return 0;
                    978: #endif BPOP
                    979: 
                    980:     if (fmsh) {
                    981:        if (stat (mp -> foldpath, &st) == NOTOK)
                    982:            padios (mp -> foldpath, "unable to stat");
                    983:        if (mtime == st.st_mtime)
                    984:            return 0;
                    985:        mtime = st.st_mtime;
                    986: 
                    987:        low = mp -> hghmsg + 1;
                    988:        m_fmsg (mp);
                    989: 
                    990:        if (!(mp = m_gmsg (fmsh)))
                    991:            padios (NULLCP, "unable to re-read folder %s", fmsh);
                    992: 
                    993:        hgh = mp -> hghmsg;
                    994: 
                    995:        for (msgp = mp -> lowmsg; msgp <= mp -> hghmsg; msgp++) {
                    996:            if (Msgs[msgp].m_top != NOTOK) {
                    997:                (void) close (Msgs[msgp].m_top);
                    998:                Msgs[msgp].m_top = NOTOK;
                    999:                numfds--;
                   1000:            }
                   1001:            if (Msgs[msgp].m_scanl) {
                   1002:                free (Msgs[msgp].m_scanl);
                   1003:                Msgs[msgp].m_scanl = NULL;
                   1004:            }
                   1005:        }
                   1006: 
                   1007:        m_init ();
                   1008: 
                   1009:        if (modified || low > hgh)
                   1010:            return 1;
                   1011:        goto check_vmh;
                   1012:     }
                   1013:     if (fstat (fileno (fp), &st) == NOTOK)
                   1014:        padios (mp -> foldpath, "unable to fstat");
                   1015:     if (mtime == st.st_mtime)
                   1016:        return 0;
                   1017:     mode = (int) (st.st_mode & 0777);
                   1018:     mtime = st.st_mtime;
                   1019: 
                   1020:     if ((msgp = read_file (Msgs[mp -> hghmsg].m_stop, mp -> hghmsg + 1)) < 1)
                   1021:        padios (NULLCP, "no messages in %s", mp -> foldpath);   /* XXX */
                   1022:     if (msgp >= MAXFOLDER)
                   1023:        padios (NULLCP, "more than %d messages in %s", MAXFOLDER,
                   1024:                mp -> foldpath);
                   1025:     if (msgp <= mp -> hghmsg)
                   1026:        return 0;               /* XXX */
                   1027: 
                   1028:     if ((mp = m_remsg (mp, 0, msgp)) == NULL)
                   1029:        padios (NULLCP, "unable to allocate folder storage");
                   1030: 
                   1031:     low = mp -> hghmsg + 1, hgh = msgp;
                   1032:     flags = scansw ? m_seqflag (mp, "unseen") : 0;
                   1033:     for (i = mp -> hghmsg + 1; i <= msgp; i++) {
                   1034:        mp -> msgstats[i] = EXISTS | flags;
                   1035:        mp -> nummsg++;
                   1036:     }
                   1037:     mp -> hghmsg = msgp;
                   1038:     m_init ();
                   1039: 
                   1040: check_vmh: ;
                   1041:     if (vmh)
                   1042:        return 1;
                   1043: 
                   1044:     advise (NULLCP, "new messages have arrived!\007");
                   1045:     if (scansw)
                   1046:        scanrange (low, hgh);
                   1047: 
                   1048:     return 1;
                   1049: }
                   1050: 
                   1051: /*  */
                   1052: 
                   1053: static void scanrange (low, hgh)
                   1054: int    low,
                   1055:        hgh;
                   1056: {
                   1057:     char    buffer[BUFSIZ];
                   1058: 
                   1059:     (void) sprintf (buffer, "%d-%d", low, hgh);
                   1060:     scanstring (buffer);
                   1061: }
                   1062: 
                   1063: 
                   1064: static void scanstring (arg)
                   1065: char   *arg;
                   1066: {
                   1067:     char   *cp,
                   1068:           **ap,
                   1069:            *vec[MAXARGS];
                   1070: 
                   1071:     if ((cp = m_find (cmd_name = "scan")) != NULL) {
                   1072:        ap = brkstring (cp = getcpy (cp), " ", "\n");
                   1073:        ap = copyip (ap, vec);
                   1074:     }
                   1075:     else
                   1076:        ap = vec;
                   1077:     *ap++ = arg;
                   1078:     *ap = NULL;
                   1079:     m_init ();
                   1080:     scancmd (vec);
                   1081:     if (cp != NULL)
                   1082:        free (cp);
                   1083: }
                   1084: 
                   1085: /*  */
                   1086: 
                   1087: readids (id)
                   1088: int     id;
                   1089: {
                   1090:     register int    cur,
                   1091:                     flags,
                   1092:                     i,
                   1093:                     msgnum;
                   1094: 
                   1095:     if (mp -> curmsg == 0)
                   1096:        m_setcur (mp, mp -> lowmsg);
                   1097:     if (id <= 0 || (flags = m_seqflag (mp, "unseen")) == 0)
                   1098:        return;
                   1099: 
                   1100:     for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
                   1101:        mp -> msgstats[msgnum] |= flags;
                   1102: 
                   1103:     if (id != 1) {
                   1104:        cur = mp -> curmsg;
                   1105: 
                   1106:        for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
                   1107:            if ((i = readid (msgnum)) > 0 && i < id) {
                   1108:                cur = msgnum + 1;
                   1109:                mp -> msgstats[msgnum] &= ~flags;
                   1110:                break;
                   1111:            }
                   1112:        for (i = mp -> lowmsg; i < msgnum; i++)
                   1113:            mp -> msgstats[i] &= ~flags;
                   1114: 
                   1115:        if (cur > mp -> hghmsg)
                   1116:            cur = mp -> hghmsg;
                   1117: 
                   1118:        m_setcur (mp, cur);
                   1119:     }
                   1120: 
                   1121:     if ((gap = 1 < id && id < (i = readid (mp -> lowmsg)) ? id : 0) && !vmh)
                   1122:        advise (NULLCP, "gap in ID:s, last seen %d, lowest present %d\n",
                   1123:                id - 1, i);
                   1124: }
                   1125: 
                   1126: /*  */
                   1127: 
                   1128: int    readid (msgnum)
                   1129: int     msgnum;
                   1130: {
                   1131:     int     i,
                   1132:             state;
                   1133: #ifdef BPOP
                   1134:     int            arg1,
                   1135:            arg2,
                   1136:            arg3;
                   1137: #endif BPOP
                   1138:     char   *bp,
                   1139:             buf[BUFSIZ],
                   1140:             name[NAMESZ];
                   1141:     register FILE *zp;
                   1142: 
                   1143:     if (Msgs[msgnum].m_bboard_id)
                   1144:        return Msgs[msgnum].m_bboard_id;
                   1145: #ifdef BPOP
                   1146:     if (pmsh) {
                   1147:        if (Msgs[msgnum].m_top == 0)
                   1148:            padios (NULLCP, "readid (%d) botch", msgnum);
                   1149:        if (pop_list (Msgs[msgnum].m_top, (int *) 0, &arg1, &arg2, &arg3) == OK
                   1150:                && arg3 > 0)
                   1151:            return (Msgs[msgnum].m_bboard_id = arg3);
                   1152:     }
                   1153: #endif BPOP
                   1154: 
                   1155:     zp = msh_ready (msgnum, 0);
                   1156:     for (state = FLD;;)
                   1157:        switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
                   1158:            case FLD:
                   1159:            case FLDEOF:
                   1160:            case FLDPLUS:
                   1161:                if (uleq (name, BBoard_ID)) {
                   1162:                    bp = getcpy (buf);
                   1163:                    while (state == FLDPLUS) {
                   1164:                        state = m_getfld (state, name, buf, sizeof buf, zp);
                   1165:                        bp = add (buf, bp);
                   1166:                    }
                   1167:                    i = atoi (bp);
                   1168:                    free (bp);
                   1169:                    if (i > 0)
                   1170:                        return (Msgs[msgnum].m_bboard_id = i);
                   1171:                    else
                   1172:                        continue;
                   1173:                }
                   1174:                while (state == FLDPLUS)
                   1175:                    state = m_getfld (state, name, buf, sizeof buf, zp);
                   1176:                if (state != FLDEOF)
                   1177:                    continue;
                   1178: 
                   1179:            default:
                   1180:                return 0;
                   1181:        }
                   1182: }
                   1183: 
                   1184: /*  */
                   1185: 
                   1186: display_info (scansw)
                   1187: int     scansw;
                   1188: {
                   1189:     int     flags,
                   1190:             sd;
                   1191: 
                   1192:     interactive = isatty (fileno (stdout));
                   1193:     if (sp == NULL) {
                   1194:        if ((sd = dup (fileno (stdout))) == NOTOK)
                   1195:            padios ("standard output", "unable to dup");
                   1196: #ifndef        BSD42                   /* XXX */
                   1197: #ifdef FIOCLEX
                   1198:        (void) ioctl (sd, FIOCLEX, NULL);
                   1199: #endif FIOCLEX
                   1200: #endif not BSD42
                   1201:        if ((sp = fdopen (sd, "w")) == NULL)
                   1202:            padios ("standard output", "unable to fdopen");
                   1203:     }
                   1204: 
                   1205:     (void) putenv ("mhfolder", mp -> foldpath);
                   1206:     if (vmh)
                   1207:        return;
                   1208: 
                   1209:     if (myname) {
                   1210:        printf ("Reading ");
                   1211:        if (SOprintf ("%s", myname))
                   1212:            printf ("%s", myname);
                   1213:        printf (", currently at message %d of %d\n",
                   1214:                mp -> curmsg, mp -> hghmsg);
                   1215:     }
                   1216:     else {
                   1217:        printf ("Reading ");
                   1218:        if (fmsh)
                   1219:            printf ("+%s", fmsh);
                   1220:        else
                   1221:            printf ("%s", mp -> foldpath);
                   1222:        printf (", currently at message %d of %d\n",
                   1223:                mp -> curmsg, mp -> hghmsg);
                   1224:     }
                   1225: 
                   1226:     if ((flags = m_seqflag (mp, "unseen"))
                   1227:            && scansw
                   1228:            && (mp -> msgstats[mp -> hghmsg] & flags))
                   1229:        scanstring ("unseen");
                   1230: }
                   1231: 
                   1232: /*  */
                   1233: 
                   1234: static write_ids ()
                   1235: {
                   1236:     int     i = 0,
                   1237:            flags,
                   1238:             msgnum;
                   1239:     char    buffer[80];
                   1240: 
                   1241:     if (pfd <= 1)
                   1242:        return;
                   1243: 
                   1244:     if (flags = m_seqflag (mp, "unseen"))
                   1245:        for (msgnum = mp -> hghmsg; msgnum >= mp -> lowmsg; msgnum--)
                   1246:            if (!(mp -> msgstats[msgnum] & flags)) {
                   1247:                if (Msgs[msgnum].m_bboard_id == 0)
                   1248:                    (void) readid (msgnum);
                   1249:                if ((i = Msgs[msgnum].m_bboard_id) > 0)
                   1250:                    break;
                   1251:            }
                   1252: 
                   1253:     (void) sprintf (buffer, "%d %d\n", i, Msgs[mp -> hghmsg].m_bboard_id);
                   1254:     (void) write (pfd, buffer, sizeof buffer);
                   1255:     (void) close (pfd);
                   1256:     pfd = NOTOK;
                   1257: }
                   1258: 
                   1259: /*  */
                   1260: 
                   1261: static void quit ()
                   1262: {
                   1263:     int     i,
                   1264:             md,
                   1265:             msgnum;
                   1266:     char   *cp,
                   1267:             tmpfil[BUFSIZ],
                   1268:             map1[BUFSIZ],
                   1269:             map2[BUFSIZ];
                   1270:     struct stat st;
                   1271:     FILE   *dp;
                   1272: 
                   1273:     if (!(mp -> msgflags & MODIFIED) || mp -> msgflags & READONLY || fmsh) {
                   1274:            if (vmh)
                   1275:                (void) rc2peer (RC_FIN, 0, NULLCP);
                   1276:        return;
                   1277:     }
                   1278: 
                   1279:     if (vmh)
                   1280:        (void) ttyNaux (NULLCMD, "FAST");
                   1281:     cp = NULL;
                   1282:     if ((dp = lkfopen (mp -> foldpath, "r")) == NULL) {
                   1283:        advise (mp -> foldpath, "unable to lock");
                   1284:        if (vmh) {
                   1285:            (void) ttyR (NULLCMD);
                   1286:            (void) pFIN ();
                   1287:        }
                   1288:        return;
                   1289:     }
                   1290:     if (fstat (fileno (dp), &st) == NOTOK) {
                   1291:        advise (mp -> foldpath, "unable to stat");
                   1292:        goto release;
                   1293:     }
                   1294:     if (mtime != st.st_mtime) {
                   1295:        advise (NULLCP, "new messages have arrived, no update");
                   1296:        goto release;
                   1297:     }
                   1298:     mode = (int) (st.st_mode & 0777);
                   1299: 
                   1300:     if (mp -> nummsg == 0) {
                   1301:        cp = concat ("Zero file \"", mp -> foldpath, "\"? ", NULLCP);
                   1302:        if (getanswer (cp)) {
                   1303:            if ((i = creat (mp -> foldpath, mode)) != NOTOK)
                   1304:                (void) close (i);
                   1305:            else
                   1306:                advise (mp -> foldpath, "error zero'ing");
                   1307:            (void) unlink (map_name (mp -> foldpath));/* XXX */
                   1308:        }
                   1309:        goto release;
                   1310:     }
                   1311: 
                   1312:     cp = concat ("Update file \"", mp -> foldpath, "\"? ", NULLCP);
                   1313:     if (!getanswer (cp))
                   1314:        goto release;
                   1315:     (void) strcpy (tmpfil, m_backup (mp -> foldpath));
                   1316:     if ((md = mbx_open (tmpfil, st.st_uid, st.st_gid, mode)) == NOTOK) {
                   1317:        advise (tmpfil, "unable to open");
                   1318:        goto release;
                   1319:     }
                   1320: 
                   1321:     for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
                   1322:        if (mp -> msgstats[msgnum] & EXISTS
                   1323:                && pack (tmpfil, md, msgnum) == NOTOK) {
                   1324:            (void) mbx_close (tmpfil, md);
                   1325:            (void) unlink (tmpfil);
                   1326:            (void) unlink (map_name (tmpfil));
                   1327:            goto release;
                   1328:        }
                   1329:     (void) mbx_close (tmpfil, md);
                   1330: 
                   1331:     if (rename (tmpfil, mp -> foldpath) == NOTOK)
                   1332:        admonish (mp -> foldpath, "unable to rename %s to", tmpfil);
                   1333:     else {
                   1334:        (void) strcpy (map1, map_name (tmpfil));
                   1335:        (void) strcpy (map2, map_name (mp -> foldpath));
                   1336: 
                   1337:        if (rename (map1, map2) == NOTOK) {
                   1338:            admonish (map2, "unable to rename %s to", map1);
                   1339:            (void) unlink (map1);
                   1340:            (void) unlink (map2);
                   1341:        }
                   1342:     }
                   1343: 
                   1344: release: ;
                   1345:     if (cp)
                   1346:        free (cp);
                   1347:     (void) lkfclose (dp, mp -> foldpath);
                   1348:     if (vmh) {
                   1349:        (void) ttyR (NULLCMD);
                   1350:        (void) pFIN ();
                   1351:     }
                   1352: }
                   1353: 
                   1354: /*  */
                   1355: 
                   1356: static int getargs (prompt, sw, cmdp)
                   1357: char   *prompt;
                   1358: struct swit *sw;
                   1359: struct Cmd *cmdp;
                   1360: {
                   1361:     int     i;
                   1362:     char   *cp;
                   1363:     static char buffer[BUFSIZ];
                   1364: 
                   1365:     told_to_quit = 0;
                   1366:     for (;;) {
                   1367:        interrupted = 0;
                   1368: #ifdef BSD42
                   1369:        switch (setjmp (sigenv)) {
                   1370:            case OK:
                   1371:                should_intr = 1;
                   1372:                break;
                   1373: 
                   1374:            default:
                   1375:                should_intr = 0;
                   1376:                if (interrupted && !told_to_quit) {
                   1377:                    (void) putchar ('\n');
                   1378:                    continue;
                   1379:                }
                   1380:                if (ppid > 0)
                   1381:                    (void) kill (ppid, SIGEMT);
                   1382:                return EOF;
                   1383:        }
                   1384: #endif BSD42
                   1385:        if (interactive) {
                   1386:            printf ("%s", prompt);
                   1387:            (void) fflush (stdout);
                   1388:        }
                   1389:        for (cp = buffer; (i = getchar ()) != '\n';) {
                   1390: #ifndef        BSD42
                   1391:            if (interrupted && !told_to_quit) {
                   1392:                buffer[0] = NULL;
                   1393:                (void) putchar ('\n');
                   1394:                break;
                   1395:            }
                   1396:            if (told_to_quit || i == EOF) {
                   1397:                if (ppid > 0)
                   1398:                    (void) kill (ppid, SIGEMT);
                   1399:                return EOF;
                   1400:            }
                   1401: #else  BSD42
                   1402:            if (i == EOF)
                   1403:                longjmp (sigenv, DONE);
                   1404: #endif BSD42
                   1405:            if (cp < &buffer[sizeof buffer - 2])
                   1406:                *cp++ = i;
                   1407:        }
                   1408:        *cp = NULL;
                   1409: 
                   1410:        if (buffer[0] == NULL)
                   1411:            continue;
                   1412:        if (buffer[0] == '?') {
                   1413:            printf ("commands:\n");
                   1414:            printsw (ALL, sw, "");
                   1415:            printf ("type CTRL-D or use ``quit'' to leave %s\n",
                   1416:                    invo_name);
                   1417:            continue;
                   1418:        }
                   1419: 
                   1420:        if (parse (buffer, cmdp) == NOTOK)
                   1421:            continue;
                   1422: 
                   1423:        switch (i = smatch (cmdp -> args[0], sw)) {
                   1424:            case AMBIGSW:
                   1425:                ambigsw (cmdp -> args[0], sw);
                   1426:                continue;
                   1427:            case UNKWNSW:
                   1428:                printf ("say what: ``%s'' -- type ? (or help) for help\n",
                   1429:                        cmdp -> args[0]);
                   1430:                continue;
                   1431:            default:
                   1432: #ifdef BSD42
                   1433:                should_intr = 0;
                   1434: #endif BSD42
                   1435:                return i;
                   1436:        }
                   1437:     }
                   1438: }
                   1439: 
                   1440: /*  */
                   1441: 
                   1442: static int getcmds (sw, cmdp, scansw)
                   1443: struct swit *sw;
                   1444: struct Cmd *cmdp;
                   1445: int    scansw;
                   1446: {
                   1447:     int     i;
                   1448:     struct record   rcs,
                   1449:                    *rc = &rcs;
                   1450: 
                   1451:     initrc (rc);
                   1452: 
                   1453:     for (;;)
                   1454:        switch (peer2rc (rc)) {
                   1455:            case RC_QRY:
                   1456:                (void) pQRY (rc -> rc_data, scansw);
                   1457:                break;
                   1458: 
                   1459:            case RC_CMD:
                   1460:                if ((i = pCMD (rc -> rc_data, sw, cmdp)) != NOTOK)
                   1461:                    return i;
                   1462:                break;
                   1463: 
                   1464:            case RC_FIN:
                   1465:                if (ppid > 0)
                   1466:                    (void) kill (ppid, SIGEMT);
                   1467:                return EOF;
                   1468: 
                   1469:            case RC_XXX:
                   1470:                padios (NULLCP, "%s", rc -> rc_data);
                   1471: 
                   1472:            default:
                   1473:                (void) fmt2peer (RC_ERR, "pLOOP protocol screw-up");
                   1474:                done (1);
                   1475:        }
                   1476: }
                   1477: 
                   1478: /*  */
                   1479: 
                   1480: static int parse (buffer, cmdp)
                   1481: char   *buffer;
                   1482: struct Cmd *cmdp;
                   1483: {
                   1484:     int     argp = 0;
                   1485:     char    c,
                   1486:            *cp,
                   1487:            *pp;
                   1488: 
                   1489:     cmdp -> line[0] = NULL;
                   1490:     pp = cmdp -> args[argp++] = cmdp -> line;
                   1491:     cmdp -> redirect = NULL;
                   1492:     cmdp -> direction = STDIO;
                   1493:     cmdp -> stream = NULL;
                   1494: 
                   1495:     for (cp = buffer; c = *cp; cp++)
                   1496:        if (!isspace (c))
                   1497:            break;
                   1498:     if (c == NULL) {
                   1499:        if (vmh)
                   1500:            (void) fmt2peer (RC_EOF, "null command");
                   1501:        return NOTOK;
                   1502:     }
                   1503: 
                   1504:     while (c = *cp++) {
                   1505:        if (isspace (c)) {
                   1506:            while (isspace (c))
                   1507:                c = *cp++;
                   1508:            if (c == NULL)
                   1509:                break;
                   1510:            *pp++ = NULL;
                   1511:            cmdp -> args[argp++] = pp;
                   1512:            *pp = NULL;
                   1513:        }
                   1514: 
                   1515:        switch (c) {
                   1516:            case '"':
                   1517:                for (;;) {
                   1518:                    switch (c = *cp++) {
                   1519:                        case NULL:
                   1520:                            padvise (NULLCP, "unmatched \"");
                   1521:                            return NOTOK;
                   1522:                        case '"':
                   1523:                            break;
                   1524:                        case QUOTE:
                   1525:                            if ((c = *cp++) == NULL)
                   1526:                                goto no_quoting;
                   1527:                        default:
                   1528:                            *pp++ = c;
                   1529:                            continue;
                   1530:                    }
                   1531:                    break;
                   1532:                }
                   1533:                continue;
                   1534: 
                   1535:            case QUOTE:
                   1536:                if ((c = *cp++) == NULL) {
                   1537:            no_quoting: ;
                   1538:                    padvise (NULLCP, "the newline character can not be quoted");
                   1539:                    return NOTOK;
                   1540:                }
                   1541: 
                   1542:            default: ;
                   1543:                *pp++ = c;
                   1544:                continue;
                   1545: 
                   1546:            case '>':
                   1547:            case '|':
                   1548:                if (pp == cmdp -> line) {
                   1549:                    padvise (NULLCP, "invalid null command");
                   1550:                    return NOTOK;
                   1551:                }
                   1552:                if (*cmdp -> args[argp - 1] == NULL)
                   1553:                    argp--;
                   1554:                cmdp -> direction = c == '>' ? CRTIO : PIPIO;
                   1555:                if (cmdp -> direction == CRTIO && (c = *cp) == '>') {
                   1556:                    cmdp -> direction = APPIO;
                   1557:                    cp++;
                   1558:                }
                   1559:                cmdp -> redirect = pp + 1;/* sigh */
                   1560:                for (; c = *cp; cp++)
                   1561:                    if (!isspace (c))
                   1562:                        break;
                   1563:                if (c == NULL) {
                   1564:                    padvise (NULLCP, cmdp -> direction != PIPIO
                   1565:                            ? "missing name for redirect"
                   1566:                            : "invalid null command");
                   1567:                    return NOTOK;
                   1568:                }
                   1569:                (void) strcpy (cmdp -> redirect, cp);
                   1570:                if (cmdp -> direction != PIPIO) {
                   1571:                    for (; *cp; cp++)
                   1572:                        if (isspace (*cp)) {
                   1573:                            padvise (NULLCP, "bad name for redirect");
                   1574:                            return NOTOK;
                   1575:                        }
                   1576:                    if (expand (cmdp -> redirect) == NOTOK)
                   1577:                        return NOTOK;
                   1578:                }
                   1579:                break;
                   1580:        }
                   1581:        break;
                   1582:     }
                   1583: 
                   1584:     *pp++ = NULL;
                   1585:     cmdp -> args[argp] = NULL;
                   1586: 
                   1587:     return OK;
                   1588: }
                   1589: 
                   1590: /*  */
                   1591: 
                   1592: int    expand (redirect)
                   1593: char   *redirect;
                   1594: {
                   1595:     char   *cp,
                   1596:            *pp;
                   1597:     char    path[BUFSIZ];
                   1598:     struct passwd  *pw;
                   1599: 
                   1600:     if (*redirect != '~')
                   1601:        return OK;
                   1602: 
                   1603:     if (cp = index (pp = redirect + 1, '/'))
                   1604:        *cp++ = NULL;
                   1605:     if (*pp == NULL)
                   1606:        pp = mypath;
                   1607:     else
                   1608:        if (pw = getpwnam (pp))
                   1609:            pp = pw -> pw_dir;
                   1610:        else {
                   1611:            padvise (NULLCP, "unknown user: %s", pp);
                   1612:            return NOTOK;
                   1613:        }
                   1614: 
                   1615:     (void) sprintf (path, "%s/%s", pp, cp ? cp : "");
                   1616:     (void) strcpy (redirect, path);
                   1617:     return OK;
                   1618: }
                   1619: 
                   1620: /*  */
                   1621: 
                   1622: static int init_io (cmdp, vio)
                   1623: register struct Cmd *cmdp;
                   1624: int    vio;
                   1625: {
                   1626:     int     io,
                   1627:             result;
                   1628: 
                   1629:     io = vmh;
                   1630: 
                   1631:     vmh = vio;
                   1632:     result = initaux_io (cmdp);
                   1633:     vmh = io;
                   1634: 
                   1635:     return result;
                   1636: }
                   1637: 
                   1638: 
                   1639: static int initaux_io (cmdp)
                   1640: register struct Cmd *cmdp;
                   1641: {
                   1642:     char   *mode;
                   1643: 
                   1644:     switch (cmdp -> direction) {
                   1645:        case STDIO:
                   1646:            return OK;
                   1647: 
                   1648:        case CRTIO:
                   1649:        case APPIO:
                   1650:            mode = cmdp -> direction == CRTIO ? "write" : "append";
                   1651:            if ((cmdp -> stream = fopen (cmdp -> redirect, mode)) == NULL) {
                   1652:                padvise (cmdp -> redirect, "unable to %s ", mode);
                   1653:                cmdp -> direction = STDIO;
                   1654:                return NOTOK;
                   1655:            }
                   1656:            break;
                   1657: 
                   1658:        case PIPIO:
                   1659:            if ((cmdp -> stream = popen (cmdp -> redirect, "w")) == NULL) {
                   1660:                padvise (cmdp -> redirect, "unable to pipe");
                   1661:                cmdp -> direction = STDIO;
                   1662:                return NOTOK;
                   1663:            }
                   1664:            (void) signal (SIGPIPE, pipeser);
                   1665:            broken_pipe = 0;
                   1666:            break;
                   1667: 
                   1668:        default:
                   1669:            padios (NULLCP, "unknown redirection for command");
                   1670:     }
                   1671: 
                   1672:     (void) fflush (stdout);
                   1673:     if (dup2 (fileno (cmdp -> stream), fileno (stdout)) == NOTOK)
                   1674:        padios ("standard output", "unable to dup2");
                   1675:     clearerr (stdout);
                   1676: 
                   1677:     return OK;
                   1678: }
                   1679: 
                   1680: /*  */
                   1681: 
                   1682: static void fin_io (cmdp, vio)
                   1683: register struct Cmd *cmdp;
                   1684: int    vio;
                   1685: {
                   1686:     int     io;
                   1687: 
                   1688:     io = vmh;
                   1689: 
                   1690:     vmh = vio;
                   1691:     finaux_io (cmdp);
                   1692:     vmh = io;
                   1693: }
                   1694: 
                   1695: 
                   1696: static int finaux_io (cmdp)
                   1697: register struct Cmd *cmdp;
                   1698: {
                   1699:     switch (cmdp -> direction) {
                   1700:        case STDIO:
                   1701:            return;
                   1702: 
                   1703:        case CRTIO:
                   1704:        case APPIO:
                   1705:            (void) fflush (stdout);
                   1706:            (void) close (fileno (stdout));
                   1707:            if (ferror (stdout))
                   1708:                padvise (NULLCP, "problems writing %s", cmdp -> redirect);
                   1709:            (void) fclose (cmdp -> stream);
                   1710:            break;
                   1711: 
                   1712:        case PIPIO:
                   1713:            (void) fflush (stdout);
                   1714:            (void) close (fileno (stdout));
                   1715:            (void) pclose (cmdp -> stream);
                   1716:            (void) signal (SIGPIPE, SIG_DFL);
                   1717:            break;
                   1718: 
                   1719:        default:
                   1720:            padios (NULLCP, "unknown redirection for command");
                   1721:     }
                   1722: 
                   1723:     if (dup2 (fileno (sp), fileno (stdout)) == NOTOK)
                   1724:        padios ("standard output", "unable to dup2");
                   1725:     clearerr (stdout);
                   1726: 
                   1727:     cmdp -> direction = STDIO;
                   1728: }
                   1729: 
                   1730: /*  */
                   1731: 
                   1732: static void m_init ()
                   1733: {
                   1734:     int     msgnum;
                   1735: 
                   1736:     for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
                   1737:        mp -> msgstats[msgnum] &= ~SELECTED;
                   1738:     mp -> lowsel = mp -> hghsel = mp -> numsel = 0;
                   1739: }
                   1740: 
                   1741: 
                   1742: m_reset ()
                   1743: {
                   1744:     write_ids ();
                   1745:     m_fmsg (mp);
                   1746:     myname = NULL;
                   1747: #ifdef BPOP
                   1748:     if (pmsh) {
                   1749:        (void) pop_done ();
                   1750:        pmsh = 0;
                   1751:     }
                   1752: #endif BPOP
                   1753: }
                   1754: 
                   1755: /*  */
                   1756: 
                   1757: void   m_setcur (mp, msgnum)
                   1758: register struct msgs *mp;
                   1759: register int msgnum;
                   1760: {
                   1761:     if (mp -> curmsg == msgnum)
                   1762:        return;
                   1763: 
                   1764:     if (mp -> curmsg && Msgs[mp -> curmsg].m_scanl) {
                   1765:        free (Msgs[mp -> curmsg].m_scanl);
                   1766:        Msgs[mp -> curmsg].m_scanl = NULL;
                   1767:     }
                   1768:     if (Msgs[msgnum].m_scanl) {
                   1769:        free (Msgs[msgnum].m_scanl);
                   1770:        Msgs[msgnum].m_scanl = NULL;
                   1771:     }
                   1772: 
                   1773:     mp -> curmsg = msgnum;
                   1774: }
                   1775: 
                   1776: /*  */
                   1777: 
                   1778: /* ARGSUSED */
                   1779: 
                   1780: static SIGDECL
                   1781: intrser(i)
                   1782:        int i;
                   1783: {
                   1784: #ifndef        BSD42
                   1785:     (void) signal (SIGINT, intrser);
                   1786: #endif not BSD42
                   1787: 
                   1788:     discard (stdout);
                   1789: 
                   1790:     interrupted++;
                   1791: #ifdef BSD42
                   1792:     if (should_intr)
                   1793:        longjmp (sigenv, NOTOK);
                   1794: #endif BSD42
                   1795: }
                   1796: 
                   1797: 
                   1798: /* ARGSUSED */
                   1799: 
                   1800: static SIGDECL
                   1801: pipeser(i)
                   1802:        int i;
                   1803: {
                   1804: #ifndef        BSD42
                   1805:     (void) signal (SIGPIPE, pipeser);
                   1806: #endif not BSD42
                   1807: 
                   1808:     if (broken_pipe++ == 0)
                   1809:        fprintf (stderr, "broken pipe\n");
                   1810:     told_to_quit++;
                   1811:     interrupted++;
                   1812: #ifdef BSD42
                   1813:     if (should_intr)
                   1814:        longjmp (sigenv, NOTOK);
                   1815: #endif BSD42
                   1816: }
                   1817: 
                   1818: 
                   1819: /* ARGSUSED */
                   1820: 
                   1821: static SIGDECL
                   1822: quitser(i)
                   1823:        int i;
                   1824: {
                   1825: #ifndef        BSD42
                   1826:     (void) signal (SIGQUIT, quitser);
                   1827: #endif BSD42
                   1828: 
                   1829:     told_to_quit++;
                   1830:     interrupted++;
                   1831: #ifdef BSD42
                   1832:     if (should_intr)
                   1833:        longjmp (sigenv, NOTOK);
                   1834: #endif BSD42
                   1835: }
                   1836: 
                   1837: /*  */
                   1838: 
                   1839: static int
                   1840: pINI()
                   1841: {
                   1842:     int     i,
                   1843:             vrsn;
                   1844:     char   *bp;
                   1845:     struct record   rcs,
                   1846:                    *rc = &rcs;
                   1847: 
                   1848:     initrc (rc);
                   1849: 
                   1850:     switch (peer2rc (rc)) {
                   1851:        case RC_INI:
                   1852:            bp = rc -> rc_data;
                   1853:            while (isspace (*bp))
                   1854:                bp++;
                   1855:            if (sscanf (bp, "%d", &vrsn) != 1) {
                   1856:        bad_init: ;
                   1857:                (void) fmt2peer (RC_ERR, "bad init \"%s\"", rc -> rc_data);
                   1858:                done (1);
                   1859:            }
                   1860:            if (vrsn != RC_VRSN) {
                   1861:                (void) fmt2peer (RC_ERR, "version %d unsupported", vrsn);
                   1862:                done (1);
                   1863:            }
                   1864: 
                   1865:            while (*bp && !isspace (*bp))
                   1866:                bp++;
                   1867:            while (isspace (*bp))
                   1868:                bp++;
                   1869:            if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0)
                   1870:                goto bad_init;
                   1871:            if (numwins > NWIN)
                   1872:                numwins = NWIN;
                   1873: 
                   1874:            for (i = 1; i <= numwins; i++) {
                   1875:                while (*bp && !isspace (*bp))
                   1876:                    bp++;
                   1877:                while (isspace (*bp))
                   1878:                    bp++;
                   1879:                if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0)
                   1880:                    goto bad_init;
                   1881:            }
                   1882:            (void) rc2peer (RC_ACK, 0, NULLCP);
                   1883:            return OK;
                   1884: 
                   1885:        case RC_XXX:
                   1886:            padios (NULLCP, "%s", rc -> rc_data);
                   1887: 
                   1888:        default:
                   1889:            (void) fmt2peer (RC_ERR, "pINI protocol screw-up");
                   1890:            done (1);           /* NOTREACHED */
                   1891:     }
                   1892: }
                   1893: 
                   1894: /*  */
                   1895: 
                   1896: /* ARGSUSED */
                   1897: 
                   1898: static int pQRY (str, scansw)
                   1899: char   *str;
                   1900: int    scansw;
                   1901: {
                   1902:     if (pQRY1 (scansw) == NOTOK || pQRY2 () == NOTOK)
                   1903:        return NOTOK;
                   1904: 
                   1905:     (void) rc2peer (RC_EOF, 0, NULLCP);
                   1906:     return OK;
                   1907: }
                   1908: 
                   1909: /*  */
                   1910: 
                   1911: static int pQRY1 (scansw)
                   1912: int    scansw;
                   1913: {
                   1914:     int     oldhgh;
                   1915:     static int  lastlow = 0,
                   1916:                 lastcur = 0,
                   1917:                 lasthgh = 0,
                   1918:                lastnum = 0;
                   1919: 
                   1920:     oldhgh = mp -> hghmsg;
                   1921:     if (check_folder (scansw) && oldhgh < mp -> hghmsg) {
                   1922:        switch (winX (STATUS)) {
                   1923:            case NOTOK:
                   1924:                return NOTOK;
                   1925: 
                   1926:            case OK:
                   1927:                printf ("new messages have arrived!");
                   1928:                (void) fflush (stdout);
                   1929:                (void) fflush (stderr);
                   1930:                _exit (0);      /* NOTREACHED */
                   1931: 
                   1932:            default:
                   1933:                lastlow = lastcur = lasthgh = lastnum = 0;
                   1934:                break;
                   1935:        }
                   1936: 
                   1937:        switch (winX (DISPLAY)) {
                   1938:            case NOTOK:
                   1939:                return NOTOK;
                   1940: 
                   1941:            case OK:
                   1942:                scanrange (oldhgh + 1, mp -> hghmsg);
                   1943:                (void) fflush (stdout);
                   1944:                (void) fflush (stderr);
                   1945:                _exit (0);      /* NOTREACHED */
                   1946: 
                   1947:            default:
                   1948:                break;
                   1949:        }
                   1950:        return OK;
                   1951:     }
                   1952: 
                   1953:     if (gap)
                   1954:        switch (winX (STATUS)) {
                   1955:            case NOTOK:
                   1956:                return NOTOK;
                   1957: 
                   1958:            case OK:
                   1959:                printf ("%s: gap in ID:s, last seen %d, lowest present %d\n",
                   1960:                    myname ? myname : fmsh ? fmsh : mp -> foldpath, gap - 1,
                   1961:                    readid (mp -> lowmsg));
                   1962:                (void) fflush (stdout);
                   1963:                (void) fflush (stderr);
                   1964:                _exit (0);      /* NOTREACHED */
                   1965: 
                   1966:            default:
                   1967:                gap = 0;
                   1968:                return OK;
                   1969:        }
                   1970: 
                   1971:     if (mp -> lowmsg != lastlow
                   1972:            || mp -> curmsg != lastcur
                   1973:            || mp -> hghmsg != lasthgh
                   1974:            || mp -> nummsg != lastnum)
                   1975:        switch (winX (STATUS)) {
                   1976:            case NOTOK:
                   1977:                return NOTOK;
                   1978: 
                   1979:            case OK:
                   1980:                foldcmd (NULLVP);
                   1981:                (void) fflush (stdout);
                   1982:                (void) fflush (stderr);
                   1983:                _exit (0);      /* NOTREACHED */
                   1984: 
                   1985:            default:
                   1986:                lastlow = mp -> lowmsg;
                   1987:                lastcur = mp -> curmsg;
                   1988:                lasthgh = mp -> hghmsg;
                   1989:                lastnum = mp -> nummsg;
                   1990:                return OK;
                   1991:        }
                   1992: 
                   1993:     return OK;
                   1994: }
                   1995: 
                   1996: /*  */
                   1997: 
                   1998: static int pQRY2 ()
                   1999: {
                   2000:     int     i,
                   2001:             j,
                   2002:            k,
                   2003:             msgnum,
                   2004:             n;
                   2005:     static int  cur = 0,
                   2006:                 num = 0,
                   2007:                lo = 0,
                   2008:                hi = 0;
                   2009: 
                   2010:     if (mp -> nummsg == 0 && mp -> nummsg != num)
                   2011:        switch (winX (SCAN)) {
                   2012:            case NOTOK:
                   2013:                return NOTOK;
                   2014: 
                   2015:            case OK:
                   2016:                printf ("empty!");
                   2017:                (void) fflush (stdout);
                   2018:                (void) fflush (stderr);
                   2019:                _exit (0);      /* NOTREACHED */
                   2020: 
                   2021:            default:
                   2022:                num = mp -> nummsg;
                   2023:                return OK;
                   2024:        }
                   2025:     num = mp -> nummsg;
                   2026: 
                   2027:     i = 0;
                   2028:     j = (k = windows[SCAN]) / 2;
                   2029:     for (msgnum = mp -> curmsg; msgnum <= mp -> hghmsg; msgnum++)
                   2030:        if (mp -> msgstats[msgnum] & EXISTS)
                   2031:            i++;
                   2032:     if (i-- > 0)
                   2033:        if (topcur)
                   2034:            k = i >= k ? 1 : k - i;
                   2035:        else
                   2036:            k -= i > j ? j : i;
                   2037: 
                   2038:     i = j = 0;
                   2039:     n = 1;
                   2040:     for (msgnum = mp -> curmsg; msgnum >= mp -> lowmsg; msgnum--)
                   2041:        if (mp -> msgstats[msgnum] & EXISTS) {
                   2042:            i = msgnum;
                   2043:            if (j == 0)
                   2044:                j = msgnum;
                   2045:            if (n++ >= k)
                   2046:                break;
                   2047:        }
                   2048:     for (msgnum = mp -> curmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
                   2049:        if (mp -> msgstats[msgnum] & EXISTS) {
                   2050:            if (i == 0)
                   2051:                i = msgnum;
                   2052:            j = msgnum;
                   2053:            if (n++ >= windows[SCAN])
                   2054:                break;
                   2055:        }
                   2056:     if (!topcur
                   2057:            && lo > 0
                   2058:            && hi > 0
                   2059:            && mp -> msgstats[lo] & EXISTS
                   2060:            && mp -> msgstats[hi] & EXISTS
                   2061:            && (lo < mp -> curmsg
                   2062:                    || (lo == mp -> curmsg && lo == mp -> lowmsg))
                   2063:            && (mp -> curmsg < hi
                   2064:                    || (hi == mp -> curmsg && hi == mp -> hghmsg))
                   2065:            && hi - lo == j - i)
                   2066:        i = lo, j = hi;
                   2067: 
                   2068:     if (mp -> curmsg != cur || modified)
                   2069:        switch (winN (NULLCMD, SCAN, 0)) {
                   2070:            case NOTOK:
                   2071:                return NOTOK;
                   2072: 
                   2073:            case OK:
                   2074:                return OK;
                   2075: 
                   2076:            default:
                   2077:                scanrange (lo = i, hi = j);
                   2078:                cur = mp -> curmsg;
                   2079:                (void) winR (NULLCMD);
                   2080:                return OK;
                   2081:        }
                   2082: 
                   2083:     return OK;
                   2084: }
                   2085: 
                   2086: /*  */
                   2087: 
                   2088: static int pCMD (str, sw, cmdp)
                   2089: char   *str;
                   2090: struct swit *sw;
                   2091: struct Cmd *cmdp;
                   2092: {
                   2093:     int     i;
                   2094: 
                   2095:     if (*str == '?')
                   2096:        switch (winX (DISPLAY)) {
                   2097:            case NOTOK:
                   2098:                return NOTOK;
                   2099: 
                   2100:            case OK:
                   2101:                printf ("commands:\n");
                   2102:                printsw (ALL, sw, "");
                   2103:                printf ("type ``quit'' to leave %s\n", invo_name);
                   2104:                (void) fflush (stdout);
                   2105:                (void) fflush (stderr);
                   2106:                _exit (0);      /* NOTREACHED */
                   2107: 
                   2108:            default:
                   2109:                (void) rc2peer (RC_EOF, 0, NULLCP);
                   2110:                return NOTOK;
                   2111:        }
                   2112: 
                   2113:     if (parse (str, cmdp) == NOTOK)
                   2114:        return NOTOK;
                   2115: 
                   2116:     switch (i = smatch (cmdp -> args[0], sw)) {
                   2117:        case AMBIGSW:
                   2118:            switch (winX (DISPLAY)) {
                   2119:                case NOTOK:
                   2120:                    return NOTOK;
                   2121: 
                   2122:                case OK:
                   2123:                    ambigsw (cmdp -> args[0], sw);
                   2124:                    (void) fflush (stdout);
                   2125:                    (void) fflush (stderr);
                   2126:                    _exit (0);  /* NOTREACHED */
                   2127: 
                   2128:                default:
                   2129:                    (void) rc2peer (RC_EOF, 0, NULLCP);
                   2130:                    return NOTOK;
                   2131:            }
                   2132: 
                   2133:        case UNKWNSW:
                   2134:            (void) fmt2peer (RC_ERR,
                   2135:                    "say what: ``%s'' -- type ? (or help) for help",
                   2136:                    cmdp -> args[0]);
                   2137:            return NOTOK;
                   2138: 
                   2139:        default:
                   2140:            return i;
                   2141:     }
                   2142: }
                   2143: 
                   2144: /*  */
                   2145: 
                   2146: static int pFIN ()
                   2147: {
                   2148:     int     status;
                   2149: 
                   2150:     switch (setjmp (peerenv)) {
                   2151:        case OK:
                   2152:            (void) signal (SIGALRM, alrmser);
                   2153:            (void) alarm (ALARM);
                   2154: 
                   2155:            status = peerwait ();
                   2156: 
                   2157:            (void) alarm (0);
                   2158:            return status;
                   2159: 
                   2160:        default:
                   2161:            return NOTOK;
                   2162:     }
                   2163: }
                   2164: 
                   2165: 
                   2166: static int peerwait ()
                   2167: {
                   2168:     struct record   rcs,
                   2169:                    *rc = &rcs;
                   2170: 
                   2171:     initrc (rc);
                   2172: 
                   2173:     switch (peer2rc (rc)) {
                   2174:        case RC_QRY:
                   2175:        case RC_CMD:
                   2176:            (void) rc2peer (RC_FIN, 0, NULLCP);
                   2177:            return OK;
                   2178: 
                   2179:        case RC_XXX:
                   2180:            advise (NULLCP, "%s", rc -> rc_data);
                   2181:            return NOTOK;
                   2182: 
                   2183:        default:
                   2184:            (void) fmt2peer (RC_FIN, "pLOOP protocol screw-up");
                   2185:            return NOTOK;
                   2186:     }
                   2187: }
                   2188: 
                   2189: 
                   2190: /* ARGSUSED */
                   2191: 
                   2192: static int alrmser (i)
                   2193: int    i;
                   2194: {
                   2195:     longjmp (peerenv, DONE);
                   2196: }
                   2197: 
                   2198: /*  */
                   2199: 
                   2200: static int ttyNaux (cmdp, s)
                   2201: register struct Cmd *cmdp;
                   2202: char   *s;
                   2203: {
                   2204:     struct record   rcs,
                   2205:                    *rc = &rcs;
                   2206: 
                   2207:     initrc (rc);
                   2208: 
                   2209:     if (cmdp && init_io (cmdp, vmh) == NOTOK)
                   2210:        return NOTOK;
                   2211: 
                   2212:     if (!fmsh)
                   2213:        (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
                   2214: 
                   2215:     vmhtty = NOTOK;
                   2216:     switch (rc2rc (RC_TTY, s ? strlen (s) : 0, s, rc)) {
                   2217:        case RC_ACK:
                   2218:            vmhtty = OK;        /* fall */
                   2219:        case RC_ERR:
                   2220:            break;
                   2221: 
                   2222:        case RC_XXX:
                   2223:            padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
                   2224: 
                   2225:        default:
                   2226:            (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
                   2227:            done (1);           /* NOTREACHED */
                   2228:     }
                   2229: 
                   2230: #ifdef SIGTSTP
                   2231:     (void) signal (SIGTSTP, tstat);
                   2232: #endif SIGTSTP
                   2233:     return vmhtty;
                   2234: }
                   2235: 
                   2236: /*  */
                   2237: 
                   2238: static int ttyR (cmdp)
                   2239: register struct Cmd *cmdp;
                   2240: {
                   2241:     struct record   rcs,
                   2242:                    *rc = &rcs;
                   2243: 
                   2244: #ifdef SIGTSTP
                   2245:     (void) signal (SIGTSTP, SIG_IGN);
                   2246: #endif SIGTSTP
                   2247: 
                   2248:     if (vmhtty != OK)
                   2249:        return NOTOK;
                   2250: 
                   2251:     initrc (rc);
                   2252: 
                   2253:     if (cmdp)
                   2254:        fin_io (cmdp, 0);
                   2255: 
                   2256:     vmhtty = NOTOK;
                   2257:     switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
                   2258:        case RC_ACK:
                   2259:            (void) rc2peer (RC_EOF, 0, NULLCP);
                   2260:            return OK;
                   2261: 
                   2262:        case RC_XXX:
                   2263:            padios (NULLCP, "%s", rc -> rc_data);/* NOTREACHED */
                   2264: 
                   2265:        default:
                   2266:            (void) fmt2peer (RC_ERR, "pTTY protocol screw-up");
                   2267:            done (1);           /* NOTREACHED */
                   2268:     }
                   2269: }
                   2270: 
                   2271: /*  */
                   2272: 
                   2273: static int winN (cmdp, n, eof)
                   2274: register struct Cmd *cmdp;
                   2275: int    n,
                   2276:        eof;
                   2277: {
                   2278:     int     i,
                   2279:             pd[2];
                   2280:     char    buffer[BUFSIZ];
                   2281:     struct record   rcs,
                   2282:                    *rc = &rcs;
                   2283: 
                   2284:     if (vmhpid == NOTOK)
                   2285:        return OK;
                   2286: 
                   2287:     initrc (rc);
                   2288: 
                   2289:     if (!fmsh)
                   2290:        (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
                   2291: 
                   2292:     vmhpid = OK;
                   2293: 
                   2294:     (void) sprintf (buffer, "%d", n);
                   2295:     switch (str2rc (RC_WIN, buffer, rc)) {
                   2296:        case RC_ACK:
                   2297:            break;
                   2298: 
                   2299:        case RC_ERR:
                   2300:            return NOTOK;
                   2301: 
                   2302:        case RC_XXX:
                   2303:            padios (NULLCP, "%s", rc -> rc_data);
                   2304: 
                   2305:        default:
                   2306:            (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2307:            done (1);
                   2308:     }
                   2309: 
                   2310:     if (pipe (pd) == NOTOK) {
                   2311:        (void) err2peer (RC_ERR, "pipe", "unable to");
                   2312:        return NOTOK;
                   2313:     }
                   2314: 
                   2315:     switch (vmhpid = fork ()) {
                   2316:        case NOTOK:
                   2317:            (void) err2peer (RC_ERR, "fork", "unable to");
                   2318:            (void) close (pd[0]);
                   2319:            (void) close (pd[1]);
                   2320:            return NOTOK;
                   2321: 
                   2322:        case OK:
                   2323:            (void) close (pd[1]);
                   2324:            (void) signal (SIGPIPE, SIG_IGN);
                   2325:            while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
                   2326:                switch (rc2rc (RC_DATA, i, buffer, rc)) {
                   2327:                    case RC_ACK:
                   2328:                        break;
                   2329: 
                   2330:                    case RC_ERR:
                   2331:                        _exit (1);
                   2332: 
                   2333:                    case RC_XXX:
                   2334:                        advise (NULLCP, "%s", rc -> rc_data);
                   2335:                        _exit (2);
                   2336: 
                   2337:                    default:
                   2338:                        (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2339:                        _exit (2);
                   2340:                }
                   2341:            if (i == OK)
                   2342:                switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
                   2343:                    case RC_ACK:
                   2344:                        if (eof)
                   2345:                            (void) rc2peer (RC_EOF, 0, NULLCP);
                   2346:                        i = 0;
                   2347:                        break;
                   2348: 
                   2349:                    case RC_XXX:
                   2350:                        advise (NULLCP, "%s", rc -> rc_data);
                   2351:                        i = 2;
                   2352:                        break;
                   2353: 
                   2354:                    default:
                   2355:                        (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2356:                        i = 2;
                   2357:                        break;
                   2358:                }
                   2359:            if (i == NOTOK)
                   2360:                (void) err2peer (RC_ERR, "pipe", "error reading from");
                   2361:            (void) close (pd[0]);
                   2362:            _exit (i != NOTOK ? i : 1);
                   2363: 
                   2364:        default:
                   2365:            if ((vmhfd0 = dup (fileno (stdin))) == NOTOK)
                   2366:                padios ("standard input", "unable to dup");
                   2367:            if ((vmhfd1 = dup (fileno (stdout))) == NOTOK)
                   2368:                padios ("standard output", "unable to dup");
                   2369:            if ((vmhfd2 = dup (fileno (stderr))) == NOTOK)
                   2370:                padios ("diagnostic output", "unable to dup");
                   2371: 
                   2372:            (void) close (0);
                   2373:            if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
                   2374:                (void) dup2 (i, fileno (stdin));
                   2375:                (void) close (i);
                   2376:            }
                   2377: 
                   2378:            (void) fflush (stdout);
                   2379:            if (dup2 (pd[1], fileno (stdout)) == NOTOK)
                   2380:                padios ("standard output", "unable to dup2");
                   2381:            clearerr (stdout);
                   2382: 
                   2383:            (void) fflush (stderr);
                   2384:            if (dup2 (pd[1], fileno (stderr)) == NOTOK)
                   2385:                padios ("diagnostic output", "unable to dup2");
                   2386:            clearerr (stderr);
                   2387: 
                   2388:            if (cmdp && init_io (cmdp, 0) == NOTOK)
                   2389:                return NOTOK;
                   2390:            pstat = signal (SIGPIPE, pipeser);
                   2391:            broken_pipe = 1;
                   2392: 
                   2393:            (void) close (pd[0]);
                   2394:            (void) close (pd[1]);
                   2395: 
                   2396:            return vmhpid;
                   2397:     }
                   2398: }
                   2399: 
                   2400: /*  */
                   2401: 
                   2402: static int winR (cmdp)
                   2403: register struct Cmd *cmdp;
                   2404: {
                   2405:     int     status;
                   2406: 
                   2407:     if (vmhpid <= OK)
                   2408:        return NOTOK;
                   2409: 
                   2410:     if (cmdp)
                   2411:        fin_io (cmdp, 0);
                   2412: 
                   2413:     if (dup2 (vmhfd0, fileno (stdin)) == NOTOK)
                   2414:        padios ("standard input", "unable to dup2");
                   2415:     clearerr (stdin);
                   2416:     (void) close (vmhfd0);
                   2417: 
                   2418:     (void) fflush (stdout);
                   2419:     if (dup2 (vmhfd1, fileno (stdout)) == NOTOK)
                   2420:        padios ("standard output", "unable to dup2");
                   2421:     clearerr (stdout);
                   2422:     (void) close (vmhfd1);
                   2423: 
                   2424:     (void) fflush (stderr);
                   2425:     if (dup2 (vmhfd2, fileno (stderr)) == NOTOK)
                   2426:        padios ("diagnostic output", "unable to dup2");
                   2427:     clearerr (stderr);
                   2428:     (void) close (vmhfd2);
                   2429: 
                   2430:     (void) signal (SIGPIPE, pstat);
                   2431: 
                   2432:     if ((status = pidwait (vmhpid, OK)) == 2)
                   2433:        done (1);
                   2434: 
                   2435:     vmhpid = OK;
                   2436:     return (status == 0 ? OK : NOTOK);
                   2437: }
                   2438: 
                   2439: /*  */
                   2440: 
                   2441: static int winX (n)
                   2442: int    n;
                   2443: {
                   2444:     int     i,
                   2445:             pid,
                   2446:             pd[2];
                   2447:     char    buffer[BUFSIZ];
                   2448:     struct record   rcs,
                   2449:                    *rc = &rcs;
                   2450: 
                   2451:     initrc (rc);
                   2452: 
                   2453:     if (!fmsh)
                   2454:        (void) fseek (fp, 0L, 0);/* XXX: fseek() too tricky for our own good */
                   2455: 
                   2456:     (void) sprintf (buffer, "%d", n);
                   2457:     switch (str2rc (RC_WIN, buffer, rc)) {
                   2458:        case RC_ACK:
                   2459:            break;
                   2460: 
                   2461:        case RC_ERR:
                   2462:            return NOTOK;
                   2463: 
                   2464:        case RC_XXX:
                   2465:            padios (NULLCP, "%s", rc -> rc_data);
                   2466: 
                   2467:        default:
                   2468:            (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2469:            done (1);
                   2470:     }
                   2471: 
                   2472:     if (pipe (pd) == NOTOK) {
                   2473:        (void) err2peer (RC_ERR, "pipe", "unable to");
                   2474:        return NOTOK;
                   2475:     }
                   2476: 
                   2477:     switch (pid = fork ()) {
                   2478:        case NOTOK:
                   2479:            (void) err2peer (RC_ERR, "fork", "unable to");
                   2480:            (void) close (pd[0]);
                   2481:            (void) close (pd[1]);
                   2482:            return NOTOK;
                   2483: 
                   2484:        case OK:
                   2485:            (void) close (fileno (stdin));
                   2486:            if ((i = open ("/dev/null", 0)) != NOTOK && i != fileno (stdin)) {
                   2487:                (void) dup2 (i, fileno (stdin));
                   2488:                (void) close (i);
                   2489:            }
                   2490:            (void) dup2 (pd[1], fileno (stdout));
                   2491:            (void) dup2 (pd[1], fileno (stderr));
                   2492:            (void) close (pd[0]);
                   2493:            (void) close (pd[1]);
                   2494:            vmhpid = NOTOK;
                   2495:            return OK;
                   2496: 
                   2497:        default:
                   2498:            (void) close (pd[1]);
                   2499:            while ((i = read (pd[0], buffer, sizeof buffer)) > 0)
                   2500:                switch (rc2rc (RC_DATA, i, buffer, rc)) {
                   2501:                    case RC_ACK:
                   2502:                        break;
                   2503: 
                   2504:                    case RC_ERR:
                   2505:                        (void) close (pd[0]);
                   2506:                        (void) pidwait (pid, OK);
                   2507:                        return NOTOK;
                   2508: 
                   2509:                    case RC_XXX:
                   2510:                        padios (NULLCP, "%s", rc -> rc_data);
                   2511: 
                   2512:                    default:
                   2513:                        (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2514:                        done (1);
                   2515:                }
                   2516:            if (i == OK)
                   2517:                switch (rc2rc (RC_EOF, 0, NULLCP, rc)) {
                   2518:                    case RC_ACK:
                   2519:                        break;
                   2520: 
                   2521:                    case RC_XXX:
                   2522:                        padios (NULLCP, "%s", rc -> rc_data);
                   2523: 
                   2524:                    default:
                   2525:                        (void) fmt2peer (RC_ERR, "pWIN protocol screw-up");
                   2526:                        done (1);
                   2527:                }
                   2528:            if (i == NOTOK)
                   2529:                (void) err2peer (RC_ERR, "pipe", "error reading from");
                   2530: 
                   2531:            (void) close (pd[0]);
                   2532:            (void) pidwait (pid, OK);
                   2533:            return (i != NOTOK ? pid : NOTOK);
                   2534:     }
                   2535: }
                   2536: 
                   2537: /*  */
                   2538: 
                   2539: /* VARARGS2 */
                   2540: 
                   2541: void   padios (what, fmt, a, b, c, d, e, f)
                   2542: char   *what,
                   2543:        *fmt,
                   2544:        *a,
                   2545:        *b,
                   2546:        *c,
                   2547:        *d,
                   2548:        *e,
                   2549:        *f;
                   2550: {
                   2551:     if (vmh) {
                   2552:        (void) err2peer (RC_FIN, what, fmt, a, b, c, d, e, f);
                   2553:        (void) rcdone ();
                   2554:     }
                   2555:     else
                   2556:        advise (what, fmt, a, b, c, d, e, f);
                   2557: 
                   2558:     done (1);
                   2559: }
                   2560: 
                   2561: 
                   2562: /* VARARGS2 */
                   2563: 
                   2564: void   padvise (what, fmt, a, b, c, d, e, f)
                   2565: char   *what,
                   2566:        *fmt,
                   2567:        *a,
                   2568:        *b,
                   2569:        *c,
                   2570:        *d,
                   2571:        *e,
                   2572:        *f;
                   2573: {
                   2574:     if (vmh)
                   2575:        (void) err2peer (RC_ERR, what, fmt, a, b, c, d, e, f);
                   2576:     else
                   2577:        advise (what, fmt, a, b, c, d, e, f);
                   2578: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.