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