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]
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
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
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
57 ** modified to handle x.out magic number and magic number
58 ** byte ordering OTHER than the vax and pdp11.
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
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
96 #include <sys/types.h>
100 #include <sys/ioctl.h>
102 #include <sys/stat.h>
110 #include <getwidth.h>
120 /* Help file will eventually go in libpath(more.help) on all systems */
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"
130 #define HELPFILE "/usr/lib/more.help"
131 #define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
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)
148 #define ctrl(letter) ((letter) & 077)
149 #define RUBOUT '\177'
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
;
159 void end_it(int sig
);
160 void onquit(int sig
);
161 void chgwinsz(int sig
);
163 void onsusp(int sig
);
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 */
173 off_t Currline
; /* Line we are currently at */
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 */
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 */
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
[])
244 setlocale( LC_ALL
, "" );
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 */
262 (void) textdomain(TEXT_DOMAIN
);
265 if(s
= getenv("MORE")) argscan(s
);
266 while (--nfiles
> 0) {
267 if ((ch
= (*++fnames
)[0]) == '-') {
270 else if (ch
== '+') {
274 for (++s
, p
= initbuf
; p
< initbuf
+ 79 && *s
!= '\0';)
280 for (initline
= 0; *s
!= '\0'; s
++)
282 initline
= initline
*10 + *s
-'0';
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
293 if (!cursor_home
|| !clr_eol
|| !clr_eos
) {
300 dlines
=(off_t
) (Lpp
- (noscroll
? 1 : 2));
304 if (!no_intty
&& nfiles
== 0) {
305 fprintf(stderr
, gettext("Usage: %s\
306 [-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename ...].\n")
313 signal(SIGQUIT
, onquit
);
314 signal(SIGINT
, end_it
);
315 signal(SIGWINCH
, chgwinsz
);
317 if (signal (SIGTSTP
, SIG_IGN
) == SIG_DFL
) {
318 signal(SIGTSTP
, onsusp
);
328 if ((ch
= Getc (f
)) == '\f')
332 if (noscroll
&& (ch
!= EOF
)) {
339 if (!setjmp(restore
)) {
341 search (initbuf
, stdin
,(off_t
) 1);
346 skiplns (initline
, stdin
);
349 left
= command(NULL
, f
);
350 screen (stdin
, left
);
357 while (fnum
< nfiles
) {
358 if ((f
= checkf (fnames
[fnum
], &clearit
)) != NULL
) {
359 context
.line
= context
.chrctr
= 0;
361 if (firstf
) setjmp (restore
);
366 search (initbuf
, f
,(off_t
) 1);
371 skiplns (initline
, f
);
373 else if (fnum
< nfiles
&& !no_tty
) {
375 left
= command (fnames
[fnum
], f
);
378 if ((noscroll
|| clearit
) && (file_size
!= LLONG_MAX
))
384 if (ceol_standout_glitch
)
388 pr("::::::::::::::");
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);
410 screen_start
.line
= screen_start
.chrctr
= 0LL;
411 context
.line
= context
.chrctr
= 0LL;
413 exitstat
|= 1; /*M003*/
417 if (wait_opt
) wait_eof();
419 return (exitstat
); /*M003*/
425 for (dlines
= 0; *s
!= '\0'; s
++)
427 dlines
= dlines
*10 + *s
- '0';
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.
455 checkf(register char *fs
, int *clearfirst
)
461 if (stat (fs
, &stbuf
) == -1) {
468 if ((stbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
469 printf(gettext("\n*** %s: directory ***\n\n"), fs
);
472 if ((f
=Fopen(fs
, "r")) == NULL
) {
478 if ((c
= Getc(f
)) == '\f') /* end M001 */
484 if ((file_size
= (off_t
)stbuf
.st_size
) == 0)
485 file_size
= LLONG_MAX
;
490 ** Print out the contents of the file f, one screenful at a time.
496 screen(register FILE *f
, register off_t num_lines
)
500 int length
; /* length of current line */
501 static int prev_len
= 1; /* length of previous line */
504 while (num_lines
> 0 && !Pause
) {
505 if ((nchars
= getaline (f
, &length
)) == EOF
)
507 if (clreol
) clreos();
510 if (ssp_opt
&& length
== 0 && prev_len
== 0)
513 if (ceol_standout_glitch
||
514 (enter_standout_mode
&& *enter_standout_mode
== ' ')
517 /* must clear before drawing line since tabs on some terminals
518 * do not erase what they tab over.
522 prbuf (Line
, length
);
523 if (nchars
< promptlen
)
524 prmpt_erase (nchars
); /* prmpt_erase () sets promptlen to 0 */
528 * cleareol(); */ /* must clear again in case we wrapped */
530 if (nchars
< Mcol
|| !fold_opt
)
537 if ((c
= Getc(f
)) == EOF
)
539 if (clreol
) clreos ();
547 Pause
= 0; startup
= 0;
548 if ((num_lines
= command (NULL
, f
)) == 0)
550 if (hard
&& promptlen
> 0)
552 if (noscroll
&& num_lines
== dlines
) {
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
574 signal(SIGQUIT
, SIG_IGN
);
578 signal(SIGQUIT
, onquit
);
579 longjmp (restore
, 1);
584 else if (!dum_opt
&& notell
) {
585 write (2, gettext("[Use q or Q to quit]"), 20);
589 signal(SIGQUIT
, onquit
);
593 ** Come here if a signal for a window size change is received
601 (void) signal(SIGWINCH
, SIG_IGN
);
602 if (ioctl(fileno(stdout
), TIOCGWINSZ
, &win
) != -1) {
603 if (win
.ws_row
!= 0) {
608 dlines
= (off_t
)(Lpp
- (noscroll
? 1 : 2));
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
635 else if (!clreol
&& (promptlen
> 0)) {
641 _exit(exitstat
); /*M003*/
645 copy_file(register FILE *f
)
649 while ((c
= getc(f
)) != EOF
)
653 static char Bell
= ctrl('G');
656 /* See whether the last component of the path name "path" is equal to the
661 tailequ(char *path
, char *string
)
663 return (!strcmp(basename(path
), string
));
667 prompt(char *filename
)
671 else if (promptlen
> 0)
675 if (enter_standout_mode
&& exit_standout_mode
)
676 putp (enter_standout_mode
);
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
));
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 ();
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
708 if (enter_standout_mode
&& exit_standout_mode
)
709 putp (enter_standout_mode
);
710 promptlen
= pr(gettext("--No more--")); /*M003*/
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();
723 ** Get a logical line
727 getaline(register FILE *f
, int *length
)
733 register int oldcolumn
;
740 if (colflg
&& c
== '\n') {
744 while (p
< &Line
[LINSIZ
- 1]) {
757 /* detect \r\n. -Hans */
758 if (p
>Line
&& p
[-1] == '\r') {
767 if (hardtabs
&& column
< promptlen
&& !hard
) {
768 if (clr_eol
&& !dumb
) {
769 column
= 1 + (column
| 7);
774 for (--p
; column
& 7 && p
< &Line
[LINSIZ
- 1]; column
++) {
777 if (column
>= promptlen
) promptlen
= 0;
781 column
= 1 + (column
| 7);
782 else if ((c
== '\b') && (ul_opt
|| !cr_opt
) && (column
> 0)) /* M008 */
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
794 else if ((c
== '\r') && !cr_opt
) {
798 else if (c
== '\f' && stop_opt
) {
808 else if (c
< ' ' && cr_opt
){ /* M008 begin */
810 *p
++ = c
| ('A' - 1);
813 else if (c
>= ' ' && c
!= RUBOUT
)
815 } /* end of code set 0 */
818 if ( column
> Mcol
&& fold_opt
) {
820 while ( column
< Mcol
) {
829 for(i
=1; i
<cw
[csno
];i
++)
832 } /* end of codeset 1 ~ 3 */
833 if (column
>= Mcol
&& fold_opt
) break;
836 if (column
>= Mcol
&& Mcol
> 0) {
841 colflg
= column
== Mcol
&& fold_opt
;
842 if (colflg
&& eat_newline_glitch
&& Wrap
) {
843 *p
++ = '\n'; /* simulate normal wrap */
851 ** Erase the rest of the prompt, assuming we are starting at column col.
855 prmpt_erase(register int col
)
866 if (!dumb
&& clr_eol
)
869 for (col
= promptlen
- col
; col
> 0; col
--)
876 ** Erase the current line entirely
883 if (!clr_eol
|| dumb
) putchar ('\r');
886 /* Print a buffer of n characters */
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) */
899 if (n
>= 2 && s
[0] == '_' && s
[1] == '\b') {
904 } else if (n
>= 2 && s
[1] == '\b' && s
[2] == '_') {
914 putp(state
? ULenter
: ULexit
);
917 if (state
&& underline_char
) {
919 putp(underline_char
);
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*/
941 if (clear_screen
&& !hard
) {
944 /* Put out carriage return so that system doesn't
945 ** get confused by escape sequences when expanding tabs
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.
966 command(char *filename
, register FILE *f
)
968 register off_t nlines
;
969 register off_t retval
;
974 char comchar
, cmdbuf
[80];
978 #define ret(val) retval=val;done++;break
986 nlines
= number (&comchar
);
988 if (comchar
== '.') { /* Repeat last command */
997 if((comchar
!= RUBOUT
) && !dum_opt
) {
998 if (comchar
== otty
.c_cc
[VERASE
]) {
1006 retval
= colon (filename
, colonch
, nlines
);
1013 register off_t initline
;
1020 if (nlines
== 0) nlines
++;
1027 printf (gettext("...back %lld page"), nlines
);
1037 initline
= Currline
- dlines
* (nlines
+ 1);
1040 if (initline
< 0) initline
= 0;
1042 Currline
= 0; /* skiplns() will make Currline correct */
1043 skiplns(initline
, f
);
1053 if (nlines
== 0) nlines
= dlines
;
1054 else if (comchar
== 'z') dlines
= nlines
;
1058 if (nlines
!= 0) nscroll
= nlines
;
1067 if (nlines
== 0) nlines
++;
1075 printf (gettext("...skipping %lld line"), nlines
);
1085 while (nlines
> 0) {
1086 while ((c
= Getc (f
)) != '\n')
1105 Fseek (f
, screen_start
.chrctr
);
1106 Currline
= screen_start
.line
;
1110 write (2, &Bell
, 1);
1116 pr (gettext("\n***Back***\n\n"));
1117 Fseek (f
, context
.chrctr
);
1118 Currline
= context
.line
;
1122 write (2, &Bell
, 1);
1127 promptlen
= printf ("%lld", Currline
);
1134 if (nlines
== 0) nlines
++;
1141 search (NULL
, f
, nlines
); /* Use previous r.e. */
1144 ttyin (cmdbuf
, 78, '/');
1146 search (cmdbuf
, f
, nlines
);
1150 do_shell (filename
);
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 ();
1169 case 'v': /* This case should go right before default */
1173 sprintf(&cmdbuf
[1], "%lld", Currline
);
1174 pr ("vi "); pr (cmdbuf
); putchar (' '); pr (fnames
[fnum
]);
1175 execute (filename
, VI
, "vi", cmdbuf
, fnames
[fnum
], 0);
1181 promptlen
= pr(gettext("[Press 'h' for instructions.]"));
1185 write (2, &Bell
, 1);
1200 * Execute a colon-prefixed command.
1201 * Returns <0 if not a command that should cause
1202 * more of the file to be printed.
1206 colon(char *filename
, int cmd
, off_t nlines
)
1217 promptlen
= printf (gettext("\"%s\" line %lld"),
1218 fnames
[fnum
], Currline
);
1221 gettext("[Not a file] line %lld"), Currline
);
1226 if (fnum
>= nfiles
- 1)
1232 skipf ((int)nlines
);
1236 write (2, &Bell
, 1);
1243 skipf ((int)-nlines
);
1246 do_shell (filename
);
1252 write (2, &Bell
, 1);
1258 ** Read a decimal number from the terminal. Set cmd to the non-digit which
1259 ** terminates the number.
1267 i
= 0; ch
= otty
.c_cc
[VKILL
];
1270 if (ch
>= '0' && ch
<= '9') {
1271 i
= i
*10 + ch
- '0';
1272 } else if (ch
== RUBOUT
) {
1276 } else if (ch
== otty
.c_cc
[VKILL
]) {
1287 do_shell(char *filename
)
1298 ttyin (cmdbuf
, 78, '!');
1299 if (expand (shell_line
, cmdbuf
)) {
1301 promptlen
= printf ("!%s", shell_line
);
1308 execute (filename
, shell
, shell
, "-c", shell_line
, 0);
1312 ** Search for nth ocurrence of regular expression contained in buf in the file
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
;
1324 static char *s
= NULL
;
1325 static char lastbuf
[80];
1331 if ((s
= regcmp(buf
, (char *) NULL
)) == NULL
)
1332 error(gettext("Regular expression botch"));
1334 strcpy(lastbuf
, buf
);
1336 if ((s
= regcmp(lastbuf
, (char *) NULL
)) == NULL
)
1337 error(gettext("No previous regular expression"));
1341 error(gettext("No previous regular expression"));
1343 context
.line
= saveln
= Currline
;
1344 context
.chrctr
= startline
;
1346 while (!feof (file
)) {
1349 line1
= Ftell (file
);
1352 if (regex(s
, Line
) != NULL
)
1354 if (lncount
> 3 || (lncount
> 1 && no_intty
))
1359 pr(gettext("...skipping\n"));
1362 Currline
-= (lncount
>= 3 ? 3 : lncount
);
1363 Fseek (file
, line3
);
1389 Fseek (file
, startline
);
1392 pr (gettext("\nPattern not found\n"));
1395 error (gettext("Pattern not found"));
1399 #define MAXARGS 10 /* enough for 9 args. We are only passed 4 now */
1402 execute (char *filename
, char *cmd
, ...)
1406 char *argp
[MAXARGS
];
1411 while ((id
= fork ()) < 0)
1414 if (no_intty
) { /*M002*/
1422 argp
[count
] = va_arg(ap
, char *);
1427 if (count
> MAXARGS
)
1428 error (gettext("Too many arguments in execute()\n"));
1429 } while (argp
[count
- 1] != NULL
);
1432 write (2, "exec failed\n", 12);
1435 signal (SIGINT
, SIG_IGN
);
1436 signal (SIGQUIT
, SIG_IGN
);
1437 signal (SIGWINCH
, SIG_IGN
);
1440 signal(SIGTSTP
, SIG_DFL
);
1443 signal (SIGINT
, end_it
);
1444 signal (SIGQUIT
, onquit
);
1445 signal (SIGWINCH
, chgwinsz
);
1448 signal(SIGTSTP
, onsusp
);
1451 * Since we were ignoring window change signals while we executed
1452 * the command, we must assume the window changed.
1457 pr ("------------------------\n");
1461 ** Skip n lines in the file f
1465 skiplns(register off_t n
, register FILE *f
)
1470 while ((c
= Getc (f
)) != '\n')
1479 ** Skip nskip files in the file list (from the command line). Nskip may be
1484 skipf(register int nskip
)
1486 if (nskip
== 0) return;
1488 if (fnum
+ nskip
> nfiles
- 1)
1489 nskip
= nfiles
- fnum
- 1;
1496 pr (gettext("\n...Skipping "));
1501 printf(gettext("...Skipping to file %s\n"), fnames
[fnum
]);
1503 printf(gettext("...Skipping back to file %s\n"), fnames
[fnum
]);
1510 /*----------------------------- Terminal I/O -------------------------------*/
1517 setbuf(stdout
, obuf
);
1518 if (!(no_tty
= ioctl(1, TCGETA
, &otty
))) {
1519 if (setupterm(NULL
, 1, &erret
) != OK
) {
1524 if (((Lpp
= lines
) < 0) || hard_copy
) {
1525 hard
++; /* Hard copy terminal */
1528 if (tailequ(fnames
[0], "page") || !hard
&& (scroll_forward
== NULL
))
1530 if ((Mcol
= columns
) < 0)
1532 Wrap
= tigetflag("am");
1534 * Set up for underlining: some terminals don't need it;
1535 * others have start/stop sequences, still others have an
1536 * underline char sequence which is assumed to move the
1537 * cursor forward one character. If underline sequence
1538 * isn't available, settle for standout sequence.
1541 if (transparent_underline
|| over_strike
)
1543 if ((ULenter
= tigetstr("smul")) == NULL
&&
1544 (!underline_char
) && (ULenter
= tigetstr("smso")) == NULL
)
1546 if ((ULexit
= tigetstr("rmul")) == NULL
&&
1547 (!underline_char
) && (ULexit
= tigetstr("rmso")) == NULL
)
1550 if ((shell
= getenv("SHELL")) == NULL
)
1551 shell
= "/usr/bin/sh";
1553 no_intty
= ioctl(0, TCGETA
, &otty
);
1554 ioctl(2, TCGETA
, &otty
);
1555 hardtabs
= !(otty
.c_oflag
& TAB3
);
1564 if (read (2, &ch
, 1) <= 0)
1566 end_it(0); /* clean up before exiting */
1568 ch
= otty
.c_cc
[VKILL
];
1572 static char BS
= '\b';
1573 static char CARAT
= '^';
1576 ttyin(char buf
[], register int nmax
, char pchar
)
1578 register char *sptr
;
1579 register unsigned char ch
;
1580 int LengthBuffer
[80];
1583 register int slash
= 0;
1587 BufferPointer
= LengthBuffer
;
1590 while (sptr
- buf
< nmax
) {
1591 if (promptlen
> maxlen
)
1598 } else if ((ch
== otty
.c_cc
[VERASE
]) && !slash
) {
1602 sptr
-= (*--BufferPointer
);
1603 if ((*sptr
< ' ' && *sptr
!= '\n') || *sptr
== RUBOUT
) {
1611 longjmp (restore
, 1);
1613 } else if ((ch
== otty
.c_cc
[VKILL
]) && !slash
) {
1629 if (slash
&& (ch
== otty
.c_cc
[VKILL
] || ch
== otty
.c_cc
[VERASE
])) {
1631 sptr
-= (*--BufferPointer
);
1635 *BufferPointer
++ = 1;
1637 if ((ch
< ' ' && ch
!= '\n' && ch
!= ESC
) || ch
== RUBOUT
) {
1638 ch
+= ch
== RUBOUT
? -0100 : 0100;
1639 write (2, &CARAT
, 1);
1643 if (ch
!= '\n' && ch
!= ESC
) {
1644 write (2, &cbuf
, 1);
1648 /* end of code set 0 */
1653 *BufferPointer
++ = cw
[csno
];
1654 buffer
[0] = *sptr
++ = ch
;
1655 for(i
=1; i
<cw
[csno
]; i
++) {
1656 buffer
[i
] = *sptr
++ = readch();
1659 write(2, buffer
, strlen((char *)buffer
));
1663 if (!clr_eol
) promptlen
= maxlen
;
1664 if (sptr
- buf
>= nmax
- 1)
1665 error (gettext("Line too long"));
1669 expand(char *outbuf
, char *inbuf
)
1674 char temp
[PATH_MAX
];
1679 while ((ch
= *in_str
++) != '\0')
1683 if (strlcpy(out_str
, fnames
[fnum
], sizeof (temp
))
1685 error(gettext("Command too long"));
1686 out_str
+= strlen (fnames
[fnum
]);
1694 error (gettext("No previous command to substitute for"));
1695 if (strlcpy(out_str
, shell_line
, sizeof (temp
)) >= sizeof (temp
))
1696 error(gettext("Command too long"));
1697 out_str
+= strlen (shell_line
);
1701 if (*in_str
== '%' || *in_str
== '!') {
1702 *out_str
++ = *in_str
++;
1709 if (strlcpy(outbuf
, temp
, sizeof (shell_line
)) >= sizeof (shell_line
))
1710 error(gettext("Command too long"));
1715 show(register char ch
)
1719 if ((ch
< ' ' && ch
!= '\n' && ch
!= ESC
) || ch
== RUBOUT
) {
1720 ch
+= ch
== RUBOUT
? -0100 : 0100;
1721 write (2, &CARAT
, 1);
1725 write (2, &cbuf
, 1);
1736 promptlen
+= strlen (mess
);
1737 if (enter_standout_mode
&& exit_standout_mode
) {
1738 putp (enter_standout_mode
);
1740 putp (exit_standout_mode
);
1746 longjmp (restore
, 1);
1753 ioctl(2, TCGETA
, &otty
); /* save old tty modes */
1754 ioctl(2, TCGETA
, &ntty
);
1755 ntty
.c_lflag
&= ~ECHO
& ~ICANON
;
1756 ntty
.c_cc
[VMIN
] = (char)1;
1757 ntty
.c_cc
[VTIME
] = (char)0;
1758 ioctl (2, TCSETAF
, &ntty
); /* set new tty modes */
1764 ioctl (2, TCSETAF
, &otty
); /* reset tty modes */
1768 rdline(register FILE *f
)
1774 while ((c
= Getc (f
)) != '\n' && c
!= EOF
&& p
- Line
< LINSIZ
- 1)
1781 /* Come here when we get a suspend signal from the terminal */
1784 * sig is put in as a dummy arg to have the compiler not to complain
1791 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
1792 signal(SIGTTOU
, SIG_IGN
);
1795 signal(SIGTTOU
, SIG_DFL
);
1797 /* Send the TSTP signal to suspend our process group */
1799 /* Pause for station break */
1802 signal (SIGTSTP
, onsusp
);
1805 longjmp (restore
, 1);