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

unix.superglobalmegacorp.com

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