# 2.11BSD#431 - /usr/src/ucb/more/more.c

##### Functions

    Sprintf           X
    argscan           X
    checkf            X
    chgwinsz          X
    cleareol          X
    clreos            X
    colon             X
    command           X
    copy_file         X
    do_shell          X
    doclear           X
    end_it            X
    erase             X
    error             X
    execute           X
    expand            X
    getline           X
    home              X
    initterm          X
    kill_line         X
    main              X
    number            X
    onquit            X
    onsusp            X
    pr                X
    prbuf             X
    printd            X
    printf            X
    prompt            X
    putch             X
    rdline            X
    readch            X
    reset_tty         X
    scanstr           X
    screen            X
    search            X
    set_tty           X
    show              X
    skipf             X
    skiplns           X
    tailequ           X
    ttyin             X

##### Variables

    Clear             X
    Currline          X
    EodClr            X
    Home              X
    Line              X
    Lpp               X
    Mcol              X
    Pause             X
    Senter            X
    Sexit             X
    ULenter           X
    ULexit            X
    Wrap              X
    bad_so            X
    catch_susp        X
    ch                X
    chBS              X
    chUL              X
    clreol            X
    copyright         X
    cursorhome        X
    cursorm           X
    dlines            X
    docrterase        X
    docrtkill         X
    dum_opt           X
    dumb              X
    eraseln           X
    errors            X
    file_pos          X
    file_size         X
    firstf            X
    fnames            X
    fnum              X
    fold_opt          X
    hard              X
    hardtabs          X
    inwait            X
    nfiles            X
    no_intty          X
    no_tty            X
    noscroll          X
    notell            X
    nscroll           X
    otty              X
    promptlen         X
    pstate            X
    restore           X
    savetty           X
    shell             X
    shell_line        X
    shellp            X
    slow_tty          X
    soglitch          X
    ssp_opt           X
    startup           X
    stop_opt          X
    ul_opt            X
    ulglitch          X
    within            X

