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

unix.superglobalmegacorp.com

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