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