Annotation of 43BSD/contrib/mh/uip/msh.c, revision 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.