Annotation of 43BSDTahoe/new/news/src/visual.c, revision 1.1.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.