1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <signal.h> 34*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 38*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 39*7c478bd9Sstevel@tonic-gate #include <ctype.h> 40*7c478bd9Sstevel@tonic-gate #include <stdio.h> 41*7c478bd9Sstevel@tonic-gate #include <wchar.h> 42*7c478bd9Sstevel@tonic-gate #include <curses.h> 43*7c478bd9Sstevel@tonic-gate #include <term.h> 44*7c478bd9Sstevel@tonic-gate #include <errno.h> 45*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 46*7c478bd9Sstevel@tonic-gate #include <regexpr.h> 47*7c478bd9Sstevel@tonic-gate #include <limits.h> 48*7c478bd9Sstevel@tonic-gate #include <locale.h> 49*7c478bd9Sstevel@tonic-gate #include <wctype.h> /* iswprint() */ 50*7c478bd9Sstevel@tonic-gate #include <string.h> 51*7c478bd9Sstevel@tonic-gate #include <unistd.h> 52*7c478bd9Sstevel@tonic-gate #include <wait.h> 53*7c478bd9Sstevel@tonic-gate #include <libw.h> 54*7c478bd9Sstevel@tonic-gate #include <regexpr.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * pg -- paginator for crt terminals 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * Includes the ability to display pages that have 61*7c478bd9Sstevel@tonic-gate * already passed by. Also gives the user the ability 62*7c478bd9Sstevel@tonic-gate * to search forward and backwards for regular expressions. 63*7c478bd9Sstevel@tonic-gate * This works for piped input by copying to a temporary file, 64*7c478bd9Sstevel@tonic-gate * and resolving backreferences from there. 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * Note: The reason that there are so many commands to do 67*7c478bd9Sstevel@tonic-gate * the same types of things is to try to accommodate 68*7c478bd9Sstevel@tonic-gate * users of other paginators. 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #define LINSIZ 1024 72*7c478bd9Sstevel@tonic-gate #define QUIT '\034' 73*7c478bd9Sstevel@tonic-gate #define BOF (EOF - 1) /* Begining of File */ 74*7c478bd9Sstevel@tonic-gate #define STOP (EOF - 2) 75*7c478bd9Sstevel@tonic-gate #define PROMPTSIZE 256 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate * Function definitions 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate static void lineset(int); 81*7c478bd9Sstevel@tonic-gate static char *setprompt(); 82*7c478bd9Sstevel@tonic-gate static int set_state(int *, wchar_t, char *); 83*7c478bd9Sstevel@tonic-gate static void help(); 84*7c478bd9Sstevel@tonic-gate static void copy_file(FILE *, FILE *); 85*7c478bd9Sstevel@tonic-gate static void re_error(int); 86*7c478bd9Sstevel@tonic-gate static void save_input(FILE *); 87*7c478bd9Sstevel@tonic-gate static void save_pipe(); 88*7c478bd9Sstevel@tonic-gate static void newdol(FILE *); 89*7c478bd9Sstevel@tonic-gate static void erase_line(int); 90*7c478bd9Sstevel@tonic-gate static void kill_line(); 91*7c478bd9Sstevel@tonic-gate static void doclear(); 92*7c478bd9Sstevel@tonic-gate static void sopr(char *, int); 93*7c478bd9Sstevel@tonic-gate static void prompt(char *); 94*7c478bd9Sstevel@tonic-gate static void error(char *); 95*7c478bd9Sstevel@tonic-gate static void terminit(); 96*7c478bd9Sstevel@tonic-gate static void compact(); 97*7c478bd9Sstevel@tonic-gate static off_t getline(FILE *); 98*7c478bd9Sstevel@tonic-gate static int mrdchar(); 99*7c478bd9Sstevel@tonic-gate static off_t find(int, off_t); 100*7c478bd9Sstevel@tonic-gate static int search(char *, off_t); 101*7c478bd9Sstevel@tonic-gate static FILE *checkf(char *); 102*7c478bd9Sstevel@tonic-gate static int skipf(int); 103*7c478bd9Sstevel@tonic-gate static int readch(); 104*7c478bd9Sstevel@tonic-gate static int ttyin(); 105*7c478bd9Sstevel@tonic-gate static int number(); 106*7c478bd9Sstevel@tonic-gate static int command(char *); 107*7c478bd9Sstevel@tonic-gate static int screen(char *); 108*7c478bd9Sstevel@tonic-gate static int fgetputc(); 109*7c478bd9Sstevel@tonic-gate static char *pg_strchr(); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate struct line { /* how line addresses are stored */ 113*7c478bd9Sstevel@tonic-gate off_t l_addr; /* file offset */ 114*7c478bd9Sstevel@tonic-gate off_t l_no; /* line number in file */ 115*7c478bd9Sstevel@tonic-gate }; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate typedef struct line LINE; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate static LINE *zero = NULL, /* first line */ 120*7c478bd9Sstevel@tonic-gate *dot, /* current line */ 121*7c478bd9Sstevel@tonic-gate *dol, /* last line */ 122*7c478bd9Sstevel@tonic-gate *contig; /* where contiguous (non-aged) lines start */ 123*7c478bd9Sstevel@tonic-gate static long nlall; /* room for how many LINEs in memory */ 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate static FILE *in_file, /* current input stream */ 126*7c478bd9Sstevel@tonic-gate *tmp_fin, /* pipe temporary file in */ 127*7c478bd9Sstevel@tonic-gate *tmp_fou; /* pipe temporary file out */ 128*7c478bd9Sstevel@tonic-gate static char tmp_name[] = "/tmp/pgXXXXXX"; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate static short sign; /* sign of command input */ 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate static int fnum, /* which file argument we're in */ 133*7c478bd9Sstevel@tonic-gate pipe_in, /* set when stdin is a pipe */ 134*7c478bd9Sstevel@tonic-gate out_is_tty; /* set if stdout is a tty */ 135*7c478bd9Sstevel@tonic-gate static gid_t my_pgid; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate static void on_brk(), 138*7c478bd9Sstevel@tonic-gate end_it(); 139*7c478bd9Sstevel@tonic-gate static short brk_hit; /* interrupt handling is pending flag */ 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static int window = 0; /* window size in lines */ 142*7c478bd9Sstevel@tonic-gate static short eof_pause = 1; /* pause w/ prompt at end of files */ 143*7c478bd9Sstevel@tonic-gate static short rmode = 0; /* deny shell escape in restricted mode */ 144*7c478bd9Sstevel@tonic-gate static short soflag = 0; /* output all messages in standout mode */ 145*7c478bd9Sstevel@tonic-gate static short promptlen; /* length of the current prompt */ 146*7c478bd9Sstevel@tonic-gate static short firstf = 1; /* set before first file has been processed */ 147*7c478bd9Sstevel@tonic-gate static short inwait, /* set while waiting for user input */ 148*7c478bd9Sstevel@tonic-gate errors; /* set if error message has been printed. */ 149*7c478bd9Sstevel@tonic-gate /* if so, need to erase it and prompt */ 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static char **fnames; 152*7c478bd9Sstevel@tonic-gate static short status = 0; /* set > 0 if error detected */ 153*7c478bd9Sstevel@tonic-gate static short fflag = 0; /* set if the f option is used */ 154*7c478bd9Sstevel@tonic-gate static short nflag = 0; /* set for "no newline" input option */ 155*7c478bd9Sstevel@tonic-gate static short clropt = 0; /* set if the clear option is used */ 156*7c478bd9Sstevel@tonic-gate static int initopt = 0; /* set if the line option is used */ 157*7c478bd9Sstevel@tonic-gate static int srchopt = 0; /* set if the search option is used */ 158*7c478bd9Sstevel@tonic-gate static int initline; 159*7c478bd9Sstevel@tonic-gate static char initbuf[BUFSIZ]; 160*7c478bd9Sstevel@tonic-gate static wchar_t leave_search = L't'; 161*7c478bd9Sstevel@tonic-gate /* where on the page to leave a found string */ 162*7c478bd9Sstevel@tonic-gate static short nfiles; 163*7c478bd9Sstevel@tonic-gate static char *shell; 164*7c478bd9Sstevel@tonic-gate static char *promptstr = ":"; 165*7c478bd9Sstevel@tonic-gate static off_t nchars; /* return from getline in find() */ 166*7c478bd9Sstevel@tonic-gate static jmp_buf restore; 167*7c478bd9Sstevel@tonic-gate static char Line[LINSIZ+2]; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate static int catch_susp; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate static void onsusp(); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate struct screen_stat { 174*7c478bd9Sstevel@tonic-gate off_t first_line; 175*7c478bd9Sstevel@tonic-gate off_t last_line; 176*7c478bd9Sstevel@tonic-gate short is_eof; 177*7c478bd9Sstevel@tonic-gate }; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate static struct screen_stat old_ss = { 0, 0, 0 }; 180*7c478bd9Sstevel@tonic-gate static struct screen_stat new_ss; 181*7c478bd9Sstevel@tonic-gate static struct termio otty; /* to save old terminal settings */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate static short termflg = 0; /* set once terminal is initialized */ 184*7c478bd9Sstevel@tonic-gate static short eoflag; /* set whenever at end of current file */ 185*7c478bd9Sstevel@tonic-gate static short doliseof; /* set when last line of file is known */ 186*7c478bd9Sstevel@tonic-gate static off_t eofl_no; /* what the last line of the file is */ 187*7c478bd9Sstevel@tonic-gate static void usage(void); 188*7c478bd9Sstevel@tonic-gate static FILE *pg_stdin; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate main(argc, argv) 191*7c478bd9Sstevel@tonic-gate int argc; 192*7c478bd9Sstevel@tonic-gate char *argv[]; 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate char *s; 195*7c478bd9Sstevel@tonic-gate char *p; 196*7c478bd9Sstevel@tonic-gate int prnames = 0; 197*7c478bd9Sstevel@tonic-gate int opt; 198*7c478bd9Sstevel@tonic-gate int i; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 201*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 202*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 203*7c478bd9Sstevel@tonic-gate #endif 204*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* check for non-standard "-#" option */ 207*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 208*7c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "--") == 0) 209*7c478bd9Sstevel@tonic-gate break; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if ((argv[i][0] == '-') && isdigit(argv[i][1])) { 212*7c478bd9Sstevel@tonic-gate if (strlen(&argv[i][1]) != 213*7c478bd9Sstevel@tonic-gate strspn(&argv[i][1], "0123456789")) { 214*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 215*7c478bd9Sstevel@tonic-gate "pg: Badly formed number\n")); 216*7c478bd9Sstevel@tonic-gate usage(); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate window = (int)strtol(&argv[i][1], (char **)NULL, 10); 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate while (i < argc) { 222*7c478bd9Sstevel@tonic-gate argv[i] = argv[i + 1]; 223*7c478bd9Sstevel@tonic-gate i++; 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate i--; 226*7c478bd9Sstevel@tonic-gate argc--; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* check for non-standard + option */ 231*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 232*7c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "--") == 0) 233*7c478bd9Sstevel@tonic-gate break; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (argv[i][0] == '+') { 236*7c478bd9Sstevel@tonic-gate if (argv[i][1] == '/') { 237*7c478bd9Sstevel@tonic-gate srchopt++; 238*7c478bd9Sstevel@tonic-gate initopt = 0; 239*7c478bd9Sstevel@tonic-gate for (s = &argv[i][2], p = initbuf; *s != '\0'; ) 240*7c478bd9Sstevel@tonic-gate if (p < initbuf + sizeof (initbuf)) 241*7c478bd9Sstevel@tonic-gate *p++ = *s++; 242*7c478bd9Sstevel@tonic-gate else { 243*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 244*7c478bd9Sstevel@tonic-gate "pg: pattern too long\n")); 245*7c478bd9Sstevel@tonic-gate return (1); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate *p = '\0'; 248*7c478bd9Sstevel@tonic-gate } else { 249*7c478bd9Sstevel@tonic-gate initopt++; 250*7c478bd9Sstevel@tonic-gate srchopt = 0; 251*7c478bd9Sstevel@tonic-gate s = &argv[i][2]; 252*7c478bd9Sstevel@tonic-gate for (; isdigit(*s); s++) 253*7c478bd9Sstevel@tonic-gate initline = initline*10 + *s -'0'; 254*7c478bd9Sstevel@tonic-gate if (*s != '\0') 255*7c478bd9Sstevel@tonic-gate usage(); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate while (i < argc) { 259*7c478bd9Sstevel@tonic-gate argv[i] = argv[i + 1]; 260*7c478bd9Sstevel@tonic-gate i++; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate i--; 263*7c478bd9Sstevel@tonic-gate argc--; 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "cefnrsp:")) != EOF) { 268*7c478bd9Sstevel@tonic-gate switch (opt) { 269*7c478bd9Sstevel@tonic-gate case 'c': 270*7c478bd9Sstevel@tonic-gate clropt = 1; 271*7c478bd9Sstevel@tonic-gate break; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate case 'e': 274*7c478bd9Sstevel@tonic-gate eof_pause = 0; 275*7c478bd9Sstevel@tonic-gate break; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate case 'f': 278*7c478bd9Sstevel@tonic-gate fflag = 1; 279*7c478bd9Sstevel@tonic-gate break; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate case 'n': 282*7c478bd9Sstevel@tonic-gate nflag = 1; 283*7c478bd9Sstevel@tonic-gate break; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate case 'r': 286*7c478bd9Sstevel@tonic-gate rmode = 1; /* restricted mode */ 287*7c478bd9Sstevel@tonic-gate break; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate case 's': 290*7c478bd9Sstevel@tonic-gate soflag = 1; /* standout mode */ 291*7c478bd9Sstevel@tonic-gate break; 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate case 'p': 294*7c478bd9Sstevel@tonic-gate promptstr = setprompt(optarg); 295*7c478bd9Sstevel@tonic-gate break; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate default: 298*7c478bd9Sstevel@tonic-gate usage(); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate nfiles = argc - optind; 303*7c478bd9Sstevel@tonic-gate fnames = &argv[optind]; 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, end_it); 306*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, end_it); 307*7c478bd9Sstevel@tonic-gate out_is_tty = isatty(1); 308*7c478bd9Sstevel@tonic-gate my_pgid = getpgrp(); 309*7c478bd9Sstevel@tonic-gate if (out_is_tty) { 310*7c478bd9Sstevel@tonic-gate terminit(); 311*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, on_brk); 312*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, on_brk); 313*7c478bd9Sstevel@tonic-gate if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) { 314*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, onsusp); 315*7c478bd9Sstevel@tonic-gate catch_susp++; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate if (window == 0) 319*7c478bd9Sstevel@tonic-gate window = lines - 1; 320*7c478bd9Sstevel@tonic-gate if (window <= 1) 321*7c478bd9Sstevel@tonic-gate window = 2; 322*7c478bd9Sstevel@tonic-gate if (initline <= 0) 323*7c478bd9Sstevel@tonic-gate initline = 1; 324*7c478bd9Sstevel@tonic-gate if (nfiles > 1) 325*7c478bd9Sstevel@tonic-gate prnames++; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (nfiles == 0) { 328*7c478bd9Sstevel@tonic-gate fnames[0] = "-"; 329*7c478bd9Sstevel@tonic-gate nfiles++; 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate while (fnum < nfiles) { 332*7c478bd9Sstevel@tonic-gate if (strcmp(fnames[fnum], "") == 0) 333*7c478bd9Sstevel@tonic-gate fnames[fnum] = "-"; 334*7c478bd9Sstevel@tonic-gate if ((in_file = checkf(fnames[fnum])) == NULL) 335*7c478bd9Sstevel@tonic-gate { 336*7c478bd9Sstevel@tonic-gate status = 2; 337*7c478bd9Sstevel@tonic-gate fnum++; 338*7c478bd9Sstevel@tonic-gate } else { 339*7c478bd9Sstevel@tonic-gate status = 0; 340*7c478bd9Sstevel@tonic-gate if (out_is_tty) 341*7c478bd9Sstevel@tonic-gate fnum += screen(fnames[fnum]); 342*7c478bd9Sstevel@tonic-gate else { 343*7c478bd9Sstevel@tonic-gate if (prnames) { 344*7c478bd9Sstevel@tonic-gate (void) fputs("::::::::::::::\n", 345*7c478bd9Sstevel@tonic-gate stdout); 346*7c478bd9Sstevel@tonic-gate (void) fputs(fnames[fnum], stdout); 347*7c478bd9Sstevel@tonic-gate (void) fputs("\n::::::::::::::\n", 348*7c478bd9Sstevel@tonic-gate stdout); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate copy_file(in_file, stdout); 351*7c478bd9Sstevel@tonic-gate fnum++; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 354*7c478bd9Sstevel@tonic-gate if (pipe_in) 355*7c478bd9Sstevel@tonic-gate save_pipe(); 356*7c478bd9Sstevel@tonic-gate else 357*7c478bd9Sstevel@tonic-gate if (in_file != tmp_fin) 358*7c478bd9Sstevel@tonic-gate (void) fclose(in_file); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate end_it(); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 364*7c478bd9Sstevel@tonic-gate return (0); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static char * 368*7c478bd9Sstevel@tonic-gate setprompt(s) 369*7c478bd9Sstevel@tonic-gate char *s; 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate int i = 0; 372*7c478bd9Sstevel@tonic-gate int pct_d = 0; 373*7c478bd9Sstevel@tonic-gate static char pstr[PROMPTSIZE]; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate while (i < PROMPTSIZE - 2) 376*7c478bd9Sstevel@tonic-gate switch (pstr[i++] = *s++) { 377*7c478bd9Sstevel@tonic-gate case '\0': 378*7c478bd9Sstevel@tonic-gate return (pstr); 379*7c478bd9Sstevel@tonic-gate case '%': 380*7c478bd9Sstevel@tonic-gate if (*s == 'd' && !pct_d) { 381*7c478bd9Sstevel@tonic-gate pct_d++; 382*7c478bd9Sstevel@tonic-gate } else if (*s != '%') 383*7c478bd9Sstevel@tonic-gate pstr[i++] = '%'; 384*7c478bd9Sstevel@tonic-gate if ((pstr[i++] = *s++) == '\0') 385*7c478bd9Sstevel@tonic-gate return (pstr); 386*7c478bd9Sstevel@tonic-gate break; 387*7c478bd9Sstevel@tonic-gate default: 388*7c478bd9Sstevel@tonic-gate break; 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("pg: prompt too long\n")); 391*7c478bd9Sstevel@tonic-gate exit(1); 392*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* 397*7c478bd9Sstevel@tonic-gate * Print out the contents of the file f, one screenful at a time. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate static int 401*7c478bd9Sstevel@tonic-gate screen(file_name) 402*7c478bd9Sstevel@tonic-gate char *file_name; 403*7c478bd9Sstevel@tonic-gate { 404*7c478bd9Sstevel@tonic-gate int cmd_ret = 0; 405*7c478bd9Sstevel@tonic-gate off_t start; 406*7c478bd9Sstevel@tonic-gate short hadchance = 0; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate old_ss.is_eof = 0; 409*7c478bd9Sstevel@tonic-gate old_ss.first_line = 0; 410*7c478bd9Sstevel@tonic-gate old_ss.last_line = 0; 411*7c478bd9Sstevel@tonic-gate new_ss = old_ss; 412*7c478bd9Sstevel@tonic-gate if (!firstf) 413*7c478bd9Sstevel@tonic-gate cmd_ret = command(file_name); 414*7c478bd9Sstevel@tonic-gate else { 415*7c478bd9Sstevel@tonic-gate firstf = 0; 416*7c478bd9Sstevel@tonic-gate if (initopt) { 417*7c478bd9Sstevel@tonic-gate initopt = 0; 418*7c478bd9Sstevel@tonic-gate new_ss.first_line = initline; 419*7c478bd9Sstevel@tonic-gate new_ss.last_line = initline + (off_t)window - 1; 420*7c478bd9Sstevel@tonic-gate } else if (srchopt) { 421*7c478bd9Sstevel@tonic-gate srchopt = 0; 422*7c478bd9Sstevel@tonic-gate if (!search(initbuf, (off_t)1)) 423*7c478bd9Sstevel@tonic-gate cmd_ret = command(file_name); 424*7c478bd9Sstevel@tonic-gate } else { 425*7c478bd9Sstevel@tonic-gate new_ss.first_line = 1; 426*7c478bd9Sstevel@tonic-gate new_ss.last_line = (off_t)window; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate for (;;) { 431*7c478bd9Sstevel@tonic-gate if (cmd_ret) 432*7c478bd9Sstevel@tonic-gate return (cmd_ret); 433*7c478bd9Sstevel@tonic-gate if (hadchance && new_ss.last_line >= eofl_no) 434*7c478bd9Sstevel@tonic-gate return (1); 435*7c478bd9Sstevel@tonic-gate hadchance = 0; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (new_ss.last_line < (off_t)window) 438*7c478bd9Sstevel@tonic-gate new_ss.last_line = (off_t)window; 439*7c478bd9Sstevel@tonic-gate if (find(0, new_ss.last_line + 1) != EOF) 440*7c478bd9Sstevel@tonic-gate new_ss.is_eof = 0; 441*7c478bd9Sstevel@tonic-gate else { 442*7c478bd9Sstevel@tonic-gate new_ss.is_eof = 1; 443*7c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 444*7c478bd9Sstevel@tonic-gate new_ss.first_line = new_ss.last_line - 445*7c478bd9Sstevel@tonic-gate (off_t)window + 1; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (new_ss.first_line < 1) 449*7c478bd9Sstevel@tonic-gate new_ss.first_line = 1; 450*7c478bd9Sstevel@tonic-gate if (clropt) { 451*7c478bd9Sstevel@tonic-gate doclear(); 452*7c478bd9Sstevel@tonic-gate start = new_ss.first_line; 453*7c478bd9Sstevel@tonic-gate } else { 454*7c478bd9Sstevel@tonic-gate if (new_ss.first_line == old_ss.last_line) 455*7c478bd9Sstevel@tonic-gate start = new_ss.first_line + 1; 456*7c478bd9Sstevel@tonic-gate else 457*7c478bd9Sstevel@tonic-gate if (new_ss.first_line > old_ss.last_line) 458*7c478bd9Sstevel@tonic-gate start = new_ss.first_line; 459*7c478bd9Sstevel@tonic-gate else 460*7c478bd9Sstevel@tonic-gate if (old_ss.first_line < new_ss.first_line) 461*7c478bd9Sstevel@tonic-gate start = old_ss.last_line + 1; 462*7c478bd9Sstevel@tonic-gate else 463*7c478bd9Sstevel@tonic-gate start = new_ss.first_line; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (start < old_ss.first_line) 466*7c478bd9Sstevel@tonic-gate sopr(gettext("...skipping backward\n"), 0); 467*7c478bd9Sstevel@tonic-gate else 468*7c478bd9Sstevel@tonic-gate if (start > old_ss.last_line + 1) 469*7c478bd9Sstevel@tonic-gate sopr(gettext("...skipping forward\n"), 0); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate for (; start <= new_ss.last_line; start++) { 473*7c478bd9Sstevel@tonic-gate (void) find(0, start); 474*7c478bd9Sstevel@tonic-gate (void) fputs(Line, stdout); 475*7c478bd9Sstevel@tonic-gate if (brk_hit) { 476*7c478bd9Sstevel@tonic-gate new_ss.last_line = find(1, 0); 477*7c478bd9Sstevel@tonic-gate new_ss.is_eof = 0; 478*7c478bd9Sstevel@tonic-gate break; 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate brk_hit = 0; 483*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 484*7c478bd9Sstevel@tonic-gate if (new_ss.is_eof) { 485*7c478bd9Sstevel@tonic-gate if (!eof_pause || eofl_no == 1) 486*7c478bd9Sstevel@tonic-gate return (1); 487*7c478bd9Sstevel@tonic-gate hadchance++; 488*7c478bd9Sstevel@tonic-gate error("(EOF)"); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate old_ss = new_ss; 491*7c478bd9Sstevel@tonic-gate cmd_ret = command((char *)NULL); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate static char cmdbuf[LINSIZ], *cmdptr; 496*7c478bd9Sstevel@tonic-gate #define BEEP() if (bell) { (void) putp(bell); (void) fflush(stdout); } 497*7c478bd9Sstevel@tonic-gate #define BLANKS(p) while (*p == ' ' || *p == '\t') p++ 498*7c478bd9Sstevel@tonic-gate #define CHECKEND() BLANKS(cmdptr); if (*cmdptr) { BEEP(); break; } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * Read a command and do it. A command consists of an optional integer 502*7c478bd9Sstevel@tonic-gate * argument followed by the command character. Return the number of files 503*7c478bd9Sstevel@tonic-gate * to skip, 0 if we're still talking about the same file. 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate static int 507*7c478bd9Sstevel@tonic-gate command(filename) 508*7c478bd9Sstevel@tonic-gate char *filename; 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate off_t nlines; 511*7c478bd9Sstevel@tonic-gate FILE *sf; 512*7c478bd9Sstevel@tonic-gate char *cmdend; 513*7c478bd9Sstevel@tonic-gate pid_t id; 514*7c478bd9Sstevel@tonic-gate int skip; 515*7c478bd9Sstevel@tonic-gate int len; 516*7c478bd9Sstevel@tonic-gate wchar_t wc; 517*7c478bd9Sstevel@tonic-gate wchar_t wc_e; 518*7c478bd9Sstevel@tonic-gate wchar_t wc_e1; 519*7c478bd9Sstevel@tonic-gate char *p; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate for (;;) { 522*7c478bd9Sstevel@tonic-gate /* 523*7c478bd9Sstevel@tonic-gate * Wait for output to drain before going on. 524*7c478bd9Sstevel@tonic-gate * This is done so that the user will not hit 525*7c478bd9Sstevel@tonic-gate * break and quit before he has seen the prompt. 526*7c478bd9Sstevel@tonic-gate */ 527*7c478bd9Sstevel@tonic-gate (void) ioctl(1, TCSBRK, 1); 528*7c478bd9Sstevel@tonic-gate if (setjmp(restore) > 0) 529*7c478bd9Sstevel@tonic-gate end_it(); 530*7c478bd9Sstevel@tonic-gate inwait = 1; 531*7c478bd9Sstevel@tonic-gate brk_hit = 0; 532*7c478bd9Sstevel@tonic-gate if (errors) 533*7c478bd9Sstevel@tonic-gate errors = 0; 534*7c478bd9Sstevel@tonic-gate else { 535*7c478bd9Sstevel@tonic-gate kill_line(); 536*7c478bd9Sstevel@tonic-gate prompt(filename); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 539*7c478bd9Sstevel@tonic-gate if (ttyin()) 540*7c478bd9Sstevel@tonic-gate continue; 541*7c478bd9Sstevel@tonic-gate cmdptr = cmdbuf; 542*7c478bd9Sstevel@tonic-gate nlines = number(); 543*7c478bd9Sstevel@tonic-gate BLANKS(cmdptr); 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, cmdptr, MB_CUR_MAX)) <= 0) { 546*7c478bd9Sstevel@tonic-gate wc = *cmdptr; 547*7c478bd9Sstevel@tonic-gate len = 1; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate cmdptr += len; 550*7c478bd9Sstevel@tonic-gate switch (wc) { 551*7c478bd9Sstevel@tonic-gate case 'h': 552*7c478bd9Sstevel@tonic-gate CHECKEND(); 553*7c478bd9Sstevel@tonic-gate help(); 554*7c478bd9Sstevel@tonic-gate break; 555*7c478bd9Sstevel@tonic-gate case '\014': /* ^L */ 556*7c478bd9Sstevel@tonic-gate case '.': /* redisplay current window */ 557*7c478bd9Sstevel@tonic-gate CHECKEND(); 558*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line; 559*7c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line; 560*7c478bd9Sstevel@tonic-gate inwait = 0; 561*7c478bd9Sstevel@tonic-gate return (0); 562*7c478bd9Sstevel@tonic-gate case 'w': /* set window size */ 563*7c478bd9Sstevel@tonic-gate case 'z': 564*7c478bd9Sstevel@tonic-gate if (sign == -1) { 565*7c478bd9Sstevel@tonic-gate BEEP(); 566*7c478bd9Sstevel@tonic-gate break; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate CHECKEND(); 569*7c478bd9Sstevel@tonic-gate if (nlines == 0) 570*7c478bd9Sstevel@tonic-gate nlines = (off_t)window; 571*7c478bd9Sstevel@tonic-gate else 572*7c478bd9Sstevel@tonic-gate if (nlines > 1) 573*7c478bd9Sstevel@tonic-gate window = (int)nlines; 574*7c478bd9Sstevel@tonic-gate else { 575*7c478bd9Sstevel@tonic-gate BEEP(); 576*7c478bd9Sstevel@tonic-gate break; 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line; 579*7c478bd9Sstevel@tonic-gate new_ss.last_line = new_ss.first_line + 580*7c478bd9Sstevel@tonic-gate (off_t)window - 1; 581*7c478bd9Sstevel@tonic-gate inwait = 0; 582*7c478bd9Sstevel@tonic-gate return (0); 583*7c478bd9Sstevel@tonic-gate case '\004': /* ^D */ 584*7c478bd9Sstevel@tonic-gate case 'd': 585*7c478bd9Sstevel@tonic-gate CHECKEND(); 586*7c478bd9Sstevel@tonic-gate if (sign == 0) 587*7c478bd9Sstevel@tonic-gate sign = 1; 588*7c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line + 589*7c478bd9Sstevel@tonic-gate (off_t)sign*window/2; 590*7c478bd9Sstevel@tonic-gate new_ss.first_line = new_ss.last_line - 591*7c478bd9Sstevel@tonic-gate (off_t)window + 1; 592*7c478bd9Sstevel@tonic-gate inwait = 0; 593*7c478bd9Sstevel@tonic-gate return (0); 594*7c478bd9Sstevel@tonic-gate case 's': 595*7c478bd9Sstevel@tonic-gate /* 596*7c478bd9Sstevel@tonic-gate * save input in filename. 597*7c478bd9Sstevel@tonic-gate * Check for filename, access, etc. 598*7c478bd9Sstevel@tonic-gate */ 599*7c478bd9Sstevel@tonic-gate BLANKS(cmdptr); 600*7c478bd9Sstevel@tonic-gate if (!*cmdptr) { 601*7c478bd9Sstevel@tonic-gate BEEP(); 602*7c478bd9Sstevel@tonic-gate break; 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate if (setjmp(restore) > 0) { 605*7c478bd9Sstevel@tonic-gate BEEP(); 606*7c478bd9Sstevel@tonic-gate } else { 607*7c478bd9Sstevel@tonic-gate char outstr[PROMPTSIZE]; 608*7c478bd9Sstevel@tonic-gate if ((sf = fopen(cmdptr, "w")) == NULL) { 609*7c478bd9Sstevel@tonic-gate error("cannot open save file"); 610*7c478bd9Sstevel@tonic-gate break; 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate kill_line(); 613*7c478bd9Sstevel@tonic-gate (void) sprintf(outstr, gettext( 614*7c478bd9Sstevel@tonic-gate "saving file %s"), cmdptr); 615*7c478bd9Sstevel@tonic-gate sopr(outstr, 1); 616*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 617*7c478bd9Sstevel@tonic-gate save_input(sf); 618*7c478bd9Sstevel@tonic-gate error("saved"); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate (void) fclose(sf); 621*7c478bd9Sstevel@tonic-gate break; 622*7c478bd9Sstevel@tonic-gate case 'q': 623*7c478bd9Sstevel@tonic-gate case 'Q': 624*7c478bd9Sstevel@tonic-gate CHECKEND(); 625*7c478bd9Sstevel@tonic-gate inwait = 0; 626*7c478bd9Sstevel@tonic-gate end_it(); 627*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate case 'f': /* skip forward screenfuls */ 630*7c478bd9Sstevel@tonic-gate CHECKEND(); 631*7c478bd9Sstevel@tonic-gate if (sign == 0) 632*7c478bd9Sstevel@tonic-gate sign++; /* skips are always relative */ 633*7c478bd9Sstevel@tonic-gate if (nlines == 0) 634*7c478bd9Sstevel@tonic-gate nlines++; 635*7c478bd9Sstevel@tonic-gate nlines = nlines * (window - 1); 636*7c478bd9Sstevel@tonic-gate if (sign == 1) 637*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line + nlines; 638*7c478bd9Sstevel@tonic-gate else 639*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line - nlines; 640*7c478bd9Sstevel@tonic-gate new_ss.last_line = new_ss.first_line + 641*7c478bd9Sstevel@tonic-gate (off_t)window - 1; 642*7c478bd9Sstevel@tonic-gate inwait = 0; 643*7c478bd9Sstevel@tonic-gate return (0); 644*7c478bd9Sstevel@tonic-gate case 'l': /* get a line */ 645*7c478bd9Sstevel@tonic-gate CHECKEND(); 646*7c478bd9Sstevel@tonic-gate if (nlines == 0) { 647*7c478bd9Sstevel@tonic-gate nlines++; 648*7c478bd9Sstevel@tonic-gate if (sign == 0) 649*7c478bd9Sstevel@tonic-gate sign = 1; 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate switch (sign) { 652*7c478bd9Sstevel@tonic-gate case 1: 653*7c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line + nlines; 654*7c478bd9Sstevel@tonic-gate new_ss.first_line = 655*7c478bd9Sstevel@tonic-gate new_ss.last_line - (off_t)window + 1; 656*7c478bd9Sstevel@tonic-gate break; 657*7c478bd9Sstevel@tonic-gate case 0: /* leave addressed line at top */ 658*7c478bd9Sstevel@tonic-gate new_ss.first_line = nlines; 659*7c478bd9Sstevel@tonic-gate new_ss.last_line = nlines + (off_t)window - 1; 660*7c478bd9Sstevel@tonic-gate break; 661*7c478bd9Sstevel@tonic-gate case -1: 662*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line - nlines; 663*7c478bd9Sstevel@tonic-gate new_ss.last_line = 664*7c478bd9Sstevel@tonic-gate new_ss.first_line + (off_t)window - 1; 665*7c478bd9Sstevel@tonic-gate break; 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate inwait = 0; 668*7c478bd9Sstevel@tonic-gate return (0); 669*7c478bd9Sstevel@tonic-gate case '\0': /* \n or blank */ 670*7c478bd9Sstevel@tonic-gate if (nlines == 0) { 671*7c478bd9Sstevel@tonic-gate nlines++; 672*7c478bd9Sstevel@tonic-gate if (sign == 0) 673*7c478bd9Sstevel@tonic-gate sign = 1; 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate nlines = (nlines - 1) * (window - 1); 676*7c478bd9Sstevel@tonic-gate switch (sign) { 677*7c478bd9Sstevel@tonic-gate case 1: 678*7c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line + nlines; 679*7c478bd9Sstevel@tonic-gate new_ss.last_line = 680*7c478bd9Sstevel@tonic-gate new_ss.first_line + (off_t)window - 1; 681*7c478bd9Sstevel@tonic-gate break; 682*7c478bd9Sstevel@tonic-gate case 0: 683*7c478bd9Sstevel@tonic-gate new_ss.first_line = nlines + 1; 684*7c478bd9Sstevel@tonic-gate new_ss.last_line = nlines + (off_t)window; 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * This if statement is to fix the obscure bug 687*7c478bd9Sstevel@tonic-gate * where you have a file that has less lines 688*7c478bd9Sstevel@tonic-gate * than a screen holds, and the user types '1', 689*7c478bd9Sstevel@tonic-gate * expecting to have the 1st page (re)displayed. 690*7c478bd9Sstevel@tonic-gate * If we didn't set the new last_line to 691*7c478bd9Sstevel@tonic-gate * eofl_no-1, the screen() routine 692*7c478bd9Sstevel@tonic-gate * would cause pg to exit. 693*7c478bd9Sstevel@tonic-gate */ 694*7c478bd9Sstevel@tonic-gate if (new_ss.first_line == 1 && 695*7c478bd9Sstevel@tonic-gate new_ss.last_line >= eofl_no) 696*7c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 697*7c478bd9Sstevel@tonic-gate break; 698*7c478bd9Sstevel@tonic-gate case -1: 699*7c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.first_line - nlines; 700*7c478bd9Sstevel@tonic-gate new_ss.first_line = 701*7c478bd9Sstevel@tonic-gate new_ss.last_line - (off_t)window + 1; 702*7c478bd9Sstevel@tonic-gate break; 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate inwait = 0; 705*7c478bd9Sstevel@tonic-gate return (0); 706*7c478bd9Sstevel@tonic-gate case 'n': /* switch to next file in arglist */ 707*7c478bd9Sstevel@tonic-gate CHECKEND(); 708*7c478bd9Sstevel@tonic-gate if (sign == 0) 709*7c478bd9Sstevel@tonic-gate sign = 1; 710*7c478bd9Sstevel@tonic-gate if (nlines == 0) 711*7c478bd9Sstevel@tonic-gate nlines++; 712*7c478bd9Sstevel@tonic-gate if ((skip = skipf(sign *nlines)) == 0) { 713*7c478bd9Sstevel@tonic-gate BEEP(); 714*7c478bd9Sstevel@tonic-gate break; 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate inwait = 0; 717*7c478bd9Sstevel@tonic-gate return (skip); 718*7c478bd9Sstevel@tonic-gate case 'p': /* switch to previous file in arglist */ 719*7c478bd9Sstevel@tonic-gate CHECKEND(); 720*7c478bd9Sstevel@tonic-gate if (sign == 0) 721*7c478bd9Sstevel@tonic-gate sign = 1; 722*7c478bd9Sstevel@tonic-gate if (nlines == 0) 723*7c478bd9Sstevel@tonic-gate nlines++; 724*7c478bd9Sstevel@tonic-gate if ((skip = skipf(-sign * nlines)) == 0) { 725*7c478bd9Sstevel@tonic-gate BEEP(); 726*7c478bd9Sstevel@tonic-gate break; 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate inwait = 0; 729*7c478bd9Sstevel@tonic-gate return (skip); 730*7c478bd9Sstevel@tonic-gate case '$': /* go to end of file */ 731*7c478bd9Sstevel@tonic-gate CHECKEND(); 732*7c478bd9Sstevel@tonic-gate sign = 1; 733*7c478bd9Sstevel@tonic-gate while (find(1, (off_t)10000) != EOF) 734*7c478bd9Sstevel@tonic-gate /* any large number will do */; 735*7c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 736*7c478bd9Sstevel@tonic-gate new_ss.first_line = eofl_no - (off_t)window; 737*7c478bd9Sstevel@tonic-gate inwait = 0; 738*7c478bd9Sstevel@tonic-gate return (0); 739*7c478bd9Sstevel@tonic-gate case '/': /* search forward for r.e. */ 740*7c478bd9Sstevel@tonic-gate case '?': /* " backwards */ 741*7c478bd9Sstevel@tonic-gate case '^': /* this ones a ? for regent100s */ 742*7c478bd9Sstevel@tonic-gate if (sign < 0) { 743*7c478bd9Sstevel@tonic-gate BEEP(); 744*7c478bd9Sstevel@tonic-gate break; 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate if (nlines == 0) 747*7c478bd9Sstevel@tonic-gate nlines++; 748*7c478bd9Sstevel@tonic-gate cmdptr--; 749*7c478bd9Sstevel@tonic-gate cmdend = cmdptr + (strlen(cmdptr) - 1); 750*7c478bd9Sstevel@tonic-gate wc_e1 = -1; 751*7c478bd9Sstevel@tonic-gate wc_e = -1; 752*7c478bd9Sstevel@tonic-gate for (p = cmdptr; p <= cmdend; p += len) { 753*7c478bd9Sstevel@tonic-gate wc_e1 = wc_e; 754*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc_e, p, MB_CUR_MAX)) <= 0) { 755*7c478bd9Sstevel@tonic-gate wc_e = *p; 756*7c478bd9Sstevel@tonic-gate len = 1; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate if (cmdend > cmdptr + 1) { 761*7c478bd9Sstevel@tonic-gate if ((wc_e1 == *cmdptr) && 762*7c478bd9Sstevel@tonic-gate ((wc_e == L't') || 763*7c478bd9Sstevel@tonic-gate (wc_e == L'm') || (wc_e == L'b'))) { 764*7c478bd9Sstevel@tonic-gate leave_search = wc_e; 765*7c478bd9Sstevel@tonic-gate wc_e = wc_e1; 766*7c478bd9Sstevel@tonic-gate cmdend--; 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate if ((cmdptr < cmdend) && (wc_e == *cmdptr)) 770*7c478bd9Sstevel@tonic-gate *cmdend = '\0'; 771*7c478bd9Sstevel@tonic-gate if (*cmdptr != '/') /* signify back search by - */ 772*7c478bd9Sstevel@tonic-gate nlines = -nlines; 773*7c478bd9Sstevel@tonic-gate if (!search(++cmdptr, (off_t)nlines)) 774*7c478bd9Sstevel@tonic-gate break; 775*7c478bd9Sstevel@tonic-gate else { 776*7c478bd9Sstevel@tonic-gate inwait = 0; 777*7c478bd9Sstevel@tonic-gate return (0); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate case '!': /* shell escape */ 780*7c478bd9Sstevel@tonic-gate if (rmode) { /* restricted mode */ 781*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 782*7c478bd9Sstevel@tonic-gate "!command not allowed in restricted mode.\n")); 783*7c478bd9Sstevel@tonic-gate break; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate if (!hard_copy) { /* redisplay the command */ 786*7c478bd9Sstevel@tonic-gate (void) fputs(cmdbuf, stdout); 787*7c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate if ((id = fork()) < 0) { 790*7c478bd9Sstevel@tonic-gate error("cannot fork, try again later"); 791*7c478bd9Sstevel@tonic-gate break; 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate if (id == (pid_t)0) { 794*7c478bd9Sstevel@tonic-gate /* 795*7c478bd9Sstevel@tonic-gate * if stdin is a pipe, need to close it so 796*7c478bd9Sstevel@tonic-gate * that the terminal is really stdin for 797*7c478bd9Sstevel@tonic-gate * the command 798*7c478bd9Sstevel@tonic-gate */ 799*7c478bd9Sstevel@tonic-gate (void) fclose(stdin); 800*7c478bd9Sstevel@tonic-gate (void) fclose(pg_stdin); 801*7c478bd9Sstevel@tonic-gate (void) dup(fileno(stdout)); 802*7c478bd9Sstevel@tonic-gate (void) execl(shell, shell, "-c", cmdptr, 0); 803*7c478bd9Sstevel@tonic-gate (void) perror("exec"); 804*7c478bd9Sstevel@tonic-gate exit(1); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 807*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 808*7c478bd9Sstevel@tonic-gate if (catch_susp) 809*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 810*7c478bd9Sstevel@tonic-gate while (wait((int *)0) != id); 811*7c478bd9Sstevel@tonic-gate { 812*7c478bd9Sstevel@tonic-gate if (errno == ECHILD) 813*7c478bd9Sstevel@tonic-gate break; 814*7c478bd9Sstevel@tonic-gate else 815*7c478bd9Sstevel@tonic-gate errno = 0; 816*7c478bd9Sstevel@tonic-gate } 817*7c478bd9Sstevel@tonic-gate (void) fputs("!\n", stdout); 818*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 819*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, on_brk); 820*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, on_brk); 821*7c478bd9Sstevel@tonic-gate if (catch_susp) 822*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, onsusp); 823*7c478bd9Sstevel@tonic-gate break; 824*7c478bd9Sstevel@tonic-gate default: 825*7c478bd9Sstevel@tonic-gate BEEP(); 826*7c478bd9Sstevel@tonic-gate break; 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate static int 832*7c478bd9Sstevel@tonic-gate number() 833*7c478bd9Sstevel@tonic-gate { 834*7c478bd9Sstevel@tonic-gate int i; 835*7c478bd9Sstevel@tonic-gate char *p; 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate i = 0; 838*7c478bd9Sstevel@tonic-gate sign = 0; 839*7c478bd9Sstevel@tonic-gate p = cmdptr; 840*7c478bd9Sstevel@tonic-gate BLANKS(p); 841*7c478bd9Sstevel@tonic-gate if (*p == '+') { 842*7c478bd9Sstevel@tonic-gate p++; 843*7c478bd9Sstevel@tonic-gate sign = 1; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate else 846*7c478bd9Sstevel@tonic-gate if (*p == '-') { 847*7c478bd9Sstevel@tonic-gate p++; 848*7c478bd9Sstevel@tonic-gate sign = -1; 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate while (isdigit(*p)) 851*7c478bd9Sstevel@tonic-gate i = i * 10 + *p++ - '0'; 852*7c478bd9Sstevel@tonic-gate cmdptr = p; 853*7c478bd9Sstevel@tonic-gate return (i); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate static int 857*7c478bd9Sstevel@tonic-gate ttyin() 858*7c478bd9Sstevel@tonic-gate { 859*7c478bd9Sstevel@tonic-gate char *sptr, *p; 860*7c478bd9Sstevel@tonic-gate wchar_t ch; 861*7c478bd9Sstevel@tonic-gate int slash = 0; 862*7c478bd9Sstevel@tonic-gate int state = 0; 863*7c478bd9Sstevel@tonic-gate int width, length; 864*7c478bd9Sstevel@tonic-gate char multic[MB_LEN_MAX]; 865*7c478bd9Sstevel@tonic-gate static int readch(); 866*7c478bd9Sstevel@tonic-gate int len; 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate (void) fixterm(); 869*7c478bd9Sstevel@tonic-gate /* initialize state processing */ 870*7c478bd9Sstevel@tonic-gate (void) set_state(&state, ' ', (char *)0); 871*7c478bd9Sstevel@tonic-gate sptr = cmdbuf; 872*7c478bd9Sstevel@tonic-gate while (state != 10) { 873*7c478bd9Sstevel@tonic-gate if ((ch = readch()) < 0 || !iswascii(ch) && !iswprint(ch)) { 874*7c478bd9Sstevel@tonic-gate BEEP(); 875*7c478bd9Sstevel@tonic-gate continue; 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate if ((length = wctomb(multic, ch)) < 0) 879*7c478bd9Sstevel@tonic-gate length = 0; 880*7c478bd9Sstevel@tonic-gate multic[length] = 0; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate if (ch == '\n' && !slash) 883*7c478bd9Sstevel@tonic-gate break; 884*7c478bd9Sstevel@tonic-gate if (ch == erasechar() && !slash) { 885*7c478bd9Sstevel@tonic-gate if (sptr > cmdbuf) { 886*7c478bd9Sstevel@tonic-gate char *oldp = cmdbuf; 887*7c478bd9Sstevel@tonic-gate wchar_t wchar; 888*7c478bd9Sstevel@tonic-gate p = cmdbuf; 889*7c478bd9Sstevel@tonic-gate while (p < sptr) { 890*7c478bd9Sstevel@tonic-gate oldp = p; 891*7c478bd9Sstevel@tonic-gate len = mbtowc(&wchar, p, MB_CUR_MAX); 892*7c478bd9Sstevel@tonic-gate if (len <= 0) { 893*7c478bd9Sstevel@tonic-gate wchar = (unsigned char)*p; 894*7c478bd9Sstevel@tonic-gate len = 1; 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate p += len; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate if ((width = wcwidth(wchar)) <= 0) 899*7c478bd9Sstevel@tonic-gate /* ascii control character */ 900*7c478bd9Sstevel@tonic-gate width = 2; 901*7c478bd9Sstevel@tonic-gate promptlen -= width; 902*7c478bd9Sstevel@tonic-gate while (width--) 903*7c478bd9Sstevel@tonic-gate (void) fputs("\b \b", stdout); 904*7c478bd9Sstevel@tonic-gate sptr = oldp; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate (void) set_state(&state, ch, sptr); 907*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 908*7c478bd9Sstevel@tonic-gate continue; 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate else 911*7c478bd9Sstevel@tonic-gate if (ch == killchar() && !slash) { 912*7c478bd9Sstevel@tonic-gate if (hard_copy) 913*7c478bd9Sstevel@tonic-gate (void) putwchar(ch); 914*7c478bd9Sstevel@tonic-gate (void) resetterm(); 915*7c478bd9Sstevel@tonic-gate return (1); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate if (ch < ' ') 918*7c478bd9Sstevel@tonic-gate width = 2; 919*7c478bd9Sstevel@tonic-gate else 920*7c478bd9Sstevel@tonic-gate if ((width = wcwidth(ch)) <= 0) 921*7c478bd9Sstevel@tonic-gate width = 0; 922*7c478bd9Sstevel@tonic-gate if (slash) { 923*7c478bd9Sstevel@tonic-gate slash = 0; 924*7c478bd9Sstevel@tonic-gate (void) fputs("\b \b", stdout); 925*7c478bd9Sstevel@tonic-gate sptr--; 926*7c478bd9Sstevel@tonic-gate promptlen--; 927*7c478bd9Sstevel@tonic-gate } else /* is there room to keep this character? */ 928*7c478bd9Sstevel@tonic-gate if (sptr >= cmdbuf + sizeof (cmdbuf) || 929*7c478bd9Sstevel@tonic-gate promptlen + width >= columns) { 930*7c478bd9Sstevel@tonic-gate BEEP(); 931*7c478bd9Sstevel@tonic-gate continue; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate else 934*7c478bd9Sstevel@tonic-gate if (ch == '\\') 935*7c478bd9Sstevel@tonic-gate slash++; 936*7c478bd9Sstevel@tonic-gate if (set_state(&state, ch, sptr) == 0) { 937*7c478bd9Sstevel@tonic-gate BEEP(); 938*7c478bd9Sstevel@tonic-gate continue; 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate (void) strncpy(sptr, multic, (size_t)length); 941*7c478bd9Sstevel@tonic-gate sptr += length; 942*7c478bd9Sstevel@tonic-gate if (ch < ' ') { 943*7c478bd9Sstevel@tonic-gate ch += 0100; 944*7c478bd9Sstevel@tonic-gate multic[0] = '^'; 945*7c478bd9Sstevel@tonic-gate multic[1] = ch; 946*7c478bd9Sstevel@tonic-gate length = 2; 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate p = multic; 949*7c478bd9Sstevel@tonic-gate while (length--) 950*7c478bd9Sstevel@tonic-gate (void) putchar(*p++); 951*7c478bd9Sstevel@tonic-gate promptlen += width; 952*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate *sptr = '\0'; 956*7c478bd9Sstevel@tonic-gate kill_line(); 957*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 958*7c478bd9Sstevel@tonic-gate (void) resetterm(); 959*7c478bd9Sstevel@tonic-gate return (0); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate static int 963*7c478bd9Sstevel@tonic-gate set_state(pstate, c, pc) 964*7c478bd9Sstevel@tonic-gate int *pstate; 965*7c478bd9Sstevel@tonic-gate wchar_t c; 966*7c478bd9Sstevel@tonic-gate char *pc; 967*7c478bd9Sstevel@tonic-gate { 968*7c478bd9Sstevel@tonic-gate static char *psign; 969*7c478bd9Sstevel@tonic-gate static char *pnumber; 970*7c478bd9Sstevel@tonic-gate static char *pcommand; 971*7c478bd9Sstevel@tonic-gate static int slash; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (*pstate == 0) { 974*7c478bd9Sstevel@tonic-gate psign = (char *)NULL; 975*7c478bd9Sstevel@tonic-gate pnumber = (char *)NULL; 976*7c478bd9Sstevel@tonic-gate pcommand = (char *)NULL; 977*7c478bd9Sstevel@tonic-gate *pstate = 1; 978*7c478bd9Sstevel@tonic-gate slash = 0; 979*7c478bd9Sstevel@tonic-gate return (1); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate if (c == '\\' && !slash) { 982*7c478bd9Sstevel@tonic-gate slash++; 983*7c478bd9Sstevel@tonic-gate return (1); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate if (c == erasechar() && !slash) 986*7c478bd9Sstevel@tonic-gate switch (*pstate) { 987*7c478bd9Sstevel@tonic-gate case 4: 988*7c478bd9Sstevel@tonic-gate if (pc > pcommand) 989*7c478bd9Sstevel@tonic-gate return (1); 990*7c478bd9Sstevel@tonic-gate pcommand = (char *)NULL; 991*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate case 3: 994*7c478bd9Sstevel@tonic-gate if (pnumber && pc > pnumber) { 995*7c478bd9Sstevel@tonic-gate *pstate = 3; 996*7c478bd9Sstevel@tonic-gate return (1); 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate pnumber = (char *)NULL; 999*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate case 2: 1002*7c478bd9Sstevel@tonic-gate if (psign && pc > psign) { 1003*7c478bd9Sstevel@tonic-gate *pstate = 2; 1004*7c478bd9Sstevel@tonic-gate return (1); 1005*7c478bd9Sstevel@tonic-gate } 1006*7c478bd9Sstevel@tonic-gate psign = (char *)NULL; 1007*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate case 1: 1010*7c478bd9Sstevel@tonic-gate *pstate = 1; 1011*7c478bd9Sstevel@tonic-gate return (1); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate slash = 0; 1015*7c478bd9Sstevel@tonic-gate switch (*pstate) { 1016*7c478bd9Sstevel@tonic-gate case 1: /* before recieving anything interesting */ 1017*7c478bd9Sstevel@tonic-gate if (c == '\t' || (!nflag && c == ' ')) 1018*7c478bd9Sstevel@tonic-gate return (1); 1019*7c478bd9Sstevel@tonic-gate if (c == '+' || c == '-') { 1020*7c478bd9Sstevel@tonic-gate psign = pc; 1021*7c478bd9Sstevel@tonic-gate *pstate = 2; 1022*7c478bd9Sstevel@tonic-gate return (1); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate case 2: /* recieved sign, waiting for digit */ 1027*7c478bd9Sstevel@tonic-gate if (iswascii(c) && isdigit(c)) { 1028*7c478bd9Sstevel@tonic-gate pnumber = pc; 1029*7c478bd9Sstevel@tonic-gate *pstate = 3; 1030*7c478bd9Sstevel@tonic-gate return (1); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate case 3: /* recieved digit, waiting for the rest of the number */ 1035*7c478bd9Sstevel@tonic-gate if (iswascii(c) && isdigit(c)) 1036*7c478bd9Sstevel@tonic-gate return (1); 1037*7c478bd9Sstevel@tonic-gate if (iswascii(c) && pg_strchr("h\014.wz\004dqQfl np$", c)) { 1038*7c478bd9Sstevel@tonic-gate pcommand = pc; 1039*7c478bd9Sstevel@tonic-gate if (nflag) 1040*7c478bd9Sstevel@tonic-gate *pstate = 10; 1041*7c478bd9Sstevel@tonic-gate else 1042*7c478bd9Sstevel@tonic-gate *pstate = 4; 1043*7c478bd9Sstevel@tonic-gate return (1); 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate if (iswascii(c) && pg_strchr("s/^?!", c)) { 1046*7c478bd9Sstevel@tonic-gate pcommand = pc; 1047*7c478bd9Sstevel@tonic-gate *pstate = 4; 1048*7c478bd9Sstevel@tonic-gate return (1); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate return (0); 1051*7c478bd9Sstevel@tonic-gate case 4: 1052*7c478bd9Sstevel@tonic-gate return (1); 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate return (0); 1055*7c478bd9Sstevel@tonic-gate } 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate static int 1058*7c478bd9Sstevel@tonic-gate readch() 1059*7c478bd9Sstevel@tonic-gate { 1060*7c478bd9Sstevel@tonic-gate return (fgetwc(pg_stdin)); 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate static void 1064*7c478bd9Sstevel@tonic-gate help() 1065*7c478bd9Sstevel@tonic-gate { 1066*7c478bd9Sstevel@tonic-gate if (clropt) 1067*7c478bd9Sstevel@tonic-gate doclear(); 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate (void) fputs(gettext( 1070*7c478bd9Sstevel@tonic-gate "-------------------------------------------------------\n" 1071*7c478bd9Sstevel@tonic-gate " h help\n" 1072*7c478bd9Sstevel@tonic-gate " q or Q quit\n" 1073*7c478bd9Sstevel@tonic-gate " <blank> or <newline> next page\n" 1074*7c478bd9Sstevel@tonic-gate " l next line\n" 1075*7c478bd9Sstevel@tonic-gate " d or <^D> display half a page more\n" 1076*7c478bd9Sstevel@tonic-gate " . or <^L> redisplay current page\n" 1077*7c478bd9Sstevel@tonic-gate " f skip the next page forward\n" 1078*7c478bd9Sstevel@tonic-gate " n next file\n" 1079*7c478bd9Sstevel@tonic-gate " p previous file\n" 1080*7c478bd9Sstevel@tonic-gate " $ last page\n" 1081*7c478bd9Sstevel@tonic-gate " w or z set window size and display next page\n" 1082*7c478bd9Sstevel@tonic-gate " s savefile save current file in savefile\n" 1083*7c478bd9Sstevel@tonic-gate " /pattern/ search forward for pattern\n" 1084*7c478bd9Sstevel@tonic-gate " ?pattern? or\n" 1085*7c478bd9Sstevel@tonic-gate " ^pattern^ search backward for pattern\n" 1086*7c478bd9Sstevel@tonic-gate " !command execute command\n" 1087*7c478bd9Sstevel@tonic-gate "\n" 1088*7c478bd9Sstevel@tonic-gate "Most commands can be preceeded by a number, as in:\n" 1089*7c478bd9Sstevel@tonic-gate "+1<newline> (next page); -1<newline> (previous page); 1<newline> (page 1).\n" 1090*7c478bd9Sstevel@tonic-gate "\n" 1091*7c478bd9Sstevel@tonic-gate "See the manual page for more detail.\n" 1092*7c478bd9Sstevel@tonic-gate "-------------------------------------------------------\n"), 1093*7c478bd9Sstevel@tonic-gate stdout); 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate /* 1097*7c478bd9Sstevel@tonic-gate * Skip nskip files in the file list (from the command line). Nskip may be 1098*7c478bd9Sstevel@tonic-gate * negative. 1099*7c478bd9Sstevel@tonic-gate */ 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate static int 1102*7c478bd9Sstevel@tonic-gate skipf(nskip) 1103*7c478bd9Sstevel@tonic-gate int nskip; 1104*7c478bd9Sstevel@tonic-gate { 1105*7c478bd9Sstevel@tonic-gate if (fnum + nskip < 0) { 1106*7c478bd9Sstevel@tonic-gate nskip = -fnum; 1107*7c478bd9Sstevel@tonic-gate if (nskip == 0) 1108*7c478bd9Sstevel@tonic-gate error("No previous file"); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate else 1111*7c478bd9Sstevel@tonic-gate if (fnum + nskip > nfiles - 1) { 1112*7c478bd9Sstevel@tonic-gate nskip = (nfiles - 1) - fnum; 1113*7c478bd9Sstevel@tonic-gate if (nskip == 0) 1114*7c478bd9Sstevel@tonic-gate error("No next file"); 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate return (nskip); 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate /* 1120*7c478bd9Sstevel@tonic-gate * Check whether the file named by fs is a file which the user may 1121*7c478bd9Sstevel@tonic-gate * access. If it is, return the opened file. Otherwise return NULL. 1122*7c478bd9Sstevel@tonic-gate */ 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate static FILE * 1125*7c478bd9Sstevel@tonic-gate checkf(fs) 1126*7c478bd9Sstevel@tonic-gate char *fs; 1127*7c478bd9Sstevel@tonic-gate { 1128*7c478bd9Sstevel@tonic-gate struct stat stbuf; 1129*7c478bd9Sstevel@tonic-gate FILE *f; 1130*7c478bd9Sstevel@tonic-gate int fd; 1131*7c478bd9Sstevel@tonic-gate int f_was_opened; 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate pipe_in = 0; 1134*7c478bd9Sstevel@tonic-gate if (strcmp(fs, "-") == 0) { 1135*7c478bd9Sstevel@tonic-gate if (tmp_fin == NULL) 1136*7c478bd9Sstevel@tonic-gate f = stdin; 1137*7c478bd9Sstevel@tonic-gate else { 1138*7c478bd9Sstevel@tonic-gate rewind(tmp_fin); 1139*7c478bd9Sstevel@tonic-gate f = tmp_fin; 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate f_was_opened = 0; 1142*7c478bd9Sstevel@tonic-gate } else { 1143*7c478bd9Sstevel@tonic-gate if ((f = fopen(fs, "r")) == (FILE *)NULL) { 1144*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1145*7c478bd9Sstevel@tonic-gate perror(fs); 1146*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate f_was_opened = 1; 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate if (fstat(fileno(f), &stbuf) == -1) { 1151*7c478bd9Sstevel@tonic-gate if (f_was_opened) 1152*7c478bd9Sstevel@tonic-gate (void) fclose(f); 1153*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1154*7c478bd9Sstevel@tonic-gate perror(fs); 1155*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 1158*7c478bd9Sstevel@tonic-gate if (f_was_opened) 1159*7c478bd9Sstevel@tonic-gate (void) fclose(f); 1160*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pg: "); 1161*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s is a directory\n"), fs); 1162*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1163*7c478bd9Sstevel@tonic-gate } 1164*7c478bd9Sstevel@tonic-gate if ((stbuf.st_mode & S_IFMT) == S_IFREG) { 1165*7c478bd9Sstevel@tonic-gate if (f == stdin) /* It may have been read from */ 1166*7c478bd9Sstevel@tonic-gate rewind(f); /* already, and not reopened */ 1167*7c478bd9Sstevel@tonic-gate } else { 1168*7c478bd9Sstevel@tonic-gate if (f != stdin) { 1169*7c478bd9Sstevel@tonic-gate if (f_was_opened) 1170*7c478bd9Sstevel@tonic-gate (void) fclose(f); 1171*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pg: "); 1172*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1173*7c478bd9Sstevel@tonic-gate "special files only handled as standard input\n")); 1174*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1175*7c478bd9Sstevel@tonic-gate } else { 1176*7c478bd9Sstevel@tonic-gate if ((fd = mkstemp(tmp_name)) < 0) { 1177*7c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 1178*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate (void) close(fd); 1181*7c478bd9Sstevel@tonic-gate if ((tmp_fou = fopen(tmp_name, "w")) == NULL) { 1182*7c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 1183*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate if ((tmp_fin = fopen(tmp_name, "r")) == NULL) { 1186*7c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 1187*7c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate pipe_in = 1; 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate lineset(BOF); 1193*7c478bd9Sstevel@tonic-gate return (f); 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate static void 1197*7c478bd9Sstevel@tonic-gate copy_file(f, out) 1198*7c478bd9Sstevel@tonic-gate FILE *f, *out; 1199*7c478bd9Sstevel@tonic-gate { 1200*7c478bd9Sstevel@tonic-gate int c; 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate while ((c = getc(f)) != EOF) 1203*7c478bd9Sstevel@tonic-gate (void) putc(c, out); 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate static void 1208*7c478bd9Sstevel@tonic-gate re_error(i) 1209*7c478bd9Sstevel@tonic-gate int i; 1210*7c478bd9Sstevel@tonic-gate { 1211*7c478bd9Sstevel@tonic-gate int j; 1212*7c478bd9Sstevel@tonic-gate static struct messages { 1213*7c478bd9Sstevel@tonic-gate char *message; 1214*7c478bd9Sstevel@tonic-gate int number; 1215*7c478bd9Sstevel@tonic-gate } re_errmsg[] = { 1216*7c478bd9Sstevel@tonic-gate "Pattern not found", 1, 1217*7c478bd9Sstevel@tonic-gate "Range endpoint too large", 11, 1218*7c478bd9Sstevel@tonic-gate "Bad number", 16, 1219*7c478bd9Sstevel@tonic-gate "`\\digit' out of range", 25, 1220*7c478bd9Sstevel@tonic-gate "No remembered search string", 41, 1221*7c478bd9Sstevel@tonic-gate "\\( \\) imbalance", 42, 1222*7c478bd9Sstevel@tonic-gate "Too many \\(", 43, 1223*7c478bd9Sstevel@tonic-gate "More than two numbers given in \\{ \\}", 44, 1224*7c478bd9Sstevel@tonic-gate "} expected after \\", 45, 1225*7c478bd9Sstevel@tonic-gate "First number exceeds second in \\{ \\}", 46, 1226*7c478bd9Sstevel@tonic-gate "[] imbalance", 49, 1227*7c478bd9Sstevel@tonic-gate "Regular expression overflow", 50, 1228*7c478bd9Sstevel@tonic-gate "Illegal byte sequence", 67, 1229*7c478bd9Sstevel@tonic-gate "Bad regular expression", 0 1230*7c478bd9Sstevel@tonic-gate }; 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate for (j = 0; re_errmsg[j].number != 0; j++) 1233*7c478bd9Sstevel@tonic-gate if (re_errmsg[j].number == i) 1234*7c478bd9Sstevel@tonic-gate break; 1235*7c478bd9Sstevel@tonic-gate error(re_errmsg[j].message); 1236*7c478bd9Sstevel@tonic-gate longjmp(restore, 1); /* restore to search() */ 1237*7c478bd9Sstevel@tonic-gate } 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate /* 1240*7c478bd9Sstevel@tonic-gate * Search for nth ocurrence of regular expression contained in buf in the file 1241*7c478bd9Sstevel@tonic-gate * negative n implies backward search 1242*7c478bd9Sstevel@tonic-gate * n 'guaranteed' non-zero 1243*7c478bd9Sstevel@tonic-gate */ 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate static int 1247*7c478bd9Sstevel@tonic-gate search(buf, n) 1248*7c478bd9Sstevel@tonic-gate char buf[]; 1249*7c478bd9Sstevel@tonic-gate off_t n; 1250*7c478bd9Sstevel@tonic-gate { 1251*7c478bd9Sstevel@tonic-gate int direction; 1252*7c478bd9Sstevel@tonic-gate static char *expbuf; 1253*7c478bd9Sstevel@tonic-gate char *nexpbuf; 1254*7c478bd9Sstevel@tonic-gate int END_COND; 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate if (setjmp(restore) <= 0) { 1257*7c478bd9Sstevel@tonic-gate nexpbuf = compile(buf, (char *)0, (char *)0); 1258*7c478bd9Sstevel@tonic-gate if (regerrno) { 1259*7c478bd9Sstevel@tonic-gate if (regerrno != 41 || expbuf == NULL) 1260*7c478bd9Sstevel@tonic-gate re_error(regerrno); 1261*7c478bd9Sstevel@tonic-gate } else { 1262*7c478bd9Sstevel@tonic-gate if (expbuf) 1263*7c478bd9Sstevel@tonic-gate free(expbuf); 1264*7c478bd9Sstevel@tonic-gate expbuf = nexpbuf; 1265*7c478bd9Sstevel@tonic-gate } 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate if (n < 0) { /* search back */ 1268*7c478bd9Sstevel@tonic-gate direction = -1; 1269*7c478bd9Sstevel@tonic-gate (void) find(0, old_ss.first_line); 1270*7c478bd9Sstevel@tonic-gate END_COND = BOF; 1271*7c478bd9Sstevel@tonic-gate } else { 1272*7c478bd9Sstevel@tonic-gate direction = 1; 1273*7c478bd9Sstevel@tonic-gate (void) find(0, old_ss.last_line); 1274*7c478bd9Sstevel@tonic-gate END_COND = EOF; 1275*7c478bd9Sstevel@tonic-gate } 1276*7c478bd9Sstevel@tonic-gate 1277*7c478bd9Sstevel@tonic-gate while (find(1, direction) != END_COND) { 1278*7c478bd9Sstevel@tonic-gate if (brk_hit) 1279*7c478bd9Sstevel@tonic-gate break; 1280*7c478bd9Sstevel@tonic-gate if (step(Line, expbuf)) 1281*7c478bd9Sstevel@tonic-gate if ((n -= direction) == 0) { 1282*7c478bd9Sstevel@tonic-gate switch (leave_search) { 1283*7c478bd9Sstevel@tonic-gate case 't': 1284*7c478bd9Sstevel@tonic-gate new_ss.first_line = 1285*7c478bd9Sstevel@tonic-gate find(1, (off_t)0); 1286*7c478bd9Sstevel@tonic-gate new_ss.last_line = 1287*7c478bd9Sstevel@tonic-gate new_ss.first_line + 1288*7c478bd9Sstevel@tonic-gate (off_t)window 1289*7c478bd9Sstevel@tonic-gate - 1; 1290*7c478bd9Sstevel@tonic-gate break; 1291*7c478bd9Sstevel@tonic-gate case 'b': 1292*7c478bd9Sstevel@tonic-gate new_ss.last_line = 1293*7c478bd9Sstevel@tonic-gate find(1, (off_t)0); 1294*7c478bd9Sstevel@tonic-gate new_ss.first_line = 1295*7c478bd9Sstevel@tonic-gate new_ss.last_line - 1296*7c478bd9Sstevel@tonic-gate (off_t)window 1297*7c478bd9Sstevel@tonic-gate + 1; 1298*7c478bd9Sstevel@tonic-gate break; 1299*7c478bd9Sstevel@tonic-gate case 'm': 1300*7c478bd9Sstevel@tonic-gate new_ss.first_line = 1301*7c478bd9Sstevel@tonic-gate find(1, (off_t)0) - 1302*7c478bd9Sstevel@tonic-gate ((off_t)window - 1)/2; 1303*7c478bd9Sstevel@tonic-gate new_ss.last_line = 1304*7c478bd9Sstevel@tonic-gate new_ss.first_line + 1305*7c478bd9Sstevel@tonic-gate (off_t)window 1306*7c478bd9Sstevel@tonic-gate - 1; 1307*7c478bd9Sstevel@tonic-gate break; 1308*7c478bd9Sstevel@tonic-gate } 1309*7c478bd9Sstevel@tonic-gate return (1); 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate } 1312*7c478bd9Sstevel@tonic-gate re_error(1); /* Pattern not found */ 1313*7c478bd9Sstevel@tonic-gate } 1314*7c478bd9Sstevel@tonic-gate BEEP(); 1315*7c478bd9Sstevel@tonic-gate return (0); 1316*7c478bd9Sstevel@tonic-gate } 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate /* 1319*7c478bd9Sstevel@tonic-gate * find -- find line in file f, subject to certain constraints. 1320*7c478bd9Sstevel@tonic-gate * 1321*7c478bd9Sstevel@tonic-gate * This is the reason for all the funny stuff with sign and nlines. 1322*7c478bd9Sstevel@tonic-gate * We need to be able to differentiate between relative and abosolute 1323*7c478bd9Sstevel@tonic-gate * address specifications. 1324*7c478bd9Sstevel@tonic-gate * 1325*7c478bd9Sstevel@tonic-gate * So...there are basically three cases that this routine 1326*7c478bd9Sstevel@tonic-gate * handles. Either line is zero, which means there is to be 1327*7c478bd9Sstevel@tonic-gate * no motion (because line numbers start at one), or 1328*7c478bd9Sstevel@tonic-gate * how and line specify a number, or line itself is negative, 1329*7c478bd9Sstevel@tonic-gate * which is the same as having how == -1 and line == abs(line). 1330*7c478bd9Sstevel@tonic-gate * 1331*7c478bd9Sstevel@tonic-gate * Then, figure where exactly it is that we are going (an absolute 1332*7c478bd9Sstevel@tonic-gate * line number). Find out if it is within what we have read, 1333*7c478bd9Sstevel@tonic-gate * if so, go there without further ado. Otherwise, do some 1334*7c478bd9Sstevel@tonic-gate * magic to get there, saving all the intervening lines, 1335*7c478bd9Sstevel@tonic-gate * in case the user wants to see them some time later. 1336*7c478bd9Sstevel@tonic-gate * 1337*7c478bd9Sstevel@tonic-gate * In any case, return the line number that we end up at. 1338*7c478bd9Sstevel@tonic-gate * (This is used by search() and screen()). If we go past EOF, 1339*7c478bd9Sstevel@tonic-gate * return EOF. 1340*7c478bd9Sstevel@tonic-gate * This EOF will go away eventually, as pg is expanded to 1341*7c478bd9Sstevel@tonic-gate * handle multiple files as one huge one. Then EOF will 1342*7c478bd9Sstevel@tonic-gate * mean we have run off the file list. 1343*7c478bd9Sstevel@tonic-gate * If the requested line number is too far back, return BOF. 1344*7c478bd9Sstevel@tonic-gate */ 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate static off_t 1347*7c478bd9Sstevel@tonic-gate find(how, line) /* find the line and seek there */ 1348*7c478bd9Sstevel@tonic-gate int how; 1349*7c478bd9Sstevel@tonic-gate off_t line; 1350*7c478bd9Sstevel@tonic-gate { 1351*7c478bd9Sstevel@tonic-gate /* no compacted memory yet */ 1352*7c478bd9Sstevel@tonic-gate FILE *f = in_file; 1353*7c478bd9Sstevel@tonic-gate off_t where; 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate if (how == 0) 1356*7c478bd9Sstevel@tonic-gate where = line; 1357*7c478bd9Sstevel@tonic-gate else 1358*7c478bd9Sstevel@tonic-gate if (dot == zero - 1) 1359*7c478bd9Sstevel@tonic-gate where = how * line; 1360*7c478bd9Sstevel@tonic-gate else 1361*7c478bd9Sstevel@tonic-gate where = how * line + dot->l_no; 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate /* now, where is either at, before, or after dol */ 1364*7c478bd9Sstevel@tonic-gate /* most likely case is after, so do it first */ 1365*7c478bd9Sstevel@tonic-gate 1366*7c478bd9Sstevel@tonic-gate eoflag = 0; 1367*7c478bd9Sstevel@tonic-gate if (where >= dol->l_no) { 1368*7c478bd9Sstevel@tonic-gate if (doliseof) { 1369*7c478bd9Sstevel@tonic-gate dot = dol; 1370*7c478bd9Sstevel@tonic-gate eoflag++; 1371*7c478bd9Sstevel@tonic-gate return (EOF); 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate if (pipe_in) 1374*7c478bd9Sstevel@tonic-gate in_file = f = stdin; 1375*7c478bd9Sstevel@tonic-gate else 1376*7c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)dol->l_addr, SEEK_SET); 1377*7c478bd9Sstevel@tonic-gate dot = dol - 1; 1378*7c478bd9Sstevel@tonic-gate while ((nchars = getline(f)) != EOF) { 1379*7c478bd9Sstevel@tonic-gate dot++; 1380*7c478bd9Sstevel@tonic-gate newdol(f); 1381*7c478bd9Sstevel@tonic-gate if (where == dot->l_no || brk_hit) 1382*7c478bd9Sstevel@tonic-gate break; 1383*7c478bd9Sstevel@tonic-gate } 1384*7c478bd9Sstevel@tonic-gate if (nchars != EOF) 1385*7c478bd9Sstevel@tonic-gate return (dot->l_no); 1386*7c478bd9Sstevel@tonic-gate else { /* EOF */ 1387*7c478bd9Sstevel@tonic-gate dot = dol; 1388*7c478bd9Sstevel@tonic-gate eoflag++; 1389*7c478bd9Sstevel@tonic-gate doliseof++; 1390*7c478bd9Sstevel@tonic-gate eofl_no = dol->l_no; 1391*7c478bd9Sstevel@tonic-gate return (EOF); 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate } else { /* where < dol->l_no */ 1394*7c478bd9Sstevel@tonic-gate if (pipe_in) { 1395*7c478bd9Sstevel@tonic-gate (void) fflush(tmp_fou); 1396*7c478bd9Sstevel@tonic-gate in_file = f = tmp_fin; 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate if (where < zero->l_no) { 1399*7c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)zero->l_addr, SEEK_SET); 1400*7c478bd9Sstevel@tonic-gate dot = zero - 1; 1401*7c478bd9Sstevel@tonic-gate return (BOF); 1402*7c478bd9Sstevel@tonic-gate } else { 1403*7c478bd9Sstevel@tonic-gate dot = zero + where - 1; 1404*7c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)dot->l_addr, SEEK_SET); 1405*7c478bd9Sstevel@tonic-gate nchars = getline(f); 1406*7c478bd9Sstevel@tonic-gate return (dot->l_no); 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate } 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate static FILE *fileptr; 1412*7c478bd9Sstevel@tonic-gate static int (*rdchar)(); 1413*7c478bd9Sstevel@tonic-gate 1414*7c478bd9Sstevel@tonic-gate static int 1415*7c478bd9Sstevel@tonic-gate mrdchar() 1416*7c478bd9Sstevel@tonic-gate { 1417*7c478bd9Sstevel@tonic-gate return (rdchar(fileptr)); 1418*7c478bd9Sstevel@tonic-gate } 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate /* 1421*7c478bd9Sstevel@tonic-gate * Get a logical line 1422*7c478bd9Sstevel@tonic-gate */ 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate static off_t 1425*7c478bd9Sstevel@tonic-gate getline(f) 1426*7c478bd9Sstevel@tonic-gate FILE *f; 1427*7c478bd9Sstevel@tonic-gate { 1428*7c478bd9Sstevel@tonic-gate char *p; 1429*7c478bd9Sstevel@tonic-gate int column; 1430*7c478bd9Sstevel@tonic-gate static char multic[MB_LEN_MAX]; 1431*7c478bd9Sstevel@tonic-gate static int savlength; 1432*7c478bd9Sstevel@tonic-gate wchar_t c; 1433*7c478bd9Sstevel@tonic-gate int length, width; 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate if (pipe_in && f == stdin) 1436*7c478bd9Sstevel@tonic-gate rdchar = fgetputc; 1437*7c478bd9Sstevel@tonic-gate else 1438*7c478bd9Sstevel@tonic-gate rdchar = (int (*)())fgetwc; 1439*7c478bd9Sstevel@tonic-gate 1440*7c478bd9Sstevel@tonic-gate fileptr = f; 1441*7c478bd9Sstevel@tonic-gate /* copy overlap from previous call to getline */ 1442*7c478bd9Sstevel@tonic-gate if (savlength) 1443*7c478bd9Sstevel@tonic-gate (void) strncpy(Line, multic, (size_t)savlength); 1444*7c478bd9Sstevel@tonic-gate for (column = 0, p = Line + savlength; ; ) { 1445*7c478bd9Sstevel@tonic-gate if ((c = mrdchar()) <= 0) { 1446*7c478bd9Sstevel@tonic-gate clearerr(f); 1447*7c478bd9Sstevel@tonic-gate if (p > Line) { /* last line doesn't have '\n', */ 1448*7c478bd9Sstevel@tonic-gate *p++ = '\n'; 1449*7c478bd9Sstevel@tonic-gate *p = '\0'; /* print it any way */ 1450*7c478bd9Sstevel@tonic-gate return (column); 1451*7c478bd9Sstevel@tonic-gate } 1452*7c478bd9Sstevel@tonic-gate return (EOF); 1453*7c478bd9Sstevel@tonic-gate } 1454*7c478bd9Sstevel@tonic-gate length = wctomb(multic, c); 1455*7c478bd9Sstevel@tonic-gate if (length < 0) { 1456*7c478bd9Sstevel@tonic-gate length = -length; 1457*7c478bd9Sstevel@tonic-gate c = 0; 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate if ((width = wcwidth(c)) < 0) 1460*7c478bd9Sstevel@tonic-gate width = 0; 1461*7c478bd9Sstevel@tonic-gate if (column + width > columns && !fflag) 1462*7c478bd9Sstevel@tonic-gate break; 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate if (p + length > &Line[LINSIZ - 2] && c != '\n') 1465*7c478bd9Sstevel@tonic-gate break; 1466*7c478bd9Sstevel@tonic-gate (void) strncpy(p, multic, (size_t)length); 1467*7c478bd9Sstevel@tonic-gate p += length; 1468*7c478bd9Sstevel@tonic-gate column += width; 1469*7c478bd9Sstevel@tonic-gate /* don't have any overlap here */ 1470*7c478bd9Sstevel@tonic-gate length = 0; 1471*7c478bd9Sstevel@tonic-gate switch (c) { 1472*7c478bd9Sstevel@tonic-gate case '\t': /* just a guess */ 1473*7c478bd9Sstevel@tonic-gate column = 1 + (column | 7); 1474*7c478bd9Sstevel@tonic-gate break; 1475*7c478bd9Sstevel@tonic-gate case '\b': 1476*7c478bd9Sstevel@tonic-gate if (column > 0) 1477*7c478bd9Sstevel@tonic-gate column--; 1478*7c478bd9Sstevel@tonic-gate break; 1479*7c478bd9Sstevel@tonic-gate case '\r': 1480*7c478bd9Sstevel@tonic-gate column = 0; 1481*7c478bd9Sstevel@tonic-gate break; 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate if (c == '\n') 1484*7c478bd9Sstevel@tonic-gate break; 1485*7c478bd9Sstevel@tonic-gate if (column >= columns && !fflag) 1486*7c478bd9Sstevel@tonic-gate break; 1487*7c478bd9Sstevel@tonic-gate } 1488*7c478bd9Sstevel@tonic-gate if (c != '\n') { /* We're stopping in the middle of the line */ 1489*7c478bd9Sstevel@tonic-gate if (column != columns || !auto_right_margin) 1490*7c478bd9Sstevel@tonic-gate *p++ = '\n'; /* for the display */ 1491*7c478bd9Sstevel@tonic-gate /* save overlap for next call to getline */ 1492*7c478bd9Sstevel@tonic-gate savlength = length; 1493*7c478bd9Sstevel@tonic-gate if (savlength == 0) { 1494*7c478bd9Sstevel@tonic-gate /* 1495*7c478bd9Sstevel@tonic-gate * check if following byte is newline and get 1496*7c478bd9Sstevel@tonic-gate * it if it is 1497*7c478bd9Sstevel@tonic-gate */ 1498*7c478bd9Sstevel@tonic-gate c = fgetwc(f); 1499*7c478bd9Sstevel@tonic-gate if (c == '\n') { 1500*7c478bd9Sstevel@tonic-gate /* gobble and copy (if necessary) newline */ 1501*7c478bd9Sstevel@tonic-gate (void) ungetwc(c, f); 1502*7c478bd9Sstevel@tonic-gate (void) (*rdchar)(f); 1503*7c478bd9Sstevel@tonic-gate } else if (c == EOF) 1504*7c478bd9Sstevel@tonic-gate clearerr(f); 1505*7c478bd9Sstevel@tonic-gate else 1506*7c478bd9Sstevel@tonic-gate (void) ungetwc(c, f); 1507*7c478bd9Sstevel@tonic-gate } 1508*7c478bd9Sstevel@tonic-gate } else 1509*7c478bd9Sstevel@tonic-gate savlength = 0; 1510*7c478bd9Sstevel@tonic-gate *p = 0; 1511*7c478bd9Sstevel@tonic-gate return (column); 1512*7c478bd9Sstevel@tonic-gate } 1513*7c478bd9Sstevel@tonic-gate 1514*7c478bd9Sstevel@tonic-gate static void 1515*7c478bd9Sstevel@tonic-gate save_input(f) 1516*7c478bd9Sstevel@tonic-gate FILE *f; 1517*7c478bd9Sstevel@tonic-gate { 1518*7c478bd9Sstevel@tonic-gate if (pipe_in) { 1519*7c478bd9Sstevel@tonic-gate save_pipe(); 1520*7c478bd9Sstevel@tonic-gate in_file = tmp_fin; 1521*7c478bd9Sstevel@tonic-gate pipe_in = 0; 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate (void) fseeko(in_file, (off_t)0, SEEK_SET); 1524*7c478bd9Sstevel@tonic-gate copy_file(in_file, f); 1525*7c478bd9Sstevel@tonic-gate } 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate static void 1528*7c478bd9Sstevel@tonic-gate save_pipe() 1529*7c478bd9Sstevel@tonic-gate { 1530*7c478bd9Sstevel@tonic-gate if (!doliseof) 1531*7c478bd9Sstevel@tonic-gate while (fgetputc(stdin) != EOF) 1532*7c478bd9Sstevel@tonic-gate if (brk_hit) { 1533*7c478bd9Sstevel@tonic-gate brk_hit = 0; 1534*7c478bd9Sstevel@tonic-gate error("Piped input only partially saved"); 1535*7c478bd9Sstevel@tonic-gate break; 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate (void) fclose(tmp_fou); 1538*7c478bd9Sstevel@tonic-gate } 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate static int 1541*7c478bd9Sstevel@tonic-gate fgetputc(f) /* copy anything read from a pipe to tmp_fou */ 1542*7c478bd9Sstevel@tonic-gate FILE *f; 1543*7c478bd9Sstevel@tonic-gate { 1544*7c478bd9Sstevel@tonic-gate int c; 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate if ((c = fgetwc(f)) != EOF) 1547*7c478bd9Sstevel@tonic-gate (void) fputwc(c, tmp_fou); 1548*7c478bd9Sstevel@tonic-gate return (c); 1549*7c478bd9Sstevel@tonic-gate } 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate static void 1552*7c478bd9Sstevel@tonic-gate lineset(how) /* initialize line memory */ 1553*7c478bd9Sstevel@tonic-gate int how; 1554*7c478bd9Sstevel@tonic-gate { 1555*7c478bd9Sstevel@tonic-gate if (zero == NULL) { 1556*7c478bd9Sstevel@tonic-gate nlall = 128; 1557*7c478bd9Sstevel@tonic-gate zero = (LINE *) malloc(nlall * sizeof (LINE)); 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate dol = contig = zero; 1560*7c478bd9Sstevel@tonic-gate zero->l_no = 1; 1561*7c478bd9Sstevel@tonic-gate zero->l_addr = 0l; 1562*7c478bd9Sstevel@tonic-gate if (how == BOF) { 1563*7c478bd9Sstevel@tonic-gate dot = zero - 1; 1564*7c478bd9Sstevel@tonic-gate eoflag = 0; 1565*7c478bd9Sstevel@tonic-gate doliseof = 0; 1566*7c478bd9Sstevel@tonic-gate eofl_no = -1; 1567*7c478bd9Sstevel@tonic-gate } else { 1568*7c478bd9Sstevel@tonic-gate dot = dol; 1569*7c478bd9Sstevel@tonic-gate eoflag = 1; 1570*7c478bd9Sstevel@tonic-gate doliseof = 1; 1571*7c478bd9Sstevel@tonic-gate eofl_no = 1; 1572*7c478bd9Sstevel@tonic-gate } 1573*7c478bd9Sstevel@tonic-gate } 1574*7c478bd9Sstevel@tonic-gate 1575*7c478bd9Sstevel@tonic-gate static void 1576*7c478bd9Sstevel@tonic-gate newdol(f) /* add address of new 'dol' */ 1577*7c478bd9Sstevel@tonic-gate /* assumes that f is currently at beginning of said line */ 1578*7c478bd9Sstevel@tonic-gate /* updates dol */ 1579*7c478bd9Sstevel@tonic-gate FILE *f; 1580*7c478bd9Sstevel@tonic-gate { 1581*7c478bd9Sstevel@tonic-gate int diff; 1582*7c478bd9Sstevel@tonic-gate 1583*7c478bd9Sstevel@tonic-gate if ((dol - zero) + 1 >= nlall) { 1584*7c478bd9Sstevel@tonic-gate LINE *ozero = zero; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate nlall += 512; 1587*7c478bd9Sstevel@tonic-gate if ((zero = (LINE *)realloc((char *)zero, 1588*7c478bd9Sstevel@tonic-gate (unsigned)(nlall * sizeof (LINE)))) == NULL) { 1589*7c478bd9Sstevel@tonic-gate zero = ozero; 1590*7c478bd9Sstevel@tonic-gate compact(); 1591*7c478bd9Sstevel@tonic-gate } 1592*7c478bd9Sstevel@tonic-gate diff = (int)((int)zero - (int)ozero); 1593*7c478bd9Sstevel@tonic-gate dot = (LINE *)((int)dot + diff); 1594*7c478bd9Sstevel@tonic-gate dol = (LINE *)((int)dol + diff); 1595*7c478bd9Sstevel@tonic-gate contig = (LINE *)((int)contig + diff); 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate dol++; 1598*7c478bd9Sstevel@tonic-gate if (!pipe_in) 1599*7c478bd9Sstevel@tonic-gate dol->l_addr = (off_t)ftello(f); 1600*7c478bd9Sstevel@tonic-gate else { 1601*7c478bd9Sstevel@tonic-gate (void) fflush(tmp_fou); 1602*7c478bd9Sstevel@tonic-gate dol->l_addr = (off_t)ftello(tmp_fou); 1603*7c478bd9Sstevel@tonic-gate } 1604*7c478bd9Sstevel@tonic-gate dol->l_no = (dol-1)->l_no + 1; 1605*7c478bd9Sstevel@tonic-gate } 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate static void 1608*7c478bd9Sstevel@tonic-gate compact() 1609*7c478bd9Sstevel@tonic-gate { 1610*7c478bd9Sstevel@tonic-gate (void) perror("realloc"); 1611*7c478bd9Sstevel@tonic-gate end_it(); 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate } 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate static void 1616*7c478bd9Sstevel@tonic-gate terminit() /* set up terminal dependencies from termlib */ 1617*7c478bd9Sstevel@tonic-gate { 1618*7c478bd9Sstevel@tonic-gate int err_ret; 1619*7c478bd9Sstevel@tonic-gate struct termio ntty; 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate for (;;) { 1622*7c478bd9Sstevel@tonic-gate gid_t my_tgid; 1623*7c478bd9Sstevel@tonic-gate my_tgid = (gid_t)tcgetpgrp(1); 1624*7c478bd9Sstevel@tonic-gate if (my_tgid < (gid_t)0 || my_tgid == my_pgid) 1625*7c478bd9Sstevel@tonic-gate break; 1626*7c478bd9Sstevel@tonic-gate (void) kill(-my_pgid, SIGTTOU); 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate if ((freopen("/dev/tty", "r+", stdout)) == NULL) { 1630*7c478bd9Sstevel@tonic-gate (void) perror("open"); 1631*7c478bd9Sstevel@tonic-gate exit(1); 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCGETA, &otty); 1634*7c478bd9Sstevel@tonic-gate termflg = 1; 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate (void) setupterm(0, fileno(stdout), &err_ret); 1637*7c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCGETA, &ntty); 1638*7c478bd9Sstevel@tonic-gate ntty.c_lflag &= ~(ECHONL | ECHO | ICANON); 1639*7c478bd9Sstevel@tonic-gate ntty.c_cc[VMIN] = 1; 1640*7c478bd9Sstevel@tonic-gate ntty.c_cc[VTIME] = 1; 1641*7c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCSETAW, &ntty); 1642*7c478bd9Sstevel@tonic-gate pg_stdin = fdopen(dup(fileno(stdout)), "r"); 1643*7c478bd9Sstevel@tonic-gate (void) saveterm(); 1644*7c478bd9Sstevel@tonic-gate (void) resetterm(); 1645*7c478bd9Sstevel@tonic-gate if (lines <= 0 || hard_copy) { 1646*7c478bd9Sstevel@tonic-gate hard_copy = 1; 1647*7c478bd9Sstevel@tonic-gate lines = 24; 1648*7c478bd9Sstevel@tonic-gate } 1649*7c478bd9Sstevel@tonic-gate if (columns <= 0) 1650*7c478bd9Sstevel@tonic-gate columns = 80; 1651*7c478bd9Sstevel@tonic-gate if (clropt && !clear_screen) 1652*7c478bd9Sstevel@tonic-gate clropt = 0; 1653*7c478bd9Sstevel@tonic-gate if ((shell = getenv("SHELL")) == (char *)NULL) 1654*7c478bd9Sstevel@tonic-gate shell = "/usr/bin/sh"; 1655*7c478bd9Sstevel@tonic-gate } 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate static void 1658*7c478bd9Sstevel@tonic-gate error(mess) 1659*7c478bd9Sstevel@tonic-gate char *mess; 1660*7c478bd9Sstevel@tonic-gate { 1661*7c478bd9Sstevel@tonic-gate kill_line(); 1662*7c478bd9Sstevel@tonic-gate sopr(gettext(mess), 1); 1663*7c478bd9Sstevel@tonic-gate prompt((char *)NULL); 1664*7c478bd9Sstevel@tonic-gate errors++; 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate static void 1668*7c478bd9Sstevel@tonic-gate prompt(filename) 1669*7c478bd9Sstevel@tonic-gate char *filename; 1670*7c478bd9Sstevel@tonic-gate { 1671*7c478bd9Sstevel@tonic-gate char outstr[PROMPTSIZE+6]; 1672*7c478bd9Sstevel@tonic-gate int pagenum; 1673*7c478bd9Sstevel@tonic-gate if (filename != NULL) { 1674*7c478bd9Sstevel@tonic-gate /* 1675*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 1676*7c478bd9Sstevel@tonic-gate * %s is a filename. 1677*7c478bd9Sstevel@tonic-gate */ 1678*7c478bd9Sstevel@tonic-gate (void) sprintf(outstr, gettext("(Next file: %s)"), filename); 1679*7c478bd9Sstevel@tonic-gate } else { 1680*7c478bd9Sstevel@tonic-gate if ((pagenum = (int)((new_ss.last_line-2)/(window-1)+1)) 1681*7c478bd9Sstevel@tonic-gate > 999999) 1682*7c478bd9Sstevel@tonic-gate pagenum = 999999; 1683*7c478bd9Sstevel@tonic-gate (void) sprintf(outstr, promptstr, pagenum); 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate sopr(outstr, 1); 1686*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1687*7c478bd9Sstevel@tonic-gate } 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate /* 1690*7c478bd9Sstevel@tonic-gate * sopr puts out the message (please no \n's) surrounded by standout 1691*7c478bd9Sstevel@tonic-gate * begins and ends 1692*7c478bd9Sstevel@tonic-gate */ 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate static void 1695*7c478bd9Sstevel@tonic-gate sopr(m, count) 1696*7c478bd9Sstevel@tonic-gate char *m; 1697*7c478bd9Sstevel@tonic-gate int count; 1698*7c478bd9Sstevel@tonic-gate { 1699*7c478bd9Sstevel@tonic-gate wchar_t wc; 1700*7c478bd9Sstevel@tonic-gate int len, n; 1701*7c478bd9Sstevel@tonic-gate char *p; 1702*7c478bd9Sstevel@tonic-gate 1703*7c478bd9Sstevel@tonic-gate if (count) { 1704*7c478bd9Sstevel@tonic-gate p = m; 1705*7c478bd9Sstevel@tonic-gate for (; *p; p += len) { 1706*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, p, MB_CUR_MAX)) <= 0) { 1707*7c478bd9Sstevel@tonic-gate len = 1; 1708*7c478bd9Sstevel@tonic-gate continue; 1709*7c478bd9Sstevel@tonic-gate } 1710*7c478bd9Sstevel@tonic-gate if ((n = wcwidth(wc)) > 0) 1711*7c478bd9Sstevel@tonic-gate promptlen += n; 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate if (soflag && enter_standout_mode && exit_standout_mode) { 1715*7c478bd9Sstevel@tonic-gate (void) putp(enter_standout_mode); 1716*7c478bd9Sstevel@tonic-gate (void) fputs(m, stdout); 1717*7c478bd9Sstevel@tonic-gate (void) putp(exit_standout_mode); 1718*7c478bd9Sstevel@tonic-gate } 1719*7c478bd9Sstevel@tonic-gate else 1720*7c478bd9Sstevel@tonic-gate (void) fputs(m, stdout); 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate static void 1724*7c478bd9Sstevel@tonic-gate doclear() 1725*7c478bd9Sstevel@tonic-gate { 1726*7c478bd9Sstevel@tonic-gate if (clear_screen) 1727*7c478bd9Sstevel@tonic-gate (void) putp(clear_screen); 1728*7c478bd9Sstevel@tonic-gate (void) putchar('\r'); /* this resets the terminal drivers character */ 1729*7c478bd9Sstevel@tonic-gate /* count in case it is trying to expand tabs */ 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate } 1732*7c478bd9Sstevel@tonic-gate 1733*7c478bd9Sstevel@tonic-gate static void 1734*7c478bd9Sstevel@tonic-gate kill_line() 1735*7c478bd9Sstevel@tonic-gate { 1736*7c478bd9Sstevel@tonic-gate erase_line(0); 1737*7c478bd9Sstevel@tonic-gate if (!clr_eol) (void) putchar('\r'); 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate } 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate /* erase from after col to end of prompt */ 1742*7c478bd9Sstevel@tonic-gate static void 1743*7c478bd9Sstevel@tonic-gate erase_line(col) 1744*7c478bd9Sstevel@tonic-gate int col; 1745*7c478bd9Sstevel@tonic-gate { 1746*7c478bd9Sstevel@tonic-gate 1747*7c478bd9Sstevel@tonic-gate if (promptlen == 0) 1748*7c478bd9Sstevel@tonic-gate return; 1749*7c478bd9Sstevel@tonic-gate if (hard_copy) 1750*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1751*7c478bd9Sstevel@tonic-gate else { 1752*7c478bd9Sstevel@tonic-gate if (col == 0) 1753*7c478bd9Sstevel@tonic-gate (void) putchar('\r'); 1754*7c478bd9Sstevel@tonic-gate if (clr_eol) { 1755*7c478bd9Sstevel@tonic-gate (void) putp(clr_eol); 1756*7c478bd9Sstevel@tonic-gate /* for the terminal driver again */ 1757*7c478bd9Sstevel@tonic-gate (void) putchar('\r'); 1758*7c478bd9Sstevel@tonic-gate } 1759*7c478bd9Sstevel@tonic-gate else 1760*7c478bd9Sstevel@tonic-gate for (col = promptlen - col; col > 0; col--) 1761*7c478bd9Sstevel@tonic-gate (void) putchar(' '); 1762*7c478bd9Sstevel@tonic-gate } 1763*7c478bd9Sstevel@tonic-gate promptlen = 0; 1764*7c478bd9Sstevel@tonic-gate } 1765*7c478bd9Sstevel@tonic-gate 1766*7c478bd9Sstevel@tonic-gate /* 1767*7c478bd9Sstevel@tonic-gate * Come here if a quit or interrupt signal is received 1768*7c478bd9Sstevel@tonic-gate */ 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate static void 1771*7c478bd9Sstevel@tonic-gate on_brk(sno) 1772*7c478bd9Sstevel@tonic-gate int sno; /* signal number generated */ 1773*7c478bd9Sstevel@tonic-gate { 1774*7c478bd9Sstevel@tonic-gate (void) signal(sno, on_brk); 1775*7c478bd9Sstevel@tonic-gate if (!inwait) { 1776*7c478bd9Sstevel@tonic-gate BEEP(); 1777*7c478bd9Sstevel@tonic-gate brk_hit = 1; 1778*7c478bd9Sstevel@tonic-gate } else { 1779*7c478bd9Sstevel@tonic-gate brk_hit = 0; 1780*7c478bd9Sstevel@tonic-gate longjmp(restore, 1); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate } 1783*7c478bd9Sstevel@tonic-gate 1784*7c478bd9Sstevel@tonic-gate /* 1785*7c478bd9Sstevel@tonic-gate * Clean up terminal state and exit. 1786*7c478bd9Sstevel@tonic-gate */ 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate void 1789*7c478bd9Sstevel@tonic-gate end_it() 1790*7c478bd9Sstevel@tonic-gate { 1791*7c478bd9Sstevel@tonic-gate 1792*7c478bd9Sstevel@tonic-gate if (out_is_tty) { 1793*7c478bd9Sstevel@tonic-gate kill_line(); 1794*7c478bd9Sstevel@tonic-gate (void) resetterm(); 1795*7c478bd9Sstevel@tonic-gate if (termflg) 1796*7c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCSETAW, &otty); 1797*7c478bd9Sstevel@tonic-gate } 1798*7c478bd9Sstevel@tonic-gate if (tmp_fin) 1799*7c478bd9Sstevel@tonic-gate (void) fclose(tmp_fin); 1800*7c478bd9Sstevel@tonic-gate if (tmp_fou) 1801*7c478bd9Sstevel@tonic-gate (void) fclose(tmp_fou); 1802*7c478bd9Sstevel@tonic-gate if (tmp_fou || tmp_fin) 1803*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 1804*7c478bd9Sstevel@tonic-gate exit(status); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate void 1808*7c478bd9Sstevel@tonic-gate onsusp() 1809*7c478bd9Sstevel@tonic-gate { 1810*7c478bd9Sstevel@tonic-gate int ttou_is_dfl; 1811*7c478bd9Sstevel@tonic-gate 1812*7c478bd9Sstevel@tonic-gate /* ignore SIGTTOU so following resetterm and flush works */ 1813*7c478bd9Sstevel@tonic-gate ttou_is_dfl = (signal(SIGTTOU, SIG_IGN) == SIG_DFL); 1814*7c478bd9Sstevel@tonic-gate (void) resetterm(); 1815*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1816*7c478bd9Sstevel@tonic-gate if (ttou_is_dfl) 1817*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_DFL); 1818*7c478bd9Sstevel@tonic-gate 1819*7c478bd9Sstevel@tonic-gate /* send SIGTSTP to stop this process group */ 1820*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 1821*7c478bd9Sstevel@tonic-gate (void) kill(-my_pgid, SIGTSTP); 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate /* continued - reset the terminal */ 1824*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 1825*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, (void (*)(int))onsusp); 1826*7c478bd9Sstevel@tonic-gate #else 1827*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, (void (*))onsusp); 1828*7c478bd9Sstevel@tonic-gate #endif 1829*7c478bd9Sstevel@tonic-gate (void) resetterm(); 1830*7c478bd9Sstevel@tonic-gate if (inwait) 1831*7c478bd9Sstevel@tonic-gate longjmp(restore, -1); 1832*7c478bd9Sstevel@tonic-gate 1833*7c478bd9Sstevel@tonic-gate } 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate static char * 1836*7c478bd9Sstevel@tonic-gate pg_strchr(str, c) 1837*7c478bd9Sstevel@tonic-gate char *str; 1838*7c478bd9Sstevel@tonic-gate wchar_t c; 1839*7c478bd9Sstevel@tonic-gate { 1840*7c478bd9Sstevel@tonic-gate while (*str) { 1841*7c478bd9Sstevel@tonic-gate if (c == *str) 1842*7c478bd9Sstevel@tonic-gate return (str); 1843*7c478bd9Sstevel@tonic-gate str++; 1844*7c478bd9Sstevel@tonic-gate } 1845*7c478bd9Sstevel@tonic-gate return (0); 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate void 1849*7c478bd9Sstevel@tonic-gate usage() 1850*7c478bd9Sstevel@tonic-gate { 1851*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1852*7c478bd9Sstevel@tonic-gate "Usage: pg [-number] [-p string] [-cefnrs] [+line] [+/pattern/] files\n")); 1853*7c478bd9Sstevel@tonic-gate exit(1); 1854*7c478bd9Sstevel@tonic-gate } 1855