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