cmd/boot: usr/src/cmd/boot build needs cleanup
[unleashed.git] / usr / src / cmd / more / more.c
blob7a806af0b696424a64e3541bca76366b4aacbf29
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 /* Copyright (c) 1987, 1988 Microsoft Corporation */
30 /* All Rights Reserved */
33 * University Copyright- Copyright (c) 1982, 1986, 1988
34 * The Regents of the University of California
35 * All Rights Reserved
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
39 * contributors.
43 * @(#) more.c 1.1 88/03/29 more:more.c
47 ** more.c - General purpose tty output filter and file perusal program
49 ** by Eric Shienbrood, UC Berkeley
51 ** modified by Geoff Peck, UCB to add underlining, single spacing
52 ** modified by John Foderaro, UCB to add -c and MORE environment variable
53 ** modified by Hans Spiller, Microsoft to handle \r better July 23, 82
54 ** added ? help command, and -w
56 ** vwh 11 Jan 83 M001
57 ** modified to handle x.out magic number and magic number
58 ** byte ordering OTHER than the vax and pdp11.
59 ** JJD 19 Jan 83 M002
60 ** - fix distributed on USENET
61 ** From decvax!ucbvax!dist2 Sun Dec 6 02:58:31 1981
62 ** Subject: FIXED: bug in src/more/more.c
63 ** - fixed bug on terminal with "magic cookie" standout
64 ** sequences.
65 ** JJD 14 Feb 83 M003
66 ** - fix exit status of more
67 ** - Made first letter of "no more" message uppercase
68 ** andyp 03 Aug 83 M004 3.0 upgrade
69 ** - moved <local/uparm.h> to cmd/include.
70 ** - use UCB, rather than XENIX, stty(2).
71 ** andyp 30 Nov 83 M005
72 ** - (thanks to reubenb). Changed frame variable to static, it is
73 ** used as a global buffer. We never saw the bug before because
74 ** of the depth of the stack.
75 ** barrys 03 Jul 84 M006
76 ** - Updated the usage message to include the 's' and 'w' options
77 ** and to make the 'n' option a separate entry (uncommented).
78 ** ericc 26 Dec 84 M007
79 ** - Replaced the constant 0x7fffffffffffffffL with MAXLONG.
80 ** ericc 25 Jul 85 M008
81 ** - made "-r" option display control characters as '^x', as documented.
82 ** - fixed processing of '\b' so that more doesn't terminate when
83 ** the sequence "\b\n" is encountered.
84 ** - changed "Hit Rubout ..." to "Hit Del ...", for ibm keyboards.
85 ** davidby 9 March 1988 Unmarked
86 ** - replaced all locally defined functions with library equivalents,
87 ** - changed from termcap to terminfo
88 ** - included <values.h> for MAXLONG value
89 ** - removed most ifdef code for V6, V7, and BSD
90 ** - added /etc/magic support for file type checking
93 #include <ctype.h>
94 #include <signal.h>
95 #include <errno.h>
96 #include <sys/types.h>
97 #include <sys/wait.h>
98 #include <curses.h>
99 #include <term.h>
100 #include <sys/ioctl.h>
101 #include <setjmp.h>
102 #include <sys/stat.h>
103 #include <values.h>
104 #include <stdlib.h>
105 #include <stdarg.h>
106 #include <string.h>
107 #include <unistd.h>
108 #include <libgen.h>
109 #include <euc.h>
110 #include <getwidth.h>
111 #include <locale.h>
112 #include <widec.h>
113 #include <wctype.h>
114 #include <limits.h>
115 eucwidth_t wp;
116 int cw[4];
117 int scw[4];
118 #include <locale.h>
120 /* Help file will eventually go in libpath(more.help) on all systems */
122 #ifdef INGRES
123 #define VI "/usr/bin/vi"
124 #define HELPFILE "/mntp/doucette/more/more.help"
125 #define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
126 #endif
128 #ifndef INGRES
129 #ifndef HELPFILE
130 #define HELPFILE "/usr/lib/more.help"
131 #define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
132 #endif
133 #define VI "vi"
134 #endif
136 #define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m))
137 #define Ftell(f) file_pos
138 #define Fseek(f,off) (file_pos=off,fseeko(f,off,0))
139 #define Getc(f) (++file_pos, getc(f))
140 #define Ungetc(c,f) (--file_pos, ungetc(c,f))
142 #define pr(s1) fputs(s1, stdout)
143 #define clreos() putp(clr_eos)
144 #define cleareol() putp(clr_eol)
145 #define home() putp(cursor_home)
147 #define LINSIZ 512
148 #define ctrl(letter) ((letter) & 077)
149 #define RUBOUT '\177'
150 #define ESC '\033'
151 #define QUIT '\034'
153 struct termio otty; /* old tty modes */
154 struct termio ntty; /* new tty modes */
155 off_t file_pos, file_size;
156 int fnum, no_intty, no_tty;
157 int dum_opt;
158 off_t dlines;
159 void end_it(int sig);
160 void onquit(int sig);
161 void chgwinsz(int sig);
162 #ifdef SIGTSTP
163 void onsusp(int sig);
164 #endif
165 int nscroll = 11; /* Number of lines scrolled by 'd' */
166 int fold_opt = 1; /* Fold long lines */
167 int stop_opt = 1; /* Stop after form feeds */
168 int ssp_opt = 0; /* Suppress white space */
169 int ul_opt = 1; /* Underline as best we can */
170 int cr_opt = 0; /* show ctrl characters as '^c' */
171 int wait_opt = 0; /* prompt for exit at eof */
172 int promptlen;
173 off_t Currline; /* Line we are currently at */
174 int startup = 1;
175 int firstf = 1;
176 int notell = 1;
177 int inwait, Pause, errors;
178 int within; /* true if we are within a file,
179 false if we are between files */
180 int hard, dumb, noscroll, hardtabs, clreol;
181 int catch_susp; /* We should catch the SIGTSTP signal */
182 char **fnames; /* The list of file names */
183 int nfiles; /* Number of files left to process */
184 char *shell; /* The name of the shell to use */
185 int shellp; /* A previous shell command exists */
186 char ch;
187 jmp_buf restore;
188 char obuf[BUFSIZ]; /* stdout buffer */
189 char Line[LINSIZ]; /* Line buffer */
190 int Lpp = 24; /* lines per page */
191 char *ULenter, *ULexit; /* enter and exit underline mode */
192 int Mcol = 80; /* number of columns */
193 int Wrap = 1; /* set if automargins */
194 int fseeko();
195 struct {
196 off_t chrctr, line;
197 } context, screen_start;
198 int exitstat = 0; /* status to use when exiting more */ /*M003*/
200 static void execute(char *filename, char *cmd, ...);
201 static void error(char *mess);
202 static void wait_eof(void);
203 static void prompt(char *filename);
204 static void argscan(char *s);
205 static void copy_file(register FILE *f);
206 static void initterm(void);
207 static void do_shell(char *filename);
208 static FILE *checkf(register char *fs, int *clearfirst);
209 static void screen(register FILE *f, register off_t num_lines);
210 static void skiplns(register off_t n, register FILE *f);
211 static void skipf(register int nskip);
212 static int readch(void);
213 static void prmpt_erase(register int col);
214 static void kill_line(void);
215 static void prbuf(register char *s, register int n);
216 static void search(char buf[], FILE *file, register off_t n);
217 static void doclear(void);
218 static void ttyin(char buf[], register int nmax, char pchar);
219 static int expand(char *outbuf, char *inbuf);
220 static void show(register char ch);
221 static void set_tty(void);
222 static void reset_tty(void);
223 static void rdline(register FILE *f);
224 static off_t command(char *filename, register FILE *f);
225 static int getaline(register FILE *f, int *length);
226 static int number(char *cmd);
227 static int colon(char *filename, int cmd, off_t nlines);
230 main(int argc, char *argv[])
232 register FILE *f;
233 register char *s;
234 register char *p;
235 register int ch;
236 register off_t left;
237 int prnames = 0;
238 int initopt = 0;
239 int srchopt = 0;
240 int clearit = 0;
241 off_t initline;
242 char initbuf[80];
244 setlocale( LC_ALL, "" );
245 getwidth(&wp);
246 cw[0] = 1;
247 cw[1] = wp._eucw1;
248 cw[2] = wp._eucw2+1;
249 cw[3] = wp._eucw3+1;
250 scw[0] = 1;
251 scw[1] = wp._scrw1;
252 scw[2] = wp._scrw2;
253 scw[3] = wp._scrw3;
255 nfiles = argc;
256 fnames = argv;
258 (void) setlocale(LC_ALL,"");
259 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
260 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
261 #endif
262 (void) textdomain(TEXT_DOMAIN);
264 initterm ();
265 if(s = getenv("MORE")) argscan(s);
266 while (--nfiles > 0) {
267 if ((ch = (*++fnames)[0]) == '-') {
268 argscan(*fnames+1);
270 else if (ch == '+') {
271 s = *fnames;
272 if (*++s == '/') {
273 srchopt++;
274 for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';)
275 *p++ = *s++;
276 *p = '\0';
278 else {
279 initopt++;
280 for (initline = 0; *s != '\0'; s++)
281 if (isdigit (*s))
282 initline = initline*10 + *s -'0';
283 --initline;
286 else break;
288 /* allow clreol only if cursor_home and clr_eol and clr_eos strings are
289 * defined, and in that case, make sure we are in noscroll mode
291 if(clreol)
293 if (!cursor_home || !clr_eol || !clr_eos) {
294 clreol = 0;
296 else noscroll = 1;
299 if (dlines == 0)
300 dlines =(off_t) (Lpp - (noscroll ? 1 : 2));
301 left = dlines;
302 if (nfiles > 1)
303 prnames++;
304 if (!no_intty && nfiles == 0) {
305 fprintf(stderr, gettext("Usage: %s\
306 [-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename ...].\n")
307 , argv[0]);
308 exit(1);
310 else
311 f = stdin;
312 if (!no_tty) {
313 signal(SIGQUIT, onquit);
314 signal(SIGINT, end_it);
315 signal(SIGWINCH, chgwinsz);
316 #ifdef SIGTSTP
317 if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
318 signal(SIGTSTP, onsusp);
319 catch_susp++;
321 #endif
322 set_tty();
324 if (no_intty) {
325 if (no_tty)
326 copy_file (stdin);
327 else {
328 if ((ch = Getc (f)) == '\f')
329 doclear();
330 else {
331 Ungetc (ch, f);
332 if (noscroll && (ch != EOF)) {
333 if (clreol)
334 home ();
335 else
336 doclear ();
339 if (!setjmp(restore)) {
340 if (srchopt) {
341 search (initbuf, stdin,(off_t) 1);
342 if (noscroll)
343 left--;
345 else if (initopt)
346 skiplns (initline, stdin);
348 else
349 left = command(NULL, f);
350 screen (stdin, left);
352 no_intty = 0;
353 prnames++;
354 firstf = 0;
357 while (fnum < nfiles) {
358 if ((f = checkf (fnames[fnum], &clearit)) != NULL) {
359 context.line = context.chrctr = 0;
360 Currline = 0;
361 if (firstf) setjmp (restore);
362 if (firstf) {
363 firstf = 0;
364 if (srchopt)
366 search (initbuf, f,(off_t) 1);
367 if (noscroll)
368 left--;
370 else if (initopt)
371 skiplns (initline, f);
373 else if (fnum < nfiles && !no_tty) {
374 setjmp (restore);
375 left = command (fnames[fnum], f);
377 if (left != 0) {
378 if ((noscroll || clearit) && (file_size != LLONG_MAX))
379 if (clreol)
380 home ();
381 else
382 doclear ();
383 if (prnames) {
384 if (ceol_standout_glitch)
385 prmpt_erase (0);
386 if (clreol)
387 cleareol ();
388 pr("::::::::::::::");
389 if (promptlen > 14)
390 prmpt_erase (14);
391 printf ("\n");
392 if(clreol) cleareol();
393 printf("%s\n", fnames[fnum]);
394 if(clreol) cleareol();
395 pr("::::::::::::::\n");
396 if (left > (off_t)(Lpp - 4))
397 left =(off_t)(Lpp - 4);
399 if (no_tty)
400 copy_file (f);
401 else {
402 within++;
403 screen(f, left);
404 within = 0;
407 setjmp (restore);
408 fflush(stdout);
409 fclose(f);
410 screen_start.line = screen_start.chrctr = 0LL;
411 context.line = context.chrctr = 0LL;
412 } else
413 exitstat |= 1; /*M003*/
414 fnum++;
415 firstf = 0;
417 if (wait_opt) wait_eof();
418 reset_tty ();
419 return (exitstat); /*M003*/
422 static void
423 argscan(char *s)
425 for (dlines = 0; *s != '\0'; s++)
426 if (isdigit(*s))
427 dlines = dlines*10 + *s - '0';
428 else if (*s == 'd')
429 dum_opt = 1;
430 else if (*s == 'l')
431 stop_opt = 0;
432 else if (*s == 'f')
433 fold_opt = 0;
434 else if (*s == 'p')
435 noscroll++;
436 else if (*s == 'c')
437 clreol++;
438 else if (*s == 's')
439 ssp_opt = 1;
440 else if (*s == 'u')
441 ul_opt = 0;
442 else if (*s == 'r')
443 cr_opt = 1;
444 else if (*s == 'w')
445 wait_opt = 1;
450 ** Check whether the file named by fs is a file which the user may
451 ** access. If it is, return the opened file. Otherwise return NULL.
454 static FILE *
455 checkf(register char *fs, int *clearfirst)
457 struct stat stbuf;
458 register FILE *f;
459 int c;
461 if (stat (fs, &stbuf) == -1) {
462 fflush(stdout);
463 if (clreol)
464 cleareol ();
465 perror(fs);
466 return (NULL);
468 if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
469 printf(gettext("\n*** %s: directory ***\n\n"), fs);
470 return (NULL);
472 if ((f=Fopen(fs, "r")) == NULL) {
473 fflush(stdout);
474 perror(fs);
475 return (NULL);
478 if ((c = Getc(f)) == '\f') /* end M001 */
479 *clearfirst = 1;
480 else {
481 *clearfirst = 0;
482 Ungetc (c, f);
484 if ((file_size = (off_t)stbuf.st_size) == 0)
485 file_size = LLONG_MAX;
486 return (f);
490 ** Print out the contents of the file f, one screenful at a time.
493 #define STOP -10
495 static void
496 screen(register FILE *f, register off_t num_lines)
498 register int c;
499 register int nchars;
500 int length; /* length of current line */
501 static int prev_len = 1; /* length of previous line */
503 for (;;) {
504 while (num_lines > 0 && !Pause) {
505 if ((nchars = getaline (f, &length)) == EOF)
507 if (clreol) clreos();
508 return;
510 if (ssp_opt && length == 0 && prev_len == 0)
511 continue;
512 prev_len = length;
513 if (ceol_standout_glitch ||
514 (enter_standout_mode && *enter_standout_mode == ' ')
515 && promptlen > 0)
516 prmpt_erase (0);
517 /* must clear before drawing line since tabs on some terminals
518 * do not erase what they tab over.
520 if (clreol)
521 cleareol ();
522 prbuf (Line, length);
523 if (nchars < promptlen)
524 prmpt_erase (nchars); /* prmpt_erase () sets promptlen to 0 */
525 else promptlen = 0;
526 /* is this needed?
527 * if (clreol)
528 * cleareol(); */ /* must clear again in case we wrapped */
530 if (nchars < Mcol || !fold_opt)
531 putchar('\n');
532 if (nchars == STOP)
533 break;
534 num_lines--;
536 fflush(stdout);
537 if ((c = Getc(f)) == EOF)
539 if (clreol) clreos ();
540 return;
543 if (Pause && clreol)
544 clreos ();
545 Ungetc (c, f);
546 setjmp (restore);
547 Pause = 0; startup = 0;
548 if ((num_lines = command (NULL, f)) == 0)
549 return;
550 if (hard && promptlen > 0)
551 prmpt_erase (0);
552 if (noscroll && num_lines == dlines) {
553 if (clreol)
554 home();
555 else
556 doclear ();
558 screen_start.line = Currline;
559 screen_start.chrctr = Ftell (f);
564 ** Come here if a quit signal is received
567 * sig is put in as a dummy arg to have the compiler not to complain
570 /* ARGSUSED */
571 void
572 onquit(int sig)
574 signal(SIGQUIT, SIG_IGN);
575 if (!inwait) {
576 putchar ('\n');
577 if (!startup) {
578 signal(SIGQUIT, onquit);
579 longjmp (restore, 1);
581 else
582 Pause++;
584 else if (!dum_opt && notell) {
585 write (2, gettext("[Use q or Q to quit]"), 20);
586 promptlen += 20;
587 notell = 0;
589 signal(SIGQUIT, onquit);
593 ** Come here if a signal for a window size change is received
595 /*ARGSUSED*/
596 void
597 chgwinsz(int sig)
599 struct winsize win;
601 (void) signal(SIGWINCH, SIG_IGN);
602 if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
603 if (win.ws_row != 0) {
604 Lpp = win.ws_row;
605 nscroll = Lpp/2 - 1;
606 if (nscroll <= 0)
607 nscroll = 1;
608 dlines = (off_t)(Lpp - (noscroll ? 1 : 2));
610 if (win.ws_col != 0)
611 Mcol = win.ws_col;
613 (void) signal(SIGWINCH, chgwinsz);
617 ** Clean up terminal state and exit. Also come here if interrupt signal received
621 * sig is put in as a dummy arg to have the compiler not to complain
624 /* ARGSUSED */
625 void
626 end_it(int sig)
629 reset_tty ();
630 if (clreol) {
631 putchar ('\r');
632 clreos ();
633 fflush (stdout);
635 else if (!clreol && (promptlen > 0)) {
636 kill_line ();
637 fflush (stdout);
639 else
640 write (2, "\n", 1);
641 _exit(exitstat); /*M003*/
644 static void
645 copy_file(register FILE *f)
647 register int c;
649 while ((c = getc(f)) != EOF)
650 putchar(c);
653 static char Bell = ctrl('G');
656 /* See whether the last component of the path name "path" is equal to the
657 ** string "string"
661 tailequ(char *path, char *string)
663 return (!strcmp(basename(path), string));
666 static void
667 prompt(char *filename)
669 if (clreol)
670 cleareol ();
671 else if (promptlen > 0)
672 kill_line ();
673 if (!hard) {
674 promptlen = 8;
675 if (enter_standout_mode && exit_standout_mode)
676 putp (enter_standout_mode);
677 if (clreol)
678 cleareol ();
679 pr(gettext("--More--"));
680 if (filename != NULL) {
681 promptlen += printf (gettext("(Next file: %s)"), filename);
683 else if (!no_intty) {
684 promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size));
686 if (dum_opt) {
687 promptlen += pr(gettext("[Hit space to continue, Del to abort]"));
689 if (enter_standout_mode && exit_standout_mode)
690 putp (exit_standout_mode);
691 if (clreol) clreos ();
692 fflush(stdout);
694 else
695 write (2, &Bell, 1);
696 inwait++;
700 * when run from another program or a shell script, it is
701 * sometimes useful to prevent the next program from scrolling
702 * us off the screen before we get a chance to read this page.
703 * -Hans, July 24, 1982
705 static void
706 wait_eof(void)
708 if (enter_standout_mode && exit_standout_mode)
709 putp (enter_standout_mode);
710 promptlen = pr(gettext("--No more--")); /*M003*/
711 if (dum_opt)
712 promptlen += pr(gettext("[Hit any key to continue]"));
713 if (enter_standout_mode && exit_standout_mode)
714 putp(exit_standout_mode);
715 if (clreol) clreos();
716 fflush(stdout);
717 readch();
718 prmpt_erase (0);
719 fflush(stdout);
723 ** Get a logical line
726 static int
727 getaline(register FILE *f, int *length)
729 register int c;
730 register char *p;
731 register int column;
732 static int colflg;
733 register int oldcolumn;
734 int csno;
736 p = Line;
737 column = 0;
738 oldcolumn = 0;
739 c = Getc (f);
740 if (colflg && c == '\n') {
741 Currline++;
742 c = Getc (f);
744 while (p < &Line[LINSIZ - 1]) {
745 csno = csetno(c);
746 if (c == EOF) {
747 if (p > Line) {
748 *p = '\0';
749 *length = p - Line;
750 return (column);
752 *length = p - Line;
753 return (EOF);
755 if (!csno) {
756 if (c == '\n') {
757 /* detect \r\n. -Hans */
758 if (p>Line && p[-1] == '\r') {
759 column = oldcolumn;
760 p--;
762 Currline++;
763 break;
765 *p++ = c;
766 if (c == '\t')
767 if (hardtabs && column < promptlen && !hard) {
768 if (clr_eol && !dumb) {
769 column = 1 + (column | 7);
770 putp (clr_eol);
771 promptlen = 0;
773 else {
774 for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
775 *p++ = ' ';
777 if (column >= promptlen) promptlen = 0;
780 else
781 column = 1 + (column | 7);
782 else if ((c == '\b') && (ul_opt || !cr_opt) && (column > 0)) /* M008 */
783 column--;
785 /* this is sort of strange. what was here before was that
786 \r always set column to zero, and the hack above to
787 detect \r\n didnt exist. the net effect is to make
788 the current line be overwritten by the prompt if it
789 had a \r at the end, and the line start after the \r
790 otherwise. I suppose this is useful for overstriking
791 on hard copy terminals, but not on anything glass
792 -Hans */
794 else if ((c == '\r') && !cr_opt) {
795 oldcolumn = column;
796 column = 0;
798 else if (c == '\f' && stop_opt) {
799 p[-1] = '^';
800 *p++ = 'L';
801 column += 2;
802 Pause++;
804 else if (c == EOF) {
805 *length = p - Line;
806 return (column);
808 else if (c < ' ' && cr_opt){ /* M008 begin */
809 p[-1] = '^';
810 *p++ = c | ('A' - 1);
811 column += 2;
812 } /* M008 end */
813 else if (c >= ' ' && c != RUBOUT)
814 column++;
815 } /* end of code set 0 */
816 else {
817 column += scw[csno];
818 if ( column > Mcol && fold_opt ) {
819 column -= scw[csno];
820 while ( column < Mcol ) {
821 column++;
822 *p++ = ' ';
824 column = Mcol;
825 Ungetc(c,f);
826 } else {
827 int i;
828 *p++ = c;
829 for(i=1; i<cw[csno];i++)
830 *p++ = Getc(f);
832 } /* end of codeset 1 ~ 3 */
833 if (column >= Mcol && fold_opt) break;
834 c = Getc (f);
836 if (column >= Mcol && Mcol > 0) {
837 if (!Wrap) {
838 *p++ = '\n';
841 colflg = column == Mcol && fold_opt;
842 if (colflg && eat_newline_glitch && Wrap) {
843 *p++ = '\n'; /* simulate normal wrap */
845 *length = p - Line;
846 *p = 0;
847 return (column);
851 ** Erase the rest of the prompt, assuming we are starting at column col.
854 static void
855 prmpt_erase(register int col)
858 if (promptlen == 0)
859 return;
860 if (hard) {
861 putchar ('\n');
863 else {
864 if (col == 0)
865 putchar ('\r');
866 if (!dumb && clr_eol)
867 putp (clr_eol);
868 else
869 for (col = promptlen - col; col > 0; col--)
870 putchar (' ');
872 promptlen = 0;
876 ** Erase the current line entirely
879 static void
880 kill_line(void)
882 prmpt_erase (0);
883 if (!clr_eol || dumb) putchar ('\r');
886 /* Print a buffer of n characters */
888 static void
889 prbuf(register char *s, register int n)
891 char c; /* next ouput character */
892 register int state = 0; /* next output char's UL state */
893 static int pstate = 0; /* current terminal UL state (off) */
895 while (--n >= 0)
896 if (!ul_opt)
897 putchar (*s++);
898 else {
899 if (n >= 2 && s[0] == '_' && s[1] == '\b') {
900 n -= 2;
901 s += 2;
902 c = *s++;
903 state = 1;
904 } else if (n >= 2 && s[1] == '\b' && s[2] == '_') {
905 n -= 2;
906 c = *s++;
907 s += 2;
908 state = 1;
909 } else {
910 c = *s++;
911 state = 0;
913 if (state != pstate)
914 putp(state ? ULenter : ULexit);
915 pstate = state;
916 putchar(c);
917 if (state && underline_char) {
918 putp(cursor_left);
919 putp(underline_char);
923 * M002
924 * You don't want to stay in standout mode at the end of the line;
925 * on some terminals, this will leave all of the remaining blank
926 * space on the line in standout mode.
928 if (state && !underline_char) { /*M002*/
929 putp(ULexit); /*M002*/
930 pstate = 0; /*M002*/
931 } /*M002*/
935 ** Clear the screen
938 static void
939 doclear(void)
941 if (clear_screen && !hard) {
942 putp(clear_screen);
944 /* Put out carriage return so that system doesn't
945 ** get confused by escape sequences when expanding tabs
947 putchar ('\r');
948 promptlen = 0;
953 static int lastcmd, lastp;
954 static off_t lastarg;
955 static int lastcolon;
956 char shell_line[PATH_MAX];
959 ** Read a command and do it. A command consists of an optional integer
960 ** argument followed by the command character. Return the number of lines
961 ** to display in the next screenful. If there is nothing more to display
962 ** in the current file, zero is returned.
965 static off_t
966 command(char *filename, register FILE *f)
968 register off_t nlines;
969 register off_t retval;
970 register int c;
971 char colonch;
972 FILE *helpf;
973 int done;
974 char comchar, cmdbuf[80];
975 char filebuf[128];
976 char *loc;
978 #define ret(val) retval=val;done++;break
980 done = 0;
981 if (!errors)
982 prompt (filename);
983 else
984 errors = 0;
985 for (;;) {
986 nlines = number (&comchar);
987 lastp = colonch = 0;
988 if (comchar == '.') { /* Repeat last command */
989 lastp++;
990 comchar = lastcmd;
991 nlines = lastarg;
992 if (lastcmd == ':')
993 colonch = lastcolon;
995 lastcmd = comchar;
996 lastarg = nlines;
997 if((comchar != RUBOUT) && !dum_opt) {
998 if (comchar == otty.c_cc[VERASE]) {
999 kill_line ();
1000 prompt (filename);
1001 continue;
1004 switch (comchar) {
1005 case ':':
1006 retval = colon (filename, colonch, nlines);
1007 if (retval >= 0)
1008 done++;
1009 break;
1010 case 'b':
1011 case ctrl('B'):
1013 register off_t initline;
1015 if (no_intty) {
1016 write(2, &bell, 1);
1017 return (-1);
1020 if (nlines == 0) nlines++;
1022 putchar ('\r');
1023 prmpt_erase (0);
1024 printf ("\n");
1025 if (clreol)
1026 cleareol ();
1027 printf (gettext("...back %lld page"), nlines);
1028 if (nlines > 1)
1029 pr ("s\n");
1030 else
1031 pr ("\n");
1033 if (clreol)
1034 cleareol ();
1035 pr ("\n");
1037 initline = Currline - dlines * (nlines + 1);
1038 if (! noscroll)
1039 --initline;
1040 if (initline < 0) initline = 0;
1041 Fseek(f, 0LL);
1042 Currline = 0; /* skiplns() will make Currline correct */
1043 skiplns(initline, f);
1044 if (! noscroll) {
1045 ret(dlines + 1);
1047 else {
1048 ret(dlines);
1051 case ' ':
1052 case 'z':
1053 if (nlines == 0) nlines = dlines;
1054 else if (comchar == 'z') dlines = nlines;
1055 ret (nlines);
1056 case 'd':
1057 case ctrl('D'):
1058 if (nlines != 0) nscroll = nlines;
1059 ret (nscroll);
1060 case RUBOUT:
1061 case 'q':
1062 case 'Q':
1063 end_it(0);
1064 /*NOTREACHED*/
1065 case 's':
1066 case 'f':
1067 if (nlines == 0) nlines++;
1068 if (comchar == 'f')
1069 nlines *= dlines;
1070 putchar ('\r');
1071 prmpt_erase (0);
1072 printf ("\n");
1073 if (clreol)
1074 cleareol ();
1075 printf (gettext("...skipping %lld line"), nlines);
1076 if (nlines > 1)
1077 pr ("s\n");
1078 else
1079 pr ("\n");
1081 if (clreol)
1082 cleareol ();
1083 pr ("\n");
1085 while (nlines > 0) {
1086 while ((c = Getc (f)) != '\n')
1087 if (c == EOF) {
1088 retval = 0;
1089 done++;
1090 goto endsw;
1092 Currline++;
1093 nlines--;
1095 ret (dlines);
1096 case '\n':
1097 if (nlines != 0)
1098 dlines = nlines;
1099 else
1100 nlines = 1;
1101 ret (nlines);
1102 case '\f':
1103 if (!no_intty) {
1104 doclear ();
1105 Fseek (f, screen_start.chrctr);
1106 Currline = screen_start.line;
1107 ret (dlines);
1109 else {
1110 write (2, &Bell, 1);
1111 break;
1113 case '\'':
1114 if (!no_intty) {
1115 kill_line ();
1116 pr (gettext("\n***Back***\n\n"));
1117 Fseek (f, context.chrctr);
1118 Currline = context.line;
1119 ret (dlines);
1121 else {
1122 write (2, &Bell, 1);
1123 break;
1125 case '=':
1126 kill_line ();
1127 promptlen = printf ("%lld", Currline);
1128 fflush (stdout);
1129 break;
1130 case 'n':
1131 lastp++;
1132 /*FALLTHROUGH*/
1133 case '/':
1134 if (nlines == 0) nlines++;
1135 kill_line ();
1136 pr ("/");
1137 promptlen = 1;
1138 fflush (stdout);
1139 if (lastp) {
1140 write (2,"\r", 1);
1141 search (NULL, f, nlines); /* Use previous r.e. */
1143 else {
1144 ttyin (cmdbuf, 78, '/');
1145 write (2, "\r", 1);
1146 search (cmdbuf, f, nlines);
1148 ret (dlines-1);
1149 case '!':
1150 do_shell (filename);
1151 break;
1152 case 'h':
1153 case '?':
1155 * First get local help file.
1157 loc = setlocale(LC_MESSAGES, 0);
1158 sprintf(filebuf, LOCAL_HELP, loc);
1160 if ((strcmp(loc, "C") == 0) || (helpf = fopen (filebuf, "r")) == NULL) {
1161 if ((helpf = fopen (HELPFILE, "r")) == NULL)
1162 error (gettext("Can't open help file"));
1164 if (noscroll) doclear ();
1165 copy_file (helpf);
1166 fclose (helpf);
1167 prompt (filename);
1168 break;
1169 case 'v': /* This case should go right before default */
1170 if (!no_intty) {
1171 kill_line ();
1172 cmdbuf[0] = '+';
1173 sprintf(&cmdbuf[1], "%lld", Currline);
1174 pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
1175 execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
1176 break;
1178 default:
1179 if (dum_opt) {
1180 kill_line ();
1181 promptlen = pr(gettext("[Press 'h' for instructions.]"));
1182 fflush (stdout);
1184 else
1185 write (2, &Bell, 1);
1186 break;
1188 if (done) break;
1190 putchar ('\r');
1191 endsw:
1192 inwait = 0;
1193 notell++;
1194 return (retval);
1197 char ch;
1200 * Execute a colon-prefixed command.
1201 * Returns <0 if not a command that should cause
1202 * more of the file to be printed.
1205 static int
1206 colon(char *filename, int cmd, off_t nlines)
1208 if (cmd == 0)
1209 ch = readch ();
1210 else
1211 ch = cmd;
1212 lastcolon = ch;
1213 switch (ch) {
1214 case 'f':
1215 kill_line ();
1216 if (!no_intty)
1217 promptlen = printf (gettext("\"%s\" line %lld"),
1218 fnames[fnum], Currline);
1219 else
1220 promptlen = printf(
1221 gettext("[Not a file] line %lld"), Currline);
1222 fflush (stdout);
1223 return (-1);
1224 case 'n':
1225 if (nlines == 0) {
1226 if (fnum >= nfiles - 1)
1227 end_it(0);
1228 nlines++;
1230 putchar ('\r');
1231 prmpt_erase (0);
1232 skipf ((int)nlines);
1233 return (0);
1234 case 'p':
1235 if (no_intty) {
1236 write (2, &Bell, 1);
1237 return (-1);
1239 putchar ('\r');
1240 prmpt_erase (0);
1241 if (nlines == 0)
1242 nlines++;
1243 skipf ((int)-nlines);
1244 return (0);
1245 case '!':
1246 do_shell (filename);
1247 return (-1);
1248 case 'q':
1249 case 'Q':
1250 end_it(0);
1251 default:
1252 write (2, &Bell, 1);
1253 return (-1);
1258 ** Read a decimal number from the terminal. Set cmd to the non-digit which
1259 ** terminates the number.
1262 static int
1263 number(char *cmd)
1265 register int i;
1267 i = 0; ch = otty.c_cc[VKILL];
1268 for (;;) {
1269 ch = readch ();
1270 if (ch >= '0' && ch <= '9') {
1271 i = i*10 + ch - '0';
1272 } else if (ch == RUBOUT) {
1273 i = 0;
1274 *cmd = ch;
1275 break;
1276 } else if (ch == otty.c_cc[VKILL]) {
1277 i = 0;
1278 } else {
1279 *cmd = ch;
1280 break;
1283 return (i);
1286 static void
1287 do_shell(char *filename)
1289 char cmdbuf[80];
1291 kill_line ();
1292 pr ("!");
1293 fflush (stdout);
1294 promptlen = 1;
1295 if (lastp)
1296 pr (shell_line);
1297 else {
1298 ttyin (cmdbuf, 78, '!');
1299 if (expand (shell_line, cmdbuf)) {
1300 kill_line ();
1301 promptlen = printf ("!%s", shell_line);
1304 fflush (stdout);
1305 write (2, "\n", 1);
1306 promptlen = 0;
1307 shellp = 1;
1308 execute (filename, shell, shell, "-c", shell_line, 0);
1312 ** Search for nth ocurrence of regular expression contained in buf in the file
1315 static void
1316 search(char buf[], FILE *file, register off_t n)
1318 off_t startline = Ftell (file);
1319 register off_t line1 = startline;
1320 register off_t line2 = startline;
1321 register off_t line3 = startline;
1322 register off_t lncount;
1323 off_t saveln;
1324 static char *s = NULL;
1325 static char lastbuf[80];
1327 if (buf != NULL) {
1328 free(s);
1329 if (*buf != '\0') {
1330 if ((s = regcmp(buf, (char *) NULL)) == NULL)
1331 error(gettext("Regular expression botch"));
1332 else
1333 strcpy(lastbuf, buf);
1334 } else {
1335 if ((s = regcmp(lastbuf, (char *) NULL)) == NULL)
1336 error(gettext("No previous regular expression"));
1338 } else {
1339 if (s == NULL)
1340 error(gettext("No previous regular expression"));
1342 context.line = saveln = Currline;
1343 context.chrctr = startline;
1344 lncount = 0;
1345 while (!feof (file)) {
1346 line3 = line2;
1347 line2 = line1;
1348 line1 = Ftell (file);
1349 rdline (file);
1350 lncount++;
1351 if (regex(s, Line) != NULL)
1352 if (--n == 0) {
1353 if (lncount > 3 || (lncount > 1 && no_intty))
1355 pr ("\n");
1356 if (clreol)
1357 cleareol ();
1358 pr(gettext("...skipping\n"));
1360 if (!no_intty) {
1361 Currline -= (lncount >= 3 ? 3 : lncount);
1362 Fseek (file, line3);
1363 if (noscroll)
1364 if (clreol) {
1365 home ();
1366 cleareol ();
1368 else
1369 doclear ();
1371 else {
1372 kill_line ();
1373 if (noscroll)
1374 if (clreol) {
1375 home ();
1376 cleareol ();
1377 } else
1378 doclear ();
1379 pr (Line);
1380 putchar ('\n');
1382 break;
1385 if (feof (file)) {
1386 if (!no_intty) {
1387 Currline = saveln;
1388 Fseek (file, startline);
1390 else {
1391 pr (gettext("\nPattern not found\n"));
1392 end_it (0);
1394 error (gettext("Pattern not found"));
1398 #define MAXARGS 10 /* enough for 9 args. We are only passed 4 now */
1400 static void
1401 execute (char *filename, char *cmd, ...)
1403 pid_t id;
1404 va_list ap;
1405 char *argp[MAXARGS];
1406 int count;
1408 fflush (stdout);
1409 reset_tty ();
1410 while ((id = fork ()) < 0)
1411 sleep (5);
1412 if (id == 0) {
1413 if (no_intty) { /*M002*/
1414 close(0); /*M002*/
1415 dup(2); /*M002*/
1416 } /*M002*/
1417 va_start(ap, cmd);
1418 count = 0;
1419 do {
1420 #ifndef lint
1421 argp[count] = va_arg(ap, char *);
1422 #else
1423 ap = ap;
1424 #endif
1425 count++;
1426 if (count > MAXARGS)
1427 error (gettext("Too many arguments in execute()\n"));
1428 } while (argp[count - 1] != NULL);
1429 va_end(ap);
1430 execvp(cmd, argp);
1431 write (2, "exec failed\n", 12);
1432 exit (1);
1434 signal (SIGINT, SIG_IGN);
1435 signal (SIGQUIT, SIG_IGN);
1436 signal (SIGWINCH, SIG_IGN);
1437 #ifdef SIGTSTP
1438 if (catch_susp)
1439 signal(SIGTSTP, SIG_DFL);
1440 #endif
1441 wait ((pid_t)0);
1442 signal (SIGINT, end_it);
1443 signal (SIGQUIT, onquit);
1444 signal (SIGWINCH, chgwinsz);
1445 #ifdef SIGTSTP
1446 if (catch_susp)
1447 signal(SIGTSTP, onsusp);
1448 #endif
1450 * Since we were ignoring window change signals while we executed
1451 * the command, we must assume the window changed.
1453 (void) chgwinsz(0);
1454 set_tty ();
1456 pr ("------------------------\n");
1457 prompt (filename);
1460 ** Skip n lines in the file f
1463 static void
1464 skiplns(register off_t n, register FILE *f)
1466 register int c;
1468 while (n > 0) {
1469 while ((c = Getc (f)) != '\n')
1470 if (c == EOF)
1471 return;
1472 n--;
1473 Currline++;
1478 ** Skip nskip files in the file list (from the command line). Nskip may be
1479 ** negative.
1482 static void
1483 skipf(register int nskip)
1485 if (nskip == 0) return;
1486 if (nskip > 0) {
1487 if (fnum + nskip > nfiles - 1)
1488 nskip = nfiles - fnum - 1;
1490 else if (within)
1491 ++fnum;
1492 fnum += nskip;
1493 if (fnum < 0)
1494 fnum = 0;
1495 pr (gettext("\n...Skipping "));
1496 pr ("\n");
1497 if (clreol)
1498 cleareol ();
1499 if (nskip > 0)
1500 printf(gettext("...Skipping to file %s\n"), fnames[fnum]);
1501 else
1502 printf(gettext("...Skipping back to file %s\n"), fnames[fnum]);
1503 if (clreol)
1504 cleareol ();
1505 pr ("\n");
1506 --fnum;
1509 /*----------------------------- Terminal I/O -------------------------------*/
1511 static void
1512 initterm(void)
1514 int erret = 0;
1516 setbuf(stdout, obuf);
1517 if (!(no_tty = ioctl(1, TCGETA, &otty))) {
1518 if (setupterm(NULL, 1, &erret) != OK) {
1519 dumb++; ul_opt = 0;
1521 else {
1522 reset_shell_mode();
1523 if (((Lpp = lines) < 0) || hard_copy) {
1524 hard++; /* Hard copy terminal */
1525 Lpp = 24;
1527 if (tailequ(fnames[0], "page") || !hard && (scroll_forward == NULL))
1528 noscroll++;
1529 if ((Mcol = columns) < 0)
1530 Mcol = 80;
1531 Wrap = tigetflag("am");
1533 * Set up for underlining: some terminals don't need it;
1534 * others have start/stop sequences, still others have an
1535 * underline char sequence which is assumed to move the
1536 * cursor forward one character. If underline sequence
1537 * isn't available, settle for standout sequence.
1540 if (transparent_underline || over_strike)
1541 ul_opt = 0;
1542 if ((ULenter = tigetstr("smul")) == NULL &&
1543 (!underline_char) && (ULenter = tigetstr("smso")) == NULL)
1544 ULenter = "";
1545 if ((ULexit = tigetstr("rmul")) == NULL &&
1546 (!underline_char) && (ULexit = tigetstr("rmso")) == NULL)
1547 ULexit = "";
1549 if ((shell = getenv("SHELL")) == NULL)
1550 shell = "/usr/bin/sh";
1552 no_intty = ioctl(0, TCGETA, &otty);
1553 ioctl(2, TCGETA, &otty);
1554 hardtabs = !(otty.c_oflag & TAB3);
1557 static int
1558 readch(void)
1560 char ch;
1561 extern int errno;
1563 if (read (2, &ch, 1) <= 0)
1564 if (errno != EINTR)
1565 end_it(0); /* clean up before exiting */
1566 else
1567 ch = otty.c_cc[VKILL];
1568 return (ch);
1571 static char BS = '\b';
1572 static char CARAT = '^';
1574 static void
1575 ttyin(char buf[], register int nmax, char pchar)
1577 register char *sptr;
1578 register unsigned char ch;
1579 int LengthBuffer[80];
1580 int *BufferPointer;
1581 int csno;
1582 register int slash = 0;
1583 int maxlen;
1584 char cbuf;
1586 BufferPointer = LengthBuffer;
1587 sptr = buf;
1588 maxlen = 0;
1589 while (sptr - buf < nmax) {
1590 if (promptlen > maxlen)
1591 maxlen = promptlen;
1592 ch = readch ();
1593 csno = csetno(ch);
1594 if (!csno) {
1595 if (ch == '\\') {
1596 slash++;
1597 } else if ((ch == otty.c_cc[VERASE]) && !slash) {
1598 if (sptr > buf) {
1599 --promptlen;
1600 write (2, &BS, 1);
1601 sptr -= (*--BufferPointer);
1602 if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
1603 --promptlen;
1604 write (2, &BS, 1);
1606 continue;
1607 } else {
1608 if (!clr_eol)
1609 promptlen = maxlen;
1610 longjmp (restore, 1);
1612 } else if ((ch == otty.c_cc[VKILL]) && !slash) {
1613 if (hard) {
1614 show(ch);
1615 putchar ('\n');
1616 putchar (pchar);
1617 } else {
1618 putchar ('\r');
1619 putchar (pchar);
1620 if (clr_eol)
1621 prmpt_erase (1);
1622 promptlen = 1;
1624 sptr = buf;
1625 fflush (stdout);
1626 continue;
1628 if (slash && (ch == otty.c_cc[VKILL] || ch == otty.c_cc[VERASE])) {
1629 write (2, &BS, 1);
1630 sptr -= (*--BufferPointer);
1632 if (ch != '\\')
1633 slash = 0;
1634 *BufferPointer++ = 1;
1635 *sptr++ = ch;
1636 if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
1637 ch += ch == RUBOUT ? -0100 : 0100;
1638 write (2, &CARAT, 1);
1639 promptlen++;
1641 cbuf = ch;
1642 if (ch != '\n' && ch != ESC) {
1643 write (2, &cbuf, 1);
1644 promptlen++;
1645 } else
1646 break;
1647 /* end of code set 0 */
1648 } else {
1649 int i;
1650 u_char buffer[5];
1652 *BufferPointer++ = cw[csno];
1653 buffer[0] = *sptr++ = ch;
1654 for(i=1; i<cw[csno]; i++) {
1655 buffer[i] = *sptr++ = readch();
1657 buffer[i]='\0';
1658 write(2, buffer, strlen((char *)buffer));
1661 *--sptr = '\0';
1662 if (!clr_eol) promptlen = maxlen;
1663 if (sptr - buf >= nmax - 1)
1664 error (gettext("Line too long"));
1667 static int
1668 expand(char *outbuf, char *inbuf)
1670 char *in_str;
1671 char *out_str;
1672 char ch;
1673 char temp[PATH_MAX];
1674 int changed = 0;
1676 in_str = inbuf;
1677 out_str = temp;
1678 while ((ch = *in_str++) != '\0')
1679 switch (ch) {
1680 case '%':
1681 if (!no_intty) {
1682 if (strlcpy(out_str, fnames[fnum], sizeof (temp))
1683 >= sizeof (temp))
1684 error(gettext("Command too long"));
1685 out_str += strlen (fnames[fnum]);
1686 changed++;
1688 else
1689 *out_str++ = ch;
1690 break;
1691 case '!':
1692 if (!shellp)
1693 error (gettext("No previous command to substitute for"));
1694 if (strlcpy(out_str, shell_line, sizeof (temp)) >= sizeof (temp))
1695 error(gettext("Command too long"));
1696 out_str += strlen (shell_line);
1697 changed++;
1698 break;
1699 case '\\':
1700 if (*in_str == '%' || *in_str == '!') {
1701 *out_str++ = *in_str++;
1702 break;
1704 default:
1705 *out_str++ = ch;
1707 *out_str++ = '\0';
1708 if (strlcpy(outbuf, temp, sizeof (shell_line)) >= sizeof (shell_line))
1709 error(gettext("Command too long"));
1710 return (changed);
1713 static void
1714 show(register char ch)
1716 char cbuf;
1718 if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
1719 ch += ch == RUBOUT ? -0100 : 0100;
1720 write (2, &CARAT, 1);
1721 promptlen++;
1723 cbuf = ch;
1724 write (2, &cbuf, 1);
1725 promptlen++;
1728 static void
1729 error (char *mess)
1731 if (clreol)
1732 cleareol ();
1733 else
1734 kill_line ();
1735 promptlen += strlen (mess);
1736 if (enter_standout_mode && exit_standout_mode) {
1737 putp (enter_standout_mode);
1738 pr(mess);
1739 putp (exit_standout_mode);
1741 else
1742 pr (mess);
1743 fflush(stdout);
1744 errors++;
1745 longjmp (restore, 1);
1749 static void
1750 set_tty(void)
1752 ioctl(2, TCGETA, &otty); /* save old tty modes */
1753 ioctl(2, TCGETA, &ntty);
1754 ntty.c_lflag &= ~ECHO & ~ICANON;
1755 ntty.c_cc[VMIN] = (char)1;
1756 ntty.c_cc[VTIME] = (char)0;
1757 ioctl (2, TCSETAF, &ntty); /* set new tty modes */
1760 static void
1761 reset_tty(void)
1763 ioctl (2, TCSETAF, &otty); /* reset tty modes */
1766 static void
1767 rdline(register FILE *f)
1769 register int c;
1770 register char *p;
1772 p = Line;
1773 while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
1774 *p++ = c;
1775 if (c == '\n')
1776 Currline++;
1777 *p = '\0';
1780 /* Come here when we get a suspend signal from the terminal */
1783 * sig is put in as a dummy arg to have the compiler not to complain
1785 #ifdef SIGTSTP
1786 /* ARGSUSED */
1787 void
1788 onsusp(int sig)
1790 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
1791 signal(SIGTTOU, SIG_IGN);
1792 reset_tty ();
1793 fflush (stdout);
1794 signal(SIGTTOU, SIG_DFL);
1796 /* Send the TSTP signal to suspend our process group */
1797 kill (0, SIGTSTP);
1798 /* Pause for station break */
1800 /* We're back */
1801 signal (SIGTSTP, onsusp);
1802 set_tty ();
1803 if (inwait)
1804 longjmp (restore, 1);
1806 #endif