Annotation of 43BSD/ucb/more/more.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: char copyright[] =
        !             9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)more.c     5.4 (Berkeley) 4/3/86";
        !            15: #endif not lint
        !            16: 
        !            17: /*
        !            18: ** more.c - General purpose tty output filter and file perusal program
        !            19: **
        !            20: **     by Eric Shienbrood, UC Berkeley
        !            21: **
        !            22: **     modified by Geoff Peck, UCB to add underlining, single spacing
        !            23: **     modified by John Foderaro, UCB to add -c and MORE environment variable
        !            24: */
        !            25: 
        !            26: #include <stdio.h>
        !            27: #include <sys/types.h>
        !            28: #include <ctype.h>
        !            29: #include <signal.h>
        !            30: #include <errno.h>
        !            31: #include <sgtty.h>
        !            32: #include <setjmp.h>
        !            33: #include <sys/stat.h>
        !            34: 
        !            35: #define HELPFILE       "/usr/lib/more.help"
        !            36: #define VI             "/usr/ucb/vi"
        !            37: 
        !            38: #define Fopen(s,m)     (Currline = 0,file_pos=0,fopen(s,m))
        !            39: #define Ftell(f)       file_pos
        !            40: #define Fseek(f,off)   (file_pos=off,fseek(f,off,0))
        !            41: #define Getc(f)                (++file_pos, getc(f))
        !            42: #define Ungetc(c,f)    (--file_pos, ungetc(c,f))
        !            43: 
        !            44: #define MBIT   CBREAK
        !            45: #define stty(fd,argp)  ioctl(fd,TIOCSETN,argp)
        !            46: 
        !            47: #define TBUFSIZ        1024
        !            48: #define LINSIZ 256
        !            49: #define ctrl(letter)   ('letter' & 077)
        !            50: #define RUBOUT '\177'
        !            51: #define ESC    '\033'
        !            52: #define QUIT   '\034'
        !            53: 
        !            54: struct sgttyb  otty, savetty;
        !            55: long           file_pos, file_size;
        !            56: int            fnum, no_intty, no_tty, slow_tty;
        !            57: int            dum_opt, dlines, onquit(), end_it(), chgwinsz();
        !            58: int            onsusp();
        !            59: int            nscroll = 11;   /* Number of lines scrolled by 'd' */
        !            60: int            fold_opt = 1;   /* Fold long lines */
        !            61: int            stop_opt = 1;   /* Stop after form feeds */
        !            62: int            ssp_opt = 0;    /* Suppress white space */
        !            63: int            ul_opt = 1;     /* Underline as best we can */
        !            64: int            promptlen;
        !            65: int            Currline;       /* Line we are currently at */
        !            66: int            startup = 1;
        !            67: int            firstf = 1;
        !            68: int            notell = 1;
        !            69: int            docrterase = 0;
        !            70: int            docrtkill = 0;
        !            71: int            bad_so; /* True if overwriting does not turn off standout */
        !            72: int            inwait, Pause, errors;
        !            73: int            within; /* true if we are within a file,
        !            74:                        false if we are between files */
        !            75: int            hard, dumb, noscroll, hardtabs, clreol;
        !            76: int            catch_susp;     /* We should catch the SIGTSTP signal */
        !            77: char           **fnames;       /* The list of file names */
        !            78: int            nfiles;         /* Number of files left to process */
        !            79: char           *shell;         /* The name of the shell to use */
        !            80: int            shellp;         /* A previous shell command exists */
        !            81: char           ch;
        !            82: jmp_buf                restore;
        !            83: char           Line[LINSIZ];   /* Line buffer */
        !            84: int            Lpp = 24;       /* lines per page */
        !            85: char           *Clear;         /* clear screen */
        !            86: char           *eraseln;       /* erase line */
        !            87: char           *Senter, *Sexit;/* enter and exit standout mode */
        !            88: char           *ULenter, *ULexit;      /* enter and exit underline mode */
        !            89: char           *chUL;          /* underline character */
        !            90: char           *chBS;          /* backspace character */
        !            91: char           *Home;          /* go to home */
        !            92: char           *cursorm;       /* cursor movement */
        !            93: char           cursorhome[40]; /* contains cursor movement to home */
        !            94: char           *EodClr;        /* clear rest of screen */
        !            95: char           *tgetstr();
        !            96: int            Mcol = 80;      /* number of columns */
        !            97: int            Wrap = 1;       /* set if automargins */
        !            98: int            soglitch;       /* terminal has standout mode glitch */
        !            99: int            ulglitch;       /* terminal has underline mode glitch */
        !           100: int            pstate = 0;     /* current UL state */
        !           101: long           fseek();
        !           102: char           *getenv();
        !           103: struct {
        !           104:     long chrctr, line;
        !           105: } context, screen_start;
        !           106: extern char    PC;             /* pad character */
        !           107: extern short   ospeed;
        !           108: 
        !           109: 
        !           110: main(argc, argv)
        !           111: int argc;
        !           112: char *argv[];
        !           113: {
        !           114:     register FILE      *f;
        !           115:     register char      *s;
        !           116:     register char      *p;
        !           117:     register char      ch;
        !           118:     register int       left;
        !           119:     int                        prnames = 0;
        !           120:     int                        initopt = 0;
        !           121:     int                        srchopt = 0;
        !           122:     int                        clearit = 0;
        !           123:     int                        initline;
        !           124:     char               initbuf[80];
        !           125:     FILE               *checkf();
        !           126: 
        !           127:     nfiles = argc;
        !           128:     fnames = argv;
        !           129:     initterm ();
        !           130:     nscroll = Lpp/2 - 1;
        !           131:     if (nscroll <= 0)
        !           132:        nscroll = 1;
        !           133:     if(s = getenv("MORE")) argscan(s);
        !           134:     while (--nfiles > 0) {
        !           135:        if ((ch = (*++fnames)[0]) == '-') {
        !           136:            argscan(*fnames+1);
        !           137:        }
        !           138:        else if (ch == '+') {
        !           139:            s = *fnames;
        !           140:            if (*++s == '/') {
        !           141:                srchopt++;
        !           142:                for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';)
        !           143:                    *p++ = *s++;
        !           144:                *p = '\0';
        !           145:            }
        !           146:            else {
        !           147:                initopt++;
        !           148:                for (initline = 0; *s != '\0'; s++)
        !           149:                    if (isdigit (*s))
        !           150:                        initline = initline*10 + *s -'0';
        !           151:                --initline;
        !           152:            }
        !           153:        }
        !           154:        else break;
        !           155:     }
        !           156:     /* allow clreol only if Home and eraseln and EodClr strings are
        !           157:      *  defined, and in that case, make sure we are in noscroll mode
        !           158:      */
        !           159:     if(clreol)
        !           160:     {
        !           161:         if((Home == NULL) || (*Home == '\0') ||
        !           162:           (eraseln == NULL) || (*eraseln == '\0') ||
        !           163:            (EodClr == NULL) || (*EodClr == '\0') )
        !           164:              clreol = 0;
        !           165:        else noscroll = 1;
        !           166:     }
        !           167:     if (dlines == 0)
        !           168:        dlines = Lpp - (noscroll ? 1 : 2);
        !           169:     left = dlines;
        !           170:     if (nfiles > 1)
        !           171:        prnames++;
        !           172:     if (!no_intty && nfiles == 0) {
        !           173:        fputs("Usage: ",stderr);
        !           174:        fputs(argv[0],stderr);
        !           175:        fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr);
        !           176:        exit(1);
        !           177:     }
        !           178:     else
        !           179:        f = stdin;
        !           180:     if (!no_tty) {
        !           181:        signal(SIGQUIT, onquit);
        !           182:        signal(SIGINT, end_it);
        !           183:        signal(SIGWINCH, chgwinsz);
        !           184:        if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
        !           185:            signal(SIGTSTP, onsusp);
        !           186:            catch_susp++;
        !           187:        }
        !           188:        stty (fileno(stderr), &otty);
        !           189:     }
        !           190:     if (no_intty) {
        !           191:        if (no_tty)
        !           192:            copy_file (stdin);
        !           193:        else {
        !           194:            if ((ch = Getc (f)) == '\f')
        !           195:                doclear();
        !           196:            else {
        !           197:                Ungetc (ch, f);
        !           198:                if (noscroll && (ch != EOF)) {
        !           199:                    if (clreol)
        !           200:                        home ();
        !           201:                    else
        !           202:                        doclear ();
        !           203:                }
        !           204:            }
        !           205:            if (srchopt)
        !           206:            {
        !           207:                search (initbuf, stdin, 1);
        !           208:                if (noscroll)
        !           209:                    left--;
        !           210:            }
        !           211:            else if (initopt)
        !           212:                skiplns (initline, stdin);
        !           213:            screen (stdin, left);
        !           214:        }
        !           215:        no_intty = 0;
        !           216:        prnames++;
        !           217:        firstf = 0;
        !           218:     }
        !           219: 
        !           220:     while (fnum < nfiles) {
        !           221:        if ((f = checkf (fnames[fnum], &clearit)) != NULL) {
        !           222:            context.line = context.chrctr = 0;
        !           223:            Currline = 0;
        !           224:            if (firstf) setjmp (restore);
        !           225:            if (firstf) {
        !           226:                firstf = 0;
        !           227:                if (srchopt)
        !           228:                {
        !           229:                    search (initbuf, f, 1);
        !           230:                    if (noscroll)
        !           231:                        left--;
        !           232:                }
        !           233:                else if (initopt)
        !           234:                    skiplns (initline, f);
        !           235:            }
        !           236:            else if (fnum < nfiles && !no_tty) {
        !           237:                setjmp (restore);
        !           238:                left = command (fnames[fnum], f);
        !           239:            }
        !           240:            if (left != 0) {
        !           241:                if ((noscroll || clearit) && (file_size != 0x7fffffffffffffffL))
        !           242:                    if (clreol)
        !           243:                        home ();
        !           244:                    else
        !           245:                        doclear ();
        !           246:                if (prnames) {
        !           247:                    if (bad_so)
        !           248:                        erase (0);
        !           249:                    if (clreol)
        !           250:                        cleareol ();
        !           251:                    pr("::::::::::::::");
        !           252:                    if (promptlen > 14)
        !           253:                        erase (14);
        !           254:                    printf ("\n");
        !           255:                    if(clreol) cleareol();
        !           256:                    printf("%s\n", fnames[fnum]);
        !           257:                    if(clreol) cleareol();
        !           258:                    printf("::::::::::::::\n", fnames[fnum]);
        !           259:                    if (left > Lpp - 4)
        !           260:                        left = Lpp - 4;
        !           261:                }
        !           262:                if (no_tty)
        !           263:                    copy_file (f);
        !           264:                else {
        !           265:                    within++;
        !           266:                    screen(f, left);
        !           267:                    within = 0;
        !           268:                }
        !           269:            }
        !           270:            setjmp (restore);
        !           271:            fflush(stdout);
        !           272:            fclose(f);
        !           273:            screen_start.line = screen_start.chrctr = 0L;
        !           274:            context.line = context.chrctr = 0L;
        !           275:        }
        !           276:        fnum++;
        !           277:        firstf = 0;
        !           278:     }
        !           279:     reset_tty ();
        !           280:     exit(0);
        !           281: }
        !           282: 
        !           283: argscan(s)
        !           284: char *s;
        !           285: {
        !           286:        for (dlines = 0; *s != '\0'; s++)
        !           287:        {
        !           288:                switch (*s)
        !           289:                {
        !           290:                  case '0': case '1': case '2':
        !           291:                  case '3': case '4': case '5':
        !           292:                  case '6': case '7': case '8':
        !           293:                  case '9':
        !           294:                        dlines = dlines*10 + *s - '0';
        !           295:                        break;
        !           296:                  case 'd':
        !           297:                        dum_opt = 1;
        !           298:                        break;
        !           299:                  case 'l':
        !           300:                        stop_opt = 0;
        !           301:                        break;
        !           302:                  case 'f':
        !           303:                        fold_opt = 0;
        !           304:                        break;
        !           305:                  case 'p':
        !           306:                        noscroll++;
        !           307:                        break;
        !           308:                  case 'c':
        !           309:                        clreol++;
        !           310:                        break;
        !           311:                  case 's':
        !           312:                        ssp_opt = 1;
        !           313:                        break;
        !           314:                  case 'u':
        !           315:                        ul_opt = 0;
        !           316:                        break;
        !           317:                }
        !           318:        }
        !           319: }
        !           320: 
        !           321: 
        !           322: /*
        !           323: ** Check whether the file named by fs is an ASCII file which the user may
        !           324: ** access.  If it is, return the opened file. Otherwise return NULL.
        !           325: */
        !           326: 
        !           327: FILE *
        !           328: checkf (fs, clearfirst)
        !           329: register char *fs;
        !           330: int *clearfirst;
        !           331: {
        !           332:     struct stat stbuf;
        !           333:     register FILE *f;
        !           334:     char c;
        !           335: 
        !           336:     if (stat (fs, &stbuf) == -1) {
        !           337:        fflush(stdout);
        !           338:        if (clreol)
        !           339:            cleareol ();
        !           340:        perror(fs);
        !           341:        return (NULL);
        !           342:     }
        !           343:     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
        !           344:        printf("\n*** %s: directory ***\n\n", fs);
        !           345:        return (NULL);
        !           346:     }
        !           347:     if ((f=Fopen(fs, "r")) == NULL) {
        !           348:        fflush(stdout);
        !           349:        perror(fs);
        !           350:        return (NULL);
        !           351:     }
        !           352:     c = Getc(f);
        !           353: 
        !           354:     /* Try to see whether it is an ASCII file */
        !           355: 
        !           356:     switch ((c | *f->_ptr << 8) & 0177777) {
        !           357:     case 0405:
        !           358:     case 0407:
        !           359:     case 0410:
        !           360:     case 0411:
        !           361:     case 0413:
        !           362:     case 0177545:
        !           363:        printf("\n******** %s: Not a text file ********\n\n", fs);
        !           364:        fclose (f);
        !           365:        return (NULL);
        !           366:     default:
        !           367:        break;
        !           368:     }
        !           369:     if (c == '\f')
        !           370:        *clearfirst = 1;
        !           371:     else {
        !           372:        *clearfirst = 0;
        !           373:        Ungetc (c, f);
        !           374:     }
        !           375:     if ((file_size = stbuf.st_size) == 0)
        !           376:        file_size = 0x7fffffffffffffffL;
        !           377:     return (f);
        !           378: }
        !           379: 
        !           380: /*
        !           381: ** A real function, for the tputs routine in termlib
        !           382: */
        !           383: 
        !           384: putch (ch)
        !           385: char ch;
        !           386: {
        !           387:     putchar (ch);
        !           388: }
        !           389: 
        !           390: /*
        !           391: ** Print out the contents of the file f, one screenful at a time.
        !           392: */
        !           393: 
        !           394: #define STOP -10
        !           395: 
        !           396: screen (f, num_lines)
        !           397: register FILE *f;
        !           398: register int num_lines;
        !           399: {
        !           400:     register int c;
        !           401:     register int nchars;
        !           402:     int length;                        /* length of current line */
        !           403:     static int prev_len = 1;   /* length of previous line */
        !           404: 
        !           405:     for (;;) {
        !           406:        while (num_lines > 0 && !Pause) {
        !           407:            if ((nchars = getline (f, &length)) == EOF)
        !           408:            {
        !           409:                if (clreol)
        !           410:                    clreos();
        !           411:                return;
        !           412:            }
        !           413:            if (ssp_opt && length == 0 && prev_len == 0)
        !           414:                continue;
        !           415:            prev_len = length;
        !           416:            if (bad_so || (Senter && *Senter == ' ') && promptlen > 0)
        !           417:                erase (0);
        !           418:            /* must clear before drawing line since tabs on some terminals
        !           419:             * do not erase what they tab over.
        !           420:             */
        !           421:            if (clreol)
        !           422:                cleareol ();
        !           423:            prbuf (Line, length);
        !           424:            if (nchars < promptlen)
        !           425:                erase (nchars); /* erase () sets promptlen to 0 */
        !           426:            else promptlen = 0;
        !           427:            /* is this needed?
        !           428:             * if (clreol)
        !           429:             *  cleareol();     /* must clear again in case we wrapped *
        !           430:             */
        !           431:            if (nchars < Mcol || !fold_opt)
        !           432:                prbuf("\n", 1); /* will turn off UL if necessary */
        !           433:            if (nchars == STOP)
        !           434:                break;
        !           435:            num_lines--;
        !           436:        }
        !           437:        if (pstate) {
        !           438:                tputs(ULexit, 1, putch);
        !           439:                pstate = 0;
        !           440:        }
        !           441:        fflush(stdout);
        !           442:        if ((c = Getc(f)) == EOF)
        !           443:        {
        !           444:            if (clreol)
        !           445:                clreos ();
        !           446:            return;
        !           447:        }
        !           448: 
        !           449:        if (Pause && clreol)
        !           450:            clreos ();
        !           451:        Ungetc (c, f);
        !           452:        setjmp (restore);
        !           453:        Pause = 0; startup = 0;
        !           454:        if ((num_lines = command (NULL, f)) == 0)
        !           455:            return;
        !           456:        if (hard && promptlen > 0)
        !           457:                erase (0);
        !           458:        if (noscroll && num_lines >= dlines)
        !           459:        {
        !           460:            if (clreol)
        !           461:                home();
        !           462:            else
        !           463:                doclear ();
        !           464:        }
        !           465:        screen_start.line = Currline;
        !           466:        screen_start.chrctr = Ftell (f);
        !           467:     }
        !           468: }
        !           469: 
        !           470: /*
        !           471: ** Come here if a quit signal is received
        !           472: */
        !           473: 
        !           474: onquit()
        !           475: {
        !           476:     signal(SIGQUIT, SIG_IGN);
        !           477:     if (!inwait) {
        !           478:        putchar ('\n');
        !           479:        if (!startup) {
        !           480:            signal(SIGQUIT, onquit);
        !           481:            longjmp (restore, 1);
        !           482:        }
        !           483:        else
        !           484:            Pause++;
        !           485:     }
        !           486:     else if (!dum_opt && notell) {
        !           487:        write (2, "[Use q or Q to quit]", 20);
        !           488:        promptlen += 20;
        !           489:        notell = 0;
        !           490:     }
        !           491:     signal(SIGQUIT, onquit);
        !           492: }
        !           493: 
        !           494: /*
        !           495: ** Come here if a signal for a window size change is received
        !           496: */
        !           497: 
        !           498: chgwinsz()
        !           499: {
        !           500:     struct winsize win;
        !           501: 
        !           502:     (void) signal(SIGWINCH, SIG_IGN);
        !           503:     if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
        !           504:        if (win.ws_row != 0) {
        !           505:            Lpp = win.ws_row;
        !           506:            nscroll = Lpp/2 - 1;
        !           507:            if (nscroll <= 0)
        !           508:                nscroll = 1;
        !           509:            dlines = Lpp - (noscroll ? 1 : 2);
        !           510:        }
        !           511:        if (win.ws_col != 0)
        !           512:            Mcol = win.ws_col;
        !           513:     }
        !           514:     (void) signal(SIGWINCH, chgwinsz);
        !           515: }
        !           516: 
        !           517: /*
        !           518: ** Clean up terminal state and exit. Also come here if interrupt signal received
        !           519: */
        !           520: 
        !           521: end_it ()
        !           522: {
        !           523: 
        !           524:     reset_tty ();
        !           525:     if (clreol) {
        !           526:        putchar ('\r');
        !           527:        clreos ();
        !           528:        fflush (stdout);
        !           529:     }
        !           530:     else if (!clreol && (promptlen > 0)) {
        !           531:        kill_line ();
        !           532:        fflush (stdout);
        !           533:     }
        !           534:     else
        !           535:        write (2, "\n", 1);
        !           536:     _exit(0);
        !           537: }
        !           538: 
        !           539: copy_file(f)
        !           540: register FILE *f;
        !           541: {
        !           542:     register int c;
        !           543: 
        !           544:     while ((c = getc(f)) != EOF)
        !           545:        putchar(c);
        !           546: }
        !           547: 
        !           548: /* Simplified printf function */
        !           549: 
        !           550: printf (fmt, args)
        !           551: register char *fmt;
        !           552: int args;
        !           553: {
        !           554:        register int *argp;
        !           555:        register char ch;
        !           556:        register int ccount;
        !           557: 
        !           558:        ccount = 0;
        !           559:        argp = &args;
        !           560:        while (*fmt) {
        !           561:                while ((ch = *fmt++) != '%') {
        !           562:                        if (ch == '\0')
        !           563:                                return (ccount);
        !           564:                        ccount++;
        !           565:                        putchar (ch);
        !           566:                }
        !           567:                switch (*fmt++) {
        !           568:                case 'd':
        !           569:                        ccount += printd (*argp);
        !           570:                        break;
        !           571:                case 's':
        !           572:                        ccount += pr ((char *)*argp);
        !           573:                        break;
        !           574:                case '%':
        !           575:                        ccount++;
        !           576:                        argp--;
        !           577:                        putchar ('%');
        !           578:                        break;
        !           579:                case '0':
        !           580:                        return (ccount);
        !           581:                default:
        !           582:                        break;
        !           583:                }
        !           584:                ++argp;
        !           585:        }
        !           586:        return (ccount);
        !           587: 
        !           588: }
        !           589: 
        !           590: /*
        !           591: ** Print an integer as a string of decimal digits,
        !           592: ** returning the length of the print representation.
        !           593: */
        !           594: 
        !           595: printd (n)
        !           596: int n;
        !           597: {
        !           598:     int a, nchars;
        !           599: 
        !           600:     if (a = n/10)
        !           601:        nchars = 1 + printd(a);
        !           602:     else
        !           603:        nchars = 1;
        !           604:     putchar (n % 10 + '0');
        !           605:     return (nchars);
        !           606: }
        !           607: 
        !           608: /* Put the print representation of an integer into a string */
        !           609: static char *sptr;
        !           610: 
        !           611: scanstr (n, str)
        !           612: int n;
        !           613: char *str;
        !           614: {
        !           615:     sptr = str;
        !           616:     Sprintf (n);
        !           617:     *sptr = '\0';
        !           618: }
        !           619: 
        !           620: Sprintf (n)
        !           621: {
        !           622:     int a;
        !           623: 
        !           624:     if (a = n/10)
        !           625:        Sprintf (a);
        !           626:     *sptr++ = n % 10 + '0';
        !           627: }
        !           628: 
        !           629: static char bell = ctrl(G);
        !           630: 
        !           631: strlen (s)
        !           632: char *s;
        !           633: {
        !           634:     register char *p;
        !           635: 
        !           636:     p = s;
        !           637:     while (*p++)
        !           638:        ;
        !           639:     return (p - s - 1);
        !           640: }
        !           641: 
        !           642: /* See whether the last component of the path name "path" is equal to the
        !           643: ** string "string"
        !           644: */
        !           645: 
        !           646: tailequ (path, string)
        !           647: char *path;
        !           648: register char *string;
        !           649: {
        !           650:        register char *tail;
        !           651: 
        !           652:        tail = path + strlen(path);
        !           653:        while (tail >= path)
        !           654:                if (*(--tail) == '/')
        !           655:                        break;
        !           656:        ++tail;
        !           657:        while (*tail++ == *string++)
        !           658:                if (*tail == '\0')
        !           659:                        return(1);
        !           660:        return(0);
        !           661: }
        !           662: 
        !           663: prompt (filename)
        !           664: char *filename;
        !           665: {
        !           666:     if (clreol)
        !           667:        cleareol ();
        !           668:     else if (promptlen > 0)
        !           669:        kill_line ();
        !           670:     if (!hard) {
        !           671:        promptlen = 8;
        !           672:        if (Senter && Sexit) {
        !           673:            tputs (Senter, 1, putch);
        !           674:            promptlen += (2 * soglitch);
        !           675:        }
        !           676:        if (clreol)
        !           677:            cleareol ();
        !           678:        pr("--More--");
        !           679:        if (filename != NULL) {
        !           680:            promptlen += printf ("(Next file: %s)", filename);
        !           681:        }
        !           682:        else if (!no_intty) {
        !           683:            promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size));
        !           684:        }
        !           685:        if (dum_opt) {
        !           686:            promptlen += pr("[Press space to continue, 'q' to quit.]");
        !           687:        }
        !           688:        if (Senter && Sexit)
        !           689:            tputs (Sexit, 1, putch);
        !           690:        if (clreol)
        !           691:            clreos ();
        !           692:        fflush(stdout);
        !           693:     }
        !           694:     else
        !           695:        write (2, &bell, 1);
        !           696:     inwait++;
        !           697: }
        !           698: 
        !           699: /*
        !           700: ** Get a logical line
        !           701: */
        !           702: 
        !           703: getline(f, length)
        !           704: register FILE *f;
        !           705: int *length;
        !           706: {
        !           707:     register int       c;
        !           708:     register char      *p;
        !           709:     register int       column;
        !           710:     static int         colflg;
        !           711: 
        !           712:     p = Line;
        !           713:     column = 0;
        !           714:     c = Getc (f);
        !           715:     if (colflg && c == '\n') {
        !           716:        Currline++;
        !           717:        c = Getc (f);
        !           718:     }
        !           719:     while (p < &Line[LINSIZ - 1]) {
        !           720:        if (c == EOF) {
        !           721:            if (p > Line) {
        !           722:                *p = '\0';
        !           723:                *length = p - Line;
        !           724:                return (column);
        !           725:            }
        !           726:            *length = p - Line;
        !           727:            return (EOF);
        !           728:        }
        !           729:        if (c == '\n') {
        !           730:            Currline++;
        !           731:            break;
        !           732:        }
        !           733:        *p++ = c;
        !           734:        if (c == '\t')
        !           735:            if (hardtabs && column < promptlen && !hard) {
        !           736:                if (eraseln && !dumb) {
        !           737:                    column = 1 + (column | 7);
        !           738:                    tputs (eraseln, 1, putch);
        !           739:                    promptlen = 0;
        !           740:                }
        !           741:                else {
        !           742:                    for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
        !           743:                        *p++ = ' ';
        !           744:                    }
        !           745:                    if (column >= promptlen) promptlen = 0;
        !           746:                }
        !           747:            }
        !           748:            else
        !           749:                column = 1 + (column | 7);
        !           750:        else if (c == '\b' && column > 0)
        !           751:            column--;
        !           752:        else if (c == '\r')
        !           753:            column = 0;
        !           754:        else if (c == '\f' && stop_opt) {
        !           755:                p[-1] = '^';
        !           756:                *p++ = 'L';
        !           757:                column += 2;
        !           758:                Pause++;
        !           759:        }
        !           760:        else if (c == EOF) {
        !           761:            *length = p - Line;
        !           762:            return (column);
        !           763:        }
        !           764:        else if (c >= ' ' && c != RUBOUT)
        !           765:            column++;
        !           766:        if (column >= Mcol && fold_opt) break;
        !           767:        c = Getc (f);
        !           768:     }
        !           769:     if (column >= Mcol && Mcol > 0) {
        !           770:        if (!Wrap) {
        !           771:            *p++ = '\n';
        !           772:        }
        !           773:     }
        !           774:     colflg = column == Mcol && fold_opt;
        !           775:     *length = p - Line;
        !           776:     *p = 0;
        !           777:     return (column);
        !           778: }
        !           779: 
        !           780: /*
        !           781: ** Erase the rest of the prompt, assuming we are starting at column col.
        !           782: */
        !           783: 
        !           784: erase (col)
        !           785: register int col;
        !           786: {
        !           787: 
        !           788:     if (promptlen == 0)
        !           789:        return;
        !           790:     if (hard) {
        !           791:        putchar ('\n');
        !           792:     }
        !           793:     else {
        !           794:        if (col == 0)
        !           795:            putchar ('\r');
        !           796:        if (!dumb && eraseln)
        !           797:            tputs (eraseln, 1, putch);
        !           798:        else
        !           799:            for (col = promptlen - col; col > 0; col--)
        !           800:                putchar (' ');
        !           801:     }
        !           802:     promptlen = 0;
        !           803: }
        !           804: 
        !           805: /*
        !           806: ** Erase the current line entirely
        !           807: */
        !           808: 
        !           809: kill_line ()
        !           810: {
        !           811:     erase (0);
        !           812:     if (!eraseln || dumb) putchar ('\r');
        !           813: }
        !           814: 
        !           815: /*
        !           816:  * force clear to end of line
        !           817:  */
        !           818: cleareol()
        !           819: {
        !           820:     tputs(eraseln, 1, putch);
        !           821: }
        !           822: 
        !           823: clreos()
        !           824: {
        !           825:     tputs(EodClr, 1, putch);
        !           826: }
        !           827: 
        !           828: /*
        !           829: **  Print string and return number of characters
        !           830: */
        !           831: 
        !           832: pr(s1)
        !           833: char   *s1;
        !           834: {
        !           835:     register char      *s;
        !           836:     register char      c;
        !           837: 
        !           838:     for (s = s1; c = *s++; )
        !           839:        putchar(c);
        !           840:     return (s - s1 - 1);
        !           841: }
        !           842: 
        !           843: 
        !           844: /* Print a buffer of n characters */
        !           845: 
        !           846: prbuf (s, n)
        !           847: register char *s;
        !           848: register int n;
        !           849: {
        !           850:     register char c;                   /* next output character */
        !           851:     register int state;                        /* next output char's UL state */
        !           852: #define wouldul(s,n)   ((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_')))
        !           853: 
        !           854:     while (--n >= 0)
        !           855:        if (!ul_opt)
        !           856:            putchar (*s++);
        !           857:        else {
        !           858:            if (*s == ' ' && pstate == 0 && ulglitch && wouldul(s+1, n-1)) {
        !           859:                s++;
        !           860:                continue;
        !           861:            }
        !           862:            if (state = wouldul(s, n)) {
        !           863:                c = (*s == '_')? s[2] : *s ;
        !           864:                n -= 2;
        !           865:                s += 3;
        !           866:            } else
        !           867:                c = *s++;
        !           868:            if (state != pstate) {
        !           869:                if (c == ' ' && state == 0 && ulglitch && wouldul(s, n-1))
        !           870:                    state = 1;
        !           871:                else
        !           872:                    tputs(state ? ULenter : ULexit, 1, putch);
        !           873:            }
        !           874:            if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0)
        !           875:                putchar(c);
        !           876:            if (state && *chUL) {
        !           877:                pr(chBS);
        !           878:                tputs(chUL, 1, putch);
        !           879:            }
        !           880:            pstate = state;
        !           881:        }
        !           882: }
        !           883: 
        !           884: /*
        !           885: **  Clear the screen
        !           886: */
        !           887: 
        !           888: doclear()
        !           889: {
        !           890:     if (Clear && !hard) {
        !           891:        tputs(Clear, 1, putch);
        !           892: 
        !           893:        /* Put out carriage return so that system doesn't
        !           894:        ** get confused by escape sequences when expanding tabs
        !           895:        */
        !           896:        putchar ('\r');
        !           897:        promptlen = 0;
        !           898:     }
        !           899: }
        !           900: 
        !           901: /*
        !           902:  * Go to home position
        !           903:  */
        !           904: home()
        !           905: {
        !           906:     tputs(Home,1,putch);
        !           907: }
        !           908: 
        !           909: static int lastcmd, lastarg, lastp;
        !           910: static int lastcolon;
        !           911: char shell_line[132];
        !           912: 
        !           913: /*
        !           914: ** Read a command and do it. A command consists of an optional integer
        !           915: ** argument followed by the command character.  Return the number of lines
        !           916: ** to display in the next screenful.  If there is nothing more to display
        !           917: ** in the current file, zero is returned.
        !           918: */
        !           919: 
        !           920: command (filename, f)
        !           921: char *filename;
        !           922: register FILE *f;
        !           923: {
        !           924:     register int nlines;
        !           925:     register int retval;
        !           926:     register char c;
        !           927:     char colonch;
        !           928:     FILE *helpf;
        !           929:     int done;
        !           930:     char comchar, cmdbuf[80], *p;
        !           931: 
        !           932: #define ret(val) retval=val;done++;break
        !           933: 
        !           934:     done = 0;
        !           935:     if (!errors)
        !           936:        prompt (filename);
        !           937:     else
        !           938:        errors = 0;
        !           939:     if (MBIT == RAW && slow_tty) {
        !           940:        otty.sg_flags |= MBIT;
        !           941:        stty(fileno(stderr), &otty);
        !           942:     }
        !           943:     for (;;) {
        !           944:        nlines = number (&comchar);
        !           945:        lastp = colonch = 0;
        !           946:        if (comchar == '.') {   /* Repeat last command */
        !           947:                lastp++;
        !           948:                comchar = lastcmd;
        !           949:                nlines = lastarg;
        !           950:                if (lastcmd == ':')
        !           951:                        colonch = lastcolon;
        !           952:        }
        !           953:        lastcmd = comchar;
        !           954:        lastarg = nlines;
        !           955:        if (comchar == otty.sg_erase) {
        !           956:            kill_line ();
        !           957:            prompt (filename);
        !           958:            continue;
        !           959:        }
        !           960:        switch (comchar) {
        !           961:        case ':':
        !           962:            retval = colon (filename, colonch, nlines);
        !           963:            if (retval >= 0)
        !           964:                done++;
        !           965:            break;
        !           966:        case 'b':
        !           967:        case ctrl(B):
        !           968:            {
        !           969:                register int initline;
        !           970: 
        !           971:                if (no_intty) {
        !           972:                    write(2, &bell, 1);
        !           973:                    return (-1);
        !           974:                }
        !           975: 
        !           976:                if (nlines == 0) nlines++;
        !           977: 
        !           978:                putchar ('\r');
        !           979:                erase (0);
        !           980:                printf ("\n");
        !           981:                if (clreol)
        !           982:                        cleareol ();
        !           983:                printf ("...back %d page", nlines);
        !           984:                if (nlines > 1)
        !           985:                        pr ("s\n");
        !           986:                else
        !           987:                        pr ("\n");
        !           988: 
        !           989:                if (clreol)
        !           990:                        cleareol ();
        !           991:                pr ("\n");
        !           992: 
        !           993:                initline = Currline - dlines * (nlines + 1);
        !           994:                if (! noscroll)
        !           995:                    --initline;
        !           996:                if (initline < 0) initline = 0;
        !           997:                Fseek(f, 0L);
        !           998:                Currline = 0;   /* skiplns() will make Currline correct */
        !           999:                skiplns(initline, f);
        !          1000:                if (! noscroll) {
        !          1001:                    ret(dlines + 1);
        !          1002:                }
        !          1003:                else {
        !          1004:                    ret(dlines);
        !          1005:                }
        !          1006:            }
        !          1007:        case ' ':
        !          1008:        case 'z':
        !          1009:            if (nlines == 0) nlines = dlines;
        !          1010:            else if (comchar == 'z') dlines = nlines;
        !          1011:            ret (nlines);
        !          1012:        case 'd':
        !          1013:        case ctrl(D):
        !          1014:            if (nlines != 0) nscroll = nlines;
        !          1015:            ret (nscroll);
        !          1016:        case 'q':
        !          1017:        case 'Q':
        !          1018:            end_it ();
        !          1019:        case 's':
        !          1020:        case 'f':
        !          1021:            if (nlines == 0) nlines++;
        !          1022:            if (comchar == 'f')
        !          1023:                nlines *= dlines;
        !          1024:            putchar ('\r');
        !          1025:            erase (0);
        !          1026:            printf ("\n");
        !          1027:            if (clreol)
        !          1028:                cleareol ();
        !          1029:            printf ("...skipping %d line", nlines);
        !          1030:            if (nlines > 1)
        !          1031:                pr ("s\n");
        !          1032:            else
        !          1033:                pr ("\n");
        !          1034: 
        !          1035:            if (clreol)
        !          1036:                cleareol ();
        !          1037:            pr ("\n");
        !          1038: 
        !          1039:            while (nlines > 0) {
        !          1040:                while ((c = Getc (f)) != '\n')
        !          1041:                    if (c == EOF) {
        !          1042:                        retval = 0;
        !          1043:                        done++;
        !          1044:                        goto endsw;
        !          1045:                    }
        !          1046:                    Currline++;
        !          1047:                    nlines--;
        !          1048:            }
        !          1049:            ret (dlines);
        !          1050:        case '\n':
        !          1051:            if (nlines != 0)
        !          1052:                dlines = nlines;
        !          1053:            else
        !          1054:                nlines = 1;
        !          1055:            ret (nlines);
        !          1056:        case '\f':
        !          1057:            if (!no_intty) {
        !          1058:                doclear ();
        !          1059:                Fseek (f, screen_start.chrctr);
        !          1060:                Currline = screen_start.line;
        !          1061:                ret (dlines);
        !          1062:            }
        !          1063:            else {
        !          1064:                write (2, &bell, 1);
        !          1065:                break;
        !          1066:            }
        !          1067:        case '\'':
        !          1068:            if (!no_intty) {
        !          1069:                kill_line ();
        !          1070:                pr ("\n***Back***\n\n");
        !          1071:                Fseek (f, context.chrctr);
        !          1072:                Currline = context.line;
        !          1073:                ret (dlines);
        !          1074:            }
        !          1075:            else {
        !          1076:                write (2, &bell, 1);
        !          1077:                break;
        !          1078:            }
        !          1079:        case '=':
        !          1080:            kill_line ();
        !          1081:            promptlen = printd (Currline);
        !          1082:            fflush (stdout);
        !          1083:            break;
        !          1084:        case 'n':
        !          1085:            lastp++;
        !          1086:        case '/':
        !          1087:            if (nlines == 0) nlines++;
        !          1088:            kill_line ();
        !          1089:            pr ("/");
        !          1090:            promptlen = 1;
        !          1091:            fflush (stdout);
        !          1092:            if (lastp) {
        !          1093:                write (2,"\r", 1);
        !          1094:                search (NULL, f, nlines);       /* Use previous r.e. */
        !          1095:            }
        !          1096:            else {
        !          1097:                ttyin (cmdbuf, 78, '/');
        !          1098:                write (2, "\r", 1);
        !          1099:                search (cmdbuf, f, nlines);
        !          1100:            }
        !          1101:            ret (dlines-1);
        !          1102:        case '!':
        !          1103:            do_shell (filename);
        !          1104:            break;
        !          1105:        case '?':
        !          1106:        case 'h':
        !          1107:            if ((helpf = fopen (HELPFILE, "r")) == NULL)
        !          1108:                error ("Can't open help file");
        !          1109:            if (noscroll) doclear ();
        !          1110:            copy_file (helpf);
        !          1111:            fclose (helpf);
        !          1112:            prompt (filename);
        !          1113:            break;
        !          1114:        case 'v':       /* This case should go right before default */
        !          1115:            if (!no_intty) {
        !          1116:                kill_line ();
        !          1117:                cmdbuf[0] = '+';
        !          1118:                scanstr (Currline - dlines < 0 ? 0
        !          1119:                                : Currline - (dlines + 1) / 2, &cmdbuf[1]);
        !          1120:                pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
        !          1121:                execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
        !          1122:                break;
        !          1123:            }
        !          1124:        default:
        !          1125:            if (dum_opt) {
        !          1126:                kill_line ();
        !          1127:                if (Senter && Sexit) {
        !          1128:                    tputs (Senter, 1, putch);
        !          1129:                    promptlen = pr ("[Press 'h' for instructions.]") + (2 * soglitch);
        !          1130:                    tputs (Sexit, 1, putch);
        !          1131:                }
        !          1132:                else
        !          1133:                    promptlen = pr ("[Press 'h' for instructions.]");
        !          1134:                fflush (stdout);
        !          1135:            }
        !          1136:            else
        !          1137:                write (2, &bell, 1);
        !          1138:            break;
        !          1139:        }
        !          1140:        if (done) break;
        !          1141:     }
        !          1142:     putchar ('\r');
        !          1143: endsw:
        !          1144:     inwait = 0;
        !          1145:     notell++;
        !          1146:     if (MBIT == RAW && slow_tty) {
        !          1147:        otty.sg_flags &= ~MBIT;
        !          1148:        stty(fileno(stderr), &otty);
        !          1149:     }
        !          1150:     return (retval);
        !          1151: }
        !          1152: 
        !          1153: char ch;
        !          1154: 
        !          1155: /*
        !          1156:  * Execute a colon-prefixed command.
        !          1157:  * Returns <0 if not a command that should cause
        !          1158:  * more of the file to be printed.
        !          1159:  */
        !          1160: 
        !          1161: colon (filename, cmd, nlines)
        !          1162: char *filename;
        !          1163: int cmd;
        !          1164: int nlines;
        !          1165: {
        !          1166:        if (cmd == 0)
        !          1167:                ch = readch ();
        !          1168:        else
        !          1169:                ch = cmd;
        !          1170:        lastcolon = ch;
        !          1171:        switch (ch) {
        !          1172:        case 'f':
        !          1173:                kill_line ();
        !          1174:                if (!no_intty)
        !          1175:                        promptlen = printf ("\"%s\" line %d", fnames[fnum], Currline);
        !          1176:                else
        !          1177:                        promptlen = printf ("[Not a file] line %d", Currline);
        !          1178:                fflush (stdout);
        !          1179:                return (-1);
        !          1180:        case 'n':
        !          1181:                if (nlines == 0) {
        !          1182:                        if (fnum >= nfiles - 1)
        !          1183:                                end_it ();
        !          1184:                        nlines++;
        !          1185:                }
        !          1186:                putchar ('\r');
        !          1187:                erase (0);
        !          1188:                skipf (nlines);
        !          1189:                return (0);
        !          1190:        case 'p':
        !          1191:                if (no_intty) {
        !          1192:                        write (2, &bell, 1);
        !          1193:                        return (-1);
        !          1194:                }
        !          1195:                putchar ('\r');
        !          1196:                erase (0);
        !          1197:                if (nlines == 0)
        !          1198:                        nlines++;
        !          1199:                skipf (-nlines);
        !          1200:                return (0);
        !          1201:        case '!':
        !          1202:                do_shell (filename);
        !          1203:                return (-1);
        !          1204:        case 'q':
        !          1205:        case 'Q':
        !          1206:                end_it ();
        !          1207:        default:
        !          1208:                write (2, &bell, 1);
        !          1209:                return (-1);
        !          1210:        }
        !          1211: }
        !          1212: 
        !          1213: /*
        !          1214: ** Read a decimal number from the terminal. Set cmd to the non-digit which
        !          1215: ** terminates the number.
        !          1216: */
        !          1217: 
        !          1218: number(cmd)
        !          1219: char *cmd;
        !          1220: {
        !          1221:        register int i;
        !          1222: 
        !          1223:        i = 0; ch = otty.sg_kill;
        !          1224:        for (;;) {
        !          1225:                ch = readch ();
        !          1226:                if (ch >= '0' && ch <= '9')
        !          1227:                        i = i*10 + ch - '0';
        !          1228:                else if (ch == otty.sg_kill)
        !          1229:                        i = 0;
        !          1230:                else {
        !          1231:                        *cmd = ch;
        !          1232:                        break;
        !          1233:                }
        !          1234:        }
        !          1235:        return (i);
        !          1236: }
        !          1237: 
        !          1238: do_shell (filename)
        !          1239: char *filename;
        !          1240: {
        !          1241:        char cmdbuf[80];
        !          1242: 
        !          1243:        kill_line ();
        !          1244:        pr ("!");
        !          1245:        fflush (stdout);
        !          1246:        promptlen = 1;
        !          1247:        if (lastp)
        !          1248:                pr (shell_line);
        !          1249:        else {
        !          1250:                ttyin (cmdbuf, 78, '!');
        !          1251:                if (expand (shell_line, cmdbuf)) {
        !          1252:                        kill_line ();
        !          1253:                        promptlen = printf ("!%s", shell_line);
        !          1254:                }
        !          1255:        }
        !          1256:        fflush (stdout);
        !          1257:        write (2, "\n", 1);
        !          1258:        promptlen = 0;
        !          1259:        shellp = 1;
        !          1260:        execute (filename, shell, shell, "-c", shell_line, 0);
        !          1261: }
        !          1262: 
        !          1263: /*
        !          1264: ** Search for nth ocurrence of regular expression contained in buf in the file
        !          1265: */
        !          1266: 
        !          1267: search (buf, file, n)
        !          1268: char buf[];
        !          1269: FILE *file;
        !          1270: register int n;
        !          1271: {
        !          1272:     long startline = Ftell (file);
        !          1273:     register long line1 = startline;
        !          1274:     register long line2 = startline;
        !          1275:     register long line3 = startline;
        !          1276:     register int lncount;
        !          1277:     int saveln, rv, re_exec();
        !          1278:     char *s, *re_comp();
        !          1279: 
        !          1280:     context.line = saveln = Currline;
        !          1281:     context.chrctr = startline;
        !          1282:     lncount = 0;
        !          1283:     if ((s = re_comp (buf)) != 0)
        !          1284:        error (s);
        !          1285:     while (!feof (file)) {
        !          1286:        line3 = line2;
        !          1287:        line2 = line1;
        !          1288:        line1 = Ftell (file);
        !          1289:        rdline (file);
        !          1290:        lncount++;
        !          1291:        if ((rv = re_exec (Line)) == 1)
        !          1292:                if (--n == 0) {
        !          1293:                    if (lncount > 3 || (lncount > 1 && no_intty))
        !          1294:                    {
        !          1295:                        pr ("\n");
        !          1296:                        if (clreol)
        !          1297:                            cleareol ();
        !          1298:                        pr("...skipping\n");
        !          1299:                    }
        !          1300:                    if (!no_intty) {
        !          1301:                        Currline -= (lncount >= 3 ? 3 : lncount);
        !          1302:                        Fseek (file, line3);
        !          1303:                        if (noscroll)
        !          1304:                            if (clreol) {
        !          1305:                                home ();
        !          1306:                                cleareol ();
        !          1307:                            }
        !          1308:                            else
        !          1309:                                doclear ();
        !          1310:                    }
        !          1311:                    else {
        !          1312:                        kill_line ();
        !          1313:                        if (noscroll)
        !          1314:                            if (clreol) {
        !          1315:                                home ();
        !          1316:                                cleareol ();
        !          1317:                            }
        !          1318:                            else
        !          1319:                                doclear ();
        !          1320:                        pr (Line);
        !          1321:                        putchar ('\n');
        !          1322:                    }
        !          1323:                    break;
        !          1324:                }
        !          1325:        else if (rv == -1)
        !          1326:            error ("Regular expression botch");
        !          1327:     }
        !          1328:     if (feof (file)) {
        !          1329:        if (!no_intty) {
        !          1330:            file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */
        !          1331:            Currline = saveln;
        !          1332:            Fseek (file, startline);
        !          1333:        }
        !          1334:        else {
        !          1335:            pr ("\nPattern not found\n");
        !          1336:            end_it ();
        !          1337:        }
        !          1338:        error ("Pattern not found");
        !          1339:     }
        !          1340: }
        !          1341: 
        !          1342: execute (filename, cmd, args)
        !          1343: char *filename;
        !          1344: char *cmd, *args;
        !          1345: {
        !          1346:        int id;
        !          1347:        int n;
        !          1348: 
        !          1349:        fflush (stdout);
        !          1350:        reset_tty ();
        !          1351:        for (n = 10; (id = fork ()) < 0 && n > 0; n--)
        !          1352:            sleep (5);
        !          1353:        if (id == 0) {
        !          1354:            if (!isatty(0)) {
        !          1355:                close(0);
        !          1356:                open("/dev/tty", 0);
        !          1357:            }
        !          1358:            execv (cmd, &args);
        !          1359:            write (2, "exec failed\n", 12);
        !          1360:            exit (1);
        !          1361:        }
        !          1362:        if (id > 0) {
        !          1363:            signal (SIGINT, SIG_IGN);
        !          1364:            signal (SIGQUIT, SIG_IGN);
        !          1365:            if (catch_susp)
        !          1366:                signal(SIGTSTP, SIG_DFL);
        !          1367:            while (wait(0) > 0);
        !          1368:            signal (SIGINT, end_it);
        !          1369:            signal (SIGQUIT, onquit);
        !          1370:            if (catch_susp)
        !          1371:                signal(SIGTSTP, onsusp);
        !          1372:        } else
        !          1373:            write(2, "can't fork\n", 11);
        !          1374:        set_tty ();
        !          1375:        pr ("------------------------\n");
        !          1376:        prompt (filename);
        !          1377: }
        !          1378: /*
        !          1379: ** Skip n lines in the file f
        !          1380: */
        !          1381: 
        !          1382: skiplns (n, f)
        !          1383: register int n;
        !          1384: register FILE *f;
        !          1385: {
        !          1386:     register char c;
        !          1387: 
        !          1388:     while (n > 0) {
        !          1389:        while ((c = Getc (f)) != '\n')
        !          1390:            if (c == EOF)
        !          1391:                return;
        !          1392:            n--;
        !          1393:            Currline++;
        !          1394:     }
        !          1395: }
        !          1396: 
        !          1397: /*
        !          1398: ** Skip nskip files in the file list (from the command line). Nskip may be
        !          1399: ** negative.
        !          1400: */
        !          1401: 
        !          1402: skipf (nskip)
        !          1403: register int nskip;
        !          1404: {
        !          1405:     if (nskip == 0) return;
        !          1406:     if (nskip > 0) {
        !          1407:        if (fnum + nskip > nfiles - 1)
        !          1408:            nskip = nfiles - fnum - 1;
        !          1409:     }
        !          1410:     else if (within)
        !          1411:        ++fnum;
        !          1412:     fnum += nskip;
        !          1413:     if (fnum < 0)
        !          1414:        fnum = 0;
        !          1415:     pr ("\n...Skipping ");
        !          1416:     pr ("\n");
        !          1417:     if (clreol)
        !          1418:        cleareol ();
        !          1419:     pr ("...Skipping ");
        !          1420:     pr (nskip > 0 ? "to file " : "back to file ");
        !          1421:     pr (fnames[fnum]);
        !          1422:     pr ("\n");
        !          1423:     if (clreol)
        !          1424:        cleareol ();
        !          1425:     pr ("\n");
        !          1426:     --fnum;
        !          1427: }
        !          1428: 
        !          1429: /*----------------------------- Terminal I/O -------------------------------*/
        !          1430: 
        !          1431: initterm ()
        !          1432: {
        !          1433:     char       buf[TBUFSIZ];
        !          1434:     static char        clearbuf[TBUFSIZ];
        !          1435:     char       *clearptr, *padstr;
        !          1436:     int                ldisc;
        !          1437:     int                lmode;
        !          1438:     char       *term;
        !          1439:     int                tgrp;
        !          1440:     struct winsize win;
        !          1441: 
        !          1442: retry:
        !          1443:     if (!(no_tty = gtty(fileno(stdout), &otty))) {
        !          1444:        if (ioctl(fileno(stdout), TIOCLGET, &lmode) < 0) {
        !          1445:            perror("TIOCLGET");
        !          1446:            exit(1);
        !          1447:        }
        !          1448:        docrterase = ((lmode & LCRTERA) != 0);
        !          1449:        docrtkill = ((lmode & LCRTKIL) != 0);
        !          1450:        /*
        !          1451:         * Wait until we're in the foreground before we save the
        !          1452:         * the terminal modes.
        !          1453:         */
        !          1454:        if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) {
        !          1455:            perror("TIOCGPGRP");
        !          1456:            exit(1);
        !          1457:        }
        !          1458:        if (tgrp != getpgrp(0)) {
        !          1459:            kill(0, SIGTTOU);
        !          1460:            goto retry;
        !          1461:        }
        !          1462:        if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) {
        !          1463:            dumb++; ul_opt = 0;
        !          1464:        }
        !          1465:        else {
        !          1466:            if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
        !          1467:                Lpp = tgetnum("li");
        !          1468:                Mcol = tgetnum("co");
        !          1469:            } else {
        !          1470:                if ((Lpp = win.ws_row) == 0)
        !          1471:                    Lpp = tgetnum("li");
        !          1472:                if ((Mcol = win.ws_col) == 0)
        !          1473:                    Mcol = tgetnum("co");
        !          1474:            }
        !          1475:            if ((Lpp <= 0) || tgetflag("hc")) {
        !          1476:                hard++; /* Hard copy terminal */
        !          1477:                Lpp = 24;
        !          1478:            }
        !          1479:            if (Mcol <= 0)
        !          1480:                Mcol = 80;
        !          1481: 
        !          1482:            if (tailequ (fnames[0], "page") || !hard && tgetflag("ns"))
        !          1483:                noscroll++;
        !          1484:            Wrap = tgetflag("am");
        !          1485:            bad_so = tgetflag ("xs");
        !          1486:            clearptr = clearbuf;
        !          1487:            eraseln = tgetstr("ce",&clearptr);
        !          1488:            Clear = tgetstr("cl", &clearptr);
        !          1489:            Senter = tgetstr("so", &clearptr);
        !          1490:            Sexit = tgetstr("se", &clearptr);
        !          1491:            if ((soglitch = tgetnum("sg")) < 0)
        !          1492:                soglitch = 0;
        !          1493: 
        !          1494:            /*
        !          1495:             *  Set up for underlining:  some terminals don't need it;
        !          1496:             *  others have start/stop sequences, still others have an
        !          1497:             *  underline char sequence which is assumed to move the
        !          1498:             *  cursor forward one character.  If underline sequence
        !          1499:             *  isn't available, settle for standout sequence.
        !          1500:             */
        !          1501: 
        !          1502:            if (tgetflag("ul") || tgetflag("os"))
        !          1503:                ul_opt = 0;
        !          1504:            if ((chUL = tgetstr("uc", &clearptr)) == NULL )
        !          1505:                chUL = "";
        !          1506:            if (((ULenter = tgetstr("us", &clearptr)) == NULL ||
        !          1507:                 (ULexit = tgetstr("ue", &clearptr)) == NULL) && !*chUL) {
        !          1508:                if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) {
        !          1509:                        ULenter = "";
        !          1510:                        ULexit = "";
        !          1511:                } else
        !          1512:                        ulglitch = soglitch;
        !          1513:            } else {
        !          1514:                if ((ulglitch = tgetnum("ug")) < 0)
        !          1515:                    ulglitch = 0;
        !          1516:            }
        !          1517: 
        !          1518:            if (padstr = tgetstr("pc", &clearptr))
        !          1519:                PC = *padstr;
        !          1520:            Home = tgetstr("ho",&clearptr);
        !          1521:            if (Home == 0 || *Home == '\0')
        !          1522:            {
        !          1523:                if ((cursorm = tgetstr("cm", &clearptr)) != NULL) {
        !          1524:                    strcpy(cursorhome, tgoto(cursorm, 0, 0));
        !          1525:                    Home = cursorhome;
        !          1526:               }
        !          1527:            }
        !          1528:            EodClr = tgetstr("cd", &clearptr);
        !          1529:            if ((chBS = tgetstr("bc", &clearptr)) == NULL)
        !          1530:                chBS = "\b";
        !          1531: 
        !          1532:        }
        !          1533:        if ((shell = getenv("SHELL")) == NULL)
        !          1534:            shell = "/bin/sh";
        !          1535:     }
        !          1536:     no_intty = gtty(fileno(stdin), &otty);
        !          1537:     gtty(fileno(stderr), &otty);
        !          1538:     savetty = otty;
        !          1539:     ospeed = otty.sg_ospeed;
        !          1540:     slow_tty = ospeed < B1200;
        !          1541:     hardtabs = (otty.sg_flags & TBDELAY) != XTABS;
        !          1542:     if (!no_tty) {
        !          1543:        otty.sg_flags &= ~ECHO;
        !          1544:        if (MBIT == CBREAK || !slow_tty)
        !          1545:            otty.sg_flags |= MBIT;
        !          1546:     }
        !          1547: }
        !          1548: 
        !          1549: readch ()
        !          1550: {
        !          1551:        char ch;
        !          1552:        extern int errno;
        !          1553: 
        !          1554:        if (read (2, &ch, 1) <= 0)
        !          1555:                if (errno != EINTR)
        !          1556:                        exit(0);
        !          1557:                else
        !          1558:                        ch = otty.sg_kill;
        !          1559:        return (ch);
        !          1560: }
        !          1561: 
        !          1562: static char BS = '\b';
        !          1563: static char *BSB = "\b \b";
        !          1564: static char CARAT = '^';
        !          1565: #define ERASEONECHAR \
        !          1566:     if (docrterase) \
        !          1567:        write (2, BSB, sizeof(BSB)); \
        !          1568:     else \
        !          1569:        write (2, &BS, sizeof(BS));
        !          1570: 
        !          1571: ttyin (buf, nmax, pchar)
        !          1572: char buf[];
        !          1573: register int nmax;
        !          1574: char pchar;
        !          1575: {
        !          1576:     register char *sptr;
        !          1577:     register char ch;
        !          1578:     register int slash = 0;
        !          1579:     int        maxlen;
        !          1580:     char cbuf;
        !          1581: 
        !          1582:     sptr = buf;
        !          1583:     maxlen = 0;
        !          1584:     while (sptr - buf < nmax) {
        !          1585:        if (promptlen > maxlen) maxlen = promptlen;
        !          1586:        ch = readch ();
        !          1587:        if (ch == '\\') {
        !          1588:            slash++;
        !          1589:        }
        !          1590:        else if ((ch == otty.sg_erase) && !slash) {
        !          1591:            if (sptr > buf) {
        !          1592:                --promptlen;
        !          1593:                ERASEONECHAR
        !          1594:                --sptr;
        !          1595:                if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
        !          1596:                    --promptlen;
        !          1597:                    ERASEONECHAR
        !          1598:                }
        !          1599:                continue;
        !          1600:            }
        !          1601:            else {
        !          1602:                if (!eraseln) promptlen = maxlen;
        !          1603:                longjmp (restore, 1);
        !          1604:            }
        !          1605:        }
        !          1606:        else if ((ch == otty.sg_kill) && !slash) {
        !          1607:            if (hard) {
        !          1608:                show (ch);
        !          1609:                putchar ('\n');
        !          1610:                putchar (pchar);
        !          1611:            }
        !          1612:            else {
        !          1613:                putchar ('\r');
        !          1614:                putchar (pchar);
        !          1615:                if (eraseln)
        !          1616:                    erase (1);
        !          1617:                else if (docrtkill)
        !          1618:                    while (promptlen-- > 1)
        !          1619:                        write (2, BSB, sizeof(BSB));
        !          1620:                promptlen = 1;
        !          1621:            }
        !          1622:            sptr = buf;
        !          1623:            fflush (stdout);
        !          1624:            continue;
        !          1625:        }
        !          1626:        if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) {
        !          1627:            ERASEONECHAR
        !          1628:            --sptr;
        !          1629:        }
        !          1630:        if (ch != '\\')
        !          1631:            slash = 0;
        !          1632:        *sptr++ = ch;
        !          1633:        if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
        !          1634:            ch += ch == RUBOUT ? -0100 : 0100;
        !          1635:            write (2, &CARAT, 1);
        !          1636:            promptlen++;
        !          1637:        }
        !          1638:        cbuf = ch;
        !          1639:        if (ch != '\n' && ch != ESC) {
        !          1640:            write (2, &cbuf, 1);
        !          1641:            promptlen++;
        !          1642:        }
        !          1643:        else
        !          1644:            break;
        !          1645:     }
        !          1646:     *--sptr = '\0';
        !          1647:     if (!eraseln) promptlen = maxlen;
        !          1648:     if (sptr - buf >= nmax - 1)
        !          1649:        error ("Line too long");
        !          1650: }
        !          1651: 
        !          1652: expand (outbuf, inbuf)
        !          1653: char *outbuf;
        !          1654: char *inbuf;
        !          1655: {
        !          1656:     register char *instr;
        !          1657:     register char *outstr;
        !          1658:     register char ch;
        !          1659:     char temp[200];
        !          1660:     int changed = 0;
        !          1661: 
        !          1662:     instr = inbuf;
        !          1663:     outstr = temp;
        !          1664:     while ((ch = *instr++) != '\0')
        !          1665:        switch (ch) {
        !          1666:        case '%':
        !          1667:            if (!no_intty) {
        !          1668:                strcpy (outstr, fnames[fnum]);
        !          1669:                outstr += strlen (fnames[fnum]);
        !          1670:                changed++;
        !          1671:            }
        !          1672:            else
        !          1673:                *outstr++ = ch;
        !          1674:            break;
        !          1675:        case '!':
        !          1676:            if (!shellp)
        !          1677:                error ("No previous command to substitute for");
        !          1678:            strcpy (outstr, shell_line);
        !          1679:            outstr += strlen (shell_line);
        !          1680:            changed++;
        !          1681:            break;
        !          1682:        case '\\':
        !          1683:            if (*instr == '%' || *instr == '!') {
        !          1684:                *outstr++ = *instr++;
        !          1685:                break;
        !          1686:            }
        !          1687:        default:
        !          1688:            *outstr++ = ch;
        !          1689:        }
        !          1690:     *outstr++ = '\0';
        !          1691:     strcpy (outbuf, temp);
        !          1692:     return (changed);
        !          1693: }
        !          1694: 
        !          1695: show (ch)
        !          1696: register char ch;
        !          1697: {
        !          1698:     char cbuf;
        !          1699: 
        !          1700:     if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
        !          1701:        ch += ch == RUBOUT ? -0100 : 0100;
        !          1702:        write (2, &CARAT, 1);
        !          1703:        promptlen++;
        !          1704:     }
        !          1705:     cbuf = ch;
        !          1706:     write (2, &cbuf, 1);
        !          1707:     promptlen++;
        !          1708: }
        !          1709: 
        !          1710: error (mess)
        !          1711: char *mess;
        !          1712: {
        !          1713:     if (clreol)
        !          1714:        cleareol ();
        !          1715:     else
        !          1716:        kill_line ();
        !          1717:     promptlen += strlen (mess);
        !          1718:     if (Senter && Sexit) {
        !          1719:        tputs (Senter, 1, putch);
        !          1720:        pr(mess);
        !          1721:        tputs (Sexit, 1, putch);
        !          1722:     }
        !          1723:     else
        !          1724:        pr (mess);
        !          1725:     fflush(stdout);
        !          1726:     errors++;
        !          1727:     longjmp (restore, 1);
        !          1728: }
        !          1729: 
        !          1730: 
        !          1731: set_tty ()
        !          1732: {
        !          1733:        otty.sg_flags |= MBIT;
        !          1734:        otty.sg_flags &= ~ECHO;
        !          1735:        stty(fileno(stderr), &otty);
        !          1736: }
        !          1737: 
        !          1738: reset_tty ()
        !          1739: {
        !          1740:     if (pstate) {
        !          1741:        tputs(ULexit, 1, putch);
        !          1742:        fflush(stdout);
        !          1743:        pstate = 0;
        !          1744:     }
        !          1745:     otty.sg_flags |= ECHO;
        !          1746:     otty.sg_flags &= ~MBIT;
        !          1747:     stty(fileno(stderr), &savetty);
        !          1748: }
        !          1749: 
        !          1750: rdline (f)
        !          1751: register FILE *f;
        !          1752: {
        !          1753:     register char c;
        !          1754:     register char *p;
        !          1755: 
        !          1756:     p = Line;
        !          1757:     while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
        !          1758:        *p++ = c;
        !          1759:     if (c == '\n')
        !          1760:        Currline++;
        !          1761:     *p = '\0';
        !          1762: }
        !          1763: 
        !          1764: /* Come here when we get a suspend signal from the terminal */
        !          1765: 
        !          1766: onsusp ()
        !          1767: {
        !          1768:     /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
        !          1769:     signal(SIGTTOU, SIG_IGN);
        !          1770:     reset_tty ();
        !          1771:     fflush (stdout);
        !          1772:     signal(SIGTTOU, SIG_DFL);
        !          1773:     /* Send the TSTP signal to suspend our process group */
        !          1774:     signal(SIGTSTP, SIG_DFL);
        !          1775:     sigsetmask(0);
        !          1776:     kill (0, SIGTSTP);
        !          1777:     /* Pause for station break */
        !          1778: 
        !          1779:     /* We're back */
        !          1780:     signal (SIGTSTP, onsusp);
        !          1781:     set_tty ();
        !          1782:     if (inwait)
        !          1783:            longjmp (restore);
        !          1784: }

unix.superglobalmegacorp.com

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