Annotation of 43BSDTahoe/new/news/src/visual.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * visual - visual news interface.
        !             3:  * Kenneth Almquist
        !             4:  */
        !             5: 
        !             6: #ifdef SCCSID
        !             7: static char    *SccsId = "@(#)visual.c 1.38    10/15/87";
        !             8: #endif /* SCCSID */
        !             9: 
        !            10: #include "rparams.h"
        !            11: #ifdef USG
        !            12: #include <sys/ioctl.h>
        !            13: #include <termio.h>
        !            14: #include <fcntl.h>
        !            15: #else /* !USG */
        !            16: #include <sgtty.h>
        !            17: #endif /* !USG */
        !            18: 
        !            19: #include <errno.h>
        !            20: #ifdef BSD4_2
        !            21: #ifndef sigmask
        !            22: #define sigmask(m) (1<<((m)-1))
        !            23: #endif /* !sigmask */
        !            24: #endif /* BSD4_2 */
        !            25: 
        !            26: #ifdef MYDB
        !            27: #include "db.h"
        !            28: #endif /* MYDB */
        !            29: 
        !            30: extern int errno;
        !            31: 
        !            32: #ifdef SIGTSTP
        !            33: #include <setjmp.h>
        !            34: #endif /* SIGTSTP */
        !            35: 
        !            36: #define ARTWLEN        (ROWS-2)/* number of lines used to display article */
        !            37: #define even(cols) ((cols&1) ? cols + 1 : cols)
        !            38: #ifdef STATTOP
        !            39: #define PRLINE 0       /* prompter line */
        !            40: #define SPLINE 1       /* secondary prompt line */
        !            41: #define ARTWIN 2       /* first line of article window */
        !            42: #define SECPRLEN 81    /* length of secondary prompter */
        !            43: #else
        !            44: #define PRLINE (ROWS-1)/* prompter line */
        !            45: #define SPLINE (ROWS-2)/* secondary prompt line */
        !            46: #define ARTWIN 0       /* first line of article window */
        !            47: #define SECPRLEN 100   /* length of secondary prompter */
        !            48: #endif
        !            49: 
        !            50: #define PIPECHAR '|'   /* indicate save command should pipe to program */
        !            51: #define        CAGAIN  ('e'&0x1F)      /* Save-to-same-place indicator */
        !            52: #define META   0200    /* meta character bit (as in emacs) */
        !            53: /* print (display) flags */
        !            54: #define HDRONLY        0001    /* print header only */
        !            55: #define NOPRT  0002    /* don't print at all */
        !            56: #define NEWART 0004    /* force article display to be regenerated */
        !            57: #define HELPMSG        0010    /* display currently contains help message */
        !            58: /* prun flags */
        !            59: #define CWAIT  0001    /* type "continue?" and wait for return */
        !            60: #define BKGRND 0002    /* run process in the background */
        !            61: /* values of curflag */
        !            62: #define CURP1  1       /* cursor after prompt */
        !            63: #define CURP2  2       /* cursor after secondary prompt */
        !            64: #define CURHOME        3       /* cursor at home position */
        !            65: /* flags for vsave routine */
        !            66: #define SVHEAD 01      /* write out article header */
        !            67: #define OVWRITE        02      /* overwrite the file if it already exists */
        !            68: /* other files */
        !            69: 
        !            70: #define        saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize
        !            71: #define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines))
        !            72: 
        !            73: /* terminal handler stuff */
        !            74: extern int _junked;
        !            75: #define okclear() (_junked = 1)
        !            76: extern int COLS;
        !            77: extern int ROWS;
        !            78: extern int hasscroll;
        !            79: 
        !            80: FILE *tmpfile();
        !            81: char *getmailname();
        !            82: #ifdef MYDB
        !            83: char *findparent();
        !            84: #endif /* MYDB */
        !            85: int onint();
        !            86: int onstop();
        !            87: int xxit();
        !            88: 
        !            89: char *Progname = "vnews";              /* for xerror */
        !            90: 
        !            91: /* variables shared between vnews routines */
        !            92: static char linebuf[LBUFLEN];          /* temporary workspace */
        !            93: static FILE *tfp;                      /* temporary file */
        !            94: static char tfname[] = "/tmp/vnXXXXXX";        /* name of temp file */
        !            95: static long artbody;                   /* offset of body into article */
        !            96: static int quitflg;                    /* if set, then quit */
        !            97: static int erased;                     /* current article has been erased */
        !            98: static int artlines;                   /* # lines in article body */
        !            99: static int artread;                    /* entire article has been read */
        !           100: static int hdrstart;                   /* beginning of header */
        !           101: static int hdrend;                     /* end of header */
        !           102: static int lastlin;                    /* number of lines in tempfile */
        !           103: static int tflinno = 0;                        /* next line in tempfile */
        !           104: static int maxlinno;                   /* number of lines in file + folded */
        !           105: static char secpr[SECPRLEN];           /* secondary prompt */
        !           106: static char prompt[30];                        /* prompter */
        !           107: static short prflags;                  /* print flags (controls updscr) */
        !           108: static short curflag;                  /* where to locate cursor */
        !           109: static int dlinno;                     /* top line on screen */
        !           110: static char timestr[20];               /* current time */
        !           111: static int ismail;                     /* true if user has mail */
        !           112: static char *mailf;                    /* user's mail file */
        !           113: static int alflag;                     /* set if unprocessed alarm signal */
        !           114: static int atend;                      /* set if at end of article */
        !           115: static char cerase;                    /* erase character */
        !           116: static char ckill;                     /* kill character */
        !           117: static char cintr;                     /* interrupt character */
        !           118: #ifdef TIOCGLTC
        !           119: static char cwerase;                   /* word erase character */
        !           120: #endif /* TIOCGLTC */
        !           121: short ospeed;                          /* terminal speed NOT STATIC */
        !           122: static int intflag;                    /* set if interrupt received */
        !           123: 
        !           124: #ifdef SIGTSTP
        !           125: static int reading;                    /* to keep stupid BSD from restarting reads */
        !           126: jmp_buf intjmp, alrmjmp;
        !           127: #endif /* SIGTSTP */
        !           128: 
        !           129: #ifdef MYDB
        !           130: static int hasdb;                      /* true if article data base exists */
        !           131: #endif /* MYDB */
        !           132: 
        !           133: #ifdef DIGPAGE
        !           134: static int endsuba;                    /* end of sub-article in digest */
        !           135: #endif
        !           136: 
        !           137: #ifdef MYDEBUG
        !           138: FILE *debugf;                          /* file to write debugging info on */
        !           139: #endif
        !           140: 
        !           141: char *tft = "/tmp/folXXXXXX";
        !           142: 
        !           143: /*
        !           144:  * These were made static for u370 with its buggy cc.
        !           145:  * I judged it better to have one copy with no ifdefs than
        !           146:  * to conditionally compile them as automatic variables
        !           147:  * in readr (which they originally were).  Performance
        !           148:  * considerations might warrant moving some of the simple
        !           149:  * things into register variables, but I don't know what
        !           150:  * breaks the u370 cc.
        !           151:  */
        !           152: #ifndef SERVER
        !           153: static char goodone[BUFLEN];           /* last decent article          */
        !           154: #endif /* !SERVER */
        !           155: static char ogroupdir[BUFLEN];         /* last groupdir                */
        !           156: static char edcmdbuf[128];
        !           157: static int rfq = 0;                    /* for last article             */
        !           158: static long ongsize;                   /* Previous ngsize              */
        !           159: static long pngsize;                   /* Printing ngsize              */
        !           160: static char *bptr;                     /* temp pointer.                */
        !           161: static char *tfilename;                        /* temporary file name          */
        !           162: static char ofilename1[BUFLEN];                /* previous file name           */
        !           163: static struct hbuf hbuf1, hbuf2;       /* for minusing                 */
        !           164: static struct hbuf *h = &hbuf1,                /* current header               */
        !           165:                *hold = &hbuf2,         /* previous header              */
        !           166:                *hptr;                  /* temporary                    */
        !           167: static char *ptr1, *ptr2, *ptr3;       /* for reply manipulation       */
        !           168: static int  aabs = FALSE;              /* TRUE if we asked absolutely  */
        !           169: static char *ed, tf[100];
        !           170: static long oobit;                     /* last bit, really             */
        !           171: static int dgest = 0;
        !           172: static FILE *fp;                       /* current article to be printed*/
        !           173: 
        !           174: readr()
        !           175: {
        !           176: 
        !           177: #ifdef MYDEBUG
        !           178:        debugf = fopen("DEBUG", "w");
        !           179:        setbuf(debugf, (char *)NULL);
        !           180: #endif
        !           181:        if (aflag) {
        !           182:                if (*datebuf) {
        !           183:                        if ((atime = cgtdate(datebuf)) == -1)
        !           184:                                xerror("Cannot parse date string");
        !           185:                } else
        !           186:                        atime = 0;
        !           187:        }
        !           188: 
        !           189:        if (SigTrap)
        !           190:                xxit(1);
        !           191:        (void) mktemp(tfname);
        !           192:        (void) close(creat(tfname,0666));
        !           193:        if ((tfp = fopen(tfname, "w+")) == NULL)
        !           194:                xerror("Can't create temp file");
        !           195:        (void) unlink(tfname);
        !           196:        mailf = getmailname();
        !           197: #ifdef MYDB
        !           198:        if (opendb() >= 0) {
        !           199:                hasdb = 1;
        !           200:                fputs("Using article data base\n", stderr);     /*DEBUG*/
        !           201:                getng();
        !           202:        }
        !           203: #endif
        !           204:        ttysave();
        !           205:        (void) signal(SIGINT, onint);
        !           206:        (void) signal(SIGQUIT, xxit);
        !           207:        if (SigTrap)
        !           208:                xxit(1);
        !           209:        ttyraw();
        !           210:        timer();
        !           211: 
        !           212:        /* loop reading articles. */
        !           213:        fp = NULL;
        !           214:        obit = -1;
        !           215:        nextng();
        !           216:        quitflg = 0;
        !           217:        while (quitflg == 0) {
        !           218:                if (getnextart(FALSE))
        !           219:                        break;
        !           220: #ifndef SERVER
        !           221:                (void) strcpy(goodone, filename);
        !           222: #endif /* !SERVER */
        !           223:                if (SigTrap)
        !           224:                        return;
        !           225:                vcmd();
        !           226:        }
        !           227: 
        !           228:        if (!news) {
        !           229:                ttycooked();
        !           230:                ospeed = 0;     /* to convince xxit() not to clear screen */
        !           231:                fprintf(stderr, "No news.\n");
        !           232:        }
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Read and execute a command.
        !           237:  */
        !           238: vcmd() {
        !           239:        register c;
        !           240:        char *p;
        !           241:        long count;
        !           242:        int countset;
        !           243: 
        !           244:        if (prflags & HDRONLY)
        !           245:                appfile(fp, lastlin + 1);
        !           246:        else
        !           247:                appfile(fp, dlinno + ARTWLEN + 1);
        !           248: 
        !           249: #ifdef DIGPAGE
        !           250:        endsuba = findend(dlinno);
        !           251:        if (artlines > dlinno + ARTWLEN
        !           252:         || endsuba > 0 && endsuba < artlines
        !           253: #else
        !           254:        if (artlines > dlinno + ARTWLEN
        !           255: #endif
        !           256:         || (prflags & HDRONLY) && artlines > hdrend) {
        !           257:                atend = 0;
        !           258:                if (prflags&HDRONLY || maxlinno == 0)
        !           259:                        (void) strcpy(prompt, "more? ");
        !           260:                else
        !           261: #ifdef DIGPAGE
        !           262:                        (void) sprintf(prompt, "more(%d%%)? ",
        !           263:                                ((((endsuba > 0) ?
        !           264:                                endsuba : (dlinno + ARTWLEN)) -
        !           265:                                hdrend) * 100) / maxlinno);
        !           266: #else /* !DIGPAGE */
        !           267:                        (void) sprintf(prompt, "more(%d%%)? ",
        !           268:                                ((dlinno + ARTWLEN - hdrend) * 100) / maxlinno);
        !           269: #endif /* !DIGPAGE */
        !           270:        } else {
        !           271:                atend = 1;
        !           272:                (void) strcpy(prompt, "next? ");
        !           273:                if (!erased)
        !           274:                        clear(bit);             /* article read */
        !           275:        }
        !           276:        curflag = CURP1;
        !           277:        p = prompt + strlen(prompt);
        !           278:        countset = 0;
        !           279:        count = 0;
        !           280:        /*
        !           281:         * Loop while accumulating a count, until an action character
        !           282:         * is entered. Also handle "meta" here.
        !           283:         *
        !           284:         * Count is the current count. Countset=0 means no count
        !           285:         * currently exists. Countset=1, count=0 is valid and means 
        !           286:         * a count of 0 has been entered 
        !           287:         */
        !           288:        for (;;) {
        !           289:                c = vgetc();
        !           290:                if (c == cerase || c == '\b' || c == '\177') {
        !           291:                        if (countset == 0)
        !           292:                                break;          /* Use as action char */
        !           293:                        if (count < 10)
        !           294:                                countset = 0;   /* Erase only char of count */
        !           295:                        else
        !           296:                                count /= 10L;   /* Erase 1 char of count */
        !           297:                } else {
        !           298: #ifdef TIOCGLTC
        !           299:                        if (c == ckill || c == cwerase) {
        !           300: #else
        !           301:                        if (c == ckill) {
        !           302: #endif
        !           303:                                if (countset == 0)
        !           304:                                        break;
        !           305:                                countset = 0;
        !           306:                        } else if (c < '0' || c > '9')
        !           307:                                        break;
        !           308:                                else {
        !           309:                                        countset = 1;
        !           310:                                        count = (count * 10) + (c - '0');
        !           311:                                }
        !           312:                }
        !           313:                if (countset) {
        !           314:                        (void) sprintf(p, "%ld", count);
        !           315:                } else {
        !           316:                        *p = '\0';
        !           317:                        count = 0;
        !           318:                }
        !           319:        }
        !           320: 
        !           321:        if (c == '\033') {                      /* escape */
        !           322:                (void) strcat(prompt, "M-");
        !           323:                c = vgetc();
        !           324:                if (c != cintr)
        !           325:                        c |= META;
        !           326:        }
        !           327:        secpr[0] = '\0';
        !           328:        if (countset == 0)
        !           329:                count = 1;
        !           330:        docmd(c, count, countset);
        !           331:        if (c != '?' && c != 'H')               /* UGGH */
        !           332:                prflags &=~ HELPMSG;
        !           333:        if (dlinno > hdrstart)
        !           334:                prflags &=~ HDRONLY;
        !           335: }
        !           336: 
        !           337: 
        !           338: /*
        !           339:  * Process one command, which has already been typed in.
        !           340:  */
        !           341: docmd(c, count, countset)
        !           342: int c;
        !           343: long count;
        !           344: int countset;
        !           345: {
        !           346:        int i;
        !           347:        long nart, Hoffset;
        !           348:        char *findhist();
        !           349: 
        !           350:        switch (c) {
        !           351: 
        !           352:        /* display list of articles in current group */
        !           353:        case 'l':
        !           354:        case 'L':
        !           355:                botscreen();
        !           356:                ttycooked();
        !           357:                list_group(groupdir, countset ? (int) count : 0,
        !           358:                        (c == 'l') ? FALSE : TRUE, pngsize);
        !           359:                ttyraw();
        !           360:                okclear();
        !           361:                updscr();
        !           362:                break;
        !           363: 
        !           364:        /* Show more of current article, or advance to next article */
        !           365:        case '\n':
        !           366:        case ' ':
        !           367: #ifdef DIGPAGE
        !           368:        case 'm':
        !           369: #endif /* DIGPAGE */
        !           370:        case '\06':     /* Control-F for vi compat */
        !           371:                prflags &=~ NOPRT;
        !           372:                if (atend)
        !           373:                        goto next;
        !           374:                else if (prflags & HDRONLY) {
        !           375:                        prflags &=~ HDRONLY;
        !           376:                        if (hasscroll)
        !           377:                                dlinno = hdrstart;}
        !           378: #ifdef DIGPAGE
        !           379:                else if (endsuba > 0)
        !           380:                        dlinno = endsuba;
        !           381:                else if (c == 'm') {
        !           382:                        do {
        !           383:                                if (lastlin >= maxlinno)
        !           384:                                        goto next;
        !           385:                                else
        !           386:                                        appfile(fp, lastlin + 1);
        !           387:                        } while(STRNCMP(linebuf, "------------------------", 24)
        !           388:                                != 0);
        !           389:                        dlinno = endsuba = lastlin;
        !           390:                }
        !           391: #endif
        !           392:                else if ((appfile(fp, dlinno + 2 * ARTWLEN), artread)
        !           393:                 && hasscroll && artlines - dlinno <= ARTWLEN + 2)
        !           394:                        dlinno = artlines - ARTWLEN;
        !           395:                else
        !           396:                        dlinno += ARTWLEN * count;
        !           397:                break;
        !           398: 
        !           399:        /* No.  Go on to next article. */
        !           400:        case '.':       /* useful if you have a keypad */
        !           401: next:  case 'n':
        !           402:                readmode = NEXT;
        !           403:                FCLOSE(fp);
        !           404:                clear(bit);
        !           405:                saveart;
        !           406:                nextbit();
        !           407:                break;
        !           408: 
        !           409: 
        !           410:        /* Back up count pages */
        !           411:        case '\b':      
        !           412:        case '\177':    
        !           413:                if (dlinno == 0)
        !           414:                        goto backupone;
        !           415:                /* NO BREAK */
        !           416:        case META|'v':
        !           417:        case '\002':    /* Control-B */
        !           418:                dlinno -= ARTWLEN * count;
        !           419:                if (dlinno < 0)
        !           420:                        dlinno = 0;
        !           421:                break;
        !           422: 
        !           423:        /* forward half a page */
        !           424:        case '\004':    /* Control-D, as in vi */
        !           425:                if (!atend)
        !           426:                        dlinno += ARTWLEN/2 * count;
        !           427:                break;
        !           428: 
        !           429:        /* backward half a page */
        !           430:        case '\025':    /* Control-U */
        !           431:                dlinno -= ARTWLEN/2 * count;
        !           432:                if (dlinno < 0)
        !           433:                        dlinno = 0;
        !           434:                break;
        !           435: 
        !           436:        /* forward count lines */
        !           437:        case '\016':    /* Control-N */
        !           438:        case '\005':    /* Control-E */
        !           439:                dlinno += count;
        !           440:                break;
        !           441: 
        !           442:        /* backwards count lines */
        !           443:        case '\020':    /* Control-P */
        !           444:        case '\031':    /* Control-Y */
        !           445:                dlinno -= count;
        !           446:                if (dlinno < 0)
        !           447:                        dlinno = 0;
        !           448:                break;
        !           449: 
        !           450:        /* Turn displaying of article back on */
        !           451:        case 'd':
        !           452:                prflags &=~ NOPRT;
        !           453:                break;
        !           454: 
        !           455:        /* display header */
        !           456:        case 'h':
        !           457:                dlinno = hdrstart;
        !           458:                prflags |= HDRONLY;
        !           459:                prflags &=~ NOPRT;
        !           460:                break;
        !           461: 
        !           462:        /*
        !           463:         * Unsubscribe to the newsgroup and go on to next group
        !           464:         */
        !           465: 
        !           466:        case 'U':
        !           467:        case 'u':
        !           468:                strcat(prompt, "u");
        !           469:                c = vgetc();
        !           470:                if (c == 'g') {
        !           471:                        obit = -1;
        !           472:                        FCLOSE(fp);
        !           473:                        zapng = TRUE;
        !           474:                        saveart;
        !           475:                        if (nextng()) {
        !           476:                                if (actdirect == BACKWARD)
        !           477:                                        msg("Can't back up.");
        !           478:                                else
        !           479:                                        quitflg = 1;    /* probably unnecessary */
        !           480:                        }
        !           481:                } else {
        !           482:                        if (c != cintr && c != ckill)
        !           483:                                beep();
        !           484:                                msg("Illegal command");
        !           485:                }
        !           486:                break;
        !           487: 
        !           488:                /* Print the current version of news */
        !           489:        case 'v':
        !           490:                msg("News version: %s", news_version);
        !           491:                break;
        !           492: 
        !           493: 
        !           494:        /* Decrypt joke.  Always does rot 13 */
        !           495:        case 'D':
        !           496:                appfile(fp, 32767);
        !           497:                for (i = hdrend ; i < artlines ; i++) {
        !           498:                        register char ch, *p;
        !           499:                        tfget(linebuf, i);
        !           500:                        for (p = linebuf ; (ch = *p) != '\0' ; p++) {
        !           501:                                if (ch >= 'a' && ch <= 'z')
        !           502:                                        *p = (ch - 'a' + 13) % 26 + 'a';
        !           503:                                else if (ch >= 'A' && ch <= 'Z')
        !           504:                                        *p = (ch - 'A' + 13) % 26 + 'A';
        !           505:                        }
        !           506:                        tfput(linebuf, i);
        !           507:                }
        !           508:                prflags |= NEWART;
        !           509:                prflags &=~ (HDRONLY|NOPRT);
        !           510:                break;
        !           511: 
        !           512:                /* write out the article someplace */
        !           513:                /* w writes out without the header */
        !           514:                /* | defaults to pipeing */
        !           515:        {
        !           516:                static char savebuf[BUFLEN];
        !           517:                int wflags;
        !           518: 
        !           519:        case PIPECHAR:
        !           520:        case 's':
        !           521:        case 'w':
        !           522:                /* We loop back to here each time user types ^U to prompt */
        !           523:                do {
        !           524:                        /* Prompt based on command char */
        !           525:                        msg( (c==PIPECHAR)? "|": "file: ");
        !           526:                        curflag = CURP2;
        !           527:                        while ((wflags = vgetc()) == ' ');
        !           528:                        if (wflags == cintr) {
        !           529:                                secpr[0] = '\0';
        !           530:                                break;
        !           531:                        }
        !           532:                        if (wflags != CAGAIN) {
        !           533:                                if ((wflags & 0x1F) == wflags) {        /* control char */
        !           534:                                        pushback(wflags);
        !           535:                                        savebuf[0] = 0;
        !           536:                                } else {
        !           537:                                        if (c == PIPECHAR) {
        !           538:                                                savebuf[0] = PIPECHAR;
        !           539:                                                savebuf[1] = wflags;
        !           540:                                                savebuf[2] = 0;
        !           541:                                        } else {
        !           542:                                                savebuf[0] = wflags;
        !           543:                                                savebuf[1] = 0;
        !           544:                                        }
        !           545:                                }
        !           546:                        } else {
        !           547:                                /* don't let them pipe to a saved filename */
        !           548:                                if (c == PIPECHAR && savebuf[0] != PIPECHAR) {
        !           549:                                        savebuf[0] = PIPECHAR;
        !           550:                                        savebuf[1] = 0;
        !           551:                                }
        !           552:                        }
        !           553:                                        
        !           554:                        wflags = prget( (savebuf[0] == PIPECHAR) ? "" : "file: ",
        !           555:                                        savebuf);
        !           556:                } while (wflags == 2);
        !           557:                if (wflags) break;      /* Interrupted out */
        !           558:                wflags = 0;
        !           559:                if (c == PIPECHAR) c = 's';
        !           560:                if (c == 's')
        !           561:                        wflags |= SVHEAD;
        !           562:                if (count != 1)
        !           563:                        wflags |= OVWRITE;
        !           564:                bptr = savebuf;
        !           565:                while( *bptr == ' ')
        !           566:                        bptr++; /* strip leading spaces */
        !           567: 
        !           568:                if (*bptr != PIPECHAR && *bptr != '/') {
        !           569:                        char    hetyped[BUFLEN];
        !           570:                        char    *boxptr;
        !           571:                        (void) strcpy(hetyped, bptr);
        !           572:                        if (hetyped[0] == '~' && hetyped[1] == '/') {
        !           573:                                strcpy(hetyped, bptr+2);
        !           574:                                strcpy(bptr, userhome);
        !           575:                        } else if (boxptr = getenv("NEWSBOX")) {
        !           576:                                if (index(boxptr, '%')) {
        !           577:                                        struct stat stbf;
        !           578:                                        sprintf(bptr, boxptr, groupdir);
        !           579:                                        if (stat(bptr,&stbf) < 0) {
        !           580:                                                if (mkdir(bptr, 0777) < 0) {
        !           581:                                                        msg("Cannot create directory %s", bptr);
        !           582:                                                        break;
        !           583:                                                }
        !           584:                                        } else if ((stbf.st_mode&S_IFMT) !=  S_IFDIR) {
        !           585:                                                msg("%s not a directory", bptr);
        !           586:                                                break;
        !           587:                                        }
        !           588:                                } else
        !           589:                                        strcpy(bptr, boxptr);
        !           590:                         } else
        !           591:                                bptr[0] = '\0';
        !           592: 
        !           593:                        if (bptr[0])
        !           594:                                (void) strcat(bptr, "/");
        !           595:                        if (hetyped[0] != '\0')
        !           596:                                (void) strcat(bptr, hetyped);
        !           597:                        else
        !           598:                                (void) strcat(bptr, "Articles");
        !           599:                }
        !           600: 
        !           601:                /* handle ~/ for pipes */
        !           602:                if (*bptr == PIPECHAR) {
        !           603:                        char    fullname[BUFLEN];
        !           604:                        bptr++;         /* skip PIPECHAR */
        !           605:                        while( *bptr == ' ')
        !           606:                                bptr++; /* strip leading spaces */
        !           607:                        if (bptr[0] == '~' && bptr[1] == '/') {
        !           608:                                strcpy(fullname,userhome);
        !           609:                                strcat(fullname,bptr+2);
        !           610:                        } else
        !           611:                                strcpy(fullname,bptr);
        !           612:                        /* we know PIPECHAR is in *savebuf */
        !           613:                        strcpy(savebuf+1,fullname);
        !           614:                        bptr = savebuf;
        !           615:                }
        !           616:                                
        !           617:                vsave(bptr, wflags);
        !           618:                break;
        !           619:        }
        !           620: 
        !           621:                /* back up  */
        !           622:        case '-':
        !           623: caseminus:
        !           624:                aabs = TRUE;
        !           625:                if (!*ofilename1) {
        !           626:                        msg("Can't back up.");
        !           627:                        break;
        !           628:                }
        !           629:                FCLOSE(fp);
        !           630:                hptr = h;
        !           631:                h = hold;
        !           632:                hold = hptr;
        !           633:                (void) strcpy(bfr, filename);
        !           634:                (void) strcpy(filename, ofilename1);
        !           635:                (void) strcpy(ofilename1, bfr);
        !           636:                obit = bit;
        !           637:                if (STRCMP(groupdir, ogroupdir)) {
        !           638:                        (void) strcpy(bfr, groupdir);
        !           639:                        selectng(ogroupdir, FALSE, FALSE);
        !           640:                        (void) strcpy(groupdir, ogroupdir);
        !           641:                        (void) strcpy(ogroupdir, bfr);
        !           642:                        ngrp = 1;
        !           643:                        back();
        !           644:                }
        !           645:                bit = oobit;
        !           646:                oobit = obit;
        !           647:                obit = -1;
        !           648:                getnextart(TRUE);
        !           649:                break;
        !           650: 
        !           651:                /* skip forwards */
        !           652:        case '+':
        !           653:        case '=':
        !           654: caseplus:      if (count == 0)
        !           655:                        break;
        !           656:                saveart;
        !           657:                last = bit;
        !           658:                for (i = 0; i < count; i++) {
        !           659:                        nextbit();
        !           660:                        if ((bit > pngsize) || (rflag && bit < 1))
        !           661:                                break;
        !           662:                }
        !           663:                FCLOSE(fp);
        !           664:                obit = -1;
        !           665:                break;
        !           666: 
        !           667:        /* exit - time updated to that of most recently read article */
        !           668:        case 'q':
        !           669:                quitflg = 1;
        !           670:                break;
        !           671: 
        !           672:        case 'x':
        !           673:                xxit(0);
        !           674:                break;
        !           675: 
        !           676:        /* cancel the article. */
        !           677:        case 'c':
        !           678:                strcpy(prompt, "cancel [n]? ");
        !           679:                if (vgetc() != 'y') {
        !           680:                        msg("Article not cancelled");
        !           681:                        break;
        !           682:                }
        !           683:                cancel_command();
        !           684:                break;
        !           685: 
        !           686:        /* escape to shell */
        !           687:        case '!': {
        !           688:                register char *p;
        !           689:                int flags;
        !           690: 
        !           691:                p = linebuf;
        !           692:                *p = 0;
        !           693:                if (prget("!", p))
        !           694:                        break;
        !           695:                flags = CWAIT;
        !           696:                if (*p == '\0') {
        !           697:                        (void) strcpy(linebuf, SHELL);
        !           698:                        flags = 0;
        !           699:                }
        !           700:                while (*p) p++;
        !           701:                while (p > linebuf && p[-1] == ' ')
        !           702:                        p--;
        !           703:                if (*--p == '&') {
        !           704:                        *p = '\0';
        !           705:                        flags = BKGRND;
        !           706:                } else if (*p == PIPECHAR) {
        !           707:                        *p = '\0';
        !           708:                        (void) sprintf(bfr, "(%s)%cmail '%s'", linebuf, PIPECHAR, username);
        !           709:                        (void) strcpy(linebuf, bfr);
        !           710:                        flags |= BKGRND;
        !           711:                } else {
        !           712:                        prflags |= NOPRT;
        !           713:                }
        !           714:                shcmd(linebuf, flags);
        !           715:                break;
        !           716:        }
        !           717: 
        !           718:        /* mail reply */
        !           719:        case 'r':
        !           720:                reply(FALSE);
        !           721:                break;
        !           722: 
        !           723:        case 'R':
        !           724:                reply(TRUE);
        !           725:                break;
        !           726: 
        !           727:        case META|'r':
        !           728:                direct_reply();
        !           729:                break;
        !           730: 
        !           731:        /* next newsgroup */
        !           732:        case 'N':
        !           733:                FCLOSE(fp);
        !           734:                if (next_ng_command())
        !           735:                        quitflg = 1;
        !           736:                break;
        !           737: 
        !           738:        /*  mark the rest of the articles in this group as read */
        !           739:        case 'K':
        !           740:                saveart;
        !           741:                while (bit <= ngsize && bit >= minartno) {
        !           742:                        clear(bit);
        !           743:                        nextbit();
        !           744:                }
        !           745:                FCLOSE(fp);
        !           746:                break;
        !           747: 
        !           748:        /* Print the full header */
        !           749:        case 'H':
        !           750:                if (fp == NULL) {
        !           751:                        msg("No current article");
        !           752:                        break;
        !           753:                }
        !           754:                move(ARTWIN, 0);
        !           755:                Hoffset = ftell(fp);
        !           756:                (void) fseek(fp, 0L, 0);
        !           757:                for (i = 0; i < ARTWLEN; i++) {
        !           758:                        if (fgets(linebuf, COLS, fp) == NULL)
        !           759:                                break;
        !           760:                        if (linebuf[0] == '\n')
        !           761:                                break;
        !           762:                        linebuf[COLS] = '\0';
        !           763:                        addstr(linebuf);
        !           764:                }
        !           765:                (void) fseek(fp, Hoffset, 0);
        !           766:                for(; i < ARTWLEN; i++)
        !           767:                        addstr(linebuf);
        !           768:                prflags |= HELPMSG|NEWART;
        !           769:                break;
        !           770:        case 'b':       /* backup 1 article */
        !           771: backupone:
        !           772:                count = bit - 1;
        !           773:                /* NO BREAK */
        !           774: 
        !           775:        case 'A':       /* specific number */
        !           776:                if (count > pngsize) {
        !           777:                        msg("not that many articles");
        !           778:                        break;
        !           779:                }
        !           780:                readmode = SPEC;
        !           781:                aabs = TRUE;
        !           782:                bit = count;
        !           783:                obit = -1;
        !           784:                FCLOSE(fp);
        !           785:                break;
        !           786: 
        !           787:        /* display parent article */
        !           788:        case 'p':
        !           789: #ifdef MYDB
        !           790:                if (hasdb && (ptr3 = findparent(h->ident, &nart)) != NULL) {
        !           791:                        msg("parent: %s/%ld", ptr3, nart);      /*DEBUG*/
        !           792:                        updscr();                               /*DEBUG*/
        !           793:                        goto selectart;
        !           794:                }
        !           795: #endif
        !           796:                if (h->followid[0] == '\0') {
        !           797:                        msg("no references line");
        !           798:                        break;
        !           799:                }
        !           800:                ptr1 = h->followid + strlen(h->followid);
        !           801:                do {
        !           802:                        ptr2 = ptr1;
        !           803:                        if (*ptr2 == '\0')
        !           804:                                ptr1 = rindex(h->followid, ' ');
        !           805:                        else {
        !           806:                                *ptr2 = '\0';
        !           807:                                ptr1 = rindex(h->followid, ' ');
        !           808:                                *ptr2 = ' ';
        !           809:                        }
        !           810:                } while (ptr1 != NULL && --count > 0);
        !           811:                if (ptr1 == NULL)
        !           812:                        ptr1 = h->followid;
        !           813:                else    ++ptr1;
        !           814:                (void) strncpy(linebuf, ptr1, ptr2 - ptr1);
        !           815:                linebuf[ptr2 - ptr1] = '\0';
        !           816:                msg("%s", linebuf);
        !           817:                curflag = CURP2;
        !           818:                updscr();               /* may take this out later */
        !           819:                goto searchid;
        !           820:        /* specific message ID. */
        !           821:        case '<':
        !           822:                /* could improve this */
        !           823:                linebuf[0] = '<'; linebuf[1] = 0;
        !           824:                if (prget("", linebuf)) {
        !           825:                        secpr[0] = 0;
        !           826:                        break;
        !           827:                }
        !           828: searchid:      secpr[0] = '\0';
        !           829:                if (index(linebuf, '@') == NULL && index(linebuf, '>') == NULL) {
        !           830:                        ptr1 = linebuf;
        !           831:                        if (*ptr1 == '<')
        !           832:                                ptr1++;
        !           833:                        ptr2 = index(ptr1, '.');
        !           834:                        if (ptr2 != NULL) {
        !           835:                                *ptr2++ = '\0';
        !           836:                                (void) sprintf(bfr, "<%s@%s.UUCP>", ptr2, ptr1);
        !           837:                                (void) strcpy(linebuf, bfr);
        !           838:                        }
        !           839:                }
        !           840:                if (index(linebuf, '>') == NULL)
        !           841:                        (void) strcat(linebuf, ">");
        !           842: 
        !           843:                ptr1 = findhist(linebuf);
        !           844:                if (ptr1 == NULL) {
        !           845:                        msg("%s not found", linebuf);
        !           846:                        break;
        !           847:                }
        !           848:                ptr2 = index(ptr1, '\t');
        !           849:                ptr3 = index(++ptr2, '\t');
        !           850:                ptr2 = index(++ptr3, ' ');
        !           851:                if (ptr2)
        !           852:                        *ptr2 = '\0';
        !           853:                ptr2 = index(ptr3, '/');
        !           854:                if (!ptr2) {
        !           855:                        if (STRCMP(ptr3, "cancelled") == 0)
        !           856:                                msg("%s has been cancelled", linebuf);
        !           857:                        else
        !           858:                                msg("%s has expired", linebuf);
        !           859:                        break;
        !           860:                }
        !           861:                *ptr2++ = '\0';
        !           862:                (void) sscanf(ptr2, "%ld", &nart);
        !           863: 
        !           864:                /*
        !           865:                 * Go to a given article.  Ptr3 specifies the newsgroup
        !           866:                 * and nart specifies the article number.
        !           867:                 */
        !           868: #ifdef MYDB
        !           869: selectart:
        !           870: #endif /* MYDB */
        !           871:                aabs = TRUE;
        !           872:                FCLOSE(fp);
        !           873:                saveart;
        !           874:                (void) strcpy(ogroupdir, ptr3);
        !           875:                if (STRCMP(groupdir, ogroupdir)) {
        !           876:                        (void) strcpy(bfr, groupdir);
        !           877:                        selectng(ogroupdir, TRUE, PERHAPS);
        !           878:                        (void) strcpy(groupdir, ogroupdir);
        !           879:                        (void) strcpy(ogroupdir, bfr);
        !           880:                        ngrp = 1;
        !           881:                        back();
        !           882:                }
        !           883:                bit = nart;
        !           884:                oobit = obit;
        !           885:                obit = -1;
        !           886:                getnextart(TRUE);
        !           887:                if (bit != nart || STRCMP(groupdir, ptr3) != 0) {
        !           888:                        msg("can't read %s/%ld", ptr3, nart);
        !           889:                        goto caseminus;
        !           890:                }
        !           891:                rfq = 0;
        !           892:                break;
        !           893: 
        !           894:        /* follow-up article */
        !           895:        case 'f':
        !           896:                if (STRCMP(h->followto, "poster") == 0) {
        !           897:                        reply(FALSE);
        !           898:                        break;
        !           899:                }
        !           900: #ifdef SERVER
        !           901:                (void) sprintf(bfr, "%s/%s", BIN, "postnews");
        !           902: #else  /* !SERVER */
        !           903:                (void) sprintf(bfr, "%s/%s %s", BIN, "postnews", goodone);
        !           904: #endif /* !SERVER */
        !           905:                shcmd(bfr, CWAIT);
        !           906:                break;
        !           907: 
        !           908:        /* erase - pretend we haven't seen this article. */
        !           909:        case 'e':
        !           910:                erased = 1;
        !           911:                set(bit);
        !           912:                goto caseplus;  /* skip this article for now */
        !           913: 
        !           914:        case '#':
        !           915:                msg("Article %ld of %ld", rfq ? oobit : bit, pngsize);
        !           916:                break;
        !           917: 
        !           918:                /* error */
        !           919:        case '?':
        !           920:                {
        !           921:                        FILE *helpf;
        !           922:                        (void) sprintf(linebuf, "%s/vnews.help", LIB);
        !           923:                        if ((helpf = fopen(linebuf, "r")) == NULL) {
        !           924:                                msg("Can't open help file");
        !           925:                                break;
        !           926:                        }
        !           927:                        move(ARTWIN, 0);
        !           928:                        while (fgets(linebuf, LBUFLEN, helpf) != NULL)
        !           929:                                addstr(linebuf);
        !           930:                        (void) fclose(helpf);
        !           931:                        prflags |= HELPMSG|NEWART;
        !           932:                }
        !           933:                break;
        !           934: 
        !           935:        default:
        !           936:                if (c != ckill && c != cintr && c != cerase) 
        !           937: #ifdef TIOCGLTC
        !           938:                        if (c != cwerase)
        !           939: #endif
        !           940:                        {
        !           941:                                beep();
        !           942:                                msg("Illegal command");
        !           943:                        }
        !           944:                break;
        !           945:        }
        !           946: }
        !           947: 
        !           948: cancel_command()
        !           949: {
        !           950:        register char *poster, *r;
        !           951:        int notauthor;
        !           952:        char *senderof();
        !           953: 
        !           954:        poster = senderof(h);
        !           955:        /* only compare up to '.' or ' ' */
        !           956:        r = index(poster,'.');
        !           957:        if (r == NULL)
        !           958:                r = index(poster,' ');
        !           959:        if (r != NULL)
        !           960:                *r = '\0';
        !           961:        tfilename = filename;
        !           962:        notauthor = STRCMP(username, poster);
        !           963:        if (uid != ROOTID && uid && notauthor) {
        !           964:                msg("Can't cancel what you didn't write.");
        !           965:                return;
        !           966:        }
        !           967:        if (!cancel(stderr, h, notauthor)) {
        !           968:                clear(bit);
        !           969:                saveart;
        !           970:                nextbit();
        !           971:                obit = -1;
        !           972:                fp = NULL;
        !           973:        }
        !           974:        FCLOSE(fp);
        !           975: }
        !           976: /*
        !           977:  * Generate replies
        !           978:  */
        !           979: 
        !           980: reply(include)
        !           981:        int include;
        !           982: {
        !           983:        char *arg[4];
        !           984:        register FILE *rfp;
        !           985:        char subj[132];
        !           986:        register char *p;
        !           987:        char *replyname();
        !           988:        struct stat statb;
        !           989:        time_t creatm;
        !           990: 
        !           991:        /* Put the user in the editor to create the body of the reply. */
        !           992:        ed = getenv("EDITOR");
        !           993:        if (ed == NULL || *ed == '\0')
        !           994:                ed = DFTEDITOR;
        !           995:        if (ed == NULL) {
        !           996:                msg("You don't have an editor");
        !           997:                return;
        !           998:        }
        !           999: 
        !          1000:        arg[0] = "/bin/sh";
        !          1001:        arg[1] = "-c";
        !          1002: 
        !          1003:        (void) strcpy(tf, tft);
        !          1004:        (void) mktemp(tf);
        !          1005:        (void) close(creat(tf,0600));
        !          1006:        if ((rfp = fopen(tf, "w")) == NULL) {
        !          1007:                msg("Can't create %s", tf) ;
        !          1008:                return;
        !          1009:        }
        !          1010:        (void) strcpy(subj, h->title);
        !          1011:        if (!PREFIX(subj, "Re:")){
        !          1012:                (void) strcpy(bfr, subj);
        !          1013:                (void) sprintf(subj, "Re: %s", bfr);
        !          1014:        }
        !          1015: 
        !          1016:        p = replyname(h);
        !          1017:        fprintf(rfp, "To: %s\n", p);
        !          1018:        fprintf(rfp, "Subject: %s\n", subj);
        !          1019:        fprintf(rfp, "In-reply-to: your article %s\n", h->ident);
        !          1020: #ifdef INTERNET
        !          1021:        fprintf(rfp, "News-Path: %s\n", h->path);
        !          1022: #endif /* INTERNET */
        !          1023:        (void) sprintf(rcbuf, "%s -t < %s; rm -f %s", MAILPARSER, tf, tf);
        !          1024:        putc('\n', rfp);
        !          1025:        if (include) {
        !          1026:                FILE *of;
        !          1027:                char buf[BUFSIZ];
        !          1028: 
        !          1029: #ifndef SERVER
        !          1030:                of = xart_open(goodone, "r");
        !          1031:                while (fgets(buf, sizeof buf, of) != NULL)
        !          1032:                        if (buf[0] == '\n')
        !          1033:                                break;
        !          1034:                while (fgets(buf, sizeof buf, of) != NULL)
        !          1035:                        fprintf(rfp, "> %s", buf);
        !          1036:                fclose(of);
        !          1037:                putc('\n', rfp);
        !          1038: #endif         /* !SERVER */
        !          1039:        }
        !          1040: 
        !          1041:        fflush(rfp);
        !          1042:        (void) fstat(fileno(rfp), &statb);
        !          1043:        creatm = statb.st_mtime;
        !          1044:        (void) fclose(rfp);
        !          1045: 
        !          1046:        (void) sprintf(edcmdbuf, "exec %s %s", ed, tf);
        !          1047:        arg[2] = edcmdbuf;
        !          1048:        arg[3] = NULL;
        !          1049:        if (prun(arg, 0) != 0) {
        !          1050:                msg("Couldn't run editor");
        !          1051:                (void) unlink(tf);
        !          1052:                return;
        !          1053:        }
        !          1054: 
        !          1055:        if (access(tf, 4) || stat(tf, &statb)) {
        !          1056:                msg("No input file - mail not sent");
        !          1057:                (void) unlink(tf);
        !          1058:                return;
        !          1059:        }
        !          1060:        if (statb.st_mtime == creatm || statb.st_size < 5) {
        !          1061:                msg("File unchanged - no message posted");
        !          1062:                (void) unlink(tf);
        !          1063:                return;
        !          1064:        }
        !          1065: 
        !          1066:        arg[2] = rcbuf;
        !          1067:        arg[3] = NULL;
        !          1068:        prun(arg, BKGRND);
        !          1069:        prflags |= NOPRT;
        !          1070: }
        !          1071: 
        !          1072: direct_reply()
        !          1073: {
        !          1074:        register char *p;
        !          1075:        register char *q;
        !          1076:        char *arg[4];
        !          1077:        char address[PATHLEN];
        !          1078:        extern char *replyname();
        !          1079:        extern char *getenv();
        !          1080: 
        !          1081:        arg[0] = "/bin/sh";
        !          1082:        arg[1] = "-c";
        !          1083:        p = replyname(h);
        !          1084:        q = address;
        !          1085:        while (*p != '\0') {
        !          1086:                if (index("\"\\$", *p) != 0)
        !          1087:                        *q++ = '\\';
        !          1088:                *q++ = *p++;
        !          1089:        }
        !          1090:        *q++ = '\0';
        !          1091:        if ((MAILER = getenv("MAILER")) == NULL)
        !          1092:                MAILER = "mail";
        !          1093:        sprintf(rcbuf, MAILER, hptr->title);
        !          1094:        sprintf(bfr, "%s %s", rcbuf, address);
        !          1095:        arg[2] = bfr;
        !          1096:        arg[3] = NULL;
        !          1097:        if (prun(arg, 0) != 0) {
        !          1098:                msg("Couldn't run mailer");
        !          1099:                return;
        !          1100:        }
        !          1101:        prflags |= NOPRT;
        !          1102: }
        !          1103: 
        !          1104: next_ng_command()
        !          1105: {
        !          1106:        set(bit);
        !          1107:        obit = -1;
        !          1108:        linebuf[0] = 0;
        !          1109:        if (prget("group? ", linebuf))
        !          1110:                return FALSE;
        !          1111:        bptr = linebuf;
        !          1112:        if (!*bptr || *bptr == '-') {
        !          1113:                if (*bptr)
        !          1114:                        actdirect = BACKWARD;
        !          1115:                saveart;
        !          1116:                if (nextng()) {
        !          1117:                        if (actdirect == BACKWARD)
        !          1118:                                msg("Can't back up.");
        !          1119:                        else
        !          1120:                                return TRUE;
        !          1121:                }
        !          1122:                return FALSE;
        !          1123:        }
        !          1124:        while (isspace(*bptr))
        !          1125:                bptr++;
        !          1126:        if (!validng(bptr)) {
        !          1127:                msg("No such group.");
        !          1128:                return FALSE;
        !          1129:        }
        !          1130:        saveart;
        !          1131:        back();
        !          1132:        selectng(bptr, TRUE, TRUE);
        !          1133:        return FALSE;
        !          1134: }
        !          1135: 
        !          1136: /*
        !          1137:  * Find the next article we want to consider, if we're done with
        !          1138:  * the last one, and show the header.
        !          1139:  */
        !          1140: getnextart(minus)
        !          1141: int minus;
        !          1142: {
        !          1143:        int noaccess;
        !          1144: #ifdef SERVER
        !          1145:        char workspace[256];
        !          1146: #else  /* !SERVER */
        !          1147:        register DIR *dirp;
        !          1148:        register struct direct *dir;
        !          1149: #endif /* !SERVER */
        !          1150:        long nextnum, tnum;
        !          1151:        long atol();
        !          1152:        noaccess = 0;
        !          1153:        if (minus)
        !          1154:                goto nextart2;  /* Kludge for "-" command. */
        !          1155: 
        !          1156:        if (bit == obit)        /* Return if still on same article as last time */
        !          1157:                return 0;
        !          1158: 
        !          1159: nextart:
        !          1160:        if (news) {
        !          1161:                curflag = CURHOME;
        !          1162:                _amove(0, 0);
        !          1163:                vflush();
        !          1164:        }
        !          1165:        dgest = 0;
        !          1166: 
        !          1167:        /* If done with this newsgroup, find the next one. */
        !          1168:        while (ngsize <= 0 || (!rflag && ((long) bit > ngsize)) || (rflag && bit < minartno)) {
        !          1169:                if (nextng()) {
        !          1170:                        if (actdirect == BACKWARD) {
        !          1171:                                msg("Can't back up.");
        !          1172:                                actdirect = FORWARD;
        !          1173:                                continue;
        !          1174:                        }
        !          1175:                        else /* if (rfq++ || pflag || cflag) */
        !          1176:                                return 1;
        !          1177:                }
        !          1178:                if (rflag)
        !          1179:                        bit = ngsize + 1;
        !          1180:                else
        !          1181:                        bit = -1;
        !          1182:                noaccess = 2;
        !          1183:        }
        !          1184: 
        !          1185:        /* speed things up by not searching for article -1 */
        !          1186:        if (bit < 0) {
        !          1187:                bit = minartno - 1;
        !          1188:                nextbit();
        !          1189:                aabs = FALSE;
        !          1190:                goto nextart;
        !          1191:        }
        !          1192: 
        !          1193: nextart2:
        !          1194:        if (rcreadok)
        !          1195:                rcreadok = 2;   /* have seen >= 1 article */
        !          1196: #ifdef SERVER
        !          1197:        if ((fp = getarticle(groupdir, bit, "ARTICLE")) == NULL)
        !          1198:                goto badart;
        !          1199:        strcpy(filename, article_name());
        !          1200:        (void) fclose(fp);
        !          1201:        fp = NULL;
        !          1202: #else  /* !SERVER */
        !          1203:        (void) sprintf(filename, "%s/%ld", dirname(groupdir), bit);
        !          1204:        if (rfq && goodone[0])  /* ??? */
        !          1205:                strcpy(filename, goodone);
        !          1206: #endif /* !SERVER */
        !          1207:        if (SigTrap == SIGHUP)
        !          1208:                return 1;
        !          1209:        /* Decide if we want to show this article. */
        !          1210:        if ((fp = art_open(filename, "r")) == NULL) {
        !          1211:                /* since there can be holes in legal article numbers, */
        !          1212:                /* we wait till we hit 5 consecutive bad articles */
        !          1213:                /* before we haul off and scan the directory */
        !          1214:                if (++noaccess < 5)
        !          1215:                        goto badart;
        !          1216:                noaccess = 0;
        !          1217: #ifdef SERVER
        !          1218:                if (*groupdir == ' ' || *groupdir == '\0' || 
        !          1219:                        set_group(groupdir) == NULL)
        !          1220:                        goto nextart;
        !          1221: #else  /* !SERVER */
        !          1222:                dirp = opendir(dirname(groupdir));
        !          1223:                if (dirp == NULL) {
        !          1224:                        if (errno != EACCES)
        !          1225:                                msg("Can't open %s", dirname(groupdir));
        !          1226:                        goto nextart;
        !          1227:                }
        !          1228: #endif /* !SERVER */
        !          1229:                nextnum = rflag ? minartno - 1 : ngsize + 1;
        !          1230: #ifdef SERVER 
        !          1231:                tnum = nextnum;
        !          1232:                for(;;){
        !          1233:                        (void) sprintf(bfr,"STAT %ld",tnum);
        !          1234:                        put_server(bfr);
        !          1235:                        (void) get_server(workspace,sizeof(workspace));
        !          1236:                        if (*workspace != CHAR_OK) {
        !          1237:                                if (rflag)
        !          1238:                                        tnum++;
        !          1239:                                else
        !          1240:                                        tnum--;
        !          1241:                                continue;
        !          1242:                        }
        !          1243: #else  /* !SERVER */
        !          1244:                while ((dir = readdir(dirp)) != NULL) {
        !          1245:                        if (!dir->d_ino)
        !          1246:                                continue;
        !          1247:                        tnum = atol(dir->d_name);
        !          1248:                        if (tnum <= 0)
        !          1249:                                continue;
        !          1250: #endif /* !SERVER */
        !          1251:                        if (rflag ? (tnum > nextnum && tnum < bit)
        !          1252:                                  : (tnum < nextnum && tnum > bit))
        !          1253:                                nextnum = tnum;
        !          1254: #ifdef SERVER
        !          1255:                        break;          /* not exactly right */
        !          1256: #endif /* SERVER */
        !          1257:                }
        !          1258: #ifndef SERVER
        !          1259:                closedir(dirp);
        !          1260: #endif /* !SERVER */
        !          1261:                if (rflag ? (nextnum >= bit) : (nextnum <= bit))
        !          1262:                        goto badart;
        !          1263:                do {
        !          1264:                        clear(bit);
        !          1265:                        nextbit();
        !          1266:                } while (rflag ? (nextnum < bit) : (nextnum > bit));
        !          1267:                obit = -1;
        !          1268:                aabs = FALSE;
        !          1269:                goto nextart;
        !          1270:        } else
        !          1271:                noaccess = 0;
        !          1272: 
        !          1273:        if (hread(h, fp, TRUE) == NULL || (!rfq && !aselect(h, aabs))) {
        !          1274: badart:
        !          1275:                FCLOSE(fp);
        !          1276:                clear(bit);
        !          1277:                obit = -1;
        !          1278:                nextbit();
        !          1279:                aabs = FALSE;
        !          1280:                goto nextart;
        !          1281:        }
        !          1282:        aabs = FALSE;
        !          1283:        actdirect = FORWARD;
        !          1284:        news = TRUE;
        !          1285:        artbody = ftell(fp);
        !          1286:        fmthdr();
        !          1287:        artlines = lastlin;
        !          1288:        artread = 0;
        !          1289:        prflags |= NEWART;
        !          1290:        prflags &=~ NOPRT;
        !          1291:        if (! cflag && hdrend < ARTWLEN && !cflag)
        !          1292:                prflags |= HDRONLY;
        !          1293:        dlinno = 0;
        !          1294:        maxlinno = NLINES(h, fp);
        !          1295:        erased = 0;
        !          1296: 
        !          1297:        obit = bit;
        !          1298: #ifdef SERVER
        !          1299:        (void) unlink(filename);
        !          1300: #endif /* SERVER */
        !          1301:        return 0;
        !          1302: }
        !          1303: 
        !          1304: /*
        !          1305:  * Print out whatever the appropriate header is
        !          1306:  */
        !          1307: fmthdr() {
        !          1308:        char *briefdate();
        !          1309:        static FILE *ngfd = NULL;
        !          1310:        static int triedopen = 0;
        !          1311:        char pbuf[BUFLEN], *printbuffer = groupdir;
        !          1312: 
        !          1313:        lastlin = 0;
        !          1314:        if (ngrp) {
        !          1315:                pngsize = ngsize;
        !          1316:                ngrp--;
        !          1317:                if (!hflag) {
        !          1318:                        if (!triedopen) {
        !          1319:                                (void) sprintf(pbuf,"%s/newsgroups", LIB);
        !          1320:                                ngfd = fopen(pbuf, "r");
        !          1321:                                triedopen++;
        !          1322:                        }
        !          1323:                        if (ngfd != NULL) {
        !          1324:                                register char *p;
        !          1325:                                char ibuf[BUFLEN];
        !          1326:                                rewind(ngfd);
        !          1327:                                while (fgets(ibuf, BUFLEN, ngfd) != NULL) {
        !          1328:                                        p = index(ibuf, '\t');
        !          1329:                                        if (p)
        !          1330:                                                *p++ = '\0';
        !          1331:                                        if (STRCMP(ibuf, groupdir) == 0) {
        !          1332:                                                register char *q;
        !          1333:                                                q = rindex(p, '\t');
        !          1334:                                                if (q) {
        !          1335:                                                        p = q;
        !          1336:                                                        *p++ = '\0';
        !          1337:                                                }
        !          1338:                                                if (p) {
        !          1339:                                                        q = index(p, '\n');
        !          1340:                                                        if (q)
        !          1341:                                                                *q = '\0';
        !          1342:                                                        if (*--q == '.')
        !          1343:                                                                *q = '\0';
        !          1344:                                                (void) sprintf(pbuf,"%s (%s)",
        !          1345:                                                        groupdir, p);
        !          1346:                                                        printbuffer = pbuf;
        !          1347:                                                }
        !          1348:                                                break;
        !          1349:                                        }
        !          1350:                                }
        !          1351:                        }
        !          1352:                        (void) sprintf(linebuf, "Newsgroup %s", printbuffer);
        !          1353:                        tfappend(linebuf);
        !          1354:                }
        !          1355:        }
        !          1356:        hdrstart = lastlin;
        !          1357:        if (!hflag) {
        !          1358:                (void) sprintf(linebuf, "Article %s %s",
        !          1359:                        h->ident, briefdate(h->subdate));
        !          1360:                tfappend(linebuf);
        !          1361:        }
        !          1362:        xtabs(h);
        !          1363:        vhprint(h, pflag ? 1 : 0);
        !          1364:        (void) sprintf(linebuf, "(%d lines)", NLINES(h, fp)); tfappend(linebuf);
        !          1365:        tfappend("");
        !          1366:        hdrend = lastlin;
        !          1367: }
        !          1368: 
        !          1369: /*
        !          1370:  * Grow tabs into spaces in header fields, 'cause the rest of this
        !          1371:  * lax program drops turds all over tabs (so it does with \b's, but ..)
        !          1372:  */
        !          1373: xtabs(p)
        !          1374: register struct hbuf *p;
        !          1375: {
        !          1376:        xtabf(p->from, sizeof p->from);
        !          1377:        xtabf(p->path, sizeof p->path);
        !          1378:        xtabf(p->nbuf, sizeof p->nbuf);
        !          1379:        xtabf(p->title, sizeof p->title);
        !          1380:        xtabf(p->ident, sizeof p->ident);
        !          1381:        xtabf(p->replyto, sizeof p->replyto);
        !          1382:        xtabf(p->followid, sizeof p->followid);
        !          1383:        xtabf(p->subdate, sizeof p->subdate);
        !          1384:        xtabf(p->expdate, sizeof p->expdate);
        !          1385:        xtabf(p->ctlmsg, sizeof p->ctlmsg);
        !          1386:        xtabf(p->sender, sizeof p->sender);
        !          1387:        xtabf(p->followto, sizeof p->followto);
        !          1388:        xtabf(p->distribution, sizeof p->distribution);
        !          1389:        xtabf(p->organization, sizeof p->organization);
        !          1390:        xtabf(p->numlines, sizeof p->numlines);
        !          1391:        xtabf(p->keywords, sizeof p->keywords);
        !          1392:        xtabf(p->summary, sizeof p->summary);
        !          1393:        xtabf(p->approved, sizeof p->approved);
        !          1394:        xtabf(p->nf_id, sizeof p->nf_id);
        !          1395:        xtabf(p->nf_from, sizeof p->nf_from);
        !          1396: #ifdef DOXREFS
        !          1397:        xtabf(p->xref, sizeof p->xref);
        !          1398: #endif /* DOXREFS */
        !          1399: }
        !          1400: 
        !          1401: xtabf(s, size)
        !          1402: char *s;
        !          1403: int size;
        !          1404: {
        !          1405:        register char *p, *str;
        !          1406:        register c, i;
        !          1407:        char buf[LBUFLEN];
        !          1408: 
        !          1409:        str = s;
        !          1410:        if (index(str, '\t') == NULL)
        !          1411:                return;
        !          1412:        i = 0;
        !          1413:        for (p = buf; c = *str++; i++) {
        !          1414:                if (c == '\t') {
        !          1415:                        *p++ = ' ';
        !          1416:                        if ((i & 7) != 7)
        !          1417:                                str--;
        !          1418:                } else if (c == '\n') {
        !          1419:                        i = -1;
        !          1420:                        *p++ = c;
        !          1421:                } else
        !          1422:                        *p++ = c;
        !          1423:        }
        !          1424:        *p = '\0';
        !          1425:        strncpy(s, buf, size - 1);
        !          1426: }
        !          1427: 
        !          1428: /*
        !          1429:  * Print the file header to the temp file.
        !          1430:  */
        !          1431: vhprint(hp, verbose)
        !          1432: register struct hbuf *hp;
        !          1433: int    verbose;
        !          1434: {
        !          1435:        register char   *p1, *p2;
        !          1436:        char    fname[BUFLEN];
        !          1437:        char *tailpath();
        !          1438: 
        !          1439:        fname[0] = '\0';                /* init name holder */
        !          1440: 
        !          1441:        p1 = index(hp->from, '(');      /* Find the sender's full name. */
        !          1442:        if (p1 == NULL && hp->path[0])
        !          1443:                p1 = index(hp->path, '(');
        !          1444:        if (p1 != NULL) {
        !          1445:                (void) strcpy(fname, p1+1);
        !          1446:                p2 = index(fname, ')');
        !          1447:                if (p2 != NULL)
        !          1448:                        *p2 = '\0';
        !          1449:        }
        !          1450: 
        !          1451:        (void) sprintf(linebuf, "Subject: %s", hp->title);
        !          1452:        tfappend(linebuf);
        !          1453:        if (!hflag && hp->summary[0])
        !          1454:                (void) sprintf(linebuf, "Summary: %s", hp->summary), tfappend(linebuf);
        !          1455:        if (!hflag && hp->keywords[0])
        !          1456:                (void) sprintf(linebuf, "Keywords: %s", hp->keywords), tfappend(linebuf);
        !          1457:        if (verbose) {
        !          1458:                (void) sprintf(linebuf, "From: %s", hp->from); tfappend(linebuf);
        !          1459:                (void) sprintf(linebuf, "Path: %s", hp->path); tfappend(linebuf);
        !          1460:                if (hp->organization[0]) {
        !          1461:                        (void) sprintf(linebuf, "Organization: %s", hp->organization);
        !          1462:                        tfappend(linebuf);
        !          1463:                }
        !          1464:        }
        !          1465:        else {
        !          1466:                if (p1 != NULL)
        !          1467:                        *--p1 = '\0';           /* bump over the '(' */
        !          1468: #ifdef INTERNET
        !          1469:                /*
        !          1470:                 * Prefer Path line if it's in internet format, or if we don't
        !          1471:                 * understand internet format here, or if there is no reply-to.
        !          1472:                 */
        !          1473:                (void) sprintf(linebuf, "From: %s", hp->from);
        !          1474: #else
        !          1475:                (void) sprintf(linebuf, "Path: %s", tailpath(hp));
        !          1476: #endif
        !          1477:                if (fname[0] || (hp->organization[0] && !hflag)) {
        !          1478:                        (void) strcat(linebuf, " (");
        !          1479:                        if (fname[0] == '\0') {
        !          1480:                                (void) strcpy(fname, hp->from);
        !          1481:                                p2 = index(fname,'@');
        !          1482:                                if (p2)
        !          1483:                                        *p2 = '\0';
        !          1484:                        }
        !          1485:                        (void) strcat(linebuf, fname);
        !          1486:                        if (hp->organization[0] && !hflag) {
        !          1487:                                (void) strcat(linebuf, " @ ");
        !          1488:                                (void) strcat(linebuf, hp->organization);
        !          1489:                        }
        !          1490:                        (void) strcat(linebuf, ")");
        !          1491:                }
        !          1492:                tfappend(linebuf);
        !          1493:                if (p1 != NULL)
        !          1494:                        *p1 = ' ';
        !          1495:                if (hp->ctlmsg[0]) {
        !          1496:                        (void) sprintf(linebuf, "Control: %s", hp->ctlmsg);
        !          1497:                        tfappend(linebuf);
        !          1498:                }
        !          1499:        }
        !          1500: 
        !          1501:        if (verbose) {
        !          1502:                (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); tfappend(linebuf);
        !          1503:                (void) sprintf(linebuf, "Date: %s", hp->subdate); tfappend(linebuf);
        !          1504:                if (hp->sender[0]) {
        !          1505:                        (void) sprintf(linebuf, "Sender: %s", hp->sender);
        !          1506:                        tfappend(linebuf);
        !          1507:                }
        !          1508:                if (hp->replyto[0]) {
        !          1509:                        (void) sprintf(linebuf, "Reply-To: %s", hp->replyto);
        !          1510:                        tfappend(linebuf);
        !          1511:                }
        !          1512:                if (hp->followto[0]) {
        !          1513:                        (void) sprintf(linebuf, "Followup-To: %s", hp->followto);
        !          1514:                        tfappend(linebuf);
        !          1515:                }
        !          1516:        }
        !          1517:        else if (STRCMP(hp->nbuf, groupdir) != 0) {
        !          1518:                (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf);
        !          1519:                tfappend(linebuf);
        !          1520:                timer();
        !          1521:        }
        !          1522: }
        !          1523: 
        !          1524: #ifdef MYDB
        !          1525: 
        !          1526: char *
        !          1527: findparent(id, num)
        !          1528: char *id;
        !          1529: long *num;
        !          1530: {
        !          1531:        struct artrec a;
        !          1532:        char idbuf[BUFSIZE];
        !          1533:        char *ngname();
        !          1534: 
        !          1535:        strcpy(idbuf, id);
        !          1536:        lcase(idbuf);
        !          1537: 
        !          1538:        if (lookart(id, &a) == DNULL)
        !          1539:                return NULL;
        !          1540:        if (a.parent == DNULL)
        !          1541:                return NULL;
        !          1542:        readrec(a.parent, &a);
        !          1543:        *num = a.groups[0].artno;
        !          1544:        return ngname(a.groups[0].newsgroup);
        !          1545: }
        !          1546: 
        !          1547: #endif
        !          1548: 
        !          1549: 
        !          1550: /*
        !          1551:  * Append file to temp file, handling control characters, folding lines, etc.
        !          1552:  * We don't grow the temp file to more than nlines so that a user won't have
        !          1553:  * to wait for 20 seconds to read in a monster file from net.sources.
        !          1554:  * What we really want is coroutines--any year now.
        !          1555:  */
        !          1556: 
        !          1557: #define ULINE 0200
        !          1558: static char *maxcol;
        !          1559: 
        !          1560: appfile(iop, nlines)
        !          1561: register FILE *iop;
        !          1562: {
        !          1563:        register int c;
        !          1564:        register char *icol;    /* &linebuf[0] <= icol <= maxcol */
        !          1565: 
        !          1566:        if (artread || artlines >= nlines || iop == NULL)
        !          1567:                return;
        !          1568:        maxcol = linebuf;
        !          1569:        icol = linebuf;
        !          1570:        while ((c = getc(iop)) != EOF) {
        !          1571:                switch (c) {
        !          1572:                case ' ':
        !          1573:                        if (icol == maxcol && icol < linebuf + LBUFLEN - 1) {
        !          1574:                                *icol++ = ' ';
        !          1575:                                maxcol = icol;
        !          1576:                        } else {
        !          1577:                                if (*icol == '_')
        !          1578:                                        *icol++ = ULINE | ' ';
        !          1579:                                else
        !          1580:                                        icol++;
        !          1581:                        }
        !          1582:                        break;
        !          1583:                case '\t':
        !          1584:                        icol = (icol - linebuf &~ 07) + 8 + linebuf;
        !          1585:                        growline(icol);
        !          1586:                        break;
        !          1587:                case '\b':
        !          1588:                        if (icol > linebuf) --icol;
        !          1589:                        break;
        !          1590:                case '\n':
        !          1591:                        outline();
        !          1592:                        if (artlines >= nlines)
        !          1593:                                return;
        !          1594:                        icol = linebuf;
        !          1595:                        break;
        !          1596:                case '\r':
        !          1597:                        icol = linebuf;
        !          1598:                        break;
        !          1599:                case '\f':
        !          1600:                        outline(); outline(); outline();
        !          1601:                        if (artlines >= nlines)
        !          1602:                                return;
        !          1603:                        icol = linebuf;
        !          1604:                        break;
        !          1605:                default:
        !          1606:                        if (c < ' ' || c > '~')
        !          1607:                                break;
        !          1608:                        else if (icol >= linebuf + LBUFLEN - 1)
        !          1609:                                icol++;
        !          1610:                        else if (icol == maxcol) {
        !          1611:                                *icol++ = c;
        !          1612:                                maxcol = icol; }
        !          1613:                        else if (c == '_')
        !          1614:                                *icol++ |= ULINE;
        !          1615:                        else if (*icol == '_')
        !          1616:                                *icol++ = (c | ULINE);
        !          1617:                        else    *icol++ = c;
        !          1618:                        break;
        !          1619:                }
        !          1620:        }
        !          1621:        if (maxcol != linebuf)          /* file not terminated with newline */
        !          1622:                outline();
        !          1623:        artread++;
        !          1624: }
        !          1625: 
        !          1626: growline(col)
        !          1627: char *col;
        !          1628: {
        !          1629:        while (maxcol < col && maxcol < linebuf + LBUFLEN - 1)
        !          1630:                *maxcol++ = ' ';
        !          1631: }
        !          1632: 
        !          1633: outline()
        !          1634: {
        !          1635:        *maxcol = '\0';
        !          1636:        if (STRNCMP(linebuf, ">From ", 6) == 0) {
        !          1637:                register char *p;
        !          1638:                for (p = linebuf ; (*p = p[1]) != '\0' ; p++);
        !          1639:        }
        !          1640:        tfappend(linebuf);
        !          1641:        if (maxcol > linebuf)
        !          1642:                artlines = lastlin;
        !          1643:        maxcol = linebuf;
        !          1644: }
        !          1645: 
        !          1646: 
        !          1647: /*
        !          1648:  * Prompt the user and get a line.
        !          1649:  * "prompter" is the prompt.  "buf" contains a string which
        !          1650:  * will be used as the initial user response (which may be edited
        !          1651:  * by the user with backspace, ^U, etc).  The resulting line is
        !          1652:  * returned in "buf".  The result of prget() is:
        !          1653:  *      0 if the line was terminated by NL or CR
        !          1654:  *      1 if it was terminated by the interrupt character.
        !          1655:  *      2 if it was terminated by erasing all the characters, including
        !          1656:  *        one or more that were prompted initially in "buf".  (If "buf"
        !          1657:  *        was empty, this will never occur.)
        !          1658:  */
        !          1659: int
        !          1660: prget(prompter, buf)
        !          1661: char *prompter, *buf;
        !          1662: {
        !          1663:        register char *p, *q, *r;
        !          1664:        register char c;
        !          1665:        char lastc;
        !          1666:        char hadprompt = buf[0];
        !          1667: 
        !          1668:        curflag = CURP2;
        !          1669:        r = buf + strlen(buf);
        !          1670:        lastc = '\0';
        !          1671:        for (;;) {
        !          1672:                p = secpr;
        !          1673:                for (q = prompter ; *q ; q++)
        !          1674:                        *p++ = *q;
        !          1675:                for (q = buf ; *q ; q++) {
        !          1676:                        if (p < &secpr[SECPRLEN-1] && *q >= ' ' && *q <= '~')
        !          1677:                                *p++ = *q;
        !          1678:                }
        !          1679:                *p = '\0';
        !          1680:                c = vgetc();
        !          1681:                if (c == '\n' || c == '\r' || c == cintr) {
        !          1682:                        break;
        !          1683:                }
        !          1684:                if (c == cerase || c == '\b' || c == '\177') {
        !          1685:                        if (lastc == '\\')
        !          1686:                                r[-1] = c;
        !          1687:                        else if (r > buf)
        !          1688:                                r--;
        !          1689:                } else if (c == ckill) {
        !          1690:                        if (lastc == '\\')
        !          1691:                                r[-1] = c;
        !          1692:                        else
        !          1693:                                r = buf;
        !          1694: #ifdef TIOCGLTC
        !          1695:                } else if (c == cwerase) {
        !          1696:                        if (lastc == '\\')
        !          1697:                                r[-1] = c;
        !          1698:                        else {
        !          1699:                                while (r > buf && (r[-1] == ' ' || r[-1] == '\t'))
        !          1700:                                        r--;
        !          1701:                                while (r > buf && r[-1] != ' ' && r[-1] != '\t')
        !          1702:                                        r--;
        !          1703:                        }
        !          1704: #endif
        !          1705:                } else {
        !          1706:                        *r++ = c;
        !          1707:                }
        !          1708:                lastc = c;
        !          1709:                *r = '\0';
        !          1710:                if ((r == buf) && hadprompt)
        !          1711:                        return 2;
        !          1712:        }
        !          1713:        curflag = CURHOME;
        !          1714:        secpr[0] = '\0';
        !          1715:        return (c == cintr);
        !          1716: }
        !          1717: 
        !          1718: 
        !          1719: 
        !          1720: /*
        !          1721:  * Execute a shell command.
        !          1722:  */
        !          1723: 
        !          1724: shcmd(cmd, flags)
        !          1725: char *cmd;
        !          1726: {
        !          1727:        char *arg[4];
        !          1728: 
        !          1729:        arg[0] = SHELL, arg[1] = "-c", arg[2] = cmd, arg[3] = NULL;
        !          1730:        return prun(arg, flags);
        !          1731: }
        !          1732: 
        !          1733: 
        !          1734: prun(args, flags)
        !          1735: char **args;
        !          1736: {
        !          1737:        int pid;
        !          1738:        int i;
        !          1739:        int (*savequit)();
        !          1740:        char *env[100], **envp, **oenvp;
        !          1741:        char a[BUFLEN + 2];
        !          1742:        extern char **environ;
        !          1743:        int pstatus, retval;
        !          1744: 
        !          1745:        if (!(flags & BKGRND)) {
        !          1746:                botscreen();
        !          1747:                ttycooked();
        !          1748: #ifdef SIGTSTP
        !          1749:                (void) signal(SIGTSTP, SIG_DFL);
        !          1750:                (void) signal(SIGTTIN, SIG_DFL);
        !          1751:                (void) signal(SIGTTOU, SIG_DFL);
        !          1752: #endif
        !          1753:        }
        !          1754: #if defined(BSD4_2) && !defined(sun)
        !          1755:        while ((pid = vfork()) == -1)
        !          1756: #else /* !BSD4_2 */
        !          1757:        /* 4.1 BSD (at least) can't handle this vfork with -ljobs */
        !          1758:        while ((pid = fork()) == -1)
        !          1759: #endif /* !BSD4_2 */
        !          1760:                sleep(1);               /* must not clear alarm */
        !          1761:        if (pid == 0) {
        !          1762:                for (i = 3 ; i < 20 ; i++)
        !          1763:                        close(i);
        !          1764:                if (flags & BKGRND) {
        !          1765:                        (void) signal(SIGINT, SIG_IGN);
        !          1766:                        (void) signal(SIGQUIT, SIG_IGN);
        !          1767: #ifdef SIGTSTP
        !          1768:                        (void) signal(SIGTSTP, SIG_IGN);
        !          1769:                        (void) signal(SIGTTIN, SIG_IGN);
        !          1770:                        (void) signal(SIGTTOU, SIG_IGN);
        !          1771: #endif
        !          1772:                        (void) close(0);
        !          1773:                        (void) close(1);
        !          1774:                        (void) open("/dev/null", 2);
        !          1775:                        (void) dup(0);
        !          1776:                }
        !          1777:                /* set $A */
        !          1778:                (void) sprintf(a, "A=%s", filename);
        !          1779:                oenvp = environ;
        !          1780:                env[0] = a;
        !          1781:                for (envp = env + 1 ; *oenvp != NULL && envp < env + 98 ; oenvp++)
        !          1782:                        if ((*oenvp)[0] != 'A' || (*oenvp)[1] != '=')
        !          1783:                                *envp++ = *oenvp;
        !          1784:                *envp = NULL;
        !          1785: 
        !          1786:                (void) umask(savmask);
        !          1787:                execve(args[0], args, env);
        !          1788:                perror(args[0]);
        !          1789:                exit(20);
        !          1790:        }
        !          1791:        if (!(flags & BKGRND)) {
        !          1792:                savequit = signal(SIGQUIT, SIG_IGN);
        !          1793:                while ((i = wait(&pstatus)) != pid && (i != -1 || errno == EINTR))
        !          1794:                        ;
        !          1795:                if (i == -1)
        !          1796:                        retval = 1;
        !          1797:                else
        !          1798:                        retval = pstatus;
        !          1799:                if (flags & CWAIT) {
        !          1800:                        fprintf(stderr, "[Hit return to continue]");
        !          1801:                        while ((errno = 0, i = getchar()) != '\n'
        !          1802:                                && (i != EOF || errno == EINTR));
        !          1803:                }
        !          1804:                (void) signal(SIGQUIT, savequit);
        !          1805:                ttyraw();
        !          1806:                okclear();
        !          1807: #ifdef SIGTSTP
        !          1808:                (void) signal(SIGTSTP, onstop);
        !          1809:                (void) signal(SIGTTIN, onstop);
        !          1810:                (void) signal(SIGTTOU, onstop);
        !          1811: #endif
        !          1812:                return retval;
        !          1813:        } else
        !          1814:                return 0;
        !          1815: }
        !          1816: 
        !          1817: #ifdef DIGPAGE
        !          1818: 
        !          1819: 
        !          1820: /*
        !          1821:  * Find end of current subarticle in digest.
        !          1822:  */
        !          1823: 
        !          1824: findend(l)
        !          1825: {
        !          1826:        register int i, n;
        !          1827:        register char *p;
        !          1828: 
        !          1829:        for (i = l ; i < l + ARTWLEN && i < lastlin ; i++) {
        !          1830:                tfget(linebuf, i);
        !          1831:                for (p = linebuf ; *p == '-' ; p++)
        !          1832:                        ;
        !          1833:                n = (int) (p - linebuf);
        !          1834:                if ( (n > 23 && n < 33) || (n > 65 && n < 79)) {
        !          1835:                        tfget(linebuf, ++i);
        !          1836:                        if (linebuf[0] == '\0')
        !          1837:                                return i + 1;
        !          1838:                }
        !          1839:        }
        !          1840:        return 0;
        !          1841: }
        !          1842: 
        !          1843: #endif
        !          1844: 
        !          1845: 
        !          1846: /*** Routines for handling temporary file ***/
        !          1847: 
        !          1848: /*
        !          1849:  * Append to temp file.
        !          1850:  * Long lines are folded.
        !          1851:  */
        !          1852: 
        !          1853: tfappend(tline)
        !          1854: register char *tline;
        !          1855: {
        !          1856:        register char *nxtlin;
        !          1857: 
        !          1858:        do {
        !          1859:                nxtlin = index(tline, '\n');
        !          1860:                if (nxtlin)
        !          1861:                        *nxtlin++ = '\0';
        !          1862: 
        !          1863:                while (strlen(tline) > COLS) {
        !          1864:                        tfput(tline, lastlin++);
        !          1865:                        tline += COLS;
        !          1866:                        maxlinno++;
        !          1867:                }
        !          1868:                tfput(tline, lastlin++);
        !          1869:        } while ((tline = nxtlin) != NULL);
        !          1870: }
        !          1871: 
        !          1872: 
        !          1873: tfput(tline, linno)
        !          1874: char *tline;
        !          1875: {
        !          1876:        register char *p;
        !          1877:        register FILE *rtfp;            /* try to make it a little faster */
        !          1878:        register int i;
        !          1879: 
        !          1880:        p = tline, i = even(COLS);
        !          1881:        tfseek(linno, 1);
        !          1882:        rtfp = tfp;
        !          1883:        while (--i >= 0) {
        !          1884:                if (*p)
        !          1885:                        putc(*p++, rtfp);
        !          1886:                else
        !          1887:                        putc('\0', rtfp);
        !          1888:        }
        !          1889:        tflinno++;
        !          1890: }
        !          1891: 
        !          1892: 
        !          1893: tfget(tline, linno)
        !          1894: char *tline;
        !          1895: {
        !          1896:        tfseek(linno, 0);
        !          1897:        fread(tline, even(COLS), 1, tfp);
        !          1898:        tline[COLS] = '\0';
        !          1899:        tflinno++;
        !          1900: }
        !          1901: 
        !          1902: 
        !          1903: tfseek(linno, wrflag)
        !          1904: {
        !          1905:        static int lastwrflag = 1;
        !          1906: 
        !          1907:        if (linno != tflinno || wrflag != lastwrflag) {
        !          1908:                (void) fseek(tfp, (long)linno * even(COLS), 0);
        !          1909:                tflinno = linno;
        !          1910:                lastwrflag = wrflag;
        !          1911:        }
        !          1912: }
        !          1913: 
        !          1914: /* VARARGS1 */
        !          1915: msg(s, a1, a2, a3, a4)
        !          1916: char *s;
        !          1917: long a1, a2, a3, a4;
        !          1918: {
        !          1919:        (void) sprintf(secpr, s, a1, a2, a3, a4);
        !          1920: }
        !          1921: 
        !          1922: 
        !          1923: /*
        !          1924:  * Update the display.
        !          1925:  * The display is entirely controlled by this routine,
        !          1926:  * which means that this routine may get pretty snarled.
        !          1927:  */
        !          1928: 
        !          1929: static int savelinno = -1;             /* dlinno on last call to updscr */
        !          1930: static int savepr;                     /* prflags on last call */
        !          1931: #ifdef TIOCGWINSZ
        !          1932: static int UPDATING = 0, WINCH = 0;
        !          1933: 
        !          1934: /*
        !          1935:  * called by winch() from virtterm.c -- resets state information back
        !          1936:  * to start-up state and forces a full redraw of the screen.  The
        !          1937:  * current article is rewound to the beginning because it's would
        !          1938:  * be very difficult to get the screen to return to the exact point
        !          1939:  * in the file that the user left off (I know, I tried).
        !          1940:  */
        !          1941: winch_upd()
        !          1942: {
        !          1943:        if(UPDATING)    /* concurrency.  wow! */
        !          1944:                WINCH++;
        !          1945:        else if((WINCH == 0) && (savelinno >= 0)) {
        !          1946:                int  saveflag = curflag;
        !          1947: 
        !          1948:                /* reread the article */
        !          1949:                FCLOSE(fp);
        !          1950:                obit = -1;
        !          1951:                getnextart(FALSE);
        !          1952:                appfile(fp, dlinno + ARTWLEN + 1);
        !          1953: 
        !          1954:                /* fix up the screen */
        !          1955:                curflag = saveflag;
        !          1956:                strcpy(prompt,"more? ");
        !          1957:                okclear();
        !          1958:                updscr();
        !          1959:        }
        !          1960: }
        !          1961: #endif /* TIOCGWINSZ */
        !          1962: 
        !          1963: 
        !          1964: updscr()
        !          1965: {
        !          1966:        int count;
        !          1967:        int i;
        !          1968: 
        !          1969: #ifdef TIOCGWINSZ
        !          1970:        UPDATING++;
        !          1971: #endif /* TIOCGWINSZ */
        !          1972:        if (checkin())
        !          1973:                return;
        !          1974:        if ((prflags & HELPMSG) == 0
        !          1975:         && (dlinno != savelinno || savepr != prflags)
        !          1976:         && quitflg == 0) {
        !          1977:                if (dlinno != savelinno)
        !          1978:                        prflags &=~ NOPRT;
        !          1979:                count = ARTWLEN;
        !          1980:                if (prflags & NOPRT)
        !          1981:                        count = 0;
        !          1982:                if ((prflags & HDRONLY) && count > hdrend)
        !          1983:                        count = hdrend - dlinno;
        !          1984: #ifdef DIGPAGE
        !          1985:                if (endsuba > 0 && count > endsuba - dlinno)
        !          1986:                        count = endsuba - dlinno;
        !          1987: #endif
        !          1988:                if ((prflags & NEWART) == 0)
        !          1989:                        ushift(ARTWIN, ARTWIN+ARTWLEN-1, dlinno - savelinno);
        !          1990:                if (count > lastlin - dlinno)
        !          1991:                        count = lastlin - dlinno;
        !          1992:                for (i = ARTWIN ; i < ARTWIN + ARTWLEN ; i++)
        !          1993:                        clrline(i);
        !          1994:                for (i = 0 ; i < count ; i++) {
        !          1995:                        tfget(linebuf, dlinno + i);
        !          1996:                        mvaddstr(ARTWIN + i, 0, linebuf);
        !          1997:                }
        !          1998:                prflags &=~ NEWART;
        !          1999:                savepr = prflags;
        !          2000:                savelinno = dlinno;
        !          2001:        }
        !          2002:        clrline(SPLINE), clrline(PRLINE);
        !          2003: #ifdef STATTOP
        !          2004:        mvaddstr(PRLINE, 0, prompt);
        !          2005: #else
        !          2006:        if (strlen(secpr) <= COLS)
        !          2007:                mvaddstr(PRLINE, 0, prompt);
        !          2008: #endif
        !          2009:        mvaddstr(PRLINE, 59, timestr);
        !          2010:        mvaddstr(PRLINE, 17, groupdir);
        !          2011:        addch(' '); addnum(bit); addch('/'); addnum(pngsize); addch(' ');
        !          2012:        if (ismail)
        !          2013:                mvaddstr(PRLINE, 75, ismail > 1? "MAIL" : "mail");
        !          2014:        mvaddstr(SPLINE, 0, secpr);
        !          2015:        if (curflag == CURP1)
        !          2016:                move(PRLINE, strlen(prompt));
        !          2017:        else if (curflag == CURHOME)
        !          2018:                move(0, 0);
        !          2019:        refresh();
        !          2020: #ifdef TIOCGWINSZ
        !          2021:        UPDATING=0;
        !          2022:        if (WINCH) { /* window changed while updating screen */
        !          2023:                WINCH = 0;
        !          2024:                winch_upd();
        !          2025:        }
        !          2026: #endif /* TIOCGWINSZ */
        !          2027: }
        !          2028: 
        !          2029: addnum(n)
        !          2030: register long n;
        !          2031: {
        !          2032:        if (n >= 10)
        !          2033:                addnum(n / 10);
        !          2034:        addch((char)(n % 10 + '0'));
        !          2035: }
        !          2036: 
        !          2037: /*
        !          2038:  * Called on alarm signal.
        !          2039:  * Simply sets flag, signal processed later.
        !          2040:  */
        !          2041: 
        !          2042: onalarm()
        !          2043: {
        !          2044: #ifdef SIGTSTP
        !          2045:        int dojump = reading;
        !          2046: 
        !          2047:        reading = FALSE;
        !          2048:        alflag++;
        !          2049:        if (dojump)
        !          2050:                longjmp(alrmjmp, 1);
        !          2051: #else /* !SIGTSTP */
        !          2052:        alflag++;
        !          2053: #endif
        !          2054: }
        !          2055: 
        !          2056: /*
        !          2057:  * Process alarm signal (or start clock)
        !          2058:  */
        !          2059: timer()
        !          2060: {
        !          2061:        time_t tod;
        !          2062:        int hour;
        !          2063:        int i;
        !          2064:        struct tm *t;
        !          2065:        struct stat statb;
        !          2066:        struct tm *localtime();
        !          2067:        static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
        !          2068:        static long oldmsize = 1000000L;
        !          2069:        static int rccount = 10;
        !          2070:        static time_t lastismail = 0;
        !          2071: 
        !          2072:        alflag = 0;
        !          2073:        (void) signal(SIGALRM, onalarm);
        !          2074:        (void) time(&tod);
        !          2075:        t = localtime(&tod);
        !          2076:        i = 60 - t->tm_sec;
        !          2077:        (void) alarm(i > 30? 30 : i);                   /* reset alarm */
        !          2078:        hour = t->tm_hour % 12;
        !          2079:        if (hour == 0)  hour = 12;
        !          2080:        (void) sprintf(timestr, "%.3s %d %d:%02d",
        !          2081:                months + 3 * t->tm_mon, t->tm_mday, hour, t->tm_min);
        !          2082:        if (mailf == NULL || stat(mailf, &statb) < 0) {
        !          2083:                statb.st_size = 0;
        !          2084:        }
        !          2085:        if (statb.st_size > oldmsize) {
        !          2086:                ismail = 2;
        !          2087:                beep();
        !          2088:        } else {
        !          2089:                if (statb.st_size == 0)
        !          2090:                        ismail = 0;
        !          2091:                                        /* force MAIL for at least 30 seconds */
        !          2092:                else if (ismail > 1 && (lastismail+30) < tod)
        !          2093:                        ismail = 1;
        !          2094:        }
        !          2095:        oldmsize = statb.st_size;
        !          2096:        lastismail = tod;
        !          2097:        if (uflag && !xflag && --rccount < 0) {
        !          2098:                writeoutrc();
        !          2099:                if (secpr[0] == '\0')
        !          2100:                        (void) strcpy(secpr, ".newsrc updated");
        !          2101:                rccount = 10;
        !          2102:        }
        !          2103: }
        !          2104: 
        !          2105: char *
        !          2106: getmailname()
        !          2107: {
        !          2108:        static char mailname[32];
        !          2109:        register char *p;
        !          2110: 
        !          2111:        if( (p = getenv("MAIL")) != NULL)
        !          2112:                return p;
        !          2113: #ifndef MMDF
        !          2114:        if (username[0] == '\0' || strlen(username) > 15)
        !          2115:                return NULL;
        !          2116: #ifdef USG
        !          2117:        (void) sprintf(mailname, "/usr/mail/%s", username);
        !          2118: #else /* !USG */
        !          2119:        (void) sprintf(mailname, "/usr/spool/mail/%s", username);
        !          2120: #endif /* !USG */
        !          2121: #else /* MMDF */
        !          2122:        (void) sprintf(mailname, "%s/mailbox", userhome);
        !          2123: #endif /* MMDF */
        !          2124:        return mailname;
        !          2125: }
        !          2126: 
        !          2127: 
        !          2128: 
        !          2129: /*** Terminal I/O ***/
        !          2130: 
        !          2131: #define INBUFSIZ 8
        !          2132: 
        !          2133: char inbuf[INBUFSIZ];                  /* input buffer */
        !          2134: char outbuf[BUFSIZ];                   /* output buffer */
        !          2135: int innleft = 0;                       /* # of chars in input buffer */
        !          2136: int outnleft = BUFSIZ;                 /* room left in output buffer */
        !          2137: char *innext;                          /* next input character */
        !          2138: char *outnext = outbuf;                        /* next space in output buffer */
        !          2139: #ifdef USG
        !          2140: int oflags;                            /* fcntl flags (for nodelay read) */
        !          2141: #endif
        !          2142: 
        !          2143: /*
        !          2144:  * Input a character
        !          2145:  */
        !          2146: 
        !          2147: vgetc()
        !          2148: {
        !          2149:        register c;
        !          2150: #if defined(BSD4_2) || defined(BSD4_1C)
        !          2151:        int readfds, exceptfds;
        !          2152: #endif
        !          2153: 
        !          2154: recurse:
        !          2155:        if (--innleft >= 0) {
        !          2156:                c = *innext++;
        !          2157:        } else {
        !          2158:                if (alflag)
        !          2159:                        timer();
        !          2160:                updscr();       /* update the display */
        !          2161:                for (;;) {
        !          2162:                        if (innleft > 0 || alflag)
        !          2163:                                goto recurse;
        !          2164:                        intflag = 0;
        !          2165: #ifdef USG
        !          2166:                        if (oflags & O_NDELAY) {
        !          2167:                                oflags &=~ O_NDELAY;
        !          2168:                                fcntl(0, F_SETFL, oflags);
        !          2169:                        }
        !          2170: #endif
        !          2171: #ifdef SIGTSTP
        !          2172:                        if (setjmp(alrmjmp))
        !          2173:                                continue;
        !          2174:                        if (setjmp(intjmp))
        !          2175:                                return cintr;
        !          2176:                        reading = TRUE;
        !          2177: #endif /* SIGTSTP */
        !          2178: #if defined(BSD4_2) || defined(BSD4_1C)
        !          2179:                        /* Use a select because it can be interrupted. */
        !          2180:                        readfds = 1; exceptfds = 1;
        !          2181:                        select(1, &readfds, (int *)0, &exceptfds, (int *)0);
        !          2182:                        if (!(readfds & 1))
        !          2183:                                break;
        !          2184: #endif
        !          2185:                        innleft = read(0, inbuf, INBUFSIZ);
        !          2186: #ifdef SIGTSTP
        !          2187:                        reading = FALSE;
        !          2188: #endif /* SIGTSTP */
        !          2189:                        if (innleft > 0)
        !          2190:                                break;
        !          2191:                        if (innleft == 0) {
        !          2192:                                quitflg++;
        !          2193:                                return cintr;
        !          2194:                        }
        !          2195:                        if (errno != EINTR)
        !          2196:                                abort();        /* "Can't happen" */
        !          2197:                        if (intflag) {
        !          2198:                                intflag--;
        !          2199:                                return cintr;
        !          2200:                        }
        !          2201:                }
        !          2202:                innext = inbuf + 1;
        !          2203:                innleft--;
        !          2204:                c = inbuf[0];
        !          2205:        }
        !          2206: #ifndef USG
        !          2207: #ifndef CBREAK
        !          2208:        c &= 0177;
        !          2209:        if (c == '\034')        /* FS character */
        !          2210:                xxit(0);
        !          2211: #endif
        !          2212: #endif
        !          2213:        if (c == '\f') {
        !          2214:                okclear();
        !          2215:                prflags &=~ NOPRT;
        !          2216:                goto recurse;
        !          2217:        }
        !          2218:        if (c == '\r')
        !          2219:                c = '\n';
        !          2220:        return c;
        !          2221: }
        !          2222: 
        !          2223: 
        !          2224: /*
        !          2225:  * Push a character back onto the input stream.
        !          2226:  */
        !          2227: 
        !          2228: pushback(c)
        !          2229: {
        !          2230:        if (innext <= inbuf)
        !          2231:                abort();
        !          2232:        *--innext = c;
        !          2233:        innleft++;
        !          2234: }
        !          2235: 
        !          2236: /*
        !          2237:  * Check for terminal input
        !          2238:  */
        !          2239: 
        !          2240: checkin()
        !          2241: {
        !          2242: #ifdef FIONREAD
        !          2243:        int count;
        !          2244: #endif
        !          2245: #ifdef STATTOP
        !          2246:        if (innleft > 0)
        !          2247: #else
        !          2248:        if (innleft > 0 || alflag)
        !          2249: #endif
        !          2250:                return 1;
        !          2251: #if defined(USG) || defined(FIONREAD)
        !          2252:        if (ospeed >= B9600)
        !          2253:                return 0;
        !          2254:        vflush();
        !          2255:        if (ospeed <= B300)
        !          2256:                ttyowait();
        !          2257: #ifdef USG
        !          2258:        if ((oflags & O_NDELAY) == 0) {
        !          2259:                oflags |= O_NDELAY;
        !          2260:                (void) fcntl(0, F_SETFL, oflags);
        !          2261:        }
        !          2262:        if ((innleft = read(0, inbuf, INBUFSIZ)) > 0) {
        !          2263:                innext = inbuf;
        !          2264:                return 1;
        !          2265:        }
        !          2266: #endif
        !          2267: #ifdef FIONREAD
        !          2268:        count = 0;                      /* in case FIONREAD fails */
        !          2269:        (void) ioctl(0, FIONREAD, (char *)&count);
        !          2270:        if (count)
        !          2271:                return 1;
        !          2272: #endif
        !          2273: #endif
        !          2274:        return 0;
        !          2275: }
        !          2276: 
        !          2277: 
        !          2278: 
        !          2279: /*
        !          2280:  * flush terminal input queue.
        !          2281:  */
        !          2282: 
        !          2283: clearin()
        !          2284: {
        !          2285: #ifdef USG
        !          2286:        (void) ioctl(0, TCFLSH, (char *)0);
        !          2287: #else
        !          2288: #ifdef TIOCFLUSH
        !          2289:        (void) ioctl(0, TIOCFLUSH, (char *)0);
        !          2290: #else
        !          2291:        struct sgttyb tty;
        !          2292:        (void) ioctl(0, TIOCGETP, &tty);
        !          2293:        (void) ioctl(0, TIOCSETP, &tty);
        !          2294: #endif
        !          2295: #endif
        !          2296:        innleft = 0;
        !          2297: }
        !          2298: 
        !          2299: vputc(c)
        !          2300: {
        !          2301:        if (--outnleft < 0) {
        !          2302:                vflush();
        !          2303:                outnleft--;
        !          2304:        }
        !          2305:        *outnext++ = c;
        !          2306: }
        !          2307: 
        !          2308: /*
        !          2309:  * Flush the output buffer
        !          2310:  */
        !          2311: 
        !          2312: vflush()
        !          2313: {
        !          2314:        register char *p;
        !          2315:        register int i;
        !          2316: #ifdef BSD4_2
        !          2317:        int mask;
        !          2318: #else
        !          2319:        unsigned oalarm;
        !          2320: #endif
        !          2321: 
        !          2322: #ifdef BSD4_2
        !          2323:        mask = sigblock(1 << (SIGALRM-1));
        !          2324: #else
        !          2325:        oalarm = alarm(0);
        !          2326: #endif
        !          2327:        for (p = outbuf ; p < outnext ; p += i) {
        !          2328:                if ((i = write(1, p, outnext - p)) < 0) {
        !          2329:                        if (errno != EINTR)
        !          2330:                                abort();        /* "Can't happen" */
        !          2331:                        i = 0;
        !          2332:                }
        !          2333:        }
        !          2334:        outnleft = BUFSIZ;
        !          2335:        outnext = outbuf;
        !          2336: #ifdef BSD4_2
        !          2337:        sigsetmask(mask);
        !          2338: #else
        !          2339:        (void) alarm(oalarm);
        !          2340: #endif
        !          2341: }
        !          2342: 
        !          2343: /*** terminal modes ***/
        !          2344: 
        !          2345: #ifdef USG
        !          2346: static struct termio oldtty, newtty;
        !          2347: 
        !          2348: /*
        !          2349:  * Save tty modes
        !          2350:  */
        !          2351: 
        !          2352: ttysave()
        !          2353: {
        !          2354:        if (ioctl(1, TCGETA, &oldtty) < 0)
        !          2355:                xerror("Can't get tty modes");
        !          2356:        newtty = oldtty;
        !          2357:        newtty.c_iflag &=~ (INLCR|IGNCR|ICRNL);
        !          2358:        newtty.c_oflag &=~ (OPOST);
        !          2359:        newtty.c_lflag &=~ (ICANON|ECHO|ECHOE|ECHOK|ECHONL);
        !          2360:        newtty.c_lflag |=  (NOFLSH);
        !          2361:        newtty.c_cc[VMIN] = 1;
        !          2362:        newtty.c_cc[VTIME] = 0;
        !          2363:        cerase = oldtty.c_cc[VERASE];
        !          2364:        ckill = oldtty.c_cc[VKILL];
        !          2365:        cintr = oldtty.c_cc[VINTR];
        !          2366:        ospeed = oldtty.c_cflag & CBAUD;
        !          2367:        initterm();
        !          2368: }
        !          2369: 
        !          2370: 
        !          2371: /*
        !          2372:  * Set tty modes for visual processing
        !          2373:  */
        !          2374: 
        !          2375: ttyraw()
        !          2376: {
        !          2377:        while (ioctl(1, TCSETAF, &newtty) < 0 && errno == EINTR)
        !          2378:                ;
        !          2379:        rawterm();
        !          2380: }
        !          2381: 
        !          2382: ttyowait()
        !          2383: {      /* wait for output queue to drain */
        !          2384:        while (ioctl(1, TCSETAW, &newtty) < 0 && errno == EINTR)
        !          2385:                ;
        !          2386: }
        !          2387: 
        !          2388: /*
        !          2389:  * Restore tty modes
        !          2390:  */
        !          2391: 
        !          2392: ttycooked()
        !          2393: {
        !          2394:        cookedterm();
        !          2395:        vflush();
        !          2396:        while (ioctl(1, TCSETAF, &oldtty) < 0 && errno == EINTR)
        !          2397:                ;
        !          2398:        oflags &=~ O_NDELAY;
        !          2399:        (void) fcntl(0, F_SETFL, oflags) ;
        !          2400: }
        !          2401: 
        !          2402: #else
        !          2403: 
        !          2404: static struct sgttyb oldtty, newtty;
        !          2405: #ifdef TIOCGLTC
        !          2406: static struct ltchars oldltchars, newltchars;
        !          2407: #endif
        !          2408: 
        !          2409: /*
        !          2410:  * Save tty modes
        !          2411:  */
        !          2412: 
        !          2413: ttysave()
        !          2414: {
        !          2415: #ifdef CBREAK
        !          2416:        struct tchars tchars;   /* special characters, including interrupt */
        !          2417: #endif
        !          2418: #ifdef SIGTSTP
        !          2419:        int getpgrp();
        !          2420: #if defined(BSD4_2) || defined(BSD4_1C)
        !          2421:        int tpgrp;
        !          2422: #else /* BSD4_1 */
        !          2423:        short tpgrp;
        !          2424: #endif /* BSD4_1 */
        !          2425: 
        !          2426: retry:
        !          2427: #ifdef BSD4_2
        !          2428:        (void) sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
        !          2429: #else /* !BSD4_2 */
        !          2430:        (void) signal(SIGTSTP, SIG_HOLD);
        !          2431:        (void) signal(SIGTTIN, SIG_HOLD);
        !          2432:        (void) signal(SIGTTOU, SIG_HOLD);
        !          2433: #endif /* !BSD4_2 */
        !          2434:        if (ioctl(2, TIOCGPGRP, (char *)&tpgrp) < 0)
        !          2435:                goto nottty;
        !          2436:        if (tpgrp != getpgrp(0)) { /* not in foreground */
        !          2437:                (void) signal(SIGTTOU, SIG_DFL);
        !          2438: #ifdef BSD4_2
        !          2439:                (void) sigsetmask(sigblock(0) & ~sigmask(SIGTTOU));
        !          2440: #endif /* BSD4_2 */
        !          2441:                (void) kill(0, SIGTTOU);
        !          2442:                /* job stops here waiting for SIGCONT */
        !          2443:                goto retry;
        !          2444:        }
        !          2445:        (void) signal(SIGTTIN, SIG_DFL);
        !          2446:        (void) signal(SIGTTOU, SIG_DFL);
        !          2447:        (void) signal(SIGTSTP, SIG_DFL);
        !          2448: #ifdef BSD4_2
        !          2449:        (void) sigsetmask(sigblock(0) & ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)));
        !          2450: #endif /* BSD4_2 */
        !          2451: #endif /* SIGTSTP */
        !          2452:        if (ioctl(1, TIOCGETP, (char *)&oldtty) < 0)
        !          2453: nottty:                xerror("Can't get tty modes");
        !          2454:        newtty = oldtty;
        !          2455:        newtty.sg_flags &=~ (CRMOD|ECHO|XTABS);
        !          2456: #ifdef CBREAK
        !          2457:        newtty.sg_flags |= CBREAK;
        !          2458:        ioctl(1, TIOCGETC, (char *)&tchars);
        !          2459:        cintr = tchars.t_intrc;
        !          2460: #else /* !CBREAK */
        !          2461:        newtty.sg_flags |= RAW;
        !          2462:        cintr = '\0177';        /* forcibly this on V6 systems */
        !          2463: #endif /* !CBREAK */
        !          2464:        cerase = oldtty.sg_erase;
        !          2465:        ckill = oldtty.sg_kill;
        !          2466:        ospeed = oldtty.sg_ospeed;
        !          2467: #ifdef TIOCGLTC
        !          2468:        if (ioctl(1, TIOCGLTC, (char *)&oldltchars) >= 0) {
        !          2469:                newltchars = oldltchars;
        !          2470:                newltchars.t_dsuspc = -1;
        !          2471:                cwerase = oldltchars.t_werasc;
        !          2472:        }
        !          2473: #endif
        !          2474:        initterm();
        !          2475: #ifdef SIGTSTP
        !          2476:        (void) signal(SIGTTIN, onstop);
        !          2477:        (void) signal(SIGTTOU, onstop);
        !          2478:        (void) signal(SIGTSTP, onstop);
        !          2479: #endif /* SIGTSTP */
        !          2480: }
        !          2481: 
        !          2482: 
        !          2483: /*
        !          2484:  * Set tty modes for visual processing
        !          2485:  */
        !          2486: 
        !          2487: ttyraw()
        !          2488: {
        !          2489:        while (ioctl(1, TIOCSETN, (char *)&newtty) < 0 && errno == EINTR)
        !          2490:                ;
        !          2491: #ifdef TIOCGLTC
        !          2492:        if (newltchars.t_dsuspc == '\377')
        !          2493:          while (ioctl(1, TIOCSLTC, (char *)&newltchars) < 0 && errno == EINTR)
        !          2494:                ;
        !          2495: #endif
        !          2496:        rawterm();
        !          2497: }
        !          2498: 
        !          2499: ttyowait()
        !          2500: {      /* wait for output queue to drain */
        !          2501: #ifdef TIOCDRAIN       /* This ioctl is a local mod on linus */
        !          2502:        (void) ioctl(1, TIOCDRAIN, (char *)0);
        !          2503: #endif
        !          2504: }
        !          2505: 
        !          2506: 
        !          2507: /*
        !          2508:  * Restore tty modes
        !          2509:  */
        !          2510: 
        !          2511: ttycooked()
        !          2512: {
        !          2513:        cookedterm();
        !          2514:        vflush();
        !          2515:        while (ioctl(1, TIOCSETN, (char *)&oldtty) < 0 && errno == EINTR)
        !          2516:                ;
        !          2517: #ifdef TIOCGLTC
        !          2518:        if (newltchars.t_dsuspc == '\377')
        !          2519:          while (ioctl(1, TIOCSLTC, (char *)&oldltchars) < 0 && errno == EINTR)
        !          2520:                ;
        !          2521: #endif
        !          2522: }
        !          2523: 
        !          2524: #endif
        !          2525: 
        !          2526: 
        !          2527: 
        !          2528: /*** signal handlers ***/
        !          2529: 
        !          2530: onint() {
        !          2531: #ifdef SIGTSTP
        !          2532:        int dojump = reading;
        !          2533: 
        !          2534:        reading = FALSE;
        !          2535: #endif /* SIGTSTP */
        !          2536:        if (!news) {
        !          2537:                ttycooked();
        !          2538:                xxit(1);
        !          2539:        }
        !          2540:        (void) signal(SIGINT, onint);
        !          2541:        clearin();                      /* flush input queue */
        !          2542: #ifdef SIGTSTP
        !          2543:        if (dojump)
        !          2544:                longjmp(intjmp, 1);
        !          2545: #endif /* SIGTSTP */
        !          2546:        intflag++;
        !          2547: }
        !          2548: 
        !          2549: #ifdef SIGTSTP
        !          2550: onstop(signo)
        !          2551: int signo;
        !          2552: {
        !          2553:        /* restore old terminal state */
        !          2554:        botscreen();
        !          2555:        vflush();
        !          2556:        ttycooked();
        !          2557:        (void) signal(signo, SIG_DFL);
        !          2558: #ifdef BSD4_2
        !          2559:        (void) sigblock(sigmask(SIGALRM)|sigmask(SIGINT));
        !          2560:        (void) sigsetmask(sigblock(0) & ~sigmask(signo));
        !          2561: #else /* BSD4_1 */
        !          2562:        (void) alarm(0);
        !          2563: #endif /* BSD4_1 */
        !          2564:        (void) kill(0, signo);  /* stop here until continued */
        !          2565: 
        !          2566:        (void) signal(signo, onstop);
        !          2567:        /* restore our special terminal state */
        !          2568:        ttyraw();
        !          2569: #ifdef TIOCGWINSZ
        !          2570:        winch();        /* get current window size and redraw screen */
        !          2571: #else  /* !TIOCGWINSZ */
        !          2572:        okclear();
        !          2573:        updscr();
        !          2574: #endif         /* !TIOCGWINSZ */
        !          2575: #ifdef BSD4_2
        !          2576:        (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM)|sigmask(SIGINT)));
        !          2577: #else /* BSD4_1 */
        !          2578:        timer();
        !          2579: #endif /* BSD4_1 */
        !          2580: }
        !          2581: #endif
        !          2582: 
        !          2583: /*** stolen from rfuncs2.c and modified ***/
        !          2584: 
        !          2585: vsave(to, flags)
        !          2586: register char *to;
        !          2587: {
        !          2588:        register FILE *ufp;
        !          2589:        int     isprogram = 0;
        !          2590:        int     isnew = 1;
        !          2591:        long    saveoff;
        !          2592:        char    temp[20];
        !          2593:        char    *fname;
        !          2594:        char    prog[BUFLEN + 24];
        !          2595:        int     err;
        !          2596: 
        !          2597:        saveoff = ftell(fp);
        !          2598:        (void) fseek(fp, artbody, 0);
        !          2599:        fname = to;
        !          2600:        if (*to == PIPECHAR) {
        !          2601:                if (strlen(to) > BUFLEN) {
        !          2602:                        msg("Command name too long");
        !          2603:                        goto out;
        !          2604:                }
        !          2605:                flags |= OVWRITE;
        !          2606:                (void) strcpy(temp, "/tmp/vnXXXXXX");
        !          2607:                (void) mktemp(temp);
        !          2608:                fname = temp;
        !          2609:                _amove(ROWS - 1, 0);
        !          2610:                vflush();
        !          2611:        }
        !          2612:        if ((flags & OVWRITE) == 0) {
        !          2613:                ufp = fopen(fname, "r");
        !          2614:                if (ufp != NULL) {
        !          2615:                        (void) fclose(ufp);
        !          2616:                        isnew = 0;
        !          2617:                }
        !          2618:        }
        !          2619:        (void) umask(savmask);
        !          2620: 
        !          2621:        if (*to == PIPECHAR)
        !          2622:                isprogram++;
        !          2623:        if ((ufp = fopen(fname, (flags & OVWRITE) == 0? "a" : "w")) == NULL) {
        !          2624:                msg("Cannot open %s", fname);
        !          2625:                goto out;
        !          2626:        }
        !          2627:        /*
        !          2628:         * V7MAIL code is here to conform to V7 mail format.
        !          2629:         * If you need a different format to be able to
        !          2630:         * use your local mail command (such as four ^A's
        !          2631:         * on the end of articles) substitute it here.
        !          2632:         */
        !          2633:        if (flags & SVHEAD) {
        !          2634: #ifdef MMDF
        !          2635:                if (!isprogram)
        !          2636:                        fprintf(ufp, "\001\001\001\001\n");
        !          2637: #endif /* MMDF */
        !          2638: #ifdef V7MAIL
        !          2639:                h->subtime = cgtdate(h->subdate);
        !          2640:                fprintf(ufp, "From %s %s", replyname(h), ctime(&h->subtime));
        !          2641: #endif
        !          2642:                hprint(h, ufp, 2);
        !          2643: #ifdef V7MAIL
        !          2644:                tprint(fp, ufp, TRUE);
        !          2645:                putc('\n', ufp);        /* force blank line at end (ugh) */
        !          2646: #else
        !          2647:                tprint(fp, ufp, FALSE);
        !          2648: #endif
        !          2649:        } else {
        !          2650:                tprint(fp, ufp, FALSE);
        !          2651:        }
        !          2652: 
        !          2653:        err = ferror(ufp);
        !          2654: 
        !          2655:        fclose(ufp);
        !          2656:        if (isprogram) {
        !          2657:                if (err)
        !          2658:                        msg("error in writing temp file, maybe disk full?");
        !          2659:                else {
        !          2660:                        (void) sprintf(prog, "(%s)<%s", to + 1, fname);
        !          2661:                        shcmd(prog, CWAIT);
        !          2662:                        prflags |= NOPRT;
        !          2663:                }
        !          2664:        } else {
        !          2665:                msg("%sfile: %s %s",
        !          2666:                        err? "ERROR WHILE WRITING ": "",
        !          2667:                        to,
        !          2668:                        (flags&OVWRITE)? "written":
        !          2669:                                isnew ? "created" : "appended");
        !          2670:        }
        !          2671: 
        !          2672:        /* If we got an error, screen may be messed.  E.g. 4.2BSD
        !          2673:         * writes "disk full" messages to the user's tty.
        !          2674:         */
        !          2675:        if (err) {
        !          2676:                okclear();
        !          2677:                updscr();
        !          2678:        }
        !          2679: 
        !          2680: out:
        !          2681:        if (isprogram) {
        !          2682:                (void) unlink(fname);
        !          2683:        }
        !          2684:        (void) umask(N_UMASK);
        !          2685:        (void) fseek(fp, saveoff, 0);
        !          2686: }
        !          2687: 
        !          2688: xxit(status)
        !          2689: int    status;
        !          2690: {
        !          2691:        (void) unlink(infile);
        !          2692:        (void) unlink(outfile);
        !          2693: #ifdef SORTACTIVE
        !          2694:        if (STRNCMP(ACTIVE,"/tmp/", 5) == 0)
        !          2695:                (void) unlink(ACTIVE);
        !          2696: #endif /* SORTACTIVE */
        !          2697: #ifdef SERVER
        !          2698:        (void) unlink(active_name());
        !          2699:        close_server(); 
        !          2700: #endif /* SERVER */
        !          2701:        if (ospeed) {   /* is == 0, we haven't been in raw mode yet */
        !          2702:                botscreen();
        !          2703:                vflush();
        !          2704:                ttycooked();
        !          2705:        }
        !          2706:        exit(status);
        !          2707: }

unix.superglobalmegacorp.com

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