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

Defined functions

Sprintf defined in line 581; used 2 times
argscan defined in line 273; used 2 times
checkf defined in line 315; used 2 times
cleareol defined in line 779; used 15 times
clreos defined in line 784; used 5 times
colon defined in line 1080; used 1 times
command defined in line 887; used 2 times
copy_file defined in line 500; used 3 times
do_shell defined in line 1158; used 2 times
doclear defined in line 855; used 8 times
end_it defined in line 481; used 7 times
erase defined in line 745; used 10 times
error defined in line 1594; used 6 times
execute defined in line 1264; used 2 times
expand defined in line 1536; used 1 times
getline defined in line 664; used 1 times
home defined in line 871; used 5 times
initterm defined in line 1362; used 1 times
kill_line defined in line 769; used 12 times
main defined in line 98; never used
number defined in line 1137; used 1 times
onquit defined in line 456; used 5 times
onsusp defined in line 1646; used 4 times
pr defined in line 793; used 29 times
prbuf defined in line 807; used 1 times
printd defined in line 556; used 3 times
printf defined in line 511; used 401 times
prompt defined in line 624; used 4 times
putch defined in line 376; used 13 times
rdline defined in line 1629; used 1 times
readch defined in line 1438; used 3 times
reset_tty defined in line 1622; used 4 times
scanstr defined in line 572; used 1 times
screen defined in line 388; used 2 times
search defined in line 1187; used 4 times
set_tty defined in line 1615; used 2 times
show defined in line 1579; used 1 times
skipf defined in line 1331; used 2 times
skiplns defined in line 1311; used 2 times
tailequ defined in line 607; used 1 times
ttyin defined in line 1454; used 2 times

Defined variables

BS defined in line 1451; used 3 times
CARAT defined in line 1452; used 2 times
Clear defined in line 75; used 3 times
Currline defined in line 57; used 17 times
EodClr defined in line 84; used 3 times
Home defined in line 81; used 6 times
Line defined in line 73; used 13 times
Lpp defined in line 74; used 5 times
Mcol defined in line 86; used 7 times
Pause defined in line 62; used 5 times
Senter defined in line 77; used 8 times
Sexit defined in line 77; used 6 times
ULenter defined in line 78; used 4 times
ULexit defined in line 78; used 5 times
Wrap defined in line 87; used 2 times
bad_so defined in line 61; used 3 times
bell defined in line 590; used 6 times
catch_susp defined in line 66; used 3 times
ch defined in line 71; used 61 times
chBS defined in line 80; used 1 times
chUL defined in line 79; used 6 times
clreol defined in line 65; used 27 times
cursorhome defined in line 83; used 2 times
cursorm defined in line 82; used 2 times
dlines defined in line 47; used 16 times
dum_opt defined in line 47; used 3 times
dumb defined in line 65; used 4 times
eraseln defined in line 76; used 11 times
errors defined in line 62; used 3 times
file_pos defined in line 45; used 6 times
file_size defined in line 45; used 4 times
firstf defined in line 59; used 5 times
fnames defined in line 67; used 15 times
fnum defined in line 46; used 21 times
fold_opt defined in line 52; used 4 times
hard defined in line 65; used 8 times
hardtabs defined in line 65; used 2 times
inwait defined in line 62; used 4 times
lastarg defined in line 876; used 2 times
lastcmd defined in line 876; used 3 times
lastcolon defined in line 877; used 2 times
lastp defined in line 876; used 5 times
nfiles defined in line 68; used 9 times
no_intty defined in line 46; used 15 times
no_tty defined in line 46; used 6 times
noscroll defined in line 65; used 12 times
notell defined in line 60; used 3 times
nscroll defined in line 51; used 2 times
otty defined in line 44; used 26 times
promptlen defined in line 56; used 39 times
restore defined in line 72; used 8 times
savetty defined in line 44; used 2 times
sccsid defined in line 2; never used
shell defined in line 69; used 4 times
shell_line defined in line 878; used 6 times
shellp defined in line 70; used 2 times
slow_tty defined in line 46; used 4 times
sptr defined in line 570; used 16 times
ssp_opt defined in line 54; used 2 times
startup defined in line 58; used 2 times
stop_opt defined in line 53; used 2 times
ul_opt defined in line 55; used 4 times
within defined in line 63; used 3 times

Defined macros

ESC defined in line 41; used 3 times
Fopen defined in line 28; used 1 times
Fseek defined in line 30; used 4 times
Ftell defined in line 29; used 3 times
Getc defined in line 31; used 9 times
HELPFILE defined in line 25; used 1 times
LINSIZ defined in line 38; used 4 times
MBIT defined in line 34; used 8 times
QUIT defined in line 42; never used
RUBOUT defined in line 40; used 6 times
STOP defined in line 386; used 1 times
TBUFSIZ defined in line 37; used 1 times
Ungetc defined in line 32; used 3 times
VI defined in line 26; used 1 times
ctrl defined in line 39; used 2 times
ret defined in line 899; used 7 times
stty defined in line 35; used 5 times
Last modified: 1984-02-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3319
Valid CSS Valid XHTML 1.0 Strict