##### Macros

    ERASEONECHAR      X
    ESC               X
    Fopen             X
    Fseek             X
    Ftell             X
    Getc              X
    HELPFILE          X
    LINSIZ            X
    MBIT              X
    QUIT              X
    RUBOUT            X
    STOP              X
    TBUFSIZ           X
    Ungetc            X
    VI                X
    ctrl              X
    ret               X
    stty              X
    wouldul           X

       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: #if !defined(lint) && defined(DOSCCS)
       8: char copyright[] =
       9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      10:  All rights reserved.\n";
      11:
      12: static char sccsid[] = "@(#)more.c	5.4.2 (2.11BSD) 1997/10/18";
      13: #endif
      14:
      15: /*
      16: ** more.c - General purpose tty output filter and file perusal program
      17: **
      18: **	by Eric Shienbrood, UC Berkeley
      19: **
      20: **	modified by Geoff Peck, UCB to add underlining, single spacing
      21: **	modified by John Foderaro, UCB to add -c and MORE environment variable
      22: */
      23:
      24: #include <stdio.h>
      25: #undef  putchar         /* force use of function rather than macro */
      26: #include <sys/types.h>
      27: #include <ctype.h>
      28: #include <signal.h>
      29: #include <errno.h>
      30: #include <paths.h>
      31: #include <sgtty.h>
      32: #include <setjmp.h>
      33: #include <sys/stat.h>
      34: #include <stdlib.h>
      35: #include <unistd.h>
      36:
      37: #define HELPFILE    "/usr/share/misc/more.help"
      38: #define VI      "/usr/ucb/vi"
      39:
      40: #define Fopen(s,m)  (Currline = 0,file_pos=0,fopen(s,m))
      41: #define Ftell(f)    file_pos
      42: #define Fseek(f,off)    (file_pos=off,fseek(f,off,0))
      43: #define Getc(f)     (++file_pos, getc(f))
      44: #define Ungetc(c,f) (--file_pos, ungetc(c,f))
      45:
      46: #define MBIT    CBREAK
      47: #define stty(fd,argp)   ioctl(fd,TIOCSETN,argp)
      48:
      49: #define TBUFSIZ 1024
      50: #define LINSIZ  256
      51: #define ctrl(letter)    ('letter' & 077)
      52: #define RUBOUT  '\177'
      53: #define ESC '\033'
      54: #define QUIT    '\034'
      55:
      56: struct sgttyb   otty, savetty;
      57: long        file_pos, file_size;
      58: int     fnum, no_intty, no_tty, slow_tty;
      59: int     dum_opt, dlines, onquit(), end_it(), chgwinsz();
      60: int     onsusp();
      61: int     nscroll = 11;   /* Number of lines scrolled by 'd' */
      62: int     fold_opt = 1;   /* Fold long lines */
      63: int     stop_opt = 1;   /* Stop after form feeds */
      64: int     ssp_opt = 0;    /* Suppress white space */
      65: int     ul_opt = 1; /* Underline as best we can */
      66: int     promptlen;
      67: int     Currline;   /* Line we are currently at */
      68: int     startup = 1;
      69: int     firstf = 1;
      70: int     notell = 1;
      71: int     docrterase = 0;
      72: int     docrtkill = 0;
      73: int     bad_so; /* True if overwriting does not turn off standout */
      74: int     inwait, Pause, errors;
      75: int     within; /* true if we are within a file,
      76: 			false if we are between files */
      77: int     hard, dumb, noscroll, hardtabs, clreol;
      78: int     catch_susp; /* We should catch the SIGTSTP signal */
      79: char        **fnames;   /* The list of file names */
      80: int     nfiles;     /* Number of files left to process */
      81: char        *shell;     /* The name of the shell to use */
      82: int     shellp;     /* A previous shell command exists */
      83: char        ch;
      84: jmp_buf     restore;
      85: char        Line[LINSIZ];   /* Line buffer */
      86: int     Lpp = 24;   /* lines per page */
      87: char        *Clear;     /* clear screen */
      88: char        *eraseln;   /* erase line */
      89: char        *Senter, *Sexit;/* enter and exit standout mode */
      90: char        *ULenter, *ULexit;  /* enter and exit underline mode */
      91: char        *chUL;      /* underline character */
      92: char        *chBS;      /* backspace character */
      93: char        *Home;      /* go to home */
      94: char        *cursorm;   /* cursor movement */
      95: char        cursorhome[40]; /* contains cursor movement to home */
      96: char        *EodClr;    /* clear rest of screen */
      97: char        *tgetstr();
      98: int     Mcol = 80;  /* number of columns */
      99: int     Wrap = 1;   /* set if automargins */
     100: int     soglitch;   /* terminal has standout mode glitch */
     101: int     ulglitch;   /* terminal has underline mode glitch */
     102: int     pstate = 0; /* current UL state */
     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: register int n;
     597: {
     598:     register 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: register int n;
     622: {
     623:     register int a;
     624:
     625:     if (a = n/10)
     626:     Sprintf (a);
     627:     *sptr++ = n % 10 + '0';
     628: }
     629:
     630: static char bell = ctrl(G);
     631:
     632: /* See whether the last component of the path name "path" is equal to the
     633: ** string "string"
     634: */
     635:
     636: tailequ (path, string)
     637: char *path;
     638: register char *string;
     639: {
     640:     register char *tail;
     641:
     642:     tail = path + strlen(path);
     643:     while (tail >= path)
     644:         if (*(--tail) == '/')
     645:             break;
     646:     ++tail;
     647:     while (*tail++ == *string++)
     648:         if (*tail == '\0')
     649:             return(1);
     650:     return(0);
     651: }
     652:
     653: prompt (filename)
     654: char *filename;
     655: {
     656:     if (clreol)
     657:     cleareol ();
     658:     else if (promptlen > 0)
     659:     kill_line ();
     660:     if (!hard) {
     661:     promptlen = 8;
     662:     if (Senter && Sexit) {
     663:         tputs (Senter, 1, putch);
     664:         promptlen += (2 * soglitch);
     665:     }
     666:     if (clreol)
     667:         cleareol ();
     668:     pr("--More--");
     669:     if (filename != NULL) {
     670:         promptlen += printf ("(Next file: %s)", filename);
     671:     }
     672:     else if (!no_intty) {
     673:         promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size));
     674:     }
     675:     if (dum_opt) {
     676:         promptlen += pr("[Press space to continue, 'q' to quit.]");
     677:     }
     678:     if (Senter && Sexit)
     679:         tputs (Sexit, 1, putch);
     680:     if (clreol)
     681:         clreos ();
     682:     fflush(stdout);
     683:     }
     684:     else
     685:     write (2, &bell, 1);
     686:     inwait++;
     687: }
     688:
     689: /*
     690: ** Get a logical line
     691: */
     692:
     693: getline(f, length)
     694: register FILE *f;
     695: int *length;
     696: {
     697:     register int    c;
     698:     register char   *p;
     699:     register int    column;
     700:     static int      colflg;
     701:
     702:     p = Line;
     703:     column = 0;
     704:     c = Getc (f);
     705:     if (colflg && c == '\n') {
     706:     Currline++;
     707:     c = Getc (f);
     708:     }
     709:     while (p < &Line[LINSIZ - 1]) {
     710:     if (c == EOF) {
     711:         if (p > Line) {
     712:         *p = '\0';
     713:         *length = p - Line;
     714:         return (column);
     715:         }
     716:         *length = p - Line;
     717:         return (EOF);
     718:     }
     719:     if (c == '\n') {
     720:         Currline++;
     721:         break;
     722:     }
     723:     *p++ = c;
     724:     if (c == '\t')
     725:         if (hardtabs && column < promptlen && !hard) {
     726:         if (eraseln && !dumb) {
     727:             column = 1 + (column | 7);
     728:             tputs (eraseln, 1, putch);
     729:             promptlen = 0;
     730:         }
     731:         else {
     732:             for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
     733:             *p++ = ' ';
     734:             }
     735:             if (column >= promptlen) promptlen = 0;
     736:         }
     737:         }
     738:         else
     739:         column = 1 + (column | 7);
     740:     else if (c == '\b' && column > 0)
     741:         column--;
     742:     else if (c == '\r')
     743:         column = 0;
     744:     else if (c == '\f' && stop_opt) {
     745:         p[-1] = '^';
     746:         *p++ = 'L';
     747:         column += 2;
     748:         Pause++;
     749:     }
     750:     else if (c == EOF) {
     751:         *length = p - Line;
     752:         return (column);
     753:     }
     754:     else if (c >= ' ' && c != RUBOUT)
     755:         column++;
     756:     if (column >= Mcol && fold_opt) break;
     757:     c = Getc (f);
     758:     }
     759:     if (column >= Mcol && Mcol > 0) {
     760:     if (!Wrap) {
     761:         *p++ = '\n';
     762:     }
     763:     }
     764:     colflg = column == Mcol && fold_opt;
     765:     *length = p - Line;
     766:     *p = 0;
     767:     return (column);
     768: }
     769:
     770: /*
     771: ** Erase the rest of the prompt, assuming we are starting at column col.
     772: */
     773:
     774: erase (col)
     775: register int col;
     776: {
     777:
     778:     if (promptlen == 0)
     779:     return;
     780:     if (hard) {
     781:     putchar ('\n');
     782:     }
     783:     else {
     784:     if (col == 0)
     785:         putchar ('\r');
     786:     if (!dumb && eraseln)
     787:         tputs (eraseln, 1, putch);
     788:     else
     789:         for (col = promptlen - col; col > 0; col--)
     790:         putchar (' ');
     791:     }
     792:     promptlen = 0;
     793: }
     794:
     795: /*
     796: ** Erase the current line entirely
     797: */
     798:
     799: kill_line ()
     800: {
     801:     erase (0);
     802:     if (!eraseln || dumb) putchar ('\r');
     803: }
     804:
     805: /*
     806:  * force clear to end of line
     807:  */
     808: cleareol()
     809: {
     810:     tputs(eraseln, 1, putch);
     811: }
     812:
     813: clreos()
     814: {
     815:     tputs(EodClr, 1, putch);
     816: }
     817:
     818: /*
     819: **  Print string and return number of characters
     820: */
     821:
     822: pr(s1)
     823: char    *s1;
     824: {
     825:     register char   *s;
     826:     register char   c;
     827:
     828:     for (s = s1; c = *s++; )
     829:     putchar(c);
     830:     return (s - s1 - 1);
     831: }
     832:
     833:
     834: /* Print a buffer of n characters */
     835:
     836: prbuf (s, n)
     837: register char *s;
     838: register int n;
     839: {
     840:     register char c;            /* next output character */
     841:     register int state;         /* next output char's UL state */
     842: #define wouldul(s,n)    ((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_')))
     843:
     844:     while (--n >= 0)
     845:     if (!ul_opt)
     846:         putchar (*s++);
     847:     else {
     848:         if (*s == ' ' && pstate == 0 && ulglitch && wouldul(s+1, n-1)) {
     849:         s++;
     850:         continue;
     851:         }
     852:         if (state = wouldul(s, n)) {
     853:         c = (*s == '_')? s[2] : *s ;
     854:         n -= 2;
     855:         s += 3;
     856:         } else
     857:         c = *s++;
     858:         if (state != pstate) {
     859:         if (c == ' ' && state == 0 && ulglitch && wouldul(s, n-1))
     860:             state = 1;
     861:         else
     862:             tputs(state ? ULenter : ULexit, 1, putch);
     863:         }
     864:         if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0)
     865:             putchar(c);
     866:         if (state && *chUL) {
     867:         pr(chBS);
     868:         tputs(chUL, 1, putch);
     869:         }
     870:         pstate = state;
     871:     }
     872: }
     873:
     874: /*
     875: **  Clear the screen
     876: */
     877:
     878: doclear()
     879: {
     880:     if (Clear && !hard) {
     881:     tputs(Clear, 1, putch);
     882:
     883:     /* Put out carriage return so that system doesn't
     884: 	** get confused by escape sequences when expanding tabs
     885: 	*/
     886:     putchar ('\r');
     887:     promptlen = 0;
     888:     }
     889: }
     890:
     891: /*
     892:  * Go to home position
     893:  */
     894: home()
     895: {
     896:     tputs(Home,1,putch);
     897: }
     898:
     899: static int lastcmd, lastarg, lastp;
     900: static int lastcolon;
     901: char shell_line[132];
     902:
     903: /*
     904: ** Read a command and do it. A command consists of an optional integer
     905: ** argument followed by the command character.  Return the number of lines
     906: ** to display in the next screenful.  If there is nothing more to display
     907: ** in the current file, zero is returned.
     908: */
     909:
     910: command (filename, f)
     911: char *filename;
     912: register FILE *f;
     913: {
     914:     register int nlines;
     915:     register int retval;
     916:     register char c;
     917:     char colonch;
     918:     FILE *helpf;
     919:     int done;
     920:     char comchar, cmdbuf[80], *p;
     921:
     922: #define ret(val) retval=val;done++;break
     923:
     924:     done = 0;
     925:     if (!errors)
     926:     prompt (filename);
     927:     else
     928:     errors = 0;
     929:     if (MBIT == RAW && slow_tty) {
     930:     otty.sg_flags |= MBIT;
     931:     stty(fileno(stderr), &otty);
     932:     }
     933:     for (;;) {
     934:     nlines = number (&comchar);
     935:     lastp = colonch = 0;
     936:     if (comchar == '.') {   /* Repeat last command */
     937:         lastp++;
     938:         comchar = lastcmd;
     939:         nlines = lastarg;
     940:         if (lastcmd == ':')
     941:             colonch = lastcolon;
     942:     }
     943:     lastcmd = comchar;
     944:     lastarg = nlines;
     945:     if (comchar == otty.sg_erase) {
     946:         kill_line ();
     947:         prompt (filename);
     948:         continue;
     949:     }
     950:     switch (comchar) {
     951:     case ':':
     952:         retval = colon (filename, colonch, nlines);
     953:         if (retval >= 0)
     954:         done++;
     955:         break;
     956:     case 'b':
     957:     case ctrl(B):
     958:         {
     959:         register int initline;
     960:
     961:         if (no_intty) {
     962:             write(2, &bell, 1);
     963:             return (-1);
     964:         }
     965:
     966:         if (nlines == 0) nlines++;
     967:
     968:         putchar ('\r');
     969:         erase (0);
     970:         printf ("\n");
     971:         if (clreol)
     972:             cleareol ();
     973:         printf ("...back %d page", nlines);
     974:         if (nlines > 1)
     975:             pr ("s\n");
     976:         else
     977:             pr ("\n");
     978:
     979:         if (clreol)
     980:             cleareol ();
     981:         pr ("\n");
     982:
     983:         initline = Currline - dlines * (nlines + 1);
     984:         if (! noscroll)
     985:             --initline;
     986:         if (initline < 0) initline = 0;
     987:         Fseek(f, 0L);
     988:         Currline = 0;   /* skiplns() will make Currline correct */
     989:         skiplns(initline, f);
     990:         if (! noscroll) {
     991:             ret(dlines + 1);
     992:         }
     993:         else {
     994:             ret(dlines);
     995:         }
     996:         }
     997:     case ' ':
     998:     case 'z':
     999:         if (nlines == 0) nlines = dlines;
    1000:         else if (comchar == 'z') dlines = nlines;
    1001:         ret (nlines);
    1002:     case 'd':
    1003:     case ctrl(D):
    1004:         if (nlines != 0) nscroll = nlines;
    1005:         ret (nscroll);
    1006:     case 'q':
    1007:     case 'Q':
    1008:         end_it ();
    1009:     case 's':
    1010:     case 'f':
    1011:         if (nlines == 0) nlines++;
    1012:         if (comchar == 'f')
    1013:         nlines *= dlines;
    1014:         putchar ('\r');
    1015:         erase (0);
    1016:         printf ("\n");
    1017:         if (clreol)
    1018:         cleareol ();
    1019:         printf ("...skipping %d line", nlines);
    1020:         if (nlines > 1)
    1021:         pr ("s\n");
    1022:         else
    1023:         pr ("\n");
    1024:
    1025:         if (clreol)
    1026:         cleareol ();
    1027:         pr ("\n");
    1028:
    1029:         while (nlines > 0) {
    1030:         while ((c = Getc (f)) != '\n')
    1031:             if (c == EOF) {
    1032:             retval = 0;
    1033:             done++;
    1034:             goto endsw;
    1035:             }
    1036:             Currline++;
    1037:             nlines--;
    1038:         }
    1039:         ret (dlines);
    1040:     case '\n':
    1041:         if (nlines != 0)
    1042:         dlines = nlines;
    1043:         else
    1044:         nlines = 1;
    1045:         ret (nlines);
    1046:     case '\f':
    1047:         if (!no_intty) {
    1048:         doclear ();
    1049:         Fseek (f, screen_start.chrctr);
    1050:         Currline = screen_start.line;
    1051:         ret (dlines);
    1052:         }
    1053:         else {
    1054:         write (2, &bell, 1);
    1055:         break;
    1056:         }
    1057:     case '\'':
    1058:         if (!no_intty) {
    1059:         kill_line ();
    1060:         pr ("\n***Back***\n\n");
    1061:         Fseek (f, context.chrctr);
    1062:         Currline = context.line;
    1063:         ret (dlines);
    1064:         }
    1065:         else {
    1066:         write (2, &bell, 1);
    1067:         break;
    1068:         }
    1069:     case '=':
    1070:         kill_line ();
    1071:         promptlen = printd (Currline);
    1072:         fflush (stdout);
    1073:         break;
    1074:     case 'n':
    1075:         lastp++;
    1076:     case '/':
    1077:         if (nlines == 0) nlines++;
    1078:         kill_line ();
    1079:         pr ("/");
    1080:         promptlen = 1;
    1081:         fflush (stdout);
    1082:         if (lastp) {
    1083:         write (2,"\r", 1);
    1084:         search (NULL, f, nlines);   /* Use previous r.e. */
    1085:         }
    1086:         else {
    1087:         ttyin (cmdbuf, 78, '/');
    1088:         write (2, "\r", 1);
    1089:         search (cmdbuf, f, nlines);
    1090:         }
    1091:         ret (dlines-1);
    1092:     case '!':
    1093:         do_shell (filename);
    1094:         break;
    1095:     case '?':
    1096:     case 'h':
    1097:         if ((helpf = fopen (HELPFILE, "r")) == NULL)
    1098:         error ("Can't open help file");
    1099:         if (noscroll) doclear ();
    1100:         copy_file (helpf);
    1101:         fclose (helpf);
    1102:         prompt (filename);
    1103:         break;
    1104:     case 'v':   /* This case should go right before default */
    1105:         if (!no_intty) {
    1106:         kill_line ();
    1107:         cmdbuf[0] = '+';
    1108:         scanstr (Currline - dlines < 0 ? 0
    1109:                 : Currline - (dlines + 1) / 2, &cmdbuf[1]);
    1110:         pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
    1111:         execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
    1112:         break;
    1113:         }
    1114:     default:
    1115:         if (dum_opt) {
    1116:         kill_line ();
    1117:         if (Senter && Sexit) {
    1118:             tputs (Senter, 1, putch);
    1119:             promptlen = pr ("[Press 'h' for instructions.]") + (2 * soglitch);
    1120:             tputs (Sexit, 1, putch);
    1121:         }
    1122:         else
    1123:             promptlen = pr ("[Press 'h' for instructions.]");
    1124:         fflush (stdout);
    1125:         }
    1126:         else
    1127:         write (2, &bell, 1);
    1128:         break;
    1129:     }
    1130:     if (done) break;
    1131:     }
    1132:     putchar ('\r');
    1133: endsw:
    1134:     inwait = 0;
    1135:     notell++;
    1136:     if (MBIT == RAW && slow_tty) {
    1137:     otty.sg_flags &= ~MBIT;
    1138:     stty(fileno(stderr), &otty);
    1139:     }
    1140:     return (retval);
    1141: }
    1142:
    1143: char ch;
    1144:
    1145: /*
    1146:  * Execute a colon-prefixed command.
    1147:  * Returns <0 if not a command that should cause
    1148:  * more of the file to be printed.
    1149:  */
    1150:
    1151: colon (filename, cmd, nlines)
    1152: char *filename;
    1153: int cmd;
    1154: int nlines;
    1155: {
    1156:     if (cmd == 0)
    1157:         ch = readch ();
    1158:     else
    1159:         ch = cmd;
    1160:     lastcolon = ch;
    1161:     switch (ch) {
    1162:     case 'f':
    1163:         kill_line ();
    1164:         if (!no_intty)
    1165:             promptlen = printf ("\"%s\" line %d", fnames[fnum], Currline);
    1166:         else
    1167:             promptlen = printf ("[Not a file] line %d", Currline);
    1168:         fflush (stdout);
    1169:         return (-1);
    1170:     case 'n':
    1171:         if (nlines == 0) {
    1172:             if (fnum >= nfiles - 1)
    1173:                 end_it ();
    1174:             nlines++;
    1175:         }
    1176:         putchar ('\r');
    1177:         erase (0);
    1178:         skipf (nlines);
    1179:         return (0);
    1180:     case 'p':
    1181:         if (no_intty) {
    1182:             write (2, &bell, 1);
    1183:             return (-1);
    1184:         }
    1185:         putchar ('\r');
    1186:         erase (0);
    1187:         if (nlines == 0)
    1188:             nlines++;
    1189:         skipf (-nlines);
    1190:         return (0);
    1191:     case '!':
    1192:         do_shell (filename);
    1193:         return (-1);
    1194:     case 'q':
    1195:     case 'Q':
    1196:         end_it ();
    1197:     default:
    1198:         write (2, &bell, 1);
    1199:         return (-1);
    1200:     }
    1201: }
    1202:
    1203: /*
    1204: ** Read a decimal number from the terminal. Set cmd to the non-digit which
    1205: ** terminates the number.
    1206: */
    1207:
    1208: number(cmd)
    1209: char *cmd;
    1210: {
    1211:     register int i;
    1212:
    1213:     i = 0; ch = otty.sg_kill;
    1214:     for (;;) {
    1215:         ch = readch ();
    1216:         if (ch >= '0' && ch <= '9')
    1217:             i = i*10 + ch - '0';
    1218:         else if (ch == otty.sg_kill)
    1219:             i = 0;
    1220:         else {
    1221:             *cmd = ch;
    1222:             break;
    1223:         }
    1224:     }
    1225:     return (i);
    1226: }
    1227:
    1228: do_shell (filename)
    1229: char *filename;
    1230: {
    1231:     char cmdbuf[80];
    1232:
    1233:     kill_line ();
    1234:     pr ("!");
    1235:     fflush (stdout);
    1236:     promptlen = 1;
    1237:     if (lastp)
    1238:         pr (shell_line);
    1239:     else {
    1240:         ttyin (cmdbuf, 78, '!');
    1241:         if (expand (shell_line, cmdbuf)) {
    1242:             kill_line ();
    1243:             promptlen = printf ("!%s", shell_line);
    1244:         }
    1245:     }
    1246:     fflush (stdout);
    1247:     write (2, "\n", 1);
    1248:     promptlen = 0;
    1249:     shellp = 1;
    1250:     execute (filename, shell, shell, "-c", shell_line, 0);
    1251: }
    1252:
    1253: /*
    1254: ** Search for nth ocurrence of regular expression contained in buf in the file
    1255: */
    1256:
    1257: search (buf, file, n)
    1258: char buf[];
    1259: FILE *file;
    1260: register int n;
    1261: {
    1262:     long startline = Ftell (file);
    1263:     register long line1 = startline;
    1264:     register long line2 = startline;
    1265:     register long line3 = startline;
    1266:     register int lncount;
    1267:     int saveln, rv;
    1268:     char *s;
    1269:
    1270:     context.line = saveln = Currline;
    1271:     context.chrctr = startline;
    1272:     lncount = 0;
    1273:     if ((s = re_comp (buf)) != 0)
    1274:     error (s);
    1275:     while (!feof (file)) {
    1276:     line3 = line2;
    1277:     line2 = line1;
    1278:     line1 = Ftell (file);
    1279:     rdline (file);
    1280:     lncount++;
    1281:     if ((rv = re_exec (Line)) == 1)
    1282:         if (--n == 0) {
    1283:             if (lncount > 3 || (lncount > 1 && no_intty))
    1284:             {
    1285:             pr ("\n");
    1286:             if (clreol)
    1287:                 cleareol ();
    1288:             pr("...skipping\n");
    1289:             }
    1290:             if (!no_intty) {
    1291:             Currline -= (lncount >= 3 ? 3 : lncount);
    1292:             Fseek (file, line3);
    1293:             if (noscroll)
    1294:                 if (clreol) {
    1295:                 home ();
    1296:                 cleareol ();
    1297:                 }
    1298:                 else
    1299:                 doclear ();
    1300:             }
    1301:             else {
    1302:             kill_line ();
    1303:             if (noscroll)
    1304:                 if (clreol) {
    1305:                     home ();
    1306:                     cleareol ();
    1307:                 }
    1308:                 else
    1309:                 doclear ();
    1310:             pr (Line);
    1311:             putchar ('\n');
    1312:             }
    1313:             break;
    1314:         }
    1315:     else if (rv == -1)
    1316:         error ("Regular expression botch");
    1317:     }
    1318:     if (feof (file)) {
    1319:     if (!no_intty) {
    1320:         file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */
    1321:         Currline = saveln;
    1322:         Fseek (file, startline);
    1323:     }
    1324:     else {
    1325:         pr ("\nPattern not found\n");
    1326:         end_it ();
    1327:     }
    1328:     error ("Pattern not found");
    1329:     }
    1330: }
    1331:
    1332: execute (filename, cmd, args)
    1333: char *filename;
    1334: char *cmd, *args;
    1335: {
    1336:     int id;
    1337:     int n;
    1338:
    1339:     fflush (stdout);
    1340:     reset_tty ();
    1341:     for (n = 10; (id = fork ()) < 0 && n > 0; n--)
    1342:         sleep (5);
    1343:     if (id == 0) {
    1344:         if (!isatty(0)) {
    1345:         close(0);
    1346:         open("/dev/tty", 0);
    1347:         }
    1348:         execv (cmd, &args);
    1349:         write (2, "exec failed\n", 12);
    1350:         exit (1);
    1351:     }
    1352:     if (id > 0) {
    1353:         signal (SIGINT, SIG_IGN);
    1354:         signal (SIGQUIT, SIG_IGN);
    1355:         if (catch_susp)
    1356:         signal(SIGTSTP, SIG_DFL);
    1357:         while (wait(0) > 0);
    1358:         signal (SIGINT, end_it);
    1359:         signal (SIGQUIT, onquit);
    1360:         if (catch_susp)
    1361:         signal(SIGTSTP, onsusp);
    1362:     } else
    1363:         write(2, "can't fork\n", 11);
    1364:     set_tty ();
    1365:     pr ("------------------------\n");
    1366:     prompt (filename);
    1367: }
    1368: /*
    1369: ** Skip n lines in the file f
    1370: */
    1371:
    1372: skiplns (n, f)
    1373: register int n;
    1374: register FILE *f;
    1375: {
    1376:     register char c;
    1377:
    1378:     while (n > 0) {
    1379:     while ((c = Getc (f)) != '\n')
    1380:         if (c == EOF)
    1381:         return;
    1382:         n--;
    1383:         Currline++;
    1384:     }
    1385: }
    1386:
    1387: /*
    1388: ** Skip nskip files in the file list (from the command line). Nskip may be
    1389: ** negative.
    1390: */
    1391:
    1392: skipf (nskip)
    1393: register int nskip;
    1394: {
    1395:     if (nskip == 0) return;
    1396:     if (nskip > 0) {
    1397:     if (fnum + nskip > nfiles - 1)
    1398:         nskip = nfiles - fnum - 1;
    1399:     }
    1400:     else if (within)
    1401:     ++fnum;
    1402:     fnum += nskip;
    1403:     if (fnum < 0)
    1404:     fnum = 0;
    1405:     pr ("\n...Skipping ");
    1406:     pr ("\n");
    1407:     if (clreol)
    1408:     cleareol ();
    1409:     pr ("...Skipping ");
    1410:     pr (nskip > 0 ? "to file " : "back to file ");
    1411:     pr (fnames[fnum]);
    1412:     pr ("\n");
    1413:     if (clreol)
    1414:     cleareol ();
    1415:     pr ("\n");
    1416:     --fnum;
    1417: }
    1418:
    1419: /*----------------------------- Terminal I/O -------------------------------*/
    1420:
    1421: initterm ()
    1422: {
    1423:     char    buf[TBUFSIZ];
    1424:     static char clearbuf[TBUFSIZ];
    1425:     char    *clearptr, *padstr;
    1426:     int     ldisc;
    1427:     int     lmode;
    1428:     char    *term;
    1429:     int     tgrp;
    1430:     struct winsize win;
    1431:
    1432: retry:
    1433:     if (!(no_tty = gtty(fileno(stdout), &otty))) {
    1434:     if (ioctl(fileno(stdout), TIOCLGET, &lmode) < 0) {
    1435:         perror("TIOCLGET");
    1436:         exit(1);
    1437:     }
    1438:     docrterase = ((lmode & LCRTERA) != 0);
    1439:     docrtkill = ((lmode & LCRTKIL) != 0);
    1440:     /*
    1441: 	 * Wait until we're in the foreground before we save the
    1442: 	 * the terminal modes.
    1443: 	 */
    1444:     if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) {
    1445:         perror("TIOCGPGRP");
    1446:         exit(1);
    1447:     }
    1448:     if (tgrp != getpgrp(0)) {
    1449:         kill(0, SIGTTOU);
    1450:         goto retry;
    1451:     }
    1452:     if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) {
    1453:         dumb++; ul_opt = 0;
    1454:     }
    1455:     else {
    1456:         if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
    1457:         Lpp = tgetnum("li");
    1458:         Mcol = tgetnum("co");
    1459:         } else {
    1460:         if ((Lpp = win.ws_row) == 0)
    1461:             Lpp = tgetnum("li");
    1462:         if ((Mcol = win.ws_col) == 0)
    1463:             Mcol = tgetnum("co");
    1464:         }
    1465:         if ((Lpp <= 0) || tgetflag("hc")) {
    1466:         hard++; /* Hard copy terminal */
    1467:         Lpp = 24;
    1468:         }
    1469:         if (Mcol <= 0)
    1470:         Mcol = 80;
    1471:
    1472:         if (tailequ (fnames[0], "page") || !hard && tgetflag("ns"))
    1473:         noscroll++;
    1474:         Wrap = tgetflag("am");
    1475:         bad_so = tgetflag ("xs");
    1476:         clearptr = clearbuf;
    1477:         eraseln = tgetstr("ce",&clearptr);
    1478:         Clear = tgetstr("cl", &clearptr);
    1479:         Senter = tgetstr("so", &clearptr);
    1480:         Sexit = tgetstr("se", &clearptr);
    1481:         if ((soglitch = tgetnum("sg")) < 0)
    1482:         soglitch = 0;
    1483:
    1484:         /*
    1485: 	     *  Set up for underlining:  some terminals don't need it;
    1486: 	     *  others have start/stop sequences, still others have an
    1487: 	     *  underline char sequence which is assumed to move the
    1488: 	     *  cursor forward one character.  If underline sequence
    1489: 	     *  isn't available, settle for standout sequence.
    1490: 	     */
    1491:
    1492:         if (tgetflag("ul") || tgetflag("os"))
    1493:         ul_opt = 0;
    1494:         if ((chUL = tgetstr("uc", &clearptr)) == NULL )
    1495:         chUL = "";
    1496:         if (((ULenter = tgetstr("us", &clearptr)) == NULL ||
    1497:              (ULexit = tgetstr("ue", &clearptr)) == NULL) && !*chUL) {
    1498:             if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) {
    1499:             ULenter = "";
    1500:             ULexit = "";
    1501:         } else
    1502:             ulglitch = soglitch;
    1503:         } else {
    1504:         if ((ulglitch = tgetnum("ug")) < 0)
    1505:             ulglitch = 0;
    1506:         }
    1507:
    1508:         if (padstr = tgetstr("pc", &clearptr))
    1509:         PC = *padstr;
    1510:         Home = tgetstr("ho",&clearptr);
    1511:         if (Home == 0 || *Home == '\0')
    1512:         {
    1513:         if ((cursorm = tgetstr("cm", &clearptr)) != NULL) {
    1514:             strcpy(cursorhome, tgoto(cursorm, 0, 0));
    1515:             Home = cursorhome;
    1516:            }
    1517:         }
    1518:         EodClr = tgetstr("cd", &clearptr);
    1519:         if ((chBS = tgetstr("bc", &clearptr)) == NULL)
    1520:         chBS = "\b";
    1521:
    1522:     }
    1523:     if ((shell = getenv("SHELL")) == NULL)
    1524:         shell = _PATH_BSHELL;
    1525:     }
    1526:     no_intty = gtty(fileno(stdin), &otty);
    1527:     gtty(fileno(stderr), &otty);
    1528:     savetty = otty;
    1529:     ospeed = otty.sg_ospeed;
    1530:     slow_tty = ospeed < B1200;
    1531:     hardtabs = !(otty.sg_flags & XTABS);
    1532:     if (!no_tty) {
    1533:     otty.sg_flags &= ~ECHO;
    1534:     if (MBIT == CBREAK || !slow_tty)
    1535:         otty.sg_flags |= MBIT;
    1536:     }
    1537: }
    1538:
    1539: readch ()
    1540: {
    1541:     char ch;
    1542:
    1543:     if (read (2, &ch, 1) <= 0)
    1544:         if (errno != EINTR)
    1545:             exit(0);
    1546:         else
    1547:             ch = otty.sg_kill;
    1548:     return (ch);
    1549: }
    1550:
    1551: static char BS = '\b';
    1552: static char *BSB = "\b \b";
    1553: static char CARAT = '^';
    1554: #define ERASEONECHAR \
    1555:     if (docrterase) \
    1556:     write (2, BSB, sizeof(BSB)); \
    1557:     else \
    1558:     write (2, &BS, sizeof(BS));
    1559:
    1560: ttyin (buf, nmax, pchar)
    1561: char buf[];
    1562: register int nmax;
    1563: char pchar;
    1564: {
    1565:     register char *sptr;
    1566:     register char ch;
    1567:     register int slash = 0;
    1568:     int maxlen;
    1569:     char cbuf;
    1570:
    1571:     sptr = buf;
    1572:     maxlen = 0;
    1573:     while (sptr - buf < nmax) {
    1574:     if (promptlen > maxlen) maxlen = promptlen;
    1575:     ch = readch ();
    1576:     if (ch == '\\') {
    1577:         slash++;
    1578:     }
    1579:     else if ((ch == otty.sg_erase) && !slash) {
    1580:         if (sptr > buf) {
    1581:         --promptlen;
    1582:         ERASEONECHAR
    1583:         --sptr;
    1584:         if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
    1585:             --promptlen;
    1586:             ERASEONECHAR
    1587:         }
    1588:         continue;
    1589:         }
    1590:         else {
    1591:         if (!eraseln) promptlen = maxlen;
    1592:         longjmp (restore, 1);
    1593:         }
    1594:     }
    1595:     else if ((ch == otty.sg_kill) && !slash) {
    1596:         if (hard) {
    1597:         show (ch);
    1598:         putchar ('\n');
    1599:         putchar (pchar);
    1600:         }
    1601:         else {
    1602:         putchar ('\r');
    1603:         putchar (pchar);
    1604:         if (eraseln)
    1605:             erase (1);
    1606:         else if (docrtkill)
    1607:             while (promptlen-- > 1)
    1608:             write (2, BSB, sizeof(BSB));
    1609:         promptlen = 1;
    1610:         }
    1611:         sptr = buf;
    1612:         fflush (stdout);
    1613:         continue;
    1614:     }
    1615:     if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) {
    1616:         ERASEONECHAR
    1617:         --sptr;
    1618:     }
    1619:     if (ch != '\\')
    1620:         slash = 0;
    1621:     *sptr++ = ch;
    1622:     if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
    1623:         ch += ch == RUBOUT ? -0100 : 0100;
    1624:         write (2, &CARAT, 1);
    1625:         promptlen++;
    1626:     }
    1627:     cbuf = ch;
    1628:     if (ch != '\n' && ch != ESC) {
    1629:         write (2, &cbuf, 1);
    1630:         promptlen++;
    1631:     }
    1632:     else
    1633:         break;
    1634:     }
    1635:     *--sptr = '\0';
    1636:     if (!eraseln) promptlen = maxlen;
    1637:     if (sptr - buf >= nmax - 1)
    1638:     error ("Line too long");
    1639: }
    1640:
    1641: expand (outbuf, inbuf)
    1642: char *outbuf;
    1643: char *inbuf;
    1644: {
    1645:     register char *instr;
    1646:     register char *outstr;
    1647:     register char ch;
    1648:     char temp[200];
    1649:     int changed = 0;
    1650:
    1651:     instr = inbuf;
    1652:     outstr = temp;
    1653:     while ((ch = *instr++) != '\0')
    1654:     switch (ch) {
    1655:     case '%':
    1656:         if (!no_intty) {
    1657:         strcpy (outstr, fnames[fnum]);
    1658:         outstr += strlen (fnames[fnum]);
    1659:         changed++;
    1660:         }
    1661:         else
    1662:         *outstr++ = ch;
    1663:         break;
    1664:     case '!':
    1665:         if (!shellp)
    1666:         error ("No previous command to substitute for");
    1667:         strcpy (outstr, shell_line);
    1668:         outstr += strlen (shell_line);
    1669:         changed++;
    1670:         break;
    1671:     case '\\':
    1672:         if (*instr == '%' || *instr == '!') {
    1673:         *outstr++ = *instr++;
    1674:         break;
    1675:         }
    1676:     default:
    1677:         *outstr++ = ch;
    1678:     }
    1679:     *outstr++ = '\0';
    1680:     strcpy (outbuf, temp);
    1681:     return (changed);
    1682: }
    1683:
    1684: show (ch)
    1685: register char ch;
    1686: {
    1687:     char cbuf;
    1688:
    1689:     if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
    1690:     ch += ch == RUBOUT ? -0100 : 0100;
    1691:     write (2, &CARAT, 1);
    1692:     promptlen++;
    1693:     }
    1694:     cbuf = ch;
    1695:     write (2, &cbuf, 1);
    1696:     promptlen++;
    1697: }
    1698:
    1699: error (mess)
    1700: char *mess;
    1701: {
    1702:     if (clreol)
    1703:     cleareol ();
    1704:     else
    1705:     kill_line ();
    1706:     promptlen += strlen (mess);
    1707:     if (Senter && Sexit) {
    1708:     tputs (Senter, 1, putch);
    1709:     pr(mess);
    1710:     tputs (Sexit, 1, putch);
    1711:     }
    1712:     else
    1713:     pr (mess);
    1714:     fflush(stdout);
    1715:     errors++;
    1716:     longjmp (restore, 1);
    1717: }
    1718:
    1719:
    1720: set_tty ()
    1721: {
    1722:     otty.sg_flags |= MBIT;
    1723:     otty.sg_flags &= ~ECHO;
    1724:     stty(fileno(stderr), &otty);
    1725: }
    1726:
    1727: reset_tty ()
    1728: {
    1729:     if (pstate) {
    1730:     tputs(ULexit, 1, putch);
    1731:     fflush(stdout);
    1732:     pstate = 0;
    1733:     }
    1734:     otty.sg_flags |= ECHO;
    1735:     otty.sg_flags &= ~MBIT;
    1736:     stty(fileno(stderr), &savetty);
    1737: }
    1738:
    1739: rdline (f)
    1740: register FILE *f;
    1741: {
    1742:     register char c;
    1743:     register char *p;
    1744:
    1745:     p = Line;
    1746:     while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
    1747:     *p++ = c;
    1748:     if (c == '\n')
    1749:     Currline++;
    1750:     *p = '\0';
    1751: }
    1752:
    1753: /* Come here when we get a suspend signal from the terminal */
    1754:
    1755: onsusp ()
    1756: {
    1757:     /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
    1758:     signal(SIGTTOU, SIG_IGN);
    1759:     reset_tty ();
    1760:     fflush (stdout);
    1761:     signal(SIGTTOU, SIG_DFL);
    1762:     /* Send the TSTP signal to suspend our process group */
    1763:     signal(SIGTSTP, SIG_DFL);
    1764:     sigsetmask(0L);
    1765:     kill (0, SIGTSTP);
    1766:     /* Pause for station break */
    1767:
    1768:     /* We're back */
    1769:     signal (SIGTSTP, onsusp);
    1770:     set_tty ();
    1771:     if (inwait)
    1772:         longjmp (restore);
    1773: }

