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