xref: /onnv-gate/usr/src/cmd/more/more.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52932Sas145665  * Common Development and Distribution License (the "License").
62932Sas145665  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
300Sstevel@tonic-gate /*	  All Rights Reserved	*/
310Sstevel@tonic-gate 
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
340Sstevel@tonic-gate  * The Regents of the University of California
350Sstevel@tonic-gate  * All Rights Reserved
360Sstevel@tonic-gate  *
370Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
380Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
390Sstevel@tonic-gate  * contributors.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate  *      @(#) more.c 1.1 88/03/29 more:more.c
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate ** more.c - General purpose tty output filter and file perusal program
480Sstevel@tonic-gate **
490Sstevel@tonic-gate **      by Eric Shienbrood, UC Berkeley
500Sstevel@tonic-gate **
510Sstevel@tonic-gate **      modified by Geoff Peck, UCB to add underlining, single spacing
520Sstevel@tonic-gate **      modified by John Foderaro, UCB to add -c and MORE environment variable
530Sstevel@tonic-gate **      modified by Hans Spiller, Microsoft to handle \r better July 23, 82
540Sstevel@tonic-gate **              added ? help command, and -w
550Sstevel@tonic-gate **
560Sstevel@tonic-gate **      vwh     11 Jan 83       M001
570Sstevel@tonic-gate **              modified to handle x.out magic number and magic number
580Sstevel@tonic-gate **              byte ordering OTHER than the vax and pdp11.
590Sstevel@tonic-gate **      JJD     19 Jan 83       M002
600Sstevel@tonic-gate **              - fix distributed on USENET
610Sstevel@tonic-gate **                From decvax!ucbvax!dist2 Sun Dec  6 02:58:31 1981
620Sstevel@tonic-gate **                Subject: FIXED:  bug in src/more/more.c
630Sstevel@tonic-gate **              - fixed bug on terminal with "magic cookie" standout
640Sstevel@tonic-gate **                sequences.
650Sstevel@tonic-gate **      JJD     14 Feb 83       M003
660Sstevel@tonic-gate **              - fix exit status of more
670Sstevel@tonic-gate **              - Made first letter of "no more" message uppercase
680Sstevel@tonic-gate **      andyp   03 Aug 83       M004    3.0 upgrade
690Sstevel@tonic-gate **      - moved <local/uparm.h> to cmd/include.
700Sstevel@tonic-gate **      - use UCB, rather than XENIX, stty(2).
710Sstevel@tonic-gate **      andyp   30 Nov 83       M005
720Sstevel@tonic-gate **      - (thanks to reubenb).  Changed frame variable to static, it is
730Sstevel@tonic-gate **        used as a global buffer.  We never saw the bug before because
740Sstevel@tonic-gate **        of the depth of the stack.
750Sstevel@tonic-gate **      barrys  03 Jul 84       M006
760Sstevel@tonic-gate **      - Updated the usage message to include the 's' and 'w' options
770Sstevel@tonic-gate **        and to make the 'n' option a separate entry (uncommented).
780Sstevel@tonic-gate **      ericc   26 Dec 84       M007
790Sstevel@tonic-gate **      - Replaced the constant 0x7fffffffffffffffL with MAXLONG.
800Sstevel@tonic-gate **      ericc   25 Jul 85       M008
810Sstevel@tonic-gate **      - made "-r" option display control characters as '^x', as documented.
820Sstevel@tonic-gate **      - fixed processing of '\b' so that more doesn't terminate when
830Sstevel@tonic-gate **        the sequence "\b\n" is encountered.
840Sstevel@tonic-gate **      - changed "Hit Rubout ..." to "Hit Del ...", for ibm keyboards.
850Sstevel@tonic-gate **	davidby 9 March 1988	Unmarked
860Sstevel@tonic-gate **	- replaced all locally defined functions with library equivalents,
870Sstevel@tonic-gate **	- changed from termcap to terminfo
880Sstevel@tonic-gate **	- included <values.h> for MAXLONG value
890Sstevel@tonic-gate **	- removed most ifdef code for V6, V7, and BSD
900Sstevel@tonic-gate **	- added /etc/magic support for file type checking
910Sstevel@tonic-gate */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate #include <ctype.h>
940Sstevel@tonic-gate #include <signal.h>
950Sstevel@tonic-gate #include <errno.h>
960Sstevel@tonic-gate #include <sys/types.h>
970Sstevel@tonic-gate #include <sys/wait.h>
980Sstevel@tonic-gate #include <curses.h>
990Sstevel@tonic-gate #include <term.h>
1000Sstevel@tonic-gate #include <sys/ioctl.h>
1010Sstevel@tonic-gate #include <setjmp.h>
1020Sstevel@tonic-gate #include <sys/stat.h>
1030Sstevel@tonic-gate #include <values.h>
1040Sstevel@tonic-gate #include <stdlib.h>
1050Sstevel@tonic-gate #include <stdarg.h>
1060Sstevel@tonic-gate #include <string.h>
1070Sstevel@tonic-gate #include <unistd.h>
1080Sstevel@tonic-gate #include <libgen.h>
1090Sstevel@tonic-gate #include <euc.h>
1100Sstevel@tonic-gate #include <getwidth.h>
1110Sstevel@tonic-gate #include <locale.h>
1120Sstevel@tonic-gate #include <widec.h>
1130Sstevel@tonic-gate #include <wctype.h>
1140Sstevel@tonic-gate #include <limits.h>
1150Sstevel@tonic-gate eucwidth_t wp;
1160Sstevel@tonic-gate int     cw[4];
1170Sstevel@tonic-gate int     scw[4];
1180Sstevel@tonic-gate #include <locale.h>
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /* Help file will eventually go in libpath(more.help) on all systems */
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate #ifdef INGRES
1230Sstevel@tonic-gate #define VI              "/usr/bin/vi"
1240Sstevel@tonic-gate #define HELPFILE        "/mntp/doucette/more/more.help"
1250Sstevel@tonic-gate #define LOCAL_HELP	"/usr/lib/locale/%s/LC_MESSAGES/more.help"
1260Sstevel@tonic-gate #endif
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate #ifndef INGRES
1290Sstevel@tonic-gate #ifndef HELPFILE
1300Sstevel@tonic-gate #define HELPFILE        "/usr/lib/more.help"
1310Sstevel@tonic-gate #define LOCAL_HELP	"/usr/lib/locale/%s/LC_MESSAGES/more.help"
1320Sstevel@tonic-gate #endif
1330Sstevel@tonic-gate #define VI              "vi"
1340Sstevel@tonic-gate #endif
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate #define Fopen(s,m)      (Currline = 0,file_pos=0,fopen(s,m))
1370Sstevel@tonic-gate #define Ftell(f)        file_pos
1380Sstevel@tonic-gate #define Fseek(f,off)    (file_pos=off,fseeko(f,off,0))
1390Sstevel@tonic-gate #define Getc(f)         (++file_pos, getc(f))
1400Sstevel@tonic-gate #define Ungetc(c,f)     (--file_pos, ungetc(c,f))
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate #define pr(s1)		fputs(s1, stdout)
1430Sstevel@tonic-gate #define clreos()	putp(clr_eos)
1440Sstevel@tonic-gate #define cleareol()	putp(clr_eol)
1450Sstevel@tonic-gate #define home()		putp(cursor_home)
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate #define LINSIZ  512
1480Sstevel@tonic-gate #define ctrl(letter)    ((letter) & 077)
1490Sstevel@tonic-gate #define RUBOUT  '\177'
1500Sstevel@tonic-gate #define ESC     '\033'
1510Sstevel@tonic-gate #define QUIT    '\034'
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate struct termio   otty;           /* old tty modes */
1540Sstevel@tonic-gate struct termio   ntty;           /* new tty modes */
1550Sstevel@tonic-gate off_t           file_pos, file_size;
1560Sstevel@tonic-gate int             fnum, no_intty, no_tty;
1570Sstevel@tonic-gate int             dum_opt;
1580Sstevel@tonic-gate off_t           dlines;
1590Sstevel@tonic-gate void end_it(int sig);
1600Sstevel@tonic-gate void onquit(int sig);
1610Sstevel@tonic-gate void chgwinsz(int sig);
1620Sstevel@tonic-gate #ifdef SIGTSTP
1630Sstevel@tonic-gate void             onsusp(int sig);
1640Sstevel@tonic-gate #endif
1650Sstevel@tonic-gate int             nscroll = 11;   /* Number of lines scrolled by 'd' */
1660Sstevel@tonic-gate int             fold_opt = 1;   /* Fold long lines */
1670Sstevel@tonic-gate int             stop_opt = 1;   /* Stop after form feeds */
1680Sstevel@tonic-gate int             ssp_opt = 0;    /* Suppress white space */
1690Sstevel@tonic-gate int             ul_opt = 1;     /* Underline as best we can */
1700Sstevel@tonic-gate int             cr_opt = 0;     /* show ctrl characters as '^c' */
1710Sstevel@tonic-gate int             wait_opt = 0;   /* prompt for exit at eof */
1720Sstevel@tonic-gate int             promptlen;
1730Sstevel@tonic-gate off_t		Currline;       /* Line we are currently at */
1740Sstevel@tonic-gate int             startup = 1;
1750Sstevel@tonic-gate int             firstf = 1;
1760Sstevel@tonic-gate int             notell = 1;
1770Sstevel@tonic-gate int             inwait, Pause, errors;
1780Sstevel@tonic-gate int             within; /* true if we are within a file,
1790Sstevel@tonic-gate                         false if we are between files */
1800Sstevel@tonic-gate int             hard, dumb, noscroll, hardtabs, clreol;
1810Sstevel@tonic-gate int             catch_susp;     /* We should catch the SIGTSTP signal */
1820Sstevel@tonic-gate char            **fnames;       /* The list of file names */
1830Sstevel@tonic-gate int             nfiles;         /* Number of files left to process */
1840Sstevel@tonic-gate char            *shell;         /* The name of the shell to use */
1850Sstevel@tonic-gate int             shellp;         /* A previous shell command exists */
1860Sstevel@tonic-gate char            ch;
1870Sstevel@tonic-gate jmp_buf         restore;
1880Sstevel@tonic-gate char            obuf[BUFSIZ];   /* stdout buffer */
1890Sstevel@tonic-gate char            Line[LINSIZ];   /* Line buffer */
1900Sstevel@tonic-gate int             Lpp = 24;       /* lines per page */
1910Sstevel@tonic-gate char            *ULenter, *ULexit;      /* enter and exit underline mode */
1920Sstevel@tonic-gate int             Mcol = 80;      /* number of columns */
1930Sstevel@tonic-gate int             Wrap = 1;       /* set if automargins */
1940Sstevel@tonic-gate int		fseeko();
1950Sstevel@tonic-gate struct {
1960Sstevel@tonic-gate     off_t chrctr, line;
1970Sstevel@tonic-gate } context, screen_start;
1980Sstevel@tonic-gate int             exitstat = 0;   /* status to use when exiting more */   /*M003*/
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate static void execute(char *filename, char *cmd, ...);
2010Sstevel@tonic-gate static void error(char *mess);
2020Sstevel@tonic-gate static void wait_eof(void);
2030Sstevel@tonic-gate static void prompt(char *filename);
2040Sstevel@tonic-gate static void argscan(char *s);
2050Sstevel@tonic-gate static void copy_file(register FILE *f);
2060Sstevel@tonic-gate static void initterm(void);
2070Sstevel@tonic-gate static void do_shell(char *filename);
2080Sstevel@tonic-gate static FILE *checkf(register char *fs, int *clearfirst);
2090Sstevel@tonic-gate static void screen(register FILE *f, register off_t num_lines);
2100Sstevel@tonic-gate static void skiplns(register off_t n, register FILE *f);
2110Sstevel@tonic-gate static void skipf(register int nskip);
2120Sstevel@tonic-gate static int readch(void);
2130Sstevel@tonic-gate static void prmpt_erase(register int col);
2140Sstevel@tonic-gate static void kill_line(void);
2150Sstevel@tonic-gate static void prbuf(register char *s, register int n);
2160Sstevel@tonic-gate static void search(char buf[], FILE *file, register off_t n);
2170Sstevel@tonic-gate static void doclear(void);
2180Sstevel@tonic-gate static void ttyin(char buf[], register int nmax, char pchar);
2190Sstevel@tonic-gate static int expand(char *outbuf, char *inbuf);
2200Sstevel@tonic-gate static void show(register char ch);
2210Sstevel@tonic-gate static void set_tty(void);
2220Sstevel@tonic-gate static void reset_tty(void);
2230Sstevel@tonic-gate static void rdline(register FILE *f);
2240Sstevel@tonic-gate static off_t command(char *filename, register FILE *f);
225*13093SRoger.Faulkner@Oracle.COM static int getaline(register FILE *f, int *length);
2260Sstevel@tonic-gate static int number(char *cmd);
2270Sstevel@tonic-gate static int colon(char *filename, int cmd, off_t nlines);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate int
main(int argc,char * argv[])2300Sstevel@tonic-gate main(int argc, char *argv[])
2310Sstevel@tonic-gate {
2320Sstevel@tonic-gate     register FILE       *f;
2330Sstevel@tonic-gate     register char       *s;
2340Sstevel@tonic-gate     register char       *p;
2350Sstevel@tonic-gate     register int	ch;
2360Sstevel@tonic-gate     register off_t      left;
2370Sstevel@tonic-gate     int                 prnames = 0;
2380Sstevel@tonic-gate     int                 initopt = 0;
2390Sstevel@tonic-gate     int                 srchopt = 0;
2400Sstevel@tonic-gate     int                 clearit = 0;
2410Sstevel@tonic-gate     off_t               initline;
2420Sstevel@tonic-gate     char                initbuf[80];
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate     setlocale( LC_ALL, "" );
2450Sstevel@tonic-gate     getwidth(&wp);
2460Sstevel@tonic-gate     cw[0] = 1;
2470Sstevel@tonic-gate     cw[1] = wp._eucw1;
2480Sstevel@tonic-gate     cw[2] = wp._eucw2+1;
2490Sstevel@tonic-gate     cw[3] = wp._eucw3+1;
2500Sstevel@tonic-gate     scw[0] = 1;
2510Sstevel@tonic-gate     scw[1] = wp._scrw1;
2520Sstevel@tonic-gate     scw[2] = wp._scrw2;
2530Sstevel@tonic-gate     scw[3] = wp._scrw3;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate     nfiles = argc;
2560Sstevel@tonic-gate     fnames = argv;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate     (void) setlocale(LC_ALL,"");
2590Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2600Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
2610Sstevel@tonic-gate #endif
2620Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate     initterm ();
2650Sstevel@tonic-gate     if(s = getenv("MORE")) argscan(s);
2660Sstevel@tonic-gate     while (--nfiles > 0) {
2670Sstevel@tonic-gate         if ((ch = (*++fnames)[0]) == '-') {
2680Sstevel@tonic-gate             argscan(*fnames+1);
2690Sstevel@tonic-gate         }
2700Sstevel@tonic-gate         else if (ch == '+') {
2710Sstevel@tonic-gate             s = *fnames;
2720Sstevel@tonic-gate             if (*++s == '/') {
2730Sstevel@tonic-gate                 srchopt++;
2740Sstevel@tonic-gate                 for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';)
2750Sstevel@tonic-gate                     *p++ = *s++;
2760Sstevel@tonic-gate                 *p = '\0';
2770Sstevel@tonic-gate             }
2780Sstevel@tonic-gate             else {
2790Sstevel@tonic-gate                 initopt++;
2800Sstevel@tonic-gate                 for (initline = 0; *s != '\0'; s++)
2810Sstevel@tonic-gate                     if (isdigit (*s))
2820Sstevel@tonic-gate                         initline = initline*10 + *s -'0';
2830Sstevel@tonic-gate                 --initline;
2840Sstevel@tonic-gate             }
2850Sstevel@tonic-gate         }
2860Sstevel@tonic-gate         else break;
2870Sstevel@tonic-gate     }
2880Sstevel@tonic-gate     /* allow clreol only if cursor_home and clr_eol and clr_eos strings are
2890Sstevel@tonic-gate      *  defined, and in that case, make sure we are in noscroll mode
2900Sstevel@tonic-gate      */
2910Sstevel@tonic-gate     if(clreol)
2920Sstevel@tonic-gate     {
2930Sstevel@tonic-gate         if (!cursor_home || !clr_eol || !clr_eos) {
2940Sstevel@tonic-gate            	clreol = 0;
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate         else noscroll = 1;
2970Sstevel@tonic-gate     }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate     if (dlines == 0)
3000Sstevel@tonic-gate         dlines =(off_t) (Lpp - (noscroll ? 1 : 2));
3010Sstevel@tonic-gate     left = dlines;
3020Sstevel@tonic-gate     if (nfiles > 1)
3030Sstevel@tonic-gate         prnames++;
3040Sstevel@tonic-gate     if (!no_intty && nfiles == 0) {
3050Sstevel@tonic-gate 	fprintf(stderr, gettext("Usage: %s\
3060Sstevel@tonic-gate  [-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename ...].\n")
3070Sstevel@tonic-gate 	, argv[0]);
3080Sstevel@tonic-gate         exit(1);
3090Sstevel@tonic-gate     }
3100Sstevel@tonic-gate     else
3110Sstevel@tonic-gate         f = stdin;
3120Sstevel@tonic-gate     if (!no_tty) {
3130Sstevel@tonic-gate         signal(SIGQUIT, onquit);
3140Sstevel@tonic-gate         signal(SIGINT, end_it);
3150Sstevel@tonic-gate         signal(SIGWINCH, chgwinsz);
3160Sstevel@tonic-gate #ifdef SIGTSTP
3170Sstevel@tonic-gate         if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
3180Sstevel@tonic-gate             signal(SIGTSTP, onsusp);
3190Sstevel@tonic-gate             catch_susp++;
3200Sstevel@tonic-gate         }
3210Sstevel@tonic-gate #endif
3220Sstevel@tonic-gate         set_tty();
3230Sstevel@tonic-gate     }
3240Sstevel@tonic-gate     if (no_intty) {
3250Sstevel@tonic-gate         if (no_tty)
3260Sstevel@tonic-gate             copy_file (stdin);
3270Sstevel@tonic-gate         else {
3280Sstevel@tonic-gate             if ((ch = Getc (f)) == '\f')
3290Sstevel@tonic-gate                 doclear();
3300Sstevel@tonic-gate             else {
3310Sstevel@tonic-gate                 Ungetc (ch, f);
3320Sstevel@tonic-gate                 if (noscroll && (ch != EOF)) {
3330Sstevel@tonic-gate                     if (clreol)
3340Sstevel@tonic-gate                         home ();
3350Sstevel@tonic-gate                     else
3360Sstevel@tonic-gate                         doclear ();
3370Sstevel@tonic-gate                 }
3380Sstevel@tonic-gate             }
3390Sstevel@tonic-gate             if (!setjmp(restore)) {
3400Sstevel@tonic-gate                 if (srchopt) {
3410Sstevel@tonic-gate                     search (initbuf, stdin,(off_t) 1);
3420Sstevel@tonic-gate                     if (noscroll)
3430Sstevel@tonic-gate                         left--;
3440Sstevel@tonic-gate                     }
3450Sstevel@tonic-gate                 else if (initopt)
3460Sstevel@tonic-gate                     skiplns (initline, stdin);
3470Sstevel@tonic-gate                 }
3480Sstevel@tonic-gate             else
3490Sstevel@tonic-gate                 left = command(NULL, f);
3500Sstevel@tonic-gate             screen (stdin, left);
3510Sstevel@tonic-gate         }
3520Sstevel@tonic-gate         no_intty = 0;
3530Sstevel@tonic-gate         prnames++;
3540Sstevel@tonic-gate         firstf = 0;
3550Sstevel@tonic-gate     }
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate     while (fnum < nfiles) {
3580Sstevel@tonic-gate         if ((f = checkf (fnames[fnum], &clearit)) != NULL) {
3590Sstevel@tonic-gate             context.line = context.chrctr = 0;
3600Sstevel@tonic-gate             Currline = 0;
3610Sstevel@tonic-gate             if (firstf) setjmp (restore);
3620Sstevel@tonic-gate             if (firstf) {
3630Sstevel@tonic-gate                 firstf = 0;
3640Sstevel@tonic-gate                 if (srchopt)
3650Sstevel@tonic-gate                 {
3660Sstevel@tonic-gate                     search (initbuf, f,(off_t) 1);
3670Sstevel@tonic-gate                     if (noscroll)
3680Sstevel@tonic-gate                         left--;
3690Sstevel@tonic-gate                 }
3700Sstevel@tonic-gate                 else if (initopt)
3710Sstevel@tonic-gate                     skiplns (initline, f);
3720Sstevel@tonic-gate             }
3730Sstevel@tonic-gate             else if (fnum < nfiles && !no_tty) {
3740Sstevel@tonic-gate                 setjmp (restore);
3750Sstevel@tonic-gate                 left = command (fnames[fnum], f);
3760Sstevel@tonic-gate             }
3770Sstevel@tonic-gate             if (left != 0) {
3780Sstevel@tonic-gate                 if ((noscroll || clearit) && (file_size != LLONG_MAX))
3790Sstevel@tonic-gate                     if (clreol)
3800Sstevel@tonic-gate                         home ();
3810Sstevel@tonic-gate                     else
3820Sstevel@tonic-gate                         doclear ();
3830Sstevel@tonic-gate                 if (prnames) {
3840Sstevel@tonic-gate                     if (ceol_standout_glitch)
3850Sstevel@tonic-gate                         prmpt_erase (0);
3860Sstevel@tonic-gate                     if (clreol)
3870Sstevel@tonic-gate                         cleareol ();
3880Sstevel@tonic-gate                     pr("::::::::::::::");
3890Sstevel@tonic-gate                     if (promptlen > 14)
3900Sstevel@tonic-gate                         prmpt_erase (14);
3910Sstevel@tonic-gate                     printf ("\n");
3920Sstevel@tonic-gate                     if(clreol) cleareol();
3930Sstevel@tonic-gate                     printf("%s\n", fnames[fnum]);
3940Sstevel@tonic-gate                     if(clreol) cleareol();
3950Sstevel@tonic-gate                     pr("::::::::::::::\n");
3960Sstevel@tonic-gate                     if (left > (off_t)(Lpp - 4))
3970Sstevel@tonic-gate                         left =(off_t)(Lpp - 4);
3980Sstevel@tonic-gate                 }
3990Sstevel@tonic-gate                 if (no_tty)
4000Sstevel@tonic-gate                     copy_file (f);
4010Sstevel@tonic-gate                 else {
4020Sstevel@tonic-gate                     within++;
4030Sstevel@tonic-gate                     screen(f, left);
4040Sstevel@tonic-gate                     within = 0;
4050Sstevel@tonic-gate                 }
4060Sstevel@tonic-gate             }
4070Sstevel@tonic-gate             setjmp (restore);
4080Sstevel@tonic-gate             fflush(stdout);
4090Sstevel@tonic-gate             fclose(f);
4100Sstevel@tonic-gate             screen_start.line = screen_start.chrctr = 0LL;
4110Sstevel@tonic-gate             context.line = context.chrctr = 0LL;
4120Sstevel@tonic-gate         } else
4130Sstevel@tonic-gate             exitstat |= 1;                      /*M003*/
4140Sstevel@tonic-gate         fnum++;
4150Sstevel@tonic-gate         firstf = 0;
4160Sstevel@tonic-gate     }
4170Sstevel@tonic-gate     if (wait_opt) wait_eof();
4180Sstevel@tonic-gate     reset_tty ();
4190Sstevel@tonic-gate     return (exitstat);                             /*M003*/
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate static void
argscan(char * s)4230Sstevel@tonic-gate argscan(char *s)
4240Sstevel@tonic-gate {
4250Sstevel@tonic-gate             for (dlines = 0; *s != '\0'; s++)
4260Sstevel@tonic-gate                 if (isdigit(*s))
4270Sstevel@tonic-gate                     dlines = dlines*10 + *s - '0';
4280Sstevel@tonic-gate                 else if (*s == 'd')
4290Sstevel@tonic-gate                     dum_opt = 1;
4300Sstevel@tonic-gate                 else if (*s == 'l')
4310Sstevel@tonic-gate                     stop_opt = 0;
4320Sstevel@tonic-gate                 else if (*s == 'f')
4330Sstevel@tonic-gate                     fold_opt = 0;
4340Sstevel@tonic-gate                 else if (*s == 'p')
4350Sstevel@tonic-gate                     noscroll++;
4360Sstevel@tonic-gate                 else if (*s == 'c')
4370Sstevel@tonic-gate                     clreol++;
4380Sstevel@tonic-gate                 else if (*s == 's')
4390Sstevel@tonic-gate                     ssp_opt = 1;
4400Sstevel@tonic-gate                 else if (*s == 'u')
4410Sstevel@tonic-gate                     ul_opt = 0;
4420Sstevel@tonic-gate                 else if (*s == 'r')
4430Sstevel@tonic-gate                     cr_opt = 1;
4440Sstevel@tonic-gate                 else if (*s == 'w')
4450Sstevel@tonic-gate                     wait_opt = 1;
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate /*
4500Sstevel@tonic-gate ** Check whether the file named by fs is a file which the user may
4510Sstevel@tonic-gate ** access.  If it is, return the opened file. Otherwise return NULL.
4520Sstevel@tonic-gate */
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate static FILE *
checkf(register char * fs,int * clearfirst)4550Sstevel@tonic-gate checkf(register char *fs, int *clearfirst)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate     struct stat stbuf;
4580Sstevel@tonic-gate     register FILE *f;
4590Sstevel@tonic-gate     int c;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate     if (stat (fs, &stbuf) == -1) {
4620Sstevel@tonic-gate         fflush(stdout);
4630Sstevel@tonic-gate         if (clreol)
4640Sstevel@tonic-gate             cleareol ();
4650Sstevel@tonic-gate         perror(fs);
4660Sstevel@tonic-gate         return (NULL);
4670Sstevel@tonic-gate     }
4680Sstevel@tonic-gate     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
4690Sstevel@tonic-gate         printf(gettext("\n*** %s: directory ***\n\n"), fs);
4700Sstevel@tonic-gate         return (NULL);
4710Sstevel@tonic-gate     }
4720Sstevel@tonic-gate     if ((f=Fopen(fs, "r")) == NULL) {
4730Sstevel@tonic-gate         fflush(stdout);
4740Sstevel@tonic-gate         perror(fs);
4750Sstevel@tonic-gate         return (NULL);
4760Sstevel@tonic-gate     }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate     if ((c = Getc(f)) == '\f')                  /* end M001 */
4790Sstevel@tonic-gate         *clearfirst = 1;
4800Sstevel@tonic-gate     else {
4810Sstevel@tonic-gate         *clearfirst = 0;
4820Sstevel@tonic-gate         Ungetc (c, f);
4830Sstevel@tonic-gate     }
4840Sstevel@tonic-gate     if ((file_size = (off_t)stbuf.st_size) == 0)
4850Sstevel@tonic-gate         file_size = LLONG_MAX;
4860Sstevel@tonic-gate     return (f);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate /*
4900Sstevel@tonic-gate ** Print out the contents of the file f, one screenful at a time.
4910Sstevel@tonic-gate */
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate #define STOP -10
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate static void
screen(register FILE * f,register off_t num_lines)4960Sstevel@tonic-gate screen(register FILE *f, register off_t num_lines)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate     register int c;
4990Sstevel@tonic-gate     register int nchars;
5000Sstevel@tonic-gate     int length;                 /* length of current line */
5010Sstevel@tonic-gate     static int prev_len = 1;    /* length of previous line */
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate     for (;;) {
5040Sstevel@tonic-gate         while (num_lines > 0 && !Pause) {
505*13093SRoger.Faulkner@Oracle.COM             if ((nchars = getaline (f, &length)) == EOF)
5060Sstevel@tonic-gate             {
5070Sstevel@tonic-gate                 if (clreol) clreos();
5080Sstevel@tonic-gate                 return;
5090Sstevel@tonic-gate             }
5100Sstevel@tonic-gate             if (ssp_opt && length == 0 && prev_len == 0)
5110Sstevel@tonic-gate                 continue;
5120Sstevel@tonic-gate             prev_len = length;
5130Sstevel@tonic-gate             if (ceol_standout_glitch ||
5140Sstevel@tonic-gate 		(enter_standout_mode && *enter_standout_mode == ' ')
5150Sstevel@tonic-gate 		&& promptlen > 0)
5160Sstevel@tonic-gate                 prmpt_erase (0);
5170Sstevel@tonic-gate             /* must clear before drawing line since tabs on some terminals
5180Sstevel@tonic-gate              * do not erase what they tab over.
5190Sstevel@tonic-gate              */
5200Sstevel@tonic-gate             if (clreol)
5210Sstevel@tonic-gate                 cleareol ();
5220Sstevel@tonic-gate             prbuf (Line, length);
5230Sstevel@tonic-gate             if (nchars < promptlen)
5240Sstevel@tonic-gate                 prmpt_erase (nchars); /* prmpt_erase () sets promptlen to 0 */
5250Sstevel@tonic-gate             else promptlen = 0;
5260Sstevel@tonic-gate             /* is this needed?
5270Sstevel@tonic-gate              * if (clreol)
5280Sstevel@tonic-gate              *  cleareol(); */    /* must clear again in case we wrapped */
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate             if (nchars < Mcol || !fold_opt)
5310Sstevel@tonic-gate                 putchar('\n');
5320Sstevel@tonic-gate             if (nchars == STOP)
5330Sstevel@tonic-gate                 break;
5340Sstevel@tonic-gate             num_lines--;
5350Sstevel@tonic-gate         }
5360Sstevel@tonic-gate         fflush(stdout);
5370Sstevel@tonic-gate         if ((c = Getc(f)) == EOF)
5380Sstevel@tonic-gate         {
5390Sstevel@tonic-gate             if (clreol) clreos ();
5400Sstevel@tonic-gate             return;
5410Sstevel@tonic-gate         }
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate         if (Pause && clreol)
5440Sstevel@tonic-gate             clreos ();
5450Sstevel@tonic-gate         Ungetc (c, f);
5460Sstevel@tonic-gate         setjmp (restore);
5470Sstevel@tonic-gate         Pause = 0; startup = 0;
5480Sstevel@tonic-gate         if ((num_lines = command (NULL, f)) == 0)
5490Sstevel@tonic-gate             return;
5500Sstevel@tonic-gate         if (hard && promptlen > 0)
5510Sstevel@tonic-gate                 prmpt_erase (0);
5520Sstevel@tonic-gate         if (noscroll && num_lines == dlines) {
5530Sstevel@tonic-gate             if (clreol)
5540Sstevel@tonic-gate                 home();
5550Sstevel@tonic-gate             else
5560Sstevel@tonic-gate                 doclear ();
5570Sstevel@tonic-gate         }
5580Sstevel@tonic-gate         screen_start.line = Currline;
5590Sstevel@tonic-gate         screen_start.chrctr = Ftell (f);
5600Sstevel@tonic-gate     }
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate ** Come here if a quit signal is received
5650Sstevel@tonic-gate */
5660Sstevel@tonic-gate /*
5670Sstevel@tonic-gate  * sig is put in as a dummy arg to have the compiler not to complain
5680Sstevel@tonic-gate  */
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate /* ARGSUSED */
5710Sstevel@tonic-gate void
onquit(int sig)5720Sstevel@tonic-gate onquit(int sig)
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate     signal(SIGQUIT, SIG_IGN);
5750Sstevel@tonic-gate     if (!inwait) {
5760Sstevel@tonic-gate         putchar ('\n');
5770Sstevel@tonic-gate         if (!startup) {
5780Sstevel@tonic-gate             signal(SIGQUIT, onquit);
5790Sstevel@tonic-gate             longjmp (restore, 1);
5800Sstevel@tonic-gate         }
5810Sstevel@tonic-gate         else
5820Sstevel@tonic-gate             Pause++;
5830Sstevel@tonic-gate     }
5840Sstevel@tonic-gate     else if (!dum_opt && notell) {
5850Sstevel@tonic-gate         write (2, gettext("[Use q or Q to quit]"), 20);
5860Sstevel@tonic-gate         promptlen += 20;
5870Sstevel@tonic-gate         notell = 0;
5880Sstevel@tonic-gate     }
5890Sstevel@tonic-gate     signal(SIGQUIT, onquit);
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate ** Come here if a signal for a window size change is received
5940Sstevel@tonic-gate */
5950Sstevel@tonic-gate /*ARGSUSED*/
5960Sstevel@tonic-gate void
chgwinsz(int sig)5970Sstevel@tonic-gate chgwinsz(int sig)
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate     struct winsize win;
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate     (void) signal(SIGWINCH, SIG_IGN);
6020Sstevel@tonic-gate     if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
6030Sstevel@tonic-gate 	if (win.ws_row != 0) {
6040Sstevel@tonic-gate 	    Lpp = win.ws_row;
6050Sstevel@tonic-gate 	    nscroll = Lpp/2 - 1;
6060Sstevel@tonic-gate 	    if (nscroll <= 0)
6070Sstevel@tonic-gate 		nscroll = 1;
6080Sstevel@tonic-gate 	    dlines = (off_t)(Lpp - (noscroll ? 1 : 2));
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate 	if (win.ws_col != 0)
6110Sstevel@tonic-gate 	    Mcol = win.ws_col;
6120Sstevel@tonic-gate     }
6130Sstevel@tonic-gate     (void) signal(SIGWINCH, chgwinsz);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate ** Clean up terminal state and exit. Also come here if interrupt signal received
6180Sstevel@tonic-gate */
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate /*
6210Sstevel@tonic-gate  * sig is put in as a dummy arg to have the compiler not to complain
6220Sstevel@tonic-gate  */
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate /* ARGSUSED */
6250Sstevel@tonic-gate void
end_it(int sig)6260Sstevel@tonic-gate end_it(int sig)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate     reset_tty ();
6300Sstevel@tonic-gate     if (clreol) {
6310Sstevel@tonic-gate         putchar ('\r');
6320Sstevel@tonic-gate         clreos ();
6330Sstevel@tonic-gate         fflush (stdout);
6340Sstevel@tonic-gate     }
6350Sstevel@tonic-gate     else if (!clreol && (promptlen > 0)) {
6360Sstevel@tonic-gate         kill_line ();
6370Sstevel@tonic-gate         fflush (stdout);
6380Sstevel@tonic-gate     }
6390Sstevel@tonic-gate     else
6400Sstevel@tonic-gate         write (2, "\n", 1);
6410Sstevel@tonic-gate     _exit(exitstat);                    /*M003*/
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate static void
copy_file(register FILE * f)6450Sstevel@tonic-gate copy_file(register FILE *f)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate     register int c;
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate     while ((c = getc(f)) != EOF)
6500Sstevel@tonic-gate         putchar(c);
6510Sstevel@tonic-gate }
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate static char Bell = ctrl('G');
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate /* See whether the last component of the path name "path" is equal to the
6570Sstevel@tonic-gate ** string "string"
6580Sstevel@tonic-gate */
6590Sstevel@tonic-gate 
660236Schin int
tailequ(char * path,char * string)661236Schin tailequ(char *path, char *string)
6620Sstevel@tonic-gate {
6630Sstevel@tonic-gate 	return (!strcmp(basename(path), string));
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate static void
prompt(char * filename)6670Sstevel@tonic-gate prompt(char *filename)
6680Sstevel@tonic-gate {
6690Sstevel@tonic-gate     if (clreol)
6700Sstevel@tonic-gate         cleareol ();
6710Sstevel@tonic-gate     else if (promptlen > 0)
6720Sstevel@tonic-gate         kill_line ();
6730Sstevel@tonic-gate     if (!hard) {
6740Sstevel@tonic-gate         promptlen = 8;
6750Sstevel@tonic-gate         if (enter_standout_mode && exit_standout_mode)
6760Sstevel@tonic-gate             putp (enter_standout_mode);
6770Sstevel@tonic-gate         if (clreol)
6780Sstevel@tonic-gate             cleareol ();
6790Sstevel@tonic-gate         pr(gettext("--More--"));
6800Sstevel@tonic-gate         if (filename != NULL) {
6810Sstevel@tonic-gate             promptlen += printf (gettext("(Next file: %s)"), filename);
6820Sstevel@tonic-gate         }
6830Sstevel@tonic-gate         else if (!no_intty) {
6840Sstevel@tonic-gate             promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size));
6850Sstevel@tonic-gate         }
6860Sstevel@tonic-gate         if (dum_opt) {
6870Sstevel@tonic-gate             promptlen += pr(gettext("[Hit space to continue, Del to abort]"));
6880Sstevel@tonic-gate         }
6890Sstevel@tonic-gate         if (enter_standout_mode && exit_standout_mode)
6900Sstevel@tonic-gate             putp (exit_standout_mode);
6910Sstevel@tonic-gate         if (clreol) clreos ();
6920Sstevel@tonic-gate         fflush(stdout);
6930Sstevel@tonic-gate     }
6940Sstevel@tonic-gate     else
6950Sstevel@tonic-gate         write (2, &Bell, 1);
6960Sstevel@tonic-gate     inwait++;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate  * when run from another program or a shell script, it is
7010Sstevel@tonic-gate  * sometimes useful to prevent the next program from scrolling
7020Sstevel@tonic-gate  * us off the screen before we get a chance to read this page.
7030Sstevel@tonic-gate  *                      -Hans, July 24, 1982
7040Sstevel@tonic-gate  */
7050Sstevel@tonic-gate static void
wait_eof(void)7060Sstevel@tonic-gate wait_eof(void)
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate         if (enter_standout_mode && exit_standout_mode)
7090Sstevel@tonic-gate                 putp (enter_standout_mode);
7100Sstevel@tonic-gate         promptlen = pr(gettext("--No more--"));          /*M003*/
7110Sstevel@tonic-gate         if (dum_opt)
7120Sstevel@tonic-gate                 promptlen += pr(gettext("[Hit any key to continue]"));
7130Sstevel@tonic-gate         if (enter_standout_mode && exit_standout_mode)
7140Sstevel@tonic-gate                 putp(exit_standout_mode);
7150Sstevel@tonic-gate         if (clreol) clreos();
7160Sstevel@tonic-gate         fflush(stdout);
7170Sstevel@tonic-gate         readch();
7180Sstevel@tonic-gate         prmpt_erase (0);
7190Sstevel@tonic-gate         fflush(stdout);
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate /*
7230Sstevel@tonic-gate ** Get a logical line
7240Sstevel@tonic-gate */
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate static int
getaline(register FILE * f,int * length)727*13093SRoger.Faulkner@Oracle.COM getaline(register FILE *f, int *length)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate     register int        c;
7300Sstevel@tonic-gate     register char       *p;
7310Sstevel@tonic-gate     register int        column;
7320Sstevel@tonic-gate     static int          colflg;
7330Sstevel@tonic-gate     register int        oldcolumn;
7340Sstevel@tonic-gate     int			csno;
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate     p = Line;
7370Sstevel@tonic-gate     column = 0;
7380Sstevel@tonic-gate     oldcolumn = 0;
7390Sstevel@tonic-gate     c = Getc (f);
7400Sstevel@tonic-gate     if (colflg && c == '\n') {
7410Sstevel@tonic-gate         Currline++;
7420Sstevel@tonic-gate         c = Getc (f);
7430Sstevel@tonic-gate     }
7440Sstevel@tonic-gate     while (p < &Line[LINSIZ - 1]) {
7450Sstevel@tonic-gate 	csno = csetno(c);
7460Sstevel@tonic-gate         if (c == EOF) {
7470Sstevel@tonic-gate             if (p > Line) {
7480Sstevel@tonic-gate                 *p = '\0';
7490Sstevel@tonic-gate                 *length = p - Line;
7500Sstevel@tonic-gate                 return (column);
7510Sstevel@tonic-gate             }
7520Sstevel@tonic-gate             *length = p - Line;
7530Sstevel@tonic-gate             return (EOF);
7540Sstevel@tonic-gate         }
7550Sstevel@tonic-gate 	if (!csno) {
7560Sstevel@tonic-gate 	        if (c == '\n') {
7570Sstevel@tonic-gate 	            /* detect \r\n.  -Hans */
7580Sstevel@tonic-gate 	            if (p>Line && p[-1] == '\r') {
7590Sstevel@tonic-gate 	                column = oldcolumn;
7600Sstevel@tonic-gate 	                p--;
7610Sstevel@tonic-gate 	            }
7620Sstevel@tonic-gate 	            Currline++;
7630Sstevel@tonic-gate 	            break;
7640Sstevel@tonic-gate 	        }
7650Sstevel@tonic-gate 	        *p++ = c;
7660Sstevel@tonic-gate 	        if (c == '\t')
7670Sstevel@tonic-gate 	            if (hardtabs && column < promptlen && !hard) {
7680Sstevel@tonic-gate 	                if (clr_eol && !dumb) {
7690Sstevel@tonic-gate 	                    column = 1 + (column | 7);
7700Sstevel@tonic-gate 	                    putp (clr_eol);
7710Sstevel@tonic-gate 	                    promptlen = 0;
7720Sstevel@tonic-gate 	                }
7730Sstevel@tonic-gate 	                else {
7740Sstevel@tonic-gate 	                    for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
7750Sstevel@tonic-gate 	                        *p++ = ' ';
7760Sstevel@tonic-gate 	                    }
7770Sstevel@tonic-gate 	                    if (column >= promptlen) promptlen = 0;
7780Sstevel@tonic-gate 	                }
7790Sstevel@tonic-gate 	            }
7800Sstevel@tonic-gate 	            else
7810Sstevel@tonic-gate 	                column = 1 + (column | 7);
7820Sstevel@tonic-gate 	        else if ((c == '\b') && (ul_opt || !cr_opt) && (column > 0))  /* M008 */
7830Sstevel@tonic-gate 	                column--;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	        /* this is sort of strange.  what was here before was that
7860Sstevel@tonic-gate 	           \r always set column to zero, and the hack above to
7870Sstevel@tonic-gate 	           detect \r\n didnt exist.  the net effect is to make
7880Sstevel@tonic-gate 	           the current line be overwritten by the prompt if it
7890Sstevel@tonic-gate 	           had a \r at the end, and the line start after the \r
7900Sstevel@tonic-gate 	           otherwise.  I suppose this is useful for overstriking
7910Sstevel@tonic-gate 	           on hard copy terminals, but not on anything glass
7920Sstevel@tonic-gate 	           -Hans */
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 	        else if ((c == '\r') && !cr_opt) {
7950Sstevel@tonic-gate 	                oldcolumn = column;
7960Sstevel@tonic-gate 	                column = 0;
7970Sstevel@tonic-gate 	        }
7980Sstevel@tonic-gate 	        else if (c == '\f' && stop_opt) {
7990Sstevel@tonic-gate 	                p[-1] = '^';
8000Sstevel@tonic-gate 	                *p++ = 'L';
8010Sstevel@tonic-gate 	                column += 2;
8020Sstevel@tonic-gate 	                Pause++;
8030Sstevel@tonic-gate 	        }
8040Sstevel@tonic-gate 	        else if (c == EOF) {
8050Sstevel@tonic-gate 	            *length = p - Line;
8060Sstevel@tonic-gate 	            return (column);
8070Sstevel@tonic-gate 	        }
8080Sstevel@tonic-gate 	        else if (c < ' ' && cr_opt){                    /* M008 begin */
8090Sstevel@tonic-gate 	                p[-1] = '^';
8100Sstevel@tonic-gate 	                *p++ = c | ('A' - 1);
8110Sstevel@tonic-gate 	                column += 2;
8120Sstevel@tonic-gate 	        }                                               /* M008 end */
8130Sstevel@tonic-gate 	        else if (c >= ' ' && c != RUBOUT)
8140Sstevel@tonic-gate 	            column++;
8150Sstevel@tonic-gate 	} /* end of code set 0 */
8160Sstevel@tonic-gate 	else {
8170Sstevel@tonic-gate 		column += scw[csno];
8180Sstevel@tonic-gate 		if ( column > Mcol && fold_opt ) {
8190Sstevel@tonic-gate 		    column -= scw[csno];
8200Sstevel@tonic-gate 		    while ( column < Mcol ) {
8210Sstevel@tonic-gate 		        column++;
8220Sstevel@tonic-gate 		        *p++ = ' ';
8230Sstevel@tonic-gate 		    }
8240Sstevel@tonic-gate 		    column = Mcol;
8250Sstevel@tonic-gate 		    Ungetc(c,f);
8260Sstevel@tonic-gate 		} else {
8270Sstevel@tonic-gate 		    int i;
8280Sstevel@tonic-gate 		    *p++ = c;
8290Sstevel@tonic-gate 		    for(i=1; i<cw[csno];i++)
8300Sstevel@tonic-gate 			*p++ = Getc(f);
8310Sstevel@tonic-gate 		}
8320Sstevel@tonic-gate 	} /* end of codeset 1 ~ 3 */
8330Sstevel@tonic-gate         if (column >= Mcol && fold_opt) break;
8340Sstevel@tonic-gate         c = Getc (f);
8350Sstevel@tonic-gate     }
8360Sstevel@tonic-gate     if (column >= Mcol && Mcol > 0) {
8370Sstevel@tonic-gate         if (!Wrap) {
8380Sstevel@tonic-gate             *p++ = '\n';
8390Sstevel@tonic-gate         }
8400Sstevel@tonic-gate     }
8410Sstevel@tonic-gate     colflg = column == Mcol && fold_opt;
8420Sstevel@tonic-gate     if (colflg && eat_newline_glitch && Wrap) {
8430Sstevel@tonic-gate 	*p++ = '\n'; /* simulate normal wrap */
8440Sstevel@tonic-gate     }
8450Sstevel@tonic-gate     *length = p - Line;
8460Sstevel@tonic-gate     *p = 0;
8470Sstevel@tonic-gate     return (column);
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate /*
8510Sstevel@tonic-gate ** Erase the rest of the prompt, assuming we are starting at column col.
8520Sstevel@tonic-gate */
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate static void
prmpt_erase(register int col)8550Sstevel@tonic-gate prmpt_erase(register int col)
8560Sstevel@tonic-gate {
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate     if (promptlen == 0)
8590Sstevel@tonic-gate         return;
8600Sstevel@tonic-gate     if (hard) {
8610Sstevel@tonic-gate         putchar ('\n');
8620Sstevel@tonic-gate     }
8630Sstevel@tonic-gate     else {
8640Sstevel@tonic-gate         if (col == 0)
8650Sstevel@tonic-gate             putchar ('\r');
8660Sstevel@tonic-gate         if (!dumb && clr_eol)
8670Sstevel@tonic-gate             putp (clr_eol);
8680Sstevel@tonic-gate         else
8690Sstevel@tonic-gate             for (col = promptlen - col; col > 0; col--)
8700Sstevel@tonic-gate                 putchar (' ');
8710Sstevel@tonic-gate     }
8720Sstevel@tonic-gate     promptlen = 0;
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate /*
8760Sstevel@tonic-gate ** Erase the current line entirely
8770Sstevel@tonic-gate */
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate static void
kill_line(void)8800Sstevel@tonic-gate kill_line(void)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate     prmpt_erase (0);
8830Sstevel@tonic-gate     if (!clr_eol || dumb) putchar ('\r');
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate /* Print a buffer of n characters */
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate static void
prbuf(register char * s,register int n)8890Sstevel@tonic-gate prbuf(register char *s, register int n)
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate     char c;                             /* next ouput character */
8920Sstevel@tonic-gate     register int state = 0;             /* next output char's UL state */
8930Sstevel@tonic-gate     static int pstate = 0;              /* current terminal UL state (off) */
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate     while (--n >= 0)
8960Sstevel@tonic-gate         if (!ul_opt)
8970Sstevel@tonic-gate             putchar (*s++);
8980Sstevel@tonic-gate         else {
8990Sstevel@tonic-gate             if (n >= 2 && s[0] == '_' && s[1] == '\b') {
9000Sstevel@tonic-gate                 n -= 2;
9010Sstevel@tonic-gate                 s += 2;
9020Sstevel@tonic-gate                 c = *s++;
9030Sstevel@tonic-gate                 state = 1;
9040Sstevel@tonic-gate             } else if (n >= 2 && s[1] == '\b' && s[2] == '_') {
9050Sstevel@tonic-gate                 n -= 2;
9060Sstevel@tonic-gate                 c = *s++;
9070Sstevel@tonic-gate                 s += 2;
9080Sstevel@tonic-gate                 state = 1;
9090Sstevel@tonic-gate             } else {
9100Sstevel@tonic-gate                 c = *s++;
9110Sstevel@tonic-gate                 state = 0;
9120Sstevel@tonic-gate             }
9130Sstevel@tonic-gate             if (state != pstate)
9140Sstevel@tonic-gate                 putp(state ? ULenter : ULexit);
9150Sstevel@tonic-gate             pstate = state;
9160Sstevel@tonic-gate             putchar(c);
9170Sstevel@tonic-gate             if (state && underline_char) {
9180Sstevel@tonic-gate                 putp(cursor_left);
9190Sstevel@tonic-gate                 putp(underline_char);
9200Sstevel@tonic-gate             }
9210Sstevel@tonic-gate         }
9220Sstevel@tonic-gate     /*
9230Sstevel@tonic-gate      * M002
9240Sstevel@tonic-gate      * You don't want to stay in standout mode at the end of the line;
9250Sstevel@tonic-gate      * on some terminals, this will leave all of the remaining blank
9260Sstevel@tonic-gate      * space on the line in standout mode.
9270Sstevel@tonic-gate      */
9280Sstevel@tonic-gate     if (state && !underline_char) {                       /*M002*/
9290Sstevel@tonic-gate             putp(ULexit);                    /*M002*/
9300Sstevel@tonic-gate             pstate = 0;                                 /*M002*/
9310Sstevel@tonic-gate     }                                                   /*M002*/
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate /*
9350Sstevel@tonic-gate **  Clear the screen
9360Sstevel@tonic-gate */
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate static void
doclear(void)9390Sstevel@tonic-gate doclear(void)
9400Sstevel@tonic-gate {
9410Sstevel@tonic-gate     if (clear_screen && !hard) {
9420Sstevel@tonic-gate         putp(clear_screen);
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate         /* Put out carriage return so that system doesn't
9450Sstevel@tonic-gate         ** get confused by escape sequences when expanding tabs
9460Sstevel@tonic-gate         */
9470Sstevel@tonic-gate         putchar ('\r');
9480Sstevel@tonic-gate         promptlen = 0;
9490Sstevel@tonic-gate     }
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate static int lastcmd, lastp;
9540Sstevel@tonic-gate static off_t lastarg;
9550Sstevel@tonic-gate static int lastcolon;
9562932Sas145665 char shell_line[PATH_MAX];
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate /*
9590Sstevel@tonic-gate ** Read a command and do it. A command consists of an optional integer
9600Sstevel@tonic-gate ** argument followed by the command character.  Return the number of lines
9610Sstevel@tonic-gate ** to display in the next screenful.  If there is nothing more to display
9620Sstevel@tonic-gate ** in the current file, zero is returned.
9630Sstevel@tonic-gate */
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate static off_t
command(char * filename,register FILE * f)9660Sstevel@tonic-gate command(char *filename, register FILE *f)
9670Sstevel@tonic-gate {
9680Sstevel@tonic-gate     register off_t nlines;
9690Sstevel@tonic-gate     register off_t retval;
9700Sstevel@tonic-gate     register int c;
9710Sstevel@tonic-gate     char colonch;
9720Sstevel@tonic-gate     FILE *helpf;
9730Sstevel@tonic-gate     int done;
9740Sstevel@tonic-gate     char comchar, cmdbuf[80];
9750Sstevel@tonic-gate     char filebuf[128];
9760Sstevel@tonic-gate     char *loc;
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate #define ret(val) retval=val;done++;break
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate     done = 0;
9810Sstevel@tonic-gate     if (!errors)
9820Sstevel@tonic-gate         prompt (filename);
9830Sstevel@tonic-gate     else
9840Sstevel@tonic-gate         errors = 0;
9850Sstevel@tonic-gate     for (;;) {
9860Sstevel@tonic-gate         nlines = number (&comchar);
9870Sstevel@tonic-gate         lastp = colonch = 0;
9880Sstevel@tonic-gate         if (comchar == '.') {   /* Repeat last command */
9890Sstevel@tonic-gate                 lastp++;
9900Sstevel@tonic-gate                 comchar = lastcmd;
9910Sstevel@tonic-gate                 nlines = lastarg;
9920Sstevel@tonic-gate                 if (lastcmd == ':')
9930Sstevel@tonic-gate                         colonch = lastcolon;
9940Sstevel@tonic-gate         }
9950Sstevel@tonic-gate         lastcmd = comchar;
9960Sstevel@tonic-gate         lastarg = nlines;
9970Sstevel@tonic-gate 	if((comchar != RUBOUT) && !dum_opt) {
9980Sstevel@tonic-gate         	if (comchar == otty.c_cc[VERASE]) {
9990Sstevel@tonic-gate            		 kill_line ();
10000Sstevel@tonic-gate             		prompt (filename);
10010Sstevel@tonic-gate             		continue;
10020Sstevel@tonic-gate         	}
10030Sstevel@tonic-gate 	}
10040Sstevel@tonic-gate         switch (comchar) {
10050Sstevel@tonic-gate         case ':':
10060Sstevel@tonic-gate             retval = colon (filename, colonch, nlines);
10070Sstevel@tonic-gate             if (retval >= 0)
10080Sstevel@tonic-gate                 done++;
10090Sstevel@tonic-gate             break;
10100Sstevel@tonic-gate 	case 'b':
10110Sstevel@tonic-gate 	case ctrl('B'):
10120Sstevel@tonic-gate 	    {
10130Sstevel@tonic-gate 		register off_t initline;
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 		if (no_intty) {
10160Sstevel@tonic-gate 		    write(2, &bell, 1);
10170Sstevel@tonic-gate 		    return (-1);
10180Sstevel@tonic-gate 		}
10190Sstevel@tonic-gate 
10200Sstevel@tonic-gate 		if (nlines == 0) nlines++;
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate 		putchar ('\r');
10230Sstevel@tonic-gate 		prmpt_erase (0);
10240Sstevel@tonic-gate 		printf ("\n");
10250Sstevel@tonic-gate 		if (clreol)
10260Sstevel@tonic-gate 			cleareol ();
10270Sstevel@tonic-gate 		printf (gettext("...back %lld page"), nlines);
10280Sstevel@tonic-gate 		if (nlines > 1)
10290Sstevel@tonic-gate 			pr ("s\n");
10300Sstevel@tonic-gate 		else
10310Sstevel@tonic-gate 			pr ("\n");
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 		if (clreol)
10340Sstevel@tonic-gate 			cleareol ();
10350Sstevel@tonic-gate 		pr ("\n");
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 		initline = Currline - dlines * (nlines + 1);
10380Sstevel@tonic-gate 		if (! noscroll)
10390Sstevel@tonic-gate 		    --initline;
10400Sstevel@tonic-gate 		if (initline < 0) initline = 0;
10410Sstevel@tonic-gate 		Fseek(f, 0LL);
10420Sstevel@tonic-gate 		Currline = 0;	/* skiplns() will make Currline correct */
10430Sstevel@tonic-gate 		skiplns(initline, f);
10440Sstevel@tonic-gate 		if (! noscroll) {
10450Sstevel@tonic-gate 		    ret(dlines + 1);
10460Sstevel@tonic-gate 		}
10470Sstevel@tonic-gate 		else {
10480Sstevel@tonic-gate 		    ret(dlines);
10490Sstevel@tonic-gate 		}
10500Sstevel@tonic-gate 	    }
10510Sstevel@tonic-gate         case ' ':
10520Sstevel@tonic-gate         case 'z':
10530Sstevel@tonic-gate             if (nlines == 0) nlines = dlines;
10540Sstevel@tonic-gate             else if (comchar == 'z') dlines = nlines;
10550Sstevel@tonic-gate             ret (nlines);
10560Sstevel@tonic-gate         case 'd':
10570Sstevel@tonic-gate         case ctrl('D'):
10580Sstevel@tonic-gate             if (nlines != 0) nscroll = nlines;
10590Sstevel@tonic-gate             ret (nscroll);
10600Sstevel@tonic-gate         case RUBOUT:
10610Sstevel@tonic-gate         case 'q':
10620Sstevel@tonic-gate         case 'Q':
10630Sstevel@tonic-gate             end_it(0);
10640Sstevel@tonic-gate 	    /*NOTREACHED*/
10650Sstevel@tonic-gate         case 's':
10660Sstevel@tonic-gate         case 'f':
10670Sstevel@tonic-gate             if (nlines == 0) nlines++;
10680Sstevel@tonic-gate             if (comchar == 'f')
10690Sstevel@tonic-gate                 nlines *= dlines;
10700Sstevel@tonic-gate             putchar ('\r');
10710Sstevel@tonic-gate             prmpt_erase (0);
10720Sstevel@tonic-gate             printf ("\n");
10730Sstevel@tonic-gate             if (clreol)
10740Sstevel@tonic-gate                 cleareol ();
10750Sstevel@tonic-gate             printf (gettext("...skipping %lld line"), nlines);
10760Sstevel@tonic-gate             if (nlines > 1)
10770Sstevel@tonic-gate                 pr ("s\n");
10780Sstevel@tonic-gate             else
10790Sstevel@tonic-gate                 pr ("\n");
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate             if (clreol)
10820Sstevel@tonic-gate                 cleareol ();
10830Sstevel@tonic-gate             pr ("\n");
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate             while (nlines > 0) {
10860Sstevel@tonic-gate                 while ((c = Getc (f)) != '\n')
10870Sstevel@tonic-gate                     if (c == EOF) {
10880Sstevel@tonic-gate                         retval = 0;
10890Sstevel@tonic-gate                         done++;
10900Sstevel@tonic-gate                         goto endsw;
10910Sstevel@tonic-gate                     }
10920Sstevel@tonic-gate                     Currline++;
10930Sstevel@tonic-gate                     nlines--;
10940Sstevel@tonic-gate             }
10950Sstevel@tonic-gate             ret (dlines);
10960Sstevel@tonic-gate         case '\n':
10970Sstevel@tonic-gate 	    if (nlines != 0)
10980Sstevel@tonic-gate                 dlines = nlines;
10990Sstevel@tonic-gate             else
11000Sstevel@tonic-gate                 nlines = 1;
11010Sstevel@tonic-gate             ret (nlines);
11020Sstevel@tonic-gate         case '\f':
11030Sstevel@tonic-gate             if (!no_intty) {
11040Sstevel@tonic-gate                 doclear ();
11050Sstevel@tonic-gate                 Fseek (f, screen_start.chrctr);
11060Sstevel@tonic-gate                 Currline = screen_start.line;
11070Sstevel@tonic-gate                 ret (dlines);
11080Sstevel@tonic-gate             }
11090Sstevel@tonic-gate             else {
11100Sstevel@tonic-gate                 write (2, &Bell, 1);
11110Sstevel@tonic-gate                 break;
11120Sstevel@tonic-gate             }
11130Sstevel@tonic-gate         case '\'':
11140Sstevel@tonic-gate             if (!no_intty) {
11150Sstevel@tonic-gate                 kill_line ();
11160Sstevel@tonic-gate                 pr (gettext("\n***Back***\n\n"));
11170Sstevel@tonic-gate                 Fseek (f, context.chrctr);
11180Sstevel@tonic-gate                 Currline = context.line;
11190Sstevel@tonic-gate                 ret (dlines);
11200Sstevel@tonic-gate             }
11210Sstevel@tonic-gate             else {
11220Sstevel@tonic-gate                 write (2, &Bell, 1);
11230Sstevel@tonic-gate                 break;
11240Sstevel@tonic-gate             }
11250Sstevel@tonic-gate         case '=':
11260Sstevel@tonic-gate             kill_line ();
11270Sstevel@tonic-gate             promptlen = printf ("%lld", Currline);
11280Sstevel@tonic-gate             fflush (stdout);
11290Sstevel@tonic-gate             break;
11300Sstevel@tonic-gate         case 'n':
11310Sstevel@tonic-gate             lastp++;
11320Sstevel@tonic-gate 	    /*FALLTHROUGH*/
11330Sstevel@tonic-gate         case '/':
11340Sstevel@tonic-gate             if (nlines == 0) nlines++;
11350Sstevel@tonic-gate             kill_line ();
11360Sstevel@tonic-gate             pr ("/");
11370Sstevel@tonic-gate             promptlen = 1;
11380Sstevel@tonic-gate             fflush (stdout);
11390Sstevel@tonic-gate             if (lastp) {
11400Sstevel@tonic-gate                 write (2,"\r", 1);
11410Sstevel@tonic-gate                 search (NULL, f, nlines);       /* Use previous r.e. */
11420Sstevel@tonic-gate             }
11430Sstevel@tonic-gate             else {
11440Sstevel@tonic-gate                 ttyin (cmdbuf, 78, '/');
11450Sstevel@tonic-gate                 write (2, "\r", 1);
11460Sstevel@tonic-gate                 search (cmdbuf, f, nlines);
11470Sstevel@tonic-gate             }
11480Sstevel@tonic-gate             ret (dlines-1);
11490Sstevel@tonic-gate         case '!':
11500Sstevel@tonic-gate             do_shell (filename);
11510Sstevel@tonic-gate             break;
11520Sstevel@tonic-gate         case 'h':
11530Sstevel@tonic-gate         case '?':
11540Sstevel@tonic-gate 	    /*
11550Sstevel@tonic-gate 	     * First get local help file.
11560Sstevel@tonic-gate 	     */
11570Sstevel@tonic-gate 	    loc = setlocale(LC_MESSAGES, 0);
11580Sstevel@tonic-gate 	    sprintf(filebuf, LOCAL_HELP, loc);
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate             if  ((strcmp(loc, "C") == 0) || (helpf = fopen (filebuf, "r")) == NULL) {
11610Sstevel@tonic-gate 		    if  ((helpf = fopen (HELPFILE, "r")) == NULL)
11620Sstevel@tonic-gate 			error (gettext("Can't open help file"));
11630Sstevel@tonic-gate 	    }
11640Sstevel@tonic-gate             if (noscroll) doclear ();
11650Sstevel@tonic-gate             copy_file (helpf);
11660Sstevel@tonic-gate             fclose (helpf);
11670Sstevel@tonic-gate             prompt (filename);
11680Sstevel@tonic-gate             break;
11690Sstevel@tonic-gate         case 'v':       /* This case should go right before default */
11700Sstevel@tonic-gate             if (!no_intty) {
11710Sstevel@tonic-gate                 kill_line ();
11720Sstevel@tonic-gate                 cmdbuf[0] = '+';
11730Sstevel@tonic-gate                 sprintf(&cmdbuf[1], "%lld", Currline);
11740Sstevel@tonic-gate                 pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
11750Sstevel@tonic-gate                 execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
11760Sstevel@tonic-gate                 break;
11770Sstevel@tonic-gate             }
11780Sstevel@tonic-gate         default:
11790Sstevel@tonic-gate 		if (dum_opt) {
11800Sstevel@tonic-gate 			kill_line ();
11810Sstevel@tonic-gate 		    	promptlen = pr(gettext("[Press 'h' for instructions.]"));
11820Sstevel@tonic-gate 			fflush (stdout);
11830Sstevel@tonic-gate 	    	}
11840Sstevel@tonic-gate 	    	else
11850Sstevel@tonic-gate             		write (2, &Bell, 1);
11860Sstevel@tonic-gate             break;
11870Sstevel@tonic-gate         }
11880Sstevel@tonic-gate         if (done) break;
11890Sstevel@tonic-gate     }
11900Sstevel@tonic-gate     putchar ('\r');
11910Sstevel@tonic-gate endsw:
11920Sstevel@tonic-gate     inwait = 0;
11930Sstevel@tonic-gate     notell++;
11940Sstevel@tonic-gate     return (retval);
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate char ch;
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate /*
12000Sstevel@tonic-gate  * Execute a colon-prefixed command.
12010Sstevel@tonic-gate  * Returns <0 if not a command that should cause
12020Sstevel@tonic-gate  * more of the file to be printed.
12030Sstevel@tonic-gate  */
12040Sstevel@tonic-gate 
12050Sstevel@tonic-gate static int
colon(char * filename,int cmd,off_t nlines)12060Sstevel@tonic-gate colon(char *filename, int cmd, off_t nlines)
12070Sstevel@tonic-gate {
12080Sstevel@tonic-gate         if (cmd == 0)
12090Sstevel@tonic-gate                 ch = readch ();
12100Sstevel@tonic-gate         else
12110Sstevel@tonic-gate                 ch = cmd;
12120Sstevel@tonic-gate         lastcolon = ch;
12130Sstevel@tonic-gate         switch (ch) {
12140Sstevel@tonic-gate         case 'f':
12150Sstevel@tonic-gate                 kill_line ();
12160Sstevel@tonic-gate                 if (!no_intty)
12170Sstevel@tonic-gate                         promptlen = printf (gettext("\"%s\" line %lld"),
12180Sstevel@tonic-gate 					    fnames[fnum], Currline);
12190Sstevel@tonic-gate                 else
12200Sstevel@tonic-gate                         promptlen = printf(
12210Sstevel@tonic-gate 			 gettext("[Not a file] line %lld"), Currline);
12220Sstevel@tonic-gate                 fflush (stdout);
12230Sstevel@tonic-gate                 return (-1);
12240Sstevel@tonic-gate         case 'n':
12250Sstevel@tonic-gate                 if (nlines == 0) {
12260Sstevel@tonic-gate                         if (fnum >= nfiles - 1)
12270Sstevel@tonic-gate                                 end_it(0);
12280Sstevel@tonic-gate                         nlines++;
12290Sstevel@tonic-gate                 }
12300Sstevel@tonic-gate                 putchar ('\r');
12310Sstevel@tonic-gate                 prmpt_erase (0);
12320Sstevel@tonic-gate                 skipf ((int)nlines);
12330Sstevel@tonic-gate                 return (0);
12340Sstevel@tonic-gate         case 'p':
12350Sstevel@tonic-gate                 if (no_intty) {
12360Sstevel@tonic-gate                         write (2, &Bell, 1);
12370Sstevel@tonic-gate                         return (-1);
12380Sstevel@tonic-gate                 }
12390Sstevel@tonic-gate                 putchar ('\r');
12400Sstevel@tonic-gate                 prmpt_erase (0);
12410Sstevel@tonic-gate                 if (nlines == 0)
12420Sstevel@tonic-gate                         nlines++;
12430Sstevel@tonic-gate                 skipf ((int)-nlines);
12440Sstevel@tonic-gate                 return (0);
12450Sstevel@tonic-gate         case '!':
12460Sstevel@tonic-gate                 do_shell (filename);
12470Sstevel@tonic-gate                 return (-1);
12480Sstevel@tonic-gate         case 'q':
12490Sstevel@tonic-gate         case 'Q':
12500Sstevel@tonic-gate                 end_it(0);
12510Sstevel@tonic-gate         default:
12520Sstevel@tonic-gate                 write (2, &Bell, 1);
12530Sstevel@tonic-gate                 return (-1);
12540Sstevel@tonic-gate         }
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate /*
12580Sstevel@tonic-gate ** Read a decimal number from the terminal. Set cmd to the non-digit which
12590Sstevel@tonic-gate ** terminates the number.
12600Sstevel@tonic-gate */
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate static int
number(char * cmd)12630Sstevel@tonic-gate number(char *cmd)
12640Sstevel@tonic-gate {
12650Sstevel@tonic-gate         register int i;
12660Sstevel@tonic-gate 
12670Sstevel@tonic-gate         i = 0; ch = otty.c_cc[VKILL];
12680Sstevel@tonic-gate         for (;;) {
12690Sstevel@tonic-gate                 ch = readch ();
12700Sstevel@tonic-gate                 if (ch >= '0' && ch <= '9') {
12710Sstevel@tonic-gate                         i = i*10 + ch - '0';
12720Sstevel@tonic-gate                 } else if (ch == RUBOUT) {
12730Sstevel@tonic-gate                         i = 0;
12740Sstevel@tonic-gate                         *cmd = ch;
12750Sstevel@tonic-gate                         break;
12760Sstevel@tonic-gate                 } else if (ch == otty.c_cc[VKILL]) {
12770Sstevel@tonic-gate                         i = 0;
12780Sstevel@tonic-gate                 } else {
12790Sstevel@tonic-gate                         *cmd = ch;
12800Sstevel@tonic-gate                         break;
12810Sstevel@tonic-gate                 }
12820Sstevel@tonic-gate         }
12830Sstevel@tonic-gate         return (i);
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate static void
do_shell(char * filename)12870Sstevel@tonic-gate do_shell(char *filename)
12880Sstevel@tonic-gate {
12890Sstevel@tonic-gate         char cmdbuf[80];
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate         kill_line ();
12920Sstevel@tonic-gate         pr ("!");
12930Sstevel@tonic-gate         fflush (stdout);
12940Sstevel@tonic-gate         promptlen = 1;
12950Sstevel@tonic-gate         if (lastp)
12960Sstevel@tonic-gate                 pr (shell_line);
12970Sstevel@tonic-gate         else {
12980Sstevel@tonic-gate                 ttyin (cmdbuf, 78, '!');
12990Sstevel@tonic-gate                 if (expand (shell_line, cmdbuf)) {
13000Sstevel@tonic-gate                         kill_line ();
13010Sstevel@tonic-gate                         promptlen = printf ("!%s", shell_line);
13020Sstevel@tonic-gate                 }
13030Sstevel@tonic-gate         }
13040Sstevel@tonic-gate         fflush (stdout);
13050Sstevel@tonic-gate         write (2, "\n", 1);
13060Sstevel@tonic-gate         promptlen = 0;
13070Sstevel@tonic-gate         shellp = 1;
13080Sstevel@tonic-gate         execute (filename, shell, shell, "-c", shell_line, 0);
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate /*
13120Sstevel@tonic-gate ** Search for nth ocurrence of regular expression contained in buf in the file
13130Sstevel@tonic-gate */
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate static void
search(char buf[],FILE * file,register off_t n)13160Sstevel@tonic-gate search(char buf[], FILE *file, register off_t n)
13170Sstevel@tonic-gate {
13180Sstevel@tonic-gate     off_t startline = Ftell (file);
13190Sstevel@tonic-gate     register off_t line1 = startline;
13200Sstevel@tonic-gate     register off_t line2 = startline;
13210Sstevel@tonic-gate     register off_t line3 = startline;
13220Sstevel@tonic-gate     register off_t lncount;
13230Sstevel@tonic-gate     off_t saveln;
13240Sstevel@tonic-gate     static char *s = NULL;
13250Sstevel@tonic-gate     static char lastbuf[80];
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate     if (buf != NULL) {
13280Sstevel@tonic-gate 	if (s != NULL)
13290Sstevel@tonic-gate 		free(s);
13300Sstevel@tonic-gate 	if (*buf != '\0') {
13310Sstevel@tonic-gate 		if ((s = regcmp(buf, (char *) NULL)) == NULL)
13320Sstevel@tonic-gate 			error(gettext("Regular expression botch"));
13330Sstevel@tonic-gate 		else
13340Sstevel@tonic-gate 			strcpy(lastbuf, buf);
13350Sstevel@tonic-gate 	} else {
13360Sstevel@tonic-gate 		if ((s = regcmp(lastbuf, (char *) NULL)) == NULL)
13370Sstevel@tonic-gate 			error(gettext("No previous regular expression"));
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate     } else {
13400Sstevel@tonic-gate 	if (s == NULL)
13410Sstevel@tonic-gate 	    error(gettext("No previous regular expression"));
13420Sstevel@tonic-gate     }
13430Sstevel@tonic-gate     context.line = saveln = Currline;
13440Sstevel@tonic-gate     context.chrctr = startline;
13450Sstevel@tonic-gate     lncount = 0;
13460Sstevel@tonic-gate     while (!feof (file)) {
13470Sstevel@tonic-gate         line3 = line2;
13480Sstevel@tonic-gate         line2 = line1;
13490Sstevel@tonic-gate         line1 = Ftell (file);
13500Sstevel@tonic-gate         rdline (file);
13510Sstevel@tonic-gate         lncount++;
13520Sstevel@tonic-gate         if (regex(s, Line) != NULL)
13530Sstevel@tonic-gate                 if (--n == 0) {
13540Sstevel@tonic-gate                     if (lncount > 3 || (lncount > 1 && no_intty))
13550Sstevel@tonic-gate                     {
13560Sstevel@tonic-gate                         pr ("\n");
13570Sstevel@tonic-gate                         if (clreol)
13580Sstevel@tonic-gate                             cleareol ();
13590Sstevel@tonic-gate                         pr(gettext("...skipping\n"));
13600Sstevel@tonic-gate                     }
13610Sstevel@tonic-gate                     if (!no_intty) {
13620Sstevel@tonic-gate                         Currline -= (lncount >= 3 ? 3 : lncount);
13630Sstevel@tonic-gate                         Fseek (file, line3);
13640Sstevel@tonic-gate                         if (noscroll)
13650Sstevel@tonic-gate                             if (clreol) {
13660Sstevel@tonic-gate                                 home ();
13670Sstevel@tonic-gate                                 cleareol ();
13680Sstevel@tonic-gate                             }
13690Sstevel@tonic-gate                             else
13700Sstevel@tonic-gate                                 doclear ();
13710Sstevel@tonic-gate                     }
13720Sstevel@tonic-gate                     else {
13730Sstevel@tonic-gate                         kill_line ();
13740Sstevel@tonic-gate                         if (noscroll)
13750Sstevel@tonic-gate                             if (clreol) {
13760Sstevel@tonic-gate                                 home ();
13770Sstevel@tonic-gate                                 cleareol ();
13780Sstevel@tonic-gate                             } else
13790Sstevel@tonic-gate                                 doclear ();
13800Sstevel@tonic-gate                         pr (Line);
13810Sstevel@tonic-gate                         putchar ('\n');
13820Sstevel@tonic-gate                     }
13830Sstevel@tonic-gate                     break;
13840Sstevel@tonic-gate                 }
13850Sstevel@tonic-gate     }
13860Sstevel@tonic-gate     if (feof (file)) {
13870Sstevel@tonic-gate         if (!no_intty) {
13880Sstevel@tonic-gate             Currline = saveln;
13890Sstevel@tonic-gate             Fseek (file, startline);
13900Sstevel@tonic-gate         }
13910Sstevel@tonic-gate         else {
13920Sstevel@tonic-gate             pr (gettext("\nPattern not found\n"));
13930Sstevel@tonic-gate             end_it (0);
13940Sstevel@tonic-gate         }
13950Sstevel@tonic-gate         error (gettext("Pattern not found"));
13960Sstevel@tonic-gate     }
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate #define MAXARGS 10 /* enough for 9 args. We are only passed 4 now */
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate static void
execute(char * filename,char * cmd,...)14020Sstevel@tonic-gate execute (char *filename, char *cmd, ...)
14030Sstevel@tonic-gate {
14040Sstevel@tonic-gate         pid_t id;
14050Sstevel@tonic-gate 	va_list ap;
14060Sstevel@tonic-gate 	char *argp[MAXARGS];
14070Sstevel@tonic-gate 	int  count;
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate         fflush (stdout);
14100Sstevel@tonic-gate         reset_tty ();
14110Sstevel@tonic-gate         while ((id = fork ()) < 0)
14120Sstevel@tonic-gate             sleep (5);
14130Sstevel@tonic-gate         if (id == 0) {
14140Sstevel@tonic-gate             if (no_intty) {     /*M002*/
14150Sstevel@tonic-gate                 close(0);       /*M002*/
14160Sstevel@tonic-gate                 dup(2);         /*M002*/
14170Sstevel@tonic-gate             }                   /*M002*/
14180Sstevel@tonic-gate 	    va_start(ap, cmd);
14190Sstevel@tonic-gate 	    count = 0;
14200Sstevel@tonic-gate 	    do {
14210Sstevel@tonic-gate #ifndef lint
14220Sstevel@tonic-gate 		argp[count] = va_arg(ap, char *);
14230Sstevel@tonic-gate #else
14240Sstevel@tonic-gate 		ap = ap;
14250Sstevel@tonic-gate #endif
14260Sstevel@tonic-gate 		count++;
14270Sstevel@tonic-gate 		if (count > MAXARGS)
14280Sstevel@tonic-gate 			error (gettext("Too many arguments in execute()\n"));
14290Sstevel@tonic-gate 	    } while (argp[count - 1] != NULL);
14300Sstevel@tonic-gate 	    va_end(ap);
14310Sstevel@tonic-gate 	    execvp(cmd, argp);
14320Sstevel@tonic-gate             write (2, "exec failed\n", 12);
14330Sstevel@tonic-gate             exit (1);
14340Sstevel@tonic-gate         }
14350Sstevel@tonic-gate         signal (SIGINT, SIG_IGN);
14360Sstevel@tonic-gate         signal (SIGQUIT, SIG_IGN);
14370Sstevel@tonic-gate 	signal (SIGWINCH, SIG_IGN);
14380Sstevel@tonic-gate #ifdef SIGTSTP
14390Sstevel@tonic-gate         if (catch_susp)
14400Sstevel@tonic-gate             signal(SIGTSTP, SIG_DFL);
14410Sstevel@tonic-gate #endif
14420Sstevel@tonic-gate         wait ((pid_t)0);
14430Sstevel@tonic-gate         signal (SIGINT, end_it);
14440Sstevel@tonic-gate         signal (SIGQUIT, onquit);
14450Sstevel@tonic-gate 	signal (SIGWINCH, chgwinsz);
14460Sstevel@tonic-gate #ifdef SIGTSTP
14470Sstevel@tonic-gate         if (catch_susp)
14480Sstevel@tonic-gate             signal(SIGTSTP, onsusp);
14490Sstevel@tonic-gate #endif
14500Sstevel@tonic-gate 	/*
14510Sstevel@tonic-gate 	 * Since we were ignoring window change signals while we executed
14520Sstevel@tonic-gate 	 * the command, we must assume the window changed.
14530Sstevel@tonic-gate 	 */
14540Sstevel@tonic-gate 	(void) chgwinsz(0);
14550Sstevel@tonic-gate 	set_tty ();
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate         pr ("------------------------\n");
14580Sstevel@tonic-gate         prompt (filename);
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate /*
14610Sstevel@tonic-gate ** Skip n lines in the file f
14620Sstevel@tonic-gate */
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate static void
skiplns(register off_t n,register FILE * f)14650Sstevel@tonic-gate skiplns(register off_t n, register FILE *f)
14660Sstevel@tonic-gate {
14670Sstevel@tonic-gate     register int c;
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate     while (n > 0) {
14700Sstevel@tonic-gate         while ((c = Getc (f)) != '\n')
14710Sstevel@tonic-gate             if (c == EOF)
14720Sstevel@tonic-gate                 return;
14730Sstevel@tonic-gate             n--;
14740Sstevel@tonic-gate             Currline++;
14750Sstevel@tonic-gate     }
14760Sstevel@tonic-gate }
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate /*
14790Sstevel@tonic-gate ** Skip nskip files in the file list (from the command line). Nskip may be
14800Sstevel@tonic-gate ** negative.
14810Sstevel@tonic-gate */
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate static void
skipf(register int nskip)14840Sstevel@tonic-gate skipf(register int nskip)
14850Sstevel@tonic-gate {
14860Sstevel@tonic-gate     if (nskip == 0) return;
14870Sstevel@tonic-gate     if (nskip > 0) {
14880Sstevel@tonic-gate         if (fnum + nskip > nfiles - 1)
14890Sstevel@tonic-gate             nskip = nfiles - fnum - 1;
14900Sstevel@tonic-gate     }
14910Sstevel@tonic-gate     else if (within)
14920Sstevel@tonic-gate         ++fnum;
14930Sstevel@tonic-gate     fnum += nskip;
14940Sstevel@tonic-gate     if (fnum < 0)
14950Sstevel@tonic-gate         fnum = 0;
14960Sstevel@tonic-gate     pr (gettext("\n...Skipping "));
14970Sstevel@tonic-gate     pr ("\n");
14980Sstevel@tonic-gate     if (clreol)
14990Sstevel@tonic-gate         cleareol ();
15000Sstevel@tonic-gate     if (nskip > 0)
15010Sstevel@tonic-gate 	printf(gettext("...Skipping to file %s\n"), fnames[fnum]);
15020Sstevel@tonic-gate     else
15030Sstevel@tonic-gate 	printf(gettext("...Skipping back to file %s\n"), fnames[fnum]);
15040Sstevel@tonic-gate     if (clreol)
15050Sstevel@tonic-gate         cleareol ();
15060Sstevel@tonic-gate     pr ("\n");
15070Sstevel@tonic-gate     --fnum;
15080Sstevel@tonic-gate }
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate /*----------------------------- Terminal I/O -------------------------------*/
15110Sstevel@tonic-gate 
15120Sstevel@tonic-gate static void
initterm(void)15130Sstevel@tonic-gate initterm(void)
15140Sstevel@tonic-gate {
15150Sstevel@tonic-gate     int         erret = 0;
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate     setbuf(stdout, obuf);
15180Sstevel@tonic-gate     if (!(no_tty = ioctl(1, TCGETA, &otty))) {
15190Sstevel@tonic-gate 	if (setupterm(NULL, 1, &erret) != OK) {
15200Sstevel@tonic-gate             dumb++; ul_opt = 0;
15210Sstevel@tonic-gate         }
15220Sstevel@tonic-gate         else {
15230Sstevel@tonic-gate 	    reset_shell_mode();
15240Sstevel@tonic-gate             if (((Lpp = lines) < 0) || hard_copy) {
15250Sstevel@tonic-gate                 hard++; /* Hard copy terminal */
15260Sstevel@tonic-gate                 Lpp = 24;
15270Sstevel@tonic-gate             }
15280Sstevel@tonic-gate             if (tailequ(fnames[0], "page") || !hard && (scroll_forward == NULL))
15290Sstevel@tonic-gate                 noscroll++;
15300Sstevel@tonic-gate             if ((Mcol = columns) < 0)
15310Sstevel@tonic-gate                 Mcol = 80;
15320Sstevel@tonic-gate             Wrap = tigetflag("am");
15330Sstevel@tonic-gate             /*
15340Sstevel@tonic-gate              *  Set up for underlining:  some terminals don't need it;
15350Sstevel@tonic-gate              *  others have start/stop sequences, still others have an
15360Sstevel@tonic-gate              *  underline char sequence which is assumed to move the
15370Sstevel@tonic-gate              *  cursor forward one character.  If underline sequence
15380Sstevel@tonic-gate              *  isn't available, settle for standout sequence.
15390Sstevel@tonic-gate              */
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate             if (transparent_underline || over_strike)
15420Sstevel@tonic-gate                 ul_opt = 0;
15430Sstevel@tonic-gate             if ((ULenter = tigetstr("smul")) == NULL &&
15440Sstevel@tonic-gate                 (!underline_char) && (ULenter = tigetstr("smso")) == NULL)
15450Sstevel@tonic-gate                 ULenter = "";
15460Sstevel@tonic-gate             if ((ULexit = tigetstr("rmul")) == NULL &&
15470Sstevel@tonic-gate                 (!underline_char) && (ULexit = tigetstr("rmso")) == NULL)
15480Sstevel@tonic-gate                 ULexit = "";
15490Sstevel@tonic-gate         }
15500Sstevel@tonic-gate         if ((shell = getenv("SHELL")) == NULL)
15510Sstevel@tonic-gate             shell = "/usr/bin/sh";
15520Sstevel@tonic-gate     }
15530Sstevel@tonic-gate     no_intty = ioctl(0, TCGETA, &otty);
15540Sstevel@tonic-gate     ioctl(2, TCGETA, &otty);
15550Sstevel@tonic-gate     hardtabs = !(otty.c_oflag & TAB3);
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate static int
readch(void)15590Sstevel@tonic-gate readch(void)
15600Sstevel@tonic-gate {
15610Sstevel@tonic-gate         char ch;
15620Sstevel@tonic-gate         extern int errno;
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate         if (read (2, &ch, 1) <= 0)
15650Sstevel@tonic-gate                 if (errno != EINTR)
15660Sstevel@tonic-gate                         end_it(0);		/* clean up before exiting */
15670Sstevel@tonic-gate                 else
15680Sstevel@tonic-gate                         ch = otty.c_cc[VKILL];
15690Sstevel@tonic-gate         return (ch);
15700Sstevel@tonic-gate }
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate static char BS = '\b';
15730Sstevel@tonic-gate static char CARAT = '^';
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate static void
ttyin(char buf[],register int nmax,char pchar)15760Sstevel@tonic-gate ttyin(char buf[], register int nmax, char pchar)
15770Sstevel@tonic-gate {
15780Sstevel@tonic-gate     register char *sptr;
15790Sstevel@tonic-gate     register unsigned char ch;
15800Sstevel@tonic-gate     int LengthBuffer[80];
15810Sstevel@tonic-gate     int *BufferPointer;
15820Sstevel@tonic-gate     int csno;
15830Sstevel@tonic-gate     register int slash = 0;
15840Sstevel@tonic-gate     int maxlen;
15850Sstevel@tonic-gate     char cbuf;
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate     BufferPointer = LengthBuffer;
15880Sstevel@tonic-gate     sptr = buf;
15890Sstevel@tonic-gate     maxlen = 0;
15900Sstevel@tonic-gate     while (sptr - buf < nmax) {
15910Sstevel@tonic-gate         if (promptlen > maxlen)
15920Sstevel@tonic-gate 	    maxlen = promptlen;
15930Sstevel@tonic-gate         ch = readch ();
15940Sstevel@tonic-gate         csno = csetno(ch);
15950Sstevel@tonic-gate         if (!csno) {
15960Sstevel@tonic-gate             if (ch == '\\') {
15970Sstevel@tonic-gate                 slash++;
15980Sstevel@tonic-gate             } else if ((ch == otty.c_cc[VERASE]) && !slash) {
15990Sstevel@tonic-gate                 if (sptr > buf) {
16000Sstevel@tonic-gate                     --promptlen;
16010Sstevel@tonic-gate                     write (2, &BS, 1);
16020Sstevel@tonic-gate 		    sptr -= (*--BufferPointer);
16030Sstevel@tonic-gate                     if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
16040Sstevel@tonic-gate                         --promptlen;
16050Sstevel@tonic-gate                         write (2, &BS, 1);
16060Sstevel@tonic-gate                     }
16070Sstevel@tonic-gate                     continue;
16080Sstevel@tonic-gate                 } else {
16090Sstevel@tonic-gate                     if (!clr_eol)
16100Sstevel@tonic-gate 			promptlen = maxlen;
16110Sstevel@tonic-gate                     longjmp (restore, 1);
16120Sstevel@tonic-gate                 }
16130Sstevel@tonic-gate             } else if ((ch == otty.c_cc[VKILL]) && !slash) {
16140Sstevel@tonic-gate                 if (hard) {
16150Sstevel@tonic-gate                     show(ch);
16160Sstevel@tonic-gate                     putchar ('\n');
16170Sstevel@tonic-gate                     putchar (pchar);
16180Sstevel@tonic-gate                 } else {
16190Sstevel@tonic-gate                     putchar ('\r');
16200Sstevel@tonic-gate 		    putchar (pchar);
16210Sstevel@tonic-gate                     if (clr_eol)
16220Sstevel@tonic-gate                         prmpt_erase (1);
16230Sstevel@tonic-gate                     promptlen = 1;
16240Sstevel@tonic-gate                 }
16250Sstevel@tonic-gate                 sptr = buf;
16260Sstevel@tonic-gate                 fflush (stdout);
16270Sstevel@tonic-gate                 continue;
16280Sstevel@tonic-gate             }
16290Sstevel@tonic-gate             if (slash && (ch == otty.c_cc[VKILL] || ch == otty.c_cc[VERASE])) {
16300Sstevel@tonic-gate                 write (2, &BS, 1);
16310Sstevel@tonic-gate 	        sptr -= (*--BufferPointer);
16320Sstevel@tonic-gate             }
16330Sstevel@tonic-gate             if (ch != '\\')
16340Sstevel@tonic-gate                 slash = 0;
16350Sstevel@tonic-gate 	    *BufferPointer++ = 1;
16360Sstevel@tonic-gate             *sptr++ = ch;
16370Sstevel@tonic-gate             if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
16380Sstevel@tonic-gate                 ch += ch == RUBOUT ? -0100 : 0100;
16390Sstevel@tonic-gate                 write (2, &CARAT, 1);
16400Sstevel@tonic-gate                 promptlen++;
16410Sstevel@tonic-gate             }
16420Sstevel@tonic-gate             cbuf = ch;
16430Sstevel@tonic-gate             if (ch != '\n' && ch != ESC) {
16440Sstevel@tonic-gate                 write (2, &cbuf, 1);
16450Sstevel@tonic-gate                 promptlen++;
16460Sstevel@tonic-gate             } else
16470Sstevel@tonic-gate                 break;
16480Sstevel@tonic-gate             /* end of code set 0 */
16490Sstevel@tonic-gate         } else {
16500Sstevel@tonic-gate 	    int i;
16510Sstevel@tonic-gate 	    u_char buffer[5];
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 	    *BufferPointer++ = cw[csno];
16540Sstevel@tonic-gate 	    buffer[0] = *sptr++ = ch;
16550Sstevel@tonic-gate 	    for(i=1; i<cw[csno]; i++) {
16560Sstevel@tonic-gate 	        buffer[i] = *sptr++ = readch();
16570Sstevel@tonic-gate 	    }
16580Sstevel@tonic-gate 	    buffer[i]='\0';
16590Sstevel@tonic-gate 	    write(2, buffer, strlen((char *)buffer));
16600Sstevel@tonic-gate 	}
16610Sstevel@tonic-gate     }
16620Sstevel@tonic-gate     *--sptr = '\0';
16630Sstevel@tonic-gate     if (!clr_eol) promptlen = maxlen;
16640Sstevel@tonic-gate     if (sptr - buf >= nmax - 1)
16650Sstevel@tonic-gate         error (gettext("Line too long"));
16660Sstevel@tonic-gate }
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate static int
expand(char * outbuf,char * inbuf)16690Sstevel@tonic-gate expand(char *outbuf, char *inbuf)
16700Sstevel@tonic-gate {
16712932Sas145665 	char *in_str;
16722932Sas145665 	char *out_str;
16732932Sas145665 	char ch;
16742932Sas145665 	char temp[PATH_MAX];
16752932Sas145665 	int changed = 0;
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate     in_str = inbuf;
16780Sstevel@tonic-gate     out_str = temp;
16790Sstevel@tonic-gate     while ((ch = *in_str++) != '\0')
16800Sstevel@tonic-gate         switch (ch) {
16810Sstevel@tonic-gate         case '%':
16820Sstevel@tonic-gate             if (!no_intty) {
16832932Sas145665 		if (strlcpy(out_str, fnames[fnum], sizeof (temp))
16842932Sas145665 		    >= sizeof (temp))
16852932Sas145665 			error(gettext("Command too long"));
16860Sstevel@tonic-gate                 out_str += strlen (fnames[fnum]);
16870Sstevel@tonic-gate                 changed++;
16880Sstevel@tonic-gate             }
16890Sstevel@tonic-gate             else
16900Sstevel@tonic-gate                 *out_str++ = ch;
16910Sstevel@tonic-gate             break;
16920Sstevel@tonic-gate         case '!':
16930Sstevel@tonic-gate             if (!shellp)
16940Sstevel@tonic-gate                 error (gettext("No previous command to substitute for"));
16952932Sas145665 	    if (strlcpy(out_str, shell_line, sizeof (temp)) >= sizeof (temp))
16962932Sas145665 		error(gettext("Command too long"));
16970Sstevel@tonic-gate             out_str += strlen (shell_line);
16980Sstevel@tonic-gate             changed++;
16990Sstevel@tonic-gate             break;
17000Sstevel@tonic-gate         case '\\':
17010Sstevel@tonic-gate             if (*in_str == '%' || *in_str == '!') {
17020Sstevel@tonic-gate                 *out_str++ = *in_str++;
17030Sstevel@tonic-gate                 break;
17040Sstevel@tonic-gate             }
17050Sstevel@tonic-gate         default:
17060Sstevel@tonic-gate             *out_str++ = ch;
17070Sstevel@tonic-gate         }
17080Sstevel@tonic-gate     *out_str++ = '\0';
17092932Sas145665 	if (strlcpy(outbuf, temp, sizeof (shell_line)) >= sizeof (shell_line))
17102932Sas145665 		error(gettext("Command too long"));
17110Sstevel@tonic-gate     return (changed);
17120Sstevel@tonic-gate }
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate static void
show(register char ch)17150Sstevel@tonic-gate show(register char ch)
17160Sstevel@tonic-gate {
17170Sstevel@tonic-gate     char cbuf;
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate     if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
17200Sstevel@tonic-gate         ch += ch == RUBOUT ? -0100 : 0100;
17210Sstevel@tonic-gate         write (2, &CARAT, 1);
17220Sstevel@tonic-gate         promptlen++;
17230Sstevel@tonic-gate     }
17240Sstevel@tonic-gate     cbuf = ch;
17250Sstevel@tonic-gate     write (2, &cbuf, 1);
17260Sstevel@tonic-gate     promptlen++;
17270Sstevel@tonic-gate }
17280Sstevel@tonic-gate 
17290Sstevel@tonic-gate static void
error(char * mess)17300Sstevel@tonic-gate error (char *mess)
17310Sstevel@tonic-gate {
17320Sstevel@tonic-gate     if (clreol)
17330Sstevel@tonic-gate         cleareol ();
17340Sstevel@tonic-gate     else
17350Sstevel@tonic-gate         kill_line ();
17360Sstevel@tonic-gate     promptlen += strlen (mess);
17370Sstevel@tonic-gate     if (enter_standout_mode && exit_standout_mode) {
17380Sstevel@tonic-gate         putp (enter_standout_mode);
17390Sstevel@tonic-gate         pr(mess);
17400Sstevel@tonic-gate         putp (exit_standout_mode);
17410Sstevel@tonic-gate     }
17420Sstevel@tonic-gate     else
17430Sstevel@tonic-gate         pr (mess);
17440Sstevel@tonic-gate     fflush(stdout);
17450Sstevel@tonic-gate     errors++;
17460Sstevel@tonic-gate     longjmp (restore, 1);
17470Sstevel@tonic-gate }
17480Sstevel@tonic-gate 
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate static void
set_tty(void)17510Sstevel@tonic-gate set_tty(void)
17520Sstevel@tonic-gate {
17530Sstevel@tonic-gate         ioctl(2, TCGETA, &otty);     /* save old tty modes */
17540Sstevel@tonic-gate         ioctl(2, TCGETA, &ntty);
17550Sstevel@tonic-gate         ntty.c_lflag &= ~ECHO & ~ICANON;
17560Sstevel@tonic-gate         ntty.c_cc[VMIN] = (char)1;
17570Sstevel@tonic-gate         ntty.c_cc[VTIME] = (char)0;
17580Sstevel@tonic-gate         ioctl (2, TCSETAF, &ntty);        /* set new tty modes */
17590Sstevel@tonic-gate }
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate static void
reset_tty(void)17620Sstevel@tonic-gate reset_tty(void)
17630Sstevel@tonic-gate {
17640Sstevel@tonic-gate         ioctl (2, TCSETAF, &otty);        /* reset tty modes */
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate static void
rdline(register FILE * f)17680Sstevel@tonic-gate rdline(register FILE *f)
17690Sstevel@tonic-gate {
17700Sstevel@tonic-gate     register int c;
17710Sstevel@tonic-gate     register char *p;
17720Sstevel@tonic-gate 
17730Sstevel@tonic-gate     p = Line;
17740Sstevel@tonic-gate     while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
17750Sstevel@tonic-gate         *p++ = c;
17760Sstevel@tonic-gate     if (c == '\n')
17770Sstevel@tonic-gate         Currline++;
17780Sstevel@tonic-gate     *p = '\0';
17790Sstevel@tonic-gate }
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate /* Come here when we get a suspend signal from the terminal */
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate /*
17840Sstevel@tonic-gate  * sig is put in as a dummy arg to have the compiler not to complain
17850Sstevel@tonic-gate  */
17860Sstevel@tonic-gate #ifdef SIGTSTP
17870Sstevel@tonic-gate /* ARGSUSED */
17880Sstevel@tonic-gate void
onsusp(int sig)17890Sstevel@tonic-gate onsusp(int sig)
17900Sstevel@tonic-gate {
17910Sstevel@tonic-gate     /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
17920Sstevel@tonic-gate     signal(SIGTTOU, SIG_IGN);
17930Sstevel@tonic-gate     reset_tty ();
17940Sstevel@tonic-gate     fflush (stdout);
17950Sstevel@tonic-gate     signal(SIGTTOU, SIG_DFL);
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate     /* Send the TSTP signal to suspend our process group */
17980Sstevel@tonic-gate     kill (0, SIGTSTP);
17990Sstevel@tonic-gate     /* Pause for station break */
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate     /* We're back */
18020Sstevel@tonic-gate     signal (SIGTSTP, onsusp);
18030Sstevel@tonic-gate     set_tty ();
18040Sstevel@tonic-gate     if (inwait)
18050Sstevel@tonic-gate             longjmp (restore, 1);
18060Sstevel@tonic-gate }
18070Sstevel@tonic-gate #endif
1808