#### Defined functions

Sprintf defined in line 620; used 2 times

- in line 616, 626

argscan defined in line 283; used 2 times

- in line 133-136(2)

checkf defined in line 327; used 2 times

- in line 125, 221

chgwinsz defined in line 498; used 3 times

- in line 59, 183, 514

cleareol defined in line 808; used 17 times

- in line 250-257(3), 339, 422, 657, 667, 972, 980, 1018, 1026, 1287, 1296, 1306, 1408, 1414, 1703

clreos defined in line 813; used 5 times

- in line 410, 445-450(2), 527, 681

colon defined in line 1151; used 1 times

- in line 952

command defined in line 910; used 2 times

- in line 238, 454

copy_file defined in line 539; used 3 times

- in line 192, 263, 1100

do_shell defined in line 1228; used 2 times

- in line 1093, 1192

doclear defined in line 878; used 8 times

- in line 195, 202, 245, 463, 1048, 1099, 1299, 1309

end_it defined in line 521; used 7 times

- in line 59, 182, 1008, 1173, 1196, 1326, 1358

erase defined in line 774; used 11 times

- in line 248-253(2), 417, 425, 457, 801, 969, 1015, 1177, 1186, 1605

error defined in line 1699; used 6 times

- in line 1098, 1274, 1316, 1328, 1638, 1666

