|
|
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) { ! 336: default: ! 337: if(c>=' ' && c<=0177) ! 338: break; ! 339: printf("\n******** %s: Not a text file ********\n\n", fs); ! 340: fclose (f); ! 341: return (NULL); ! 342: case '\b': ! 343: case '\t': ! 344: case '\n': ! 345: case '\f': ! 346: case '\r': ! 347: break; ! 348: } ! 349: if (c == '\f') ! 350: *clearfirst = 1; ! 351: else { ! 352: *clearfirst = 0; ! 353: Ungetc (c, f); ! 354: } ! 355: if ((file_size = stbuf.st_size) == 0) ! 356: file_size = 0x7fffffffffffffffL; ! 357: return (f); ! 358: } ! 359: ! 360: /* ! 361: ** A real function, for the tputs routine in termlib ! 362: */ ! 363: ! 364: putch (ch) ! 365: char ch; ! 366: { ! 367: putchar (ch); ! 368: } ! 369: ! 370: /* ! 371: ** Print out the contents of the file f, one screenful at a time. ! 372: */ ! 373: ! 374: #define STOP -10 ! 375: ! 376: screen (f, num_lines) ! 377: register FILE *f; ! 378: register int num_lines; ! 379: { ! 380: register int c; ! 381: register int nchars; ! 382: int length; /* length of current line */ ! 383: static int prev_len = 1; /* length of previous line */ ! 384: ! 385: for (;;) { ! 386: while (num_lines > 0 && !Pause) { ! 387: if ((nchars = getline (f, &length)) == EOF) ! 388: { ! 389: if (clreol) ! 390: clreos(); ! 391: return; ! 392: } ! 393: if (ssp_opt && length == 0 && prev_len == 0) ! 394: continue; ! 395: prev_len = length; ! 396: if (bad_so || (Senter && *Senter == ' ') && promptlen > 0) ! 397: erase (0); ! 398: /* must clear before drawing line since tabs on some terminals ! 399: * do not erase what they tab over. ! 400: */ ! 401: if (clreol) ! 402: cleareol (); ! 403: prbuf (Line, length); ! 404: if (nchars < promptlen) ! 405: erase (nchars); /* erase () sets promptlen to 0 */ ! 406: else promptlen = 0; ! 407: /* is this needed? ! 408: * if (clreol) ! 409: * cleareol(); /* must clear again in case we wrapped * ! 410: */ ! 411: if (nchars < Mcol || !fold_opt) ! 412: putchar('\n'); ! 413: if (nchars == STOP) ! 414: break; ! 415: num_lines--; ! 416: } ! 417: fflush(stdout); ! 418: if ((c = Getc(f)) == EOF) ! 419: { ! 420: if (clreol) ! 421: clreos (); ! 422: return; ! 423: } ! 424: ! 425: if (Pause && clreol) ! 426: clreos (); ! 427: Ungetc (c, f); ! 428: setjmp (restore); ! 429: Pause = 0; startup = 0; ! 430: if ((num_lines = command (NULL, f)) == 0) ! 431: return; ! 432: if (hard && promptlen > 0) ! 433: erase (0); ! 434: if (noscroll && num_lines >= dlines) ! 435: { ! 436: if (clreol) ! 437: home(); ! 438: else ! 439: doclear (); ! 440: } ! 441: screen_start.line = Currline; ! 442: screen_start.chrctr = Ftell (f); ! 443: } ! 444: } ! 445: ! 446: /* ! 447: ** Come here if a quit signal is received ! 448: */ ! 449: ! 450: onquit() ! 451: { ! 452: signal(SIGQUIT, SIG_IGN); ! 453: if (!inwait) { ! 454: putchar ('\n'); ! 455: if (!startup) { ! 456: signal(SIGQUIT, onquit); ! 457: longjmp (restore, 1); ! 458: } ! 459: else ! 460: Pause++; ! 461: } ! 462: else if (!dum_opt && notell) { ! 463: write (2, "[Use q or Q to quit]", 20); ! 464: promptlen += 20; ! 465: notell = 0; ! 466: } ! 467: signal(SIGQUIT, onquit); ! 468: } ! 469: ! 470: /* ! 471: ** Clean up terminal state and exit. Also come here if interrupt signal received ! 472: */ ! 473: ! 474: end_it () ! 475: { ! 476: ! 477: reset_tty (); ! 478: if (clreol) { ! 479: putchar ('\r'); ! 480: clreos (); ! 481: fflush (stdout); ! 482: } ! 483: else if (!clreol && (promptlen > 0)) { ! 484: kill_line (); ! 485: fflush (stdout); ! 486: } ! 487: else ! 488: write (2, "\n", 1); ! 489: _exit(0); ! 490: } ! 491: ! 492: copy_file(f) ! 493: register FILE *f; ! 494: { ! 495: register int c; ! 496: ! 497: while ((c = getc(f)) != EOF) ! 498: putchar(c); ! 499: } ! 500: ! 501: /* Simplified printf function */ ! 502: ! 503: printf (fmt, args) ! 504: register char *fmt; ! 505: int args; ! 506: { ! 507: register int *argp; ! 508: register char ch; ! 509: register int ccount; ! 510: ! 511: ccount = 0; ! 512: argp = &args; ! 513: while (*fmt) { ! 514: while ((ch = *fmt++) != '%') { ! 515: if (ch == '\0') ! 516: return (ccount); ! 517: ccount++; ! 518: putchar (ch); ! 519: } ! 520: switch (*fmt++) { ! 521: case 'd': ! 522: ccount += printd (*argp); ! 523: break; ! 524: case 's': ! 525: ccount += pr ((char *)*argp); ! 526: break; ! 527: case '%': ! 528: ccount++; ! 529: argp--; ! 530: putchar ('%'); ! 531: break; ! 532: case '0': ! 533: return (ccount); ! 534: default: ! 535: break; ! 536: } ! 537: ++argp; ! 538: } ! 539: return (ccount); ! 540: ! 541: } ! 542: ! 543: /* ! 544: ** Print an integer as a string of decimal digits, ! 545: ** returning the length of the print representation. ! 546: */ ! 547: ! 548: printd (n) ! 549: int n; ! 550: { ! 551: int a, nchars; ! 552: ! 553: if (a = n/10) ! 554: nchars = 1 + printd(a); ! 555: else ! 556: nchars = 1; ! 557: putchar (n % 10 + '0'); ! 558: return (nchars); ! 559: } ! 560: ! 561: /* Put the print representation of an integer into a string */ ! 562: static char *sptr; ! 563: ! 564: scanstr (n, str) ! 565: int n; ! 566: char *str; ! 567: { ! 568: sptr = str; ! 569: Sprintf (n); ! 570: *sptr = '\0'; ! 571: } ! 572: ! 573: Sprintf (n) ! 574: { ! 575: int a; ! 576: ! 577: if (a = n/10) ! 578: Sprintf (a); ! 579: *sptr++ = n % 10 + '0'; ! 580: } ! 581: ! 582: static char bell = ctrl(G); ! 583: ! 584: strlen (s) ! 585: char *s; ! 586: { ! 587: register char *p; ! 588: ! 589: p = s; ! 590: while (*p++) ! 591: ; ! 592: return (p - s - 1); ! 593: } ! 594: ! 595: /* See whether the last component of the path name "path" is equal to the ! 596: ** string "string" ! 597: */ ! 598: ! 599: tailequ (path, string) ! 600: char *path; ! 601: register char *string; ! 602: { ! 603: register char *tail; ! 604: ! 605: tail = path + strlen(path); ! 606: while (tail >= path) ! 607: if (*(--tail) == '/') ! 608: break; ! 609: ++tail; ! 610: while (*tail++ == *string++) ! 611: if (*tail == '\0') ! 612: return(1); ! 613: return(0); ! 614: } ! 615: ! 616: prompt (filename) ! 617: char *filename; ! 618: { ! 619: if (clreol) ! 620: cleareol (); ! 621: else if (promptlen > 0) ! 622: kill_line (); ! 623: if (!hard) { ! 624: promptlen = 8; ! 625: if (Senter && Sexit) ! 626: tputs (Senter, 1, putch); ! 627: if (clreol) ! 628: cleareol (); ! 629: pr("--More--"); ! 630: if (filename != NULL) { ! 631: promptlen += printf ("(Next file: %s)", filename); ! 632: } ! 633: else if (!no_intty) { ! 634: promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size)); ! 635: } ! 636: if (dum_opt) { ! 637: promptlen += pr("[Hit space to continue, Rubout to abort]"); ! 638: } ! 639: if (Senter && Sexit) ! 640: tputs (Sexit, 1, putch); ! 641: if (clreol) ! 642: clreos (); ! 643: fflush(stdout); ! 644: } ! 645: else ! 646: write (2, &bell, 1); ! 647: inwait++; ! 648: } ! 649: ! 650: /* ! 651: ** Get a logical line ! 652: */ ! 653: ! 654: getline(f, length) ! 655: register FILE *f; ! 656: int *length; ! 657: { ! 658: register int c; ! 659: register char *p; ! 660: register int column; ! 661: static int colflg; ! 662: ! 663: p = Line; ! 664: column = 0; ! 665: c = Getc (f); ! 666: if (colflg && c == '\n') { ! 667: Currline++; ! 668: c = Getc (f); ! 669: } ! 670: while (p < &Line[LINSIZ - 1]) { ! 671: if (c == EOF) { ! 672: if (p > Line) { ! 673: *p = '\0'; ! 674: *length = p - Line; ! 675: return (column); ! 676: } ! 677: *length = p - Line; ! 678: return (EOF); ! 679: } ! 680: if (c == '\n') { ! 681: Currline++; ! 682: break; ! 683: } ! 684: *p++ = c; ! 685: if (c == '\t') ! 686: if (hardtabs && column < promptlen && !hard) { ! 687: if (eraseln && !dumb) { ! 688: column = 1 + (column | 7); ! 689: tputs (eraseln, 1, putch); ! 690: promptlen = 0; ! 691: } ! 692: else { ! 693: for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) { ! 694: *p++ = ' '; ! 695: } ! 696: if (column >= promptlen) promptlen = 0; ! 697: } ! 698: } ! 699: else ! 700: column = 1 + (column | 7); ! 701: else if (c == '\b' && column > 0) ! 702: column--; ! 703: else if (c == '\r') ! 704: column = 0; ! 705: else if (c == '\f' && stop_opt) { ! 706: p[-1] = '^'; ! 707: *p++ = 'L'; ! 708: column += 2; ! 709: Pause++; ! 710: } ! 711: else if (c == EOF) { ! 712: *length = p - Line; ! 713: return (column); ! 714: } ! 715: else if (c >= ' ' && c != RUBOUT) ! 716: column++; ! 717: if (column >= Mcol && fold_opt) break; ! 718: c = Getc (f); ! 719: } ! 720: if (column >= Mcol && Mcol > 0) { ! 721: if (!Wrap) { ! 722: *p++ = '\n'; ! 723: } ! 724: } ! 725: colflg = column == Mcol && fold_opt; ! 726: *length = p - Line; ! 727: *p = 0; ! 728: return (column); ! 729: } ! 730: ! 731: /* ! 732: ** Erase the rest of the prompt, assuming we are starting at column col. ! 733: */ ! 734: ! 735: erase (col) ! 736: register int col; ! 737: { ! 738: ! 739: if (promptlen == 0) ! 740: return; ! 741: if (hard) { ! 742: putchar ('\n'); ! 743: } ! 744: else { ! 745: if (col == 0) ! 746: putchar ('\r'); ! 747: if (!dumb && eraseln) ! 748: tputs (eraseln, 1, putch); ! 749: else ! 750: for (col = promptlen - col; col > 0; col--) ! 751: putchar (' '); ! 752: } ! 753: promptlen = 0; ! 754: } ! 755: ! 756: /* ! 757: ** Erase the current line entirely ! 758: */ ! 759: ! 760: kill_line () ! 761: { ! 762: erase (0); ! 763: if (!eraseln || dumb) putchar ('\r'); ! 764: } ! 765: ! 766: /* ! 767: * force clear to end of line ! 768: */ ! 769: cleareol() ! 770: { ! 771: tputs(eraseln, 1, putch); ! 772: } ! 773: ! 774: clreos() ! 775: { ! 776: tputs(EodClr, 1, putch); ! 777: } ! 778: ! 779: /* ! 780: ** Print string and return number of characters ! 781: */ ! 782: ! 783: pr(s1) ! 784: char *s1; ! 785: { ! 786: register char *s; ! 787: register char c; ! 788: ! 789: for (s = s1; c = *s++; ) ! 790: putchar(c); ! 791: return (s - s1 - 1); ! 792: } ! 793: ! 794: ! 795: /* Print a buffer of n characters */ ! 796: ! 797: prbuf (s, n) ! 798: register char *s; ! 799: register int n; ! 800: { ! 801: char c; /* next ouput character */ ! 802: register int state; /* next output char's UL state */ ! 803: static int pstate = 0; /* current terminal UL state (off) */ ! 804: ! 805: while (--n >= 0) ! 806: if (!ul_opt) ! 807: putchar (*s++); ! 808: else { ! 809: if (n >= 2 && s[0] == '_' && s[1] == '\b') { ! 810: n -= 2; ! 811: s += 2; ! 812: c = *s++; ! 813: state = 1; ! 814: } else if (n >= 2 && s[1] == '\b' && s[2] == '_') { ! 815: n -= 2; ! 816: c = *s++; ! 817: s += 2; ! 818: state = 1; ! 819: } else { ! 820: c = *s++; ! 821: state = 0; ! 822: } ! 823: if (state != pstate) ! 824: tputs(state ? ULenter : ULexit, 1, putch); ! 825: pstate = state; ! 826: putchar(c); ! 827: if (state && *chUL) { ! 828: pr(chBS); ! 829: tputs(chUL, 1, putch); ! 830: } ! 831: } ! 832: } ! 833: ! 834: /* ! 835: ** Clear the screen ! 836: */ ! 837: ! 838: doclear() ! 839: { ! 840: if (Clear && !hard) { ! 841: tputs(Clear, 1, putch); ! 842: ! 843: /* Put out carriage return so that system doesn't ! 844: ** get confused by escape sequences when expanding tabs ! 845: */ ! 846: putchar ('\r'); ! 847: promptlen = 0; ! 848: } ! 849: } ! 850: ! 851: /* ! 852: * Go to home position ! 853: */ ! 854: home() ! 855: { ! 856: tputs(Home,1,putch); ! 857: } ! 858: ! 859: static int lastcmd, lastarg, lastp; ! 860: static int lastcolon; ! 861: char shell_line[132]; ! 862: ! 863: /* ! 864: ** Read a command and do it. A command consists of an optional integer ! 865: ** argument followed by the command character. Return the number of lines ! 866: ** to display in the next screenful. If there is nothing more to display ! 867: ** in the current file, zero is returned. ! 868: */ ! 869: ! 870: command (filename, f) ! 871: char *filename; ! 872: register FILE *f; ! 873: { ! 874: register int nlines; ! 875: register int retval; ! 876: register char c; ! 877: char colonch; ! 878: FILE *helpf; ! 879: int done; ! 880: char comchar, cmdbuf[80], *p; ! 881: ! 882: #define ret(val) retval=val;done++;break ! 883: ! 884: done = 0; ! 885: if (!errors) ! 886: prompt (filename); ! 887: else ! 888: errors = 0; ! 889: if (MBIT == RAW && slow_tty) { ! 890: otty.sg_flags |= MBIT; ! 891: stty(2, &otty); ! 892: } ! 893: for (;;) { ! 894: nlines = number (&comchar); ! 895: lastp = colonch = 0; ! 896: if (comchar == '.') { /* Repeat last command */ ! 897: lastp++; ! 898: comchar = lastcmd; ! 899: nlines = lastarg; ! 900: if (lastcmd == ':') ! 901: colonch = lastcolon; ! 902: } ! 903: lastcmd = comchar; ! 904: lastarg = nlines; ! 905: if (comchar == otty.sg_erase) { ! 906: kill_line (); ! 907: prompt (filename); ! 908: continue; ! 909: } ! 910: switch (comchar) { ! 911: case ':': ! 912: retval = colon (filename, colonch, nlines); ! 913: if (retval >= 0) ! 914: done++; ! 915: break; ! 916: case ' ': ! 917: case 'z': ! 918: if (nlines == 0) nlines = dlines; ! 919: else if (comchar == 'z') dlines = nlines; ! 920: ret (nlines); ! 921: case 'd': ! 922: case ctrl(D): ! 923: if (nlines != 0) nscroll = nlines; ! 924: ret (nscroll); ! 925: case RUBOUT: ! 926: case 'q': ! 927: case 'Q': ! 928: end_it (); ! 929: case 's': ! 930: case 'f': ! 931: if (nlines == 0) nlines++; ! 932: if (comchar == 'f') ! 933: nlines *= dlines; ! 934: putchar ('\r'); ! 935: erase (0); ! 936: printf ("\n"); ! 937: if (clreol) ! 938: cleareol (); ! 939: printf ("...skipping %d line", nlines); ! 940: if (nlines > 1) ! 941: pr ("s\n"); ! 942: else ! 943: pr ("\n"); ! 944: ! 945: if (clreol) ! 946: cleareol (); ! 947: pr ("\n"); ! 948: ! 949: while (nlines > 0) { ! 950: while ((c = Getc (f)) != '\n') ! 951: if (c == EOF) { ! 952: retval = 0; ! 953: done++; ! 954: goto endsw; ! 955: } ! 956: Currline++; ! 957: nlines--; ! 958: } ! 959: ret (dlines); ! 960: case '\n': ! 961: if (nlines != 0) ! 962: dlines = nlines; ! 963: else ! 964: nlines = 1; ! 965: ret (nlines); ! 966: case '\f': ! 967: if (!no_intty) { ! 968: doclear (); ! 969: Fseek (f, screen_start.chrctr); ! 970: Currline = screen_start.line; ! 971: ret (dlines); ! 972: } ! 973: else { ! 974: write (2, &bell, 1); ! 975: break; ! 976: } ! 977: case '\'': ! 978: if (!no_intty) { ! 979: kill_line (); ! 980: pr ("\n***Back***\n\n"); ! 981: Fseek (f, context.chrctr); ! 982: Currline = context.line; ! 983: ret (dlines); ! 984: } ! 985: else { ! 986: write (2, &bell, 1); ! 987: break; ! 988: } ! 989: case '=': ! 990: kill_line (); ! 991: promptlen = printd (Currline); ! 992: fflush (stdout); ! 993: break; ! 994: case 'n': ! 995: lastp++; ! 996: case '/': ! 997: if (nlines == 0) nlines++; ! 998: kill_line (); ! 999: pr ("/"); ! 1000: promptlen = 1; ! 1001: fflush (stdout); ! 1002: if (lastp) { ! 1003: write (2,"\r", 1); ! 1004: search (NULL, f, nlines); /* Use previous r.e. */ ! 1005: } ! 1006: else { ! 1007: ttyin (cmdbuf, 78, '/'); ! 1008: write (2, "\r", 1); ! 1009: search (cmdbuf, f, nlines); ! 1010: } ! 1011: ret (dlines-1); ! 1012: case '!': ! 1013: do_shell (filename); ! 1014: break; ! 1015: case 'h': ! 1016: if ((helpf = fopen (HELPFILE, "r")) == NULL) ! 1017: error ("Can't open help file"); ! 1018: if (noscroll) doclear (); ! 1019: copy_file (helpf); ! 1020: close (helpf); ! 1021: prompt (filename); ! 1022: break; ! 1023: case 'v': /* This case should go right before default */ ! 1024: if (!no_intty) { ! 1025: kill_line (); ! 1026: cmdbuf[0] = '+'; ! 1027: scanstr (Currline, &cmdbuf[1]); ! 1028: pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]); ! 1029: execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0); ! 1030: break; ! 1031: } ! 1032: default: ! 1033: write (2, &bell, 1); ! 1034: break; ! 1035: } ! 1036: if (done) break; ! 1037: } ! 1038: putchar ('\r'); ! 1039: endsw: ! 1040: inwait = 0; ! 1041: notell++; ! 1042: if (MBIT == RAW && slow_tty) { ! 1043: otty.sg_flags &= ~MBIT; ! 1044: stty(2, &otty); ! 1045: } ! 1046: return (retval); ! 1047: } ! 1048: ! 1049: char ch; ! 1050: ! 1051: /* ! 1052: * Execute a colon-prefixed command. ! 1053: * Returns <0 if not a command that should cause ! 1054: * more of the file to be printed. ! 1055: */ ! 1056: ! 1057: colon (filename, cmd, nlines) ! 1058: char *filename; ! 1059: int cmd; ! 1060: int nlines; ! 1061: { ! 1062: if (cmd == 0) ! 1063: ch = readch (); ! 1064: else ! 1065: ch = cmd; ! 1066: lastcolon = ch; ! 1067: switch (ch) { ! 1068: case 'f': ! 1069: kill_line (); ! 1070: if (!no_intty) ! 1071: promptlen = printf ("\"%s\" line %d", fnames[fnum], Currline); ! 1072: else ! 1073: promptlen = printf ("[Not a file] line %d", Currline); ! 1074: fflush (stdout); ! 1075: return (-1); ! 1076: case 'n': ! 1077: if (nlines == 0) { ! 1078: if (fnum >= nfiles - 1) ! 1079: end_it (); ! 1080: nlines++; ! 1081: } ! 1082: putchar ('\r'); ! 1083: erase (0); ! 1084: skipf (nlines); ! 1085: return (0); ! 1086: case 'p': ! 1087: if (no_intty) { ! 1088: write (2, &bell, 1); ! 1089: return (-1); ! 1090: } ! 1091: putchar ('\r'); ! 1092: erase (0); ! 1093: if (nlines == 0) ! 1094: nlines++; ! 1095: skipf (-nlines); ! 1096: return (0); ! 1097: case '!': ! 1098: do_shell (filename); ! 1099: return (-1); ! 1100: case 'q': ! 1101: case 'Q': ! 1102: end_it (); ! 1103: default: ! 1104: write (2, &bell, 1); ! 1105: return (-1); ! 1106: } ! 1107: } ! 1108: ! 1109: /* ! 1110: ** Read a decimal number from the terminal. Set cmd to the non-digit which ! 1111: ** terminates the number. ! 1112: */ ! 1113: ! 1114: number(cmd) ! 1115: char *cmd; ! 1116: { ! 1117: register int i; ! 1118: ! 1119: i = 0; ch = otty.sg_kill; ! 1120: for (;;) { ! 1121: ch = readch (); ! 1122: if (ch >= '0' && ch <= '9') ! 1123: i = i*10 + ch - '0'; ! 1124: else if (ch == otty.sg_kill) ! 1125: i = 0; ! 1126: else { ! 1127: *cmd = ch; ! 1128: break; ! 1129: } ! 1130: } ! 1131: return (i); ! 1132: } ! 1133: ! 1134: do_shell (filename) ! 1135: char *filename; ! 1136: { ! 1137: char cmdbuf[80]; ! 1138: ! 1139: kill_line (); ! 1140: pr ("!"); ! 1141: fflush (stdout); ! 1142: promptlen = 1; ! 1143: if (lastp) ! 1144: pr (shell_line); ! 1145: else { ! 1146: ttyin (cmdbuf, 78, '!'); ! 1147: if (expand (shell_line, cmdbuf)) { ! 1148: kill_line (); ! 1149: promptlen = printf ("!%s", shell_line); ! 1150: } ! 1151: } ! 1152: fflush (stdout); ! 1153: write (2, "\n", 1); ! 1154: promptlen = 0; ! 1155: shellp = 1; ! 1156: execute (filename, shell, shell, "-c", shell_line, 0); ! 1157: } ! 1158: ! 1159: /* ! 1160: ** Search for nth ocurrence of regular expression contained in buf in the file ! 1161: */ ! 1162: ! 1163: search (buf, file, n) ! 1164: char buf[]; ! 1165: FILE *file; ! 1166: register int n; ! 1167: { ! 1168: long startline = Ftell (file); ! 1169: register long line1 = startline; ! 1170: register long line2 = startline; ! 1171: register long line3 = startline; ! 1172: register int lncount; ! 1173: int saveln, rv, re_exec(); ! 1174: char *s, *re_comp(); ! 1175: ! 1176: context.line = saveln = Currline; ! 1177: context.chrctr = startline; ! 1178: lncount = 0; ! 1179: if ((s = re_comp (buf)) != 0) ! 1180: error (s); ! 1181: while (!feof (file)) { ! 1182: line3 = line2; ! 1183: line2 = line1; ! 1184: line1 = Ftell (file); ! 1185: rdline (file); ! 1186: lncount++; ! 1187: if ((rv = re_exec (Line)) == 1) ! 1188: if (--n == 0) { ! 1189: if (lncount > 3 || (lncount > 1 && no_intty)) ! 1190: { ! 1191: pr ("\n"); ! 1192: if (clreol) ! 1193: cleareol (); ! 1194: pr("...skipping\n"); ! 1195: } ! 1196: if (!no_intty) { ! 1197: Currline -= (lncount >= 3 ? 3 : lncount); ! 1198: Fseek (file, line3); ! 1199: if (noscroll) ! 1200: if (clreol) { ! 1201: home (); ! 1202: cleareol (); ! 1203: } ! 1204: else ! 1205: doclear (); ! 1206: } ! 1207: else { ! 1208: kill_line (); ! 1209: if (noscroll) ! 1210: if (clreol) { ! 1211: home (); ! 1212: cleareol (); ! 1213: } ! 1214: else ! 1215: doclear (); ! 1216: pr (Line); ! 1217: putchar ('\n'); ! 1218: } ! 1219: break; ! 1220: } ! 1221: else if (rv == -1) ! 1222: error ("Regular expression botch"); ! 1223: } ! 1224: if (feof (file)) { ! 1225: if (!no_intty) { ! 1226: file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */ ! 1227: Currline = saveln; ! 1228: Fseek (file, startline); ! 1229: } ! 1230: else { ! 1231: pr ("\nPattern not found\n"); ! 1232: end_it (); ! 1233: } ! 1234: error ("Pattern not found"); ! 1235: } ! 1236: } ! 1237: ! 1238: execute (filename, cmd, args) ! 1239: char *filename; ! 1240: char *cmd, *args; ! 1241: { ! 1242: int id; ! 1243: ! 1244: fflush (stdout); ! 1245: reset_tty (); ! 1246: while ((id = fork ()) < 0) ! 1247: sleep (5); ! 1248: if (id == 0) { ! 1249: execv (cmd, &args); ! 1250: write (2, "exec failed\n", 12); ! 1251: exit (1); ! 1252: } ! 1253: signal (SIGINT, SIG_IGN); ! 1254: signal (SIGQUIT, SIG_IGN); ! 1255: if (catch_susp) ! 1256: signal(SIGTSTP, SIG_DFL); ! 1257: wait (0); ! 1258: signal (SIGINT, end_it); ! 1259: signal (SIGQUIT, onquit); ! 1260: if (catch_susp) ! 1261: signal(SIGTSTP, onsusp); ! 1262: set_tty (); ! 1263: pr ("------------------------\n"); ! 1264: prompt (filename); ! 1265: } ! 1266: /* ! 1267: ** Skip n lines in the file f ! 1268: */ ! 1269: ! 1270: skiplns (n, f) ! 1271: register int n; ! 1272: register FILE *f; ! 1273: { ! 1274: register char c; ! 1275: ! 1276: while (n > 0) { ! 1277: while ((c = Getc (f)) != '\n') ! 1278: if (c == EOF) ! 1279: return; ! 1280: n--; ! 1281: Currline++; ! 1282: } ! 1283: } ! 1284: ! 1285: /* ! 1286: ** Skip nskip files in the file list (from the command line). Nskip may be ! 1287: ** negative. ! 1288: */ ! 1289: ! 1290: skipf (nskip) ! 1291: register int nskip; ! 1292: { ! 1293: if (nskip == 0) return; ! 1294: if (nskip > 0) { ! 1295: if (fnum + nskip > nfiles - 1) ! 1296: nskip = nfiles - fnum - 1; ! 1297: } ! 1298: else if (within) ! 1299: ++fnum; ! 1300: fnum += nskip; ! 1301: if (fnum < 0) ! 1302: fnum = 0; ! 1303: pr ("\n...Skipping "); ! 1304: pr ("\n"); ! 1305: if (clreol) ! 1306: cleareol (); ! 1307: pr ("...Skipping "); ! 1308: pr (nskip > 0 ? "to file " : "back to file "); ! 1309: pr (fnames[fnum]); ! 1310: pr ("\n"); ! 1311: if (clreol) ! 1312: cleareol (); ! 1313: pr ("\n"); ! 1314: --fnum; ! 1315: } ! 1316: ! 1317: /*----------------------------- Terminal I/O -------------------------------*/ ! 1318: ! 1319: initterm () ! 1320: { ! 1321: char buf[TBUFSIZ]; ! 1322: char clearbuf[100]; ! 1323: char *clearptr, *padstr; ! 1324: int ldisc; ! 1325: char *term; ! 1326: ! 1327: setbuf(stdout, obuf); ! 1328: if (!(no_tty = gtty(1, &otty))) { ! 1329: if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) { ! 1330: dumb++; ul_opt = 0; ! 1331: } ! 1332: else { ! 1333: if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) { ! 1334: hard++; /* Hard copy terminal */ ! 1335: Lpp = 24; ! 1336: } ! 1337: if (tailequ (fnames[0], "page") || !hard && tgetflag("ns")) ! 1338: noscroll++; ! 1339: if ((Mcol = tgetnum("co")) < 0) ! 1340: Mcol = 80; ! 1341: Wrap = tgetflag("am"); ! 1342: bad_so = tgetflag ("xs"); ! 1343: clearptr = clearbuf; ! 1344: eraseln = tgetstr("ce",&clearptr); ! 1345: Clear = tgetstr("cl", &clearptr); ! 1346: Senter = tgetstr("so", &clearptr); ! 1347: Sexit = tgetstr("se", &clearptr); ! 1348: ! 1349: /* ! 1350: * Set up for underlining: some terminals don't need it; ! 1351: * others have start/stop sequences, still others have an ! 1352: * underline char sequence which is assumed to move the ! 1353: * cursor forward one character. If underline sequence ! 1354: * isn't available, settle for standout sequence. ! 1355: */ ! 1356: ! 1357: if (tgetflag("ul") || tgetflag("os")) ! 1358: ul_opt = 0; ! 1359: if ((chUL = tgetstr("uc", &clearptr)) == NULL ) ! 1360: chUL = ""; ! 1361: if ((ULenter = tgetstr("us", &clearptr)) == NULL && ! 1362: (!*chUL) && (ULenter = tgetstr("so", &clearptr)) == NULL) ! 1363: ULenter = ""; ! 1364: if ((ULexit = tgetstr("ue", &clearptr)) == NULL && ! 1365: (!*chUL) && (ULexit = tgetstr("se", &clearptr)) == NULL) ! 1366: ULexit = ""; ! 1367: ! 1368: if (padstr = tgetstr("pc", &clearptr)) ! 1369: PC = *padstr; ! 1370: Home = tgetstr("ho",&clearptr); ! 1371: if (Home == 0 || *Home == '\0') ! 1372: { ! 1373: if ((cursorm = tgetstr("cm", &clearptr)) != NULL) { ! 1374: strcpy(cursorhome, tgoto(cursorm, 0, 0)); ! 1375: Home = cursorhome; ! 1376: } ! 1377: } ! 1378: EodClr = tgetstr("cd", &clearptr); ! 1379: } ! 1380: if ((shell = getenv("SHELL")) == NULL) ! 1381: shell = "/bin/sh"; ! 1382: } ! 1383: no_intty = gtty(0, &otty); ! 1384: gtty(2, &otty); ! 1385: savetty = otty; ! 1386: ospeed = otty.sg_ospeed; ! 1387: slow_tty = ospeed < B1200; ! 1388: hardtabs = !(otty.sg_flags & XTABS); ! 1389: if (!no_tty) { ! 1390: otty.sg_flags &= ~ECHO; ! 1391: if (MBIT == CBREAK || !slow_tty) ! 1392: otty.sg_flags |= MBIT; ! 1393: } ! 1394: } ! 1395: ! 1396: readch () ! 1397: { ! 1398: char ch; ! 1399: extern int errno; ! 1400: ! 1401: if (read (2, &ch, 1) <= 0) ! 1402: if (errno != EINTR) ! 1403: exit(0); ! 1404: else ! 1405: ch = otty.sg_kill; ! 1406: return (ch); ! 1407: } ! 1408: ! 1409: static char BS = '\b'; ! 1410: static char CARAT = '^'; ! 1411: ! 1412: ttyin (buf, nmax, pchar) ! 1413: char buf[]; ! 1414: register int nmax; ! 1415: char pchar; ! 1416: { ! 1417: register char *sptr; ! 1418: register char ch; ! 1419: register int slash = 0; ! 1420: int maxlen; ! 1421: char cbuf; ! 1422: ! 1423: sptr = buf; ! 1424: maxlen = 0; ! 1425: while (sptr - buf < nmax) { ! 1426: if (promptlen > maxlen) maxlen = promptlen; ! 1427: ch = readch (); ! 1428: if (ch == '\\') { ! 1429: slash++; ! 1430: } ! 1431: else if ((ch == otty.sg_erase) && !slash) { ! 1432: if (sptr > buf) { ! 1433: --promptlen; ! 1434: write (2, &BS, 1); ! 1435: --sptr; ! 1436: if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) { ! 1437: --promptlen; ! 1438: write (2, &BS, 1); ! 1439: } ! 1440: continue; ! 1441: } ! 1442: else { ! 1443: if (!eraseln) promptlen = maxlen; ! 1444: longjmp (restore, 1); ! 1445: } ! 1446: } ! 1447: else if ((ch == otty.sg_kill) && !slash) { ! 1448: if (hard) { ! 1449: show (ch); ! 1450: putchar ('\n'); ! 1451: putchar (pchar); ! 1452: } ! 1453: else { ! 1454: putchar ('\r'); ! 1455: putchar (pchar); ! 1456: if (eraseln) ! 1457: erase (1); ! 1458: promptlen = 1; ! 1459: } ! 1460: sptr = buf; ! 1461: fflush (stdout); ! 1462: continue; ! 1463: } ! 1464: if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) { ! 1465: write (2, &BS, 1); ! 1466: --sptr; ! 1467: } ! 1468: if (ch != '\\') ! 1469: slash = 0; ! 1470: *sptr++ = ch; ! 1471: if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { ! 1472: ch += ch == RUBOUT ? -0100 : 0100; ! 1473: write (2, &CARAT, 1); ! 1474: promptlen++; ! 1475: } ! 1476: cbuf = ch; ! 1477: if (ch != '\n' && ch != ESC) { ! 1478: write (2, &cbuf, 1); ! 1479: promptlen++; ! 1480: } ! 1481: else ! 1482: break; ! 1483: } ! 1484: *--sptr = '\0'; ! 1485: if (!eraseln) promptlen = maxlen; ! 1486: if (sptr - buf >= nmax - 1) ! 1487: error ("Line too long"); ! 1488: } ! 1489: ! 1490: expand (outbuf, inbuf) ! 1491: char *outbuf; ! 1492: char *inbuf; ! 1493: { ! 1494: register char *instr; ! 1495: register char *outstr; ! 1496: register char ch; ! 1497: char temp[200]; ! 1498: int changed = 0; ! 1499: ! 1500: instr = inbuf; ! 1501: outstr = temp; ! 1502: while ((ch = *instr++) != '\0') ! 1503: switch (ch) { ! 1504: case '%': ! 1505: if (!no_intty) { ! 1506: strcpy (outstr, fnames[fnum]); ! 1507: outstr += strlen (fnames[fnum]); ! 1508: changed++; ! 1509: } ! 1510: else ! 1511: *outstr++ = ch; ! 1512: break; ! 1513: case '!': ! 1514: if (!shellp) ! 1515: error ("No previous command to substitute for"); ! 1516: strcpy (outstr, shell_line); ! 1517: outstr += strlen (shell_line); ! 1518: changed++; ! 1519: break; ! 1520: case '\\': ! 1521: if (*instr == '%' || *instr == '!') { ! 1522: *outstr++ = *instr++; ! 1523: break; ! 1524: } ! 1525: default: ! 1526: *outstr++ = ch; ! 1527: } ! 1528: *outstr++ = '\0'; ! 1529: strcpy (outbuf, temp); ! 1530: return (changed); ! 1531: } ! 1532: ! 1533: show (ch) ! 1534: register char ch; ! 1535: { ! 1536: char cbuf; ! 1537: ! 1538: if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { ! 1539: ch += ch == RUBOUT ? -0100 : 0100; ! 1540: write (2, &CARAT, 1); ! 1541: promptlen++; ! 1542: } ! 1543: cbuf = ch; ! 1544: write (2, &cbuf, 1); ! 1545: promptlen++; ! 1546: } ! 1547: ! 1548: error (mess) ! 1549: char *mess; ! 1550: { ! 1551: if (clreol) ! 1552: cleareol (); ! 1553: else ! 1554: kill_line (); ! 1555: promptlen += strlen (mess); ! 1556: if (Senter && Sexit) { ! 1557: tputs (Senter, 1, putch); ! 1558: pr(mess); ! 1559: tputs (Sexit, 1, putch); ! 1560: } ! 1561: else ! 1562: pr (mess); ! 1563: fflush(stdout); ! 1564: errors++; ! 1565: longjmp (restore, 1); ! 1566: } ! 1567: ! 1568: ! 1569: set_tty () ! 1570: { ! 1571: otty.sg_flags |= MBIT; ! 1572: otty.sg_flags &= ~ECHO; ! 1573: stty(2, &otty); ! 1574: } ! 1575: ! 1576: reset_tty () ! 1577: { ! 1578: otty.sg_flags |= ECHO; ! 1579: otty.sg_flags &= ~MBIT; ! 1580: stty(2, &savetty); ! 1581: } ! 1582: ! 1583: rdline (f) ! 1584: register FILE *f; ! 1585: { ! 1586: register char c; ! 1587: register char *p; ! 1588: ! 1589: p = Line; ! 1590: while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) ! 1591: *p++ = c; ! 1592: if (c == '\n') ! 1593: Currline++; ! 1594: *p = '\0'; ! 1595: } ! 1596: ! 1597: /* Come here when we get a suspend signal from the terminal */ ! 1598: ! 1599: onsusp () ! 1600: { ! 1601: /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ ! 1602: signal(SIGTTOU, SIG_IGN); ! 1603: reset_tty (); ! 1604: fflush (stdout); ! 1605: signal(SIGTTOU, SIG_DFL); ! 1606: /* Send the TSTP signal to suspend our process group */ ! 1607: signal(SIGTSTP, SIG_DFL); ! 1608: sigsetmask(0); ! 1609: kill (0, SIGTSTP); ! 1610: /* Pause for station break */ ! 1611: ! 1612: /* We're back */ ! 1613: signal (SIGTSTP, onsusp); ! 1614: set_tty (); ! 1615: if (inwait) ! 1616: longjmp (restore); ! 1617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.