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