execute defined in line 1332; used 2 times

- in line 1111, 1250

expand defined in line 1641; used 1 times

- in line 1241

getline defined in line 693; used 1 times

- in line 407

home defined in line 894; used 5 times

- in line 200, 243, 461, 1295, 1305

initterm defined in line 1421; used 1 times

- in line 129

kill_line defined in line 799; used 13 times

- in line 531, 659, 946, 1059, 1070, 1078, 1106, 1116, 1163, 1233, 1242, 1302, 1705

main defined in line 110; never used
number defined in line 1208; used 1 times

- in line 934

onquit defined in line 474; used 5 times

- in line 59, 181, 480, 491, 1359

onsusp defined in line 1755; used 4 times

- in line 60, 185, 1361, 1769

pr defined in line 822; used 34 times

- in line 251, 572, 668, 676, 867, 975-981(3), 1021-1027(3), 1060, 1079, 1110(3), 1119-1123(2), 1234-1238(2), 1285-1288(2), 1310, 1325, 1365, 1405-1415(7), 1709-1713(2)

prbuf defined in line 836; used 2 times

- in line 423, 432

printd defined in line 595; used 3 times

- in line 569, 601, 1071

printf defined in line 550; used 14 times

- in line 254-258(3), 344, 363, 670-673(2), 970-973(2), 1016-1019(2), 1165-1167(2), 1243

