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