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

unix.superglobalmegacorp.com

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