prompt defined in line 653; used 4 times

- in line 926, 947, 1102, 1366

putch defined in line 384; used 16 times

- in line 438, 663, 679, 728, 787, 810-815(2), 862, 868, 881, 896, 1118-1120(2), 1708-1710(2), 1730

rdline defined in line 1739; used 1 times

- in line 1279

readch defined in line 1539; used 3 times

- in line 1157, 1215, 1575

reset_tty defined in line 1727; used 4 times

- in line 279, 524, 1340, 1759

scanstr defined in line 611; used 1 times

- in line 1108

screen defined in line 396; used 2 times

- in line 213, 266

search defined in line 1257; used 4 times

- in line 207, 229, 1084-1089(2)

set_tty defined in line 1720; used 2 times

- in line 1364, 1770

show defined in line 1684; used 1 times

- in line 1597

skipf defined in line 1392; used 2 times

- in line 1178, 1189

skiplns defined in line 1372; used 3 times

- in line 212, 234, 989

tailequ defined in line 636; used 1 times

- in line 1472

ttyin defined in line 1560; used 2 times

- in line 1087, 1240

#### Defined variables

BS defined in line 1551; used 2 times

- in line 1558(2)

BSB defined in line 1552; used 4 times

- in line 1556(2), 1608(2)

CARAT defined in line 1553; used 2 times

