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>
99 #include <sys/termio.h>
101 #include <sys/ioctl.h>
103 #include <sys/stat.h>
111 #include <getwidth.h>
121 /* Help file will eventually go in libpath(more.help) on all systems */
124 #define VI "/usr/bin/vi"
125 #define HELPFILE "/mntp/doucette/more/more.help"
126 #define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
131 #define HELPFILE "/usr/lib/more.help"
132 #define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
137 #define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m))
138 #define Ftell(f) file_pos
139 #define Fseek(f,off) (file_pos=off,fseeko(f,off,0))
140 #define Getc(f) (++file_pos, getc(f))
141 #define Ungetc(c,f) (--file_pos, ungetc(c,f))
143 #define pr(s1) fputs(s1, stdout)
144 #define clreos() putp(clr_eos)
145 #define cleareol() putp(clr_eol)
146 #define home() putp(cursor_home)
149 #define ctrl(letter) ((letter) & 077)
150 #define RUBOUT '\177'
154 struct termio otty
; /* old tty modes */
155 struct termio ntty
; /* new tty modes */
156 off_t file_pos
, file_size
;
157 int fnum
, no_intty
, no_tty
;
160 void end_it(int sig
);
161 void onquit(int sig
);
162 void chgwinsz(int sig
);
164 void onsusp(int sig
);
166 int nscroll
= 11; /* Number of lines scrolled by 'd' */
167 int fold_opt
= 1; /* Fold long lines */
168 int stop_opt
= 1; /* Stop after form feeds */
169 int ssp_opt
= 0; /* Suppress white space */
170 int ul_opt
= 1; /* Underline as best we can */
171 int cr_opt
= 0; /* show ctrl characters as '^c' */
172 int wait_opt
= 0; /* prompt for exit at eof */
174 off_t Currline
; /* Line we are currently at */
178 int inwait
, Pause
, errors
;
179 int within
; /* true if we are within a file,
180 false if we are between files */
181 int hard
, dumb
, noscroll
, hardtabs
, clreol
;
182 int catch_susp
; /* We should catch the SIGTSTP signal */
183 char **fnames
; /* The list of file names */
184 int nfiles
; /* Number of files left to process */
185 char *shell
; /* The name of the shell to use */
186 int shellp
; /* A previous shell command exists */
189 char obuf
[BUFSIZ
]; /* stdout buffer */
190 char Line
[LINSIZ
]; /* Line buffer */
191 int Lpp
= 24; /* lines per page */
192 char *ULenter
, *ULexit
; /* enter and exit underline mode */
193 int Mcol
= 80; /* number of columns */
194 int Wrap
= 1; /* set if automargins */
198 } context
, screen_start
;
199 int exitstat
= 0; /* status to use when exiting more */ /*M003*/
201 static void execute(char *filename
, char *cmd
, ...);
202 static void error(char *mess
);
203 static void wait_eof(void);
204 static void prompt(char *filename
);
205 static void argscan(char *s
);
206 static void copy_file(register FILE *f
);
207 static void initterm(void);
208 static void do_shell(char *filename
);
209 static FILE *checkf(register char *fs
, int *clearfirst
);
210 static void screen(register FILE *f
, register off_t num_lines
);
211 static void skiplns(register off_t n
, register FILE *f
);
212 static void skipf(register int nskip
);
213 static int readch(void);
214 static void prmpt_erase(register int col
);
215 static void kill_line(void);
216 static void prbuf(register char *s
, register int n
);
217 static void search(char buf
[], FILE *file
, register off_t n
);
218 static void doclear(void);
219 static void ttyin(char buf
[], register int nmax
, char pchar
);
220 static int expand(char *outbuf
, char *inbuf
);
221 static void show(register char ch
);
222 static void set_tty(void);
223 static void reset_tty(void);
224 static void rdline(register FILE *f
);
225 static off_t
command(char *filename
, register FILE *f
);
226 static int getaline(register FILE *f
, int *length
);
227 static int number(char *cmd
);
228 static int colon(char *filename
, int cmd
, off_t nlines
);
231 main(int argc
, char *argv
[])
245 setlocale( LC_ALL
, "" );
259 (void) setlocale(LC_ALL
,"");
260 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
261 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
263 (void) textdomain(TEXT_DOMAIN
);
266 if(s
= getenv("MORE")) argscan(s
);
267 while (--nfiles
> 0) {
268 if ((ch
= (*++fnames
)[0]) == '-') {
271 else if (ch
== '+') {
275 for (++s
, p
= initbuf
; p
< initbuf
+ 79 && *s
!= '\0';)
281 for (initline
= 0; *s
!= '\0'; s
++)
283 initline
= initline
*10 + *s
-'0';
289 /* allow clreol only if cursor_home and clr_eol and clr_eos strings are
290 * defined, and in that case, make sure we are in noscroll mode
294 if (!cursor_home
|| !clr_eol
|| !clr_eos
) {
301 dlines
=(off_t
) (Lpp
- (noscroll
? 1 : 2));
305 if (!no_intty
&& nfiles
== 0) {
306 fprintf(stderr
, gettext("Usage: %s\
307 [-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename ...].\n")
314 signal(SIGQUIT
, onquit
);
315 signal(SIGINT
, end_it
);
316 signal(SIGWINCH
, chgwinsz
);
318 if (signal (SIGTSTP
, SIG_IGN
) == SIG_DFL
) {
319 signal(SIGTSTP
, onsusp
);
329 if ((ch
= Getc (f
)) == '\f')
333 if (noscroll
&& (ch
!= EOF
)) {
340 if (!setjmp(restore
)) {
342 search (initbuf
, stdin
,(off_t
) 1);
347 skiplns (initline
, stdin
);
350 left
= command(NULL
, f
);
351 screen (stdin
, left
);
358 while (fnum
< nfiles
) {
359 if ((f
= checkf (fnames
[fnum
], &clearit
)) != NULL
) {
360 context
.line
= context
.chrctr
= 0;
362 if (firstf
) setjmp (restore
);
367 search (initbuf
, f
,(off_t
) 1);
372 skiplns (initline
, f
);
374 else if (fnum
< nfiles
&& !no_tty
) {
376 left
= command (fnames
[fnum
], f
);
379 if ((noscroll
|| clearit
) && (file_size
!= LLONG_MAX
))
385 if (ceol_standout_glitch
)
389 pr("::::::::::::::");
393 if(clreol
) cleareol();
394 printf("%s\n", fnames
[fnum
]);
395 if(clreol
) cleareol();
396 pr("::::::::::::::\n");
397 if (left
> (off_t
)(Lpp
- 4))
398 left
=(off_t
)(Lpp
- 4);
411 screen_start
.line
= screen_start
.chrctr
= 0LL;
412 context
.line
= context
.chrctr
= 0LL;
414 exitstat
|= 1; /*M003*/
418 if (wait_opt
) wait_eof();
420 return (exitstat
); /*M003*/
426 for (dlines
= 0; *s
!= '\0'; s
++)
428 dlines
= dlines
*10 + *s
- '0';
451 ** Check whether the file named by fs is a file which the user may
452 ** access. If it is, return the opened file. Otherwise return NULL.
456 checkf(register char *fs
, int *clearfirst
)
462 if (stat (fs
, &stbuf
) == -1) {
469 if ((stbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
470 printf(gettext("\n*** %s: directory ***\n\n"), fs
);
473 if ((f
=Fopen(fs
, "r")) == NULL
) {
479 if ((c
= Getc(f
)) == '\f') /* end M001 */
485 if ((file_size
= (off_t
)stbuf
.st_size
) == 0)
486 file_size
= LLONG_MAX
;
491 ** Print out the contents of the file f, one screenful at a time.
497 screen(register FILE *f
, register off_t num_lines
)
501 int length
; /* length of current line */
502 static int prev_len
= 1; /* length of previous line */
505 while (num_lines
> 0 && !Pause
) {
506 if ((nchars
= getaline (f
, &length
)) == EOF
)
508 if (clreol
) clreos();
511 if (ssp_opt
&& length
== 0 && prev_len
== 0)
514 if (ceol_standout_glitch
||
515 (enter_standout_mode
&& *enter_standout_mode
== ' ')
518 /* must clear before drawing line since tabs on some terminals
519 * do not erase what they tab over.
523 prbuf (Line
, length
);
524 if (nchars
< promptlen
)
525 prmpt_erase (nchars
); /* prmpt_erase () sets promptlen to 0 */
529 * cleareol(); */ /* must clear again in case we wrapped */
531 if (nchars
< Mcol
|| !fold_opt
)
538 if ((c
= Getc(f
)) == EOF
)
540 if (clreol
) clreos ();
548 Pause
= 0; startup
= 0;
549 if ((num_lines
= command (NULL
, f
)) == 0)
551 if (hard
&& promptlen
> 0)
553 if (noscroll
&& num_lines
== dlines
) {
559 screen_start
.line
= Currline
;
560 screen_start
.chrctr
= Ftell (f
);
565 ** Come here if a quit signal is received
568 * sig is put in as a dummy arg to have the compiler not to complain
575 signal(SIGQUIT
, SIG_IGN
);
579 signal(SIGQUIT
, onquit
);
580 longjmp (restore
, 1);
585 else if (!dum_opt
&& notell
) {
586 write (2, gettext("[Use q or Q to quit]"), 20);
590 signal(SIGQUIT
, onquit
);
594 ** Come here if a signal for a window size change is received
602 (void) signal(SIGWINCH
, SIG_IGN
);
603 if (ioctl(fileno(stdout
), TIOCGWINSZ
, &win
) != -1) {
604 if (win
.ws_row
!= 0) {
609 dlines
= (off_t
)(Lpp
- (noscroll
? 1 : 2));
614 (void) signal(SIGWINCH
, chgwinsz
);
618 ** Clean up terminal state and exit. Also come here if interrupt signal received
622 * sig is put in as a dummy arg to have the compiler not to complain
636 else if (!clreol
&& (promptlen
> 0)) {
642 _exit(exitstat
); /*M003*/
646 copy_file(register FILE *f
)
650 while ((c
= getc(f
)) != EOF
)
654 static char Bell
= ctrl('G');
657 /* See whether the last component of the path name "path" is equal to the
662 tailequ(char *path
, char *string
)
664 return (!strcmp(basename(path
), string
));
668 prompt(char *filename
)
672 else if (promptlen
> 0)
676 if (enter_standout_mode
&& exit_standout_mode
)
677 putp (enter_standout_mode
);
680 pr(gettext("--More--"));
681 if (filename
!= NULL
) {
682 promptlen
+= printf (gettext("(Next file: %s)"), filename
);
684 else if (!no_intty
) {
685 promptlen
+= printf ("(%d%%)", (int)((file_pos
* 100) / file_size
));
688 promptlen
+= pr(gettext("[Hit space to continue, Del to abort]"));
690 if (enter_standout_mode
&& exit_standout_mode
)
691 putp (exit_standout_mode
);
692 if (clreol
) clreos ();
701 * when run from another program or a shell script, it is
702 * sometimes useful to prevent the next program from scrolling
703 * us off the screen before we get a chance to read this page.
704 * -Hans, July 24, 1982
709 if (enter_standout_mode
&& exit_standout_mode
)
710 putp (enter_standout_mode
);
711 promptlen
= pr(gettext("--No more--")); /*M003*/
713 promptlen
+= pr(gettext("[Hit any key to continue]"));
714 if (enter_standout_mode
&& exit_standout_mode
)
715 putp(exit_standout_mode
);
716 if (clreol
) clreos();
724 ** Get a logical line
728 getaline(register FILE *f
, int *length
)
734 register int oldcolumn
;
741 if (colflg
&& c
== '\n') {
745 while (p
< &Line
[LINSIZ
- 1]) {
758 /* detect \r\n. -Hans */
759 if (p
>Line
&& p
[-1] == '\r') {
768 if (hardtabs
&& column
< promptlen
&& !hard
) {
769 if (clr_eol
&& !dumb
) {
770 column
= 1 + (column
| 7);
775 for (--p
; column
& 7 && p
< &Line
[LINSIZ
- 1]; column
++) {
778 if (column
>= promptlen
) promptlen
= 0;
782 column
= 1 + (column
| 7);
783 else if ((c
== '\b') && (ul_opt
|| !cr_opt
) && (column
> 0)) /* M008 */
786 /* this is sort of strange. what was here before was that
787 \r always set column to zero, and the hack above to
788 detect \r\n didnt exist. the net effect is to make
789 the current line be overwritten by the prompt if it
790 had a \r at the end, and the line start after the \r
791 otherwise. I suppose this is useful for overstriking
792 on hard copy terminals, but not on anything glass
795 else if ((c
== '\r') && !cr_opt
) {
799 else if (c
== '\f' && stop_opt
) {
809 else if (c
< ' ' && cr_opt
){ /* M008 begin */
811 *p
++ = c
| ('A' - 1);
814 else if (c
>= ' ' && c
!= RUBOUT
)
816 } /* end of code set 0 */
819 if ( column
> Mcol
&& fold_opt
) {
821 while ( column
< Mcol
) {
830 for(i
=1; i
<cw
[csno
];i
++)
833 } /* end of codeset 1 ~ 3 */
834 if (column
>= Mcol
&& fold_opt
) break;
837 if (column
>= Mcol
&& Mcol
> 0) {
842 colflg
= column
== Mcol
&& fold_opt
;
843 if (colflg
&& eat_newline_glitch
&& Wrap
) {
844 *p
++ = '\n'; /* simulate normal wrap */
852 ** Erase the rest of the prompt, assuming we are starting at column col.
856 prmpt_erase(register int col
)
867 if (!dumb
&& clr_eol
)
870 for (col
= promptlen
- col
; col
> 0; col
--)
877 ** Erase the current line entirely
884 if (!clr_eol
|| dumb
) putchar ('\r');
887 /* Print a buffer of n characters */
890 prbuf(register char *s
, register int n
)
892 char c
; /* next ouput character */
893 register int state
= 0; /* next output char's UL state */
894 static int pstate
= 0; /* current terminal UL state (off) */
900 if (n
>= 2 && s
[0] == '_' && s
[1] == '\b') {
905 } else if (n
>= 2 && s
[1] == '\b' && s
[2] == '_') {
915 putp(state
? ULenter
: ULexit
);
918 if (state
&& underline_char
) {
920 putp(underline_char
);
925 * You don't want to stay in standout mode at the end of the line;
926 * on some terminals, this will leave all of the remaining blank
927 * space on the line in standout mode.
929 if (state
&& !underline_char
) { /*M002*/
930 putp(ULexit
); /*M002*/
942 if (clear_screen
&& !hard
) {
945 /* Put out carriage return so that system doesn't
946 ** get confused by escape sequences when expanding tabs
954 static int lastcmd
, lastp
;
955 static off_t lastarg
;
956 static int lastcolon
;
957 char shell_line
[PATH_MAX
];
960 ** Read a command and do it. A command consists of an optional integer
961 ** argument followed by the command character. Return the number of lines
962 ** to display in the next screenful. If there is nothing more to display
963 ** in the current file, zero is returned.
967 command(char *filename
, register FILE *f
)
969 register off_t nlines
;
970 register off_t retval
;
975 char comchar
, cmdbuf
[80];
979 #define ret(val) retval=val;done++;break
987 nlines
= number (&comchar
);
989 if (comchar
== '.') { /* Repeat last command */
998 if((comchar
!= RUBOUT
) && !dum_opt
) {
999 if (comchar
== otty
.c_cc
[VERASE
]) {
1007 retval
= colon (filename
, colonch
, nlines
);
1014 register off_t initline
;
1021 if (nlines
== 0) nlines
++;
1028 printf (gettext("...back %lld page"), nlines
);
1038 initline
= Currline
- dlines
* (nlines
+ 1);
1041 if (initline
< 0) initline
= 0;
1043 Currline
= 0; /* skiplns() will make Currline correct */
1044 skiplns(initline
, f
);
1054 if (nlines
== 0) nlines
= dlines
;
1055 else if (comchar
== 'z') dlines
= nlines
;
1059 if (nlines
!= 0) nscroll
= nlines
;
1068 if (nlines
== 0) nlines
++;
1076 printf (gettext("...skipping %lld line"), nlines
);
1086 while (nlines
> 0) {
1087 while ((c
= Getc (f
)) != '\n')
1106 Fseek (f
, screen_start
.chrctr
);
1107 Currline
= screen_start
.line
;
1111 write (2, &Bell
, 1);
1117 pr (gettext("\n***Back***\n\n"));
1118 Fseek (f
, context
.chrctr
);
1119 Currline
= context
.line
;
1123 write (2, &Bell
, 1);
1128 promptlen
= printf ("%lld", Currline
);
1135 if (nlines
== 0) nlines
++;
1142 search (NULL
, f
, nlines
); /* Use previous r.e. */
1145 ttyin (cmdbuf
, 78, '/');
1147 search (cmdbuf
, f
, nlines
);
1151 do_shell (filename
);
1156 * First get local help file.
1158 loc
= setlocale(LC_MESSAGES
, 0);
1159 sprintf(filebuf
, LOCAL_HELP
, loc
);
1161 if ((strcmp(loc
, "C") == 0) || (helpf
= fopen (filebuf
, "r")) == NULL
) {
1162 if ((helpf
= fopen (HELPFILE
, "r")) == NULL
)
1163 error (gettext("Can't open help file"));
1165 if (noscroll
) doclear ();
1170 case 'v': /* This case should go right before default */
1174 sprintf(&cmdbuf
[1], "%lld", Currline
);
1175 pr ("vi "); pr (cmdbuf
); putchar (' '); pr (fnames
[fnum
]);
1176 execute (filename
, VI
, "vi", cmdbuf
, fnames
[fnum
], 0);
1182 promptlen
= pr(gettext("[Press 'h' for instructions.]"));
1186 write (2, &Bell
, 1);
1201 * Execute a colon-prefixed command.
1202 * Returns <0 if not a command that should cause
1203 * more of the file to be printed.
1207 colon(char *filename
, int cmd
, off_t nlines
)
1218 promptlen
= printf (gettext("\"%s\" line %lld"),
1219 fnames
[fnum
], Currline
);
1222 gettext("[Not a file] line %lld"), Currline
);
1227 if (fnum
>= nfiles
- 1)
1233 skipf ((int)nlines
);
1237 write (2, &Bell
, 1);
1244 skipf ((int)-nlines
);
1247 do_shell (filename
);
1253 write (2, &Bell
, 1);
1259 ** Read a decimal number from the terminal. Set cmd to the non-digit which
1260 ** terminates the number.
1268 i
= 0; ch
= otty
.c_cc
[VKILL
];
1271 if (ch
>= '0' && ch
<= '9') {
1272 i
= i
*10 + ch
- '0';
1273 } else if (ch
== RUBOUT
) {
1277 } else if (ch
== otty
.c_cc
[VKILL
]) {
1288 do_shell(char *filename
)
1299 ttyin (cmdbuf
, 78, '!');
1300 if (expand (shell_line
, cmdbuf
)) {
1302 promptlen
= printf ("!%s", shell_line
);
1309 execute (filename
, shell
, shell
, "-c", shell_line
, 0);
1313 ** Search for nth ocurrence of regular expression contained in buf in the file
1317 search(char buf
[], FILE *file
, register off_t n
)
1319 off_t startline
= Ftell (file
);
1320 register off_t line1
= startline
;
1321 register off_t line2
= startline
;
1322 register off_t line3
= startline
;
1323 register off_t lncount
;
1325 static char *s
= NULL
;
1326 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*/
1421 argp
[count
] = va_arg(ap
, char *);
1423 if (count
> MAXARGS
)
1424 error (gettext("Too many arguments in execute()\n"));
1425 } while (argp
[count
- 1] != NULL
);
1428 write (2, "exec failed\n", 12);
1431 signal (SIGINT
, SIG_IGN
);
1432 signal (SIGQUIT
, SIG_IGN
);
1433 signal (SIGWINCH
, SIG_IGN
);
1436 signal(SIGTSTP
, SIG_DFL
);
1439 signal (SIGINT
, end_it
);
1440 signal (SIGQUIT
, onquit
);
1441 signal (SIGWINCH
, chgwinsz
);
1444 signal(SIGTSTP
, onsusp
);
1447 * Since we were ignoring window change signals while we executed
1448 * the command, we must assume the window changed.
1453 pr ("------------------------\n");
1457 ** Skip n lines in the file f
1461 skiplns(register off_t n
, register FILE *f
)
1466 while ((c
= Getc (f
)) != '\n')
1475 ** Skip nskip files in the file list (from the command line). Nskip may be
1480 skipf(register int nskip
)
1482 if (nskip
== 0) return;
1484 if (fnum
+ nskip
> nfiles
- 1)
1485 nskip
= nfiles
- fnum
- 1;
1492 pr (gettext("\n...Skipping "));
1497 printf(gettext("...Skipping to file %s\n"), fnames
[fnum
]);
1499 printf(gettext("...Skipping back to file %s\n"), fnames
[fnum
]);
1506 /*----------------------------- Terminal I/O -------------------------------*/
1513 setbuf(stdout
, obuf
);
1514 if (!(no_tty
= ioctl(1, TCGETA
, &otty
))) {
1515 if (setupterm(NULL
, 1, &erret
) != OK
) {
1520 if (((Lpp
= lines
) < 0) || hard_copy
) {
1521 hard
++; /* Hard copy terminal */
1524 if (tailequ(fnames
[0], "page") || !hard
&& (scroll_forward
== NULL
))
1526 if ((Mcol
= columns
) < 0)
1528 Wrap
= tigetflag("am");
1530 * Set up for underlining: some terminals don't need it;
1531 * others have start/stop sequences, still others have an
1532 * underline char sequence which is assumed to move the
1533 * cursor forward one character. If underline sequence
1534 * isn't available, settle for standout sequence.
1537 if (transparent_underline
|| over_strike
)
1539 if ((ULenter
= tigetstr("smul")) == NULL
&&
1540 (!underline_char
) && (ULenter
= tigetstr("smso")) == NULL
)
1542 if ((ULexit
= tigetstr("rmul")) == NULL
&&
1543 (!underline_char
) && (ULexit
= tigetstr("rmso")) == NULL
)
1546 if ((shell
= getenv("SHELL")) == NULL
)
1547 shell
= "/usr/bin/sh";
1549 no_intty
= ioctl(0, TCGETA
, &otty
);
1550 ioctl(2, TCGETA
, &otty
);
1551 hardtabs
= !(otty
.c_oflag
& TAB3
);
1560 if (read (2, &ch
, 1) <= 0)
1562 end_it(0); /* clean up before exiting */
1564 ch
= otty
.c_cc
[VKILL
];
1568 static char BS
= '\b';
1569 static char CARAT
= '^';
1572 ttyin(char buf
[], register int nmax
, char pchar
)
1574 register char *sptr
;
1575 register unsigned char ch
;
1576 int LengthBuffer
[80];
1579 register int slash
= 0;
1583 BufferPointer
= LengthBuffer
;
1586 while (sptr
- buf
< nmax
) {
1587 if (promptlen
> maxlen
)
1594 } else if ((ch
== otty
.c_cc
[VERASE
]) && !slash
) {
1598 sptr
-= (*--BufferPointer
);
1599 if ((*sptr
< ' ' && *sptr
!= '\n') || *sptr
== RUBOUT
) {
1607 longjmp (restore
, 1);
1609 } else if ((ch
== otty
.c_cc
[VKILL
]) && !slash
) {
1625 if (slash
&& (ch
== otty
.c_cc
[VKILL
] || ch
== otty
.c_cc
[VERASE
])) {
1627 sptr
-= (*--BufferPointer
);
1631 *BufferPointer
++ = 1;
1633 if ((ch
< ' ' && ch
!= '\n' && ch
!= ESC
) || ch
== RUBOUT
) {
1634 ch
+= ch
== RUBOUT
? -0100 : 0100;
1635 write (2, &CARAT
, 1);
1639 if (ch
!= '\n' && ch
!= ESC
) {
1640 write (2, &cbuf
, 1);
1644 /* end of code set 0 */
1649 *BufferPointer
++ = cw
[csno
];
1650 buffer
[0] = *sptr
++ = ch
;
1651 for(i
=1; i
<cw
[csno
]; i
++) {
1652 buffer
[i
] = *sptr
++ = readch();
1655 write(2, buffer
, strlen((char *)buffer
));
1659 if (!clr_eol
) promptlen
= maxlen
;
1660 if (sptr
- buf
>= nmax
- 1)
1661 error (gettext("Line too long"));
1665 expand(char *outbuf
, char *inbuf
)
1670 char temp
[PATH_MAX
];
1675 while ((ch
= *in_str
++) != '\0')
1679 if (strlcpy(out_str
, fnames
[fnum
], sizeof (temp
))
1681 error(gettext("Command too long"));
1682 out_str
+= strlen (fnames
[fnum
]);
1690 error (gettext("No previous command to substitute for"));
1691 if (strlcpy(out_str
, shell_line
, sizeof (temp
)) >= sizeof (temp
))
1692 error(gettext("Command too long"));
1693 out_str
+= strlen (shell_line
);
1697 if (*in_str
== '%' || *in_str
== '!') {
1698 *out_str
++ = *in_str
++;
1705 if (strlcpy(outbuf
, temp
, sizeof (shell_line
)) >= sizeof (shell_line
))
1706 error(gettext("Command too long"));
1711 show(register char ch
)
1715 if ((ch
< ' ' && ch
!= '\n' && ch
!= ESC
) || ch
== RUBOUT
) {
1716 ch
+= ch
== RUBOUT
? -0100 : 0100;
1717 write (2, &CARAT
, 1);
1721 write (2, &cbuf
, 1);
1732 promptlen
+= strlen (mess
);
1733 if (enter_standout_mode
&& exit_standout_mode
) {
1734 putp (enter_standout_mode
);
1736 putp (exit_standout_mode
);
1742 longjmp (restore
, 1);
1749 ioctl(2, TCGETA
, &otty
); /* save old tty modes */
1750 ioctl(2, TCGETA
, &ntty
);
1751 ntty
.c_lflag
&= ~ECHO
& ~ICANON
;
1752 ntty
.c_cc
[VMIN
] = (char)1;
1753 ntty
.c_cc
[VTIME
] = (char)0;
1754 ioctl (2, TCSETAF
, &ntty
); /* set new tty modes */
1760 ioctl (2, TCSETAF
, &otty
); /* reset tty modes */
1764 rdline(register FILE *f
)
1770 while ((c
= Getc (f
)) != '\n' && c
!= EOF
&& p
- Line
< LINSIZ
- 1)
1777 /* Come here when we get a suspend signal from the terminal */
1780 * sig is put in as a dummy arg to have the compiler not to complain
1787 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
1788 signal(SIGTTOU
, SIG_IGN
);
1791 signal(SIGTTOU
, SIG_DFL
);
1793 /* Send the TSTP signal to suspend our process group */
1795 /* Pause for station break */
1798 signal (SIGTSTP
, onsusp
);
1801 longjmp (restore
, 1);