Annotation of 43BSD/contrib/news/src/visual.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * visual - visual news interface.
        !             3:  * Kenneth Almquist
        !             4:  */
        !             5: 
        !             6: #ifdef SCCSID
        !             7: static char    *SccsId = "@(#)visual.c 1.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.