- in line 1624, 1691

Clear defined in line 87; used 3 times

- in line 880-881(2), 1478

Currline defined in line 67; used 20 times

- in line 40, 223, 465, 706, 720, 983-988(2), 1036, 1050, 1062, 1071, 1108-1109(2), 1165-1167(2), 1270, 1291, 1321, 1383, 1749

EodClr defined in line 96; used 4 times

- in line 163(2), 815, 1518

Home defined in line 93; used 7 times

- in line 161(2), 896, 1510-1515(4)

Line defined in line 85; used 13 times

- in line 423, 702, 709-716(4), 732, 751, 765, 1281, 1310, 1745-1746(2)

Lpp defined in line 86; used 12 times

- in line 130, 168, 259-260(2), 505-509(3), 1457-1467(5)

Mcol defined in line 98; used 11 times

- in line 431, 512, 756-764(4), 1458-1463(3), 1469-1470(2)

Pause defined in line 74; used 5 times

- in line 406, 449-453(2), 484, 748

Senter defined in line 89; used 11 times

- in line 416(2), 662-663(2), 678, 1117-1118(2), 1479, 1498, 1707-1708(2)

Sexit defined in line 89; used 9 times

- in line 662, 678-679(2), 1117-1120(2), 1480, 1498, 1707-1710(2)

