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