ULenter defined in line 90; used 4 times

- in line 862, 1496-1499(3)

ULexit defined in line 90; used 6 times

- in line 438, 862, 1497-1500(3), 1730

Wrap defined in line 99; used 2 times

- in line 760, 1474

bad_so defined in line 73; used 3 times

- in line 247, 416, 1475

bell defined in line 630; used 7 times

- in line 685, 962, 1054, 1066, 1127, 1182, 1198

catch_susp defined in line 78; used 3 times

- in line 186, 1355-1360(2)

ch defined in line 1143; used 61 times

- in line 117, 135-138(2), 194-198(3), 384-387(3), 555, 561-565(3), 1157-1161(4), 1213-1221(7), 1541-1548(4), 1566, 1575-1579(3), 1595-1597(2), 1615-1628(13), 1647, 1653-1654(2), 1662, 1677, 1684-1694(9)

chBS defined in line 92; used 3 times

- in line 867, 1519-1520(2)

chUL defined in line 91; used 5 times

- in line 866-868(2), 1494-1497(3)

clreol defined in line 77; used 29 times

- in line 159-164(2), 199, 242, 249, 255-257(2), 309, 338, 409, 421, 444-449(2), 460, 525-530(2), 656, 666, 680, 971, 979, 1017, 1025, 1286, 1294, 1304, 1407, 1413, 1702

copyright defined in line 8; never used
cursorhome defined in line 95; used 2 times

- in line 1514-1515(2)

cursorm defined in line 94; used 2 times

- in line 1513-1514(2)

dlines defined in line 59; used 21 times

- in line 167-169(3), 286, 294(2), 458, 509, 983, 991-1000(4), 1013, 1039-1042(2), 1051, 1063, 1091, 1108-1109(2)

docrterase defined in line 71; used 2 times

- in line 1438, 1555

docrtkill defined in line 72; used 2 times

- in line 1439, 1606

dum_opt defined in line 59; used 4 times

- in line 297, 486, 675, 1115

dumb defined in line 77; used 4 times

- in line 726, 786, 802, 1453

eraseln defined in line 88; used 12 times

- in line 162(2), 726-728(2), 786-787(2), 802, 810, 1477, 1591, 1604, 1636

errors defined in line 74; used 3 times

- in line 925-928(2), 1715

file_pos defined in line 57; used 6 times

- in line 40-44(5), 673

file_size defined in line 57; used 4 times

- in line 241, 375-376(2), 673

firstf defined in line 69; used 5 times

- in line 217, 224-226(3), 277

fnames defined in line 79; used 15 times

- in line 128, 135-139(3), 221, 238, 256-258(2), 1110-1111(2), 1165, 1411, 1472, 1657-1658(2)

fnum defined in line 58; used 21 times

- in line 220-221(2), 236-238(2), 256-258(2), 276, 1110-1111(2), 1165, 1172, 1397-1404(6), 1411-1416(2), 1657-1658(2)

fold_opt defined in line 62; used 4 times

- in line 303, 431, 756, 764

hard defined in line 77; used 8 times

- in line 456, 660, 725, 780, 880, 1466, 1472, 1596

hardtabs defined in line 77; used 2 times

- in line 725, 1531

inwait defined in line 74; used 4 times

- in line 477, 686, 1134, 1771

lastarg defined in line 899; used 2 times

- in line 939-944(2)

lastcmd defined in line 899; used 3 times

- in line 938-943(3)

lastcolon defined in line 900; used 2 times

- in line 941, 1160

lastp defined in line 899; used 5 times

- in line 935-937(2), 1075, 1082, 1237

nfiles defined in line 80; used 9 times

- in line 127, 134, 170-172(2), 220, 236, 1172, 1397-1398(2)

no_intty defined in line 58; used 15 times

- in line 172, 190, 215, 672, 961, 1047, 1058, 1105, 1164, 1181, 1283, 1290, 1319, 1526, 1656

no_tty defined in line 58; used 6 times

- in line 180, 191, 236, 262, 1433, 1532

noscroll defined in line 77; used 15 times

- in line 165-168(2), 198, 208, 230, 241, 306, 458, 509, 984, 990, 1099, 1293, 1303, 1473

notell defined in line 70; used 3 times

- in line 486-489(2), 1135

nscroll defined in line 61; used 8 times

- in line 130-132(3), 506-508(3), 1004-1005(2)

otty defined in line 56; used 26 times

- in line 188, 930-931(2), 945, 1137-1138(2), 1213-1218(2), 1433, 1526-1535(7), 1547, 1579, 1595, 1615(2), 1722-1724(3), 1734-1735(2)

promptlen defined in line 66; used 43 times

- in line 252, 416, 424-426(2), 456, 488, 530, 658-664(3), 670-676(3), 725-729(2), 735(2), 778, 789-792(2), 887, 1071, 1080, 1119-1123(2), 1165-1167(2), 1236, 1243-1248(2), 1574(2), 1581-1585(2), 1591, 1607-1609(2), 1625-1630(2), 1636, 1692-1696(2), 1706

pstate defined in line 102; used 8 times

- in line 437-439(2), 848, 858, 864, 870, 1729-1732(2)

restore defined in line 84; used 8 times

- in line 224, 237, 270, 452, 481, 1592, 1716, 1772

savetty defined in line 56; used 2 times

- in line 1528, 1736

sccsid defined in line 12; never used
shell defined in line 81; used 4 times

- in line 1250(2), 1523-1524(2)

shell_line defined in line 901; used 6 times

- in line 1238-1243(3), 1250, 1667-1668(2)

shellp defined in line 82; used 2 times

- in line 1249, 1665

slow_tty defined in line 58; used 4 times

- in line 929, 1136, 1530-1534(2)

soglitch defined in line 100; used 5 times

- in line 664, 1119, 1481-1482(2), 1502

sptr defined in line 609; used 16 times

- in line 615-617(2), 627, 1565, 1571-1573(2), 1580-1584(5), 1611, 1617-1621(2), 1635-1637(2)

ssp_opt defined in line 64; used 2 times

- in line 312, 413

startup defined in line 68; used 2 times

- in line 453, 479

stop_opt defined in line 63; used 2 times

- in line 300, 744

ul_opt defined in line 65; used 4 times

- in line 315, 845, 1453, 1493

ulglitch defined in line 101; used 6 times

- in line 848, 859-864(2), 1502-1505(3)

within defined in line 75; used 3 times

- in line 265-267(2), 1400

#### Defined macros

ERASEONECHAR defined in line 1554; used 3 times

- in line 1582-1586(2), 1616

ESC defined in line 53; used 3 times

- in line 1622, 1628, 1689

Fopen defined in line 40; used 1 times

- in line 347

Fseek defined in line 42; used 5 times

- in line 987, 1049, 1061, 1292, 1322

Ftell defined in line 41; used 3 times

- in line 466, 1262, 1278

Getc defined in line 43; used 9 times

- in line 194, 352, 442, 704-707(2), 757, 1030, 1379, 1746

HELPFILE defined in line 37; used 1 times

- in line 1097

LINSIZ defined in line 50; used 4 times

- in line 85, 709, 732, 1746

MBIT defined in line 46; used 8 times

- in line 929-930(2), 1136-1137(2), 1534-1535(2), 1722, 1735

QUIT defined in line 54; never used
RUBOUT defined in line 52; used 6 times

- in line 754, 1584, 1622-1623(2), 1689-1690(2)

STOP defined in line 394; used 1 times

- in line 433

TBUFSIZ defined in line 49; used 2 times

- in line 1423-1424(2)

Ungetc defined in line 44; used 3 times

- in line 197, 373, 451

VI defined in line 38; used 1 times

- in line 1111

ctrl defined in line 51; used 3 times

- in line 630, 957, 1003

ret defined in line 922; used 9 times

- in line 991-994(2), 1001-1005(2), 1039, 1045, 1051, 1063, 1091

stty defined in line 47; used 5 times

- in line 188, 931, 1138, 1724, 1736

wouldul defined in line 842; used 3 times

- in line 848-852(2), 859

Last modified: 1997-10-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 6759 |