17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*4fce32e1Smuffin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*4fce32e1Smuffin /* All Rights Reserved */ 30*4fce32e1Smuffin 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <signal.h> 347c478bd9Sstevel@tonic-gate #include <setjmp.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <stdio.h> 417c478bd9Sstevel@tonic-gate #include <wchar.h> 427c478bd9Sstevel@tonic-gate #include <curses.h> 437c478bd9Sstevel@tonic-gate #include <term.h> 447c478bd9Sstevel@tonic-gate #include <errno.h> 457c478bd9Sstevel@tonic-gate #include <stdlib.h> 467c478bd9Sstevel@tonic-gate #include <regexpr.h> 477c478bd9Sstevel@tonic-gate #include <limits.h> 487c478bd9Sstevel@tonic-gate #include <locale.h> 497c478bd9Sstevel@tonic-gate #include <wctype.h> /* iswprint() */ 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <unistd.h> 527c478bd9Sstevel@tonic-gate #include <wait.h> 537c478bd9Sstevel@tonic-gate #include <libw.h> 547c478bd9Sstevel@tonic-gate #include <regexpr.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * pg -- paginator for crt terminals 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * Includes the ability to display pages that have 617c478bd9Sstevel@tonic-gate * already passed by. Also gives the user the ability 627c478bd9Sstevel@tonic-gate * to search forward and backwards for regular expressions. 637c478bd9Sstevel@tonic-gate * This works for piped input by copying to a temporary file, 647c478bd9Sstevel@tonic-gate * and resolving backreferences from there. 657c478bd9Sstevel@tonic-gate * 667c478bd9Sstevel@tonic-gate * Note: The reason that there are so many commands to do 677c478bd9Sstevel@tonic-gate * the same types of things is to try to accommodate 687c478bd9Sstevel@tonic-gate * users of other paginators. 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define LINSIZ 1024 727c478bd9Sstevel@tonic-gate #define QUIT '\034' 737c478bd9Sstevel@tonic-gate #define BOF (EOF - 1) /* Begining of File */ 747c478bd9Sstevel@tonic-gate #define STOP (EOF - 2) 757c478bd9Sstevel@tonic-gate #define PROMPTSIZE 256 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Function definitions 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate static void lineset(int); 817c478bd9Sstevel@tonic-gate static char *setprompt(); 827c478bd9Sstevel@tonic-gate static int set_state(int *, wchar_t, char *); 837c478bd9Sstevel@tonic-gate static void help(); 847c478bd9Sstevel@tonic-gate static void copy_file(FILE *, FILE *); 857c478bd9Sstevel@tonic-gate static void re_error(int); 867c478bd9Sstevel@tonic-gate static void save_input(FILE *); 877c478bd9Sstevel@tonic-gate static void save_pipe(); 887c478bd9Sstevel@tonic-gate static void newdol(FILE *); 897c478bd9Sstevel@tonic-gate static void erase_line(int); 907c478bd9Sstevel@tonic-gate static void kill_line(); 917c478bd9Sstevel@tonic-gate static void doclear(); 927c478bd9Sstevel@tonic-gate static void sopr(char *, int); 937c478bd9Sstevel@tonic-gate static void prompt(char *); 947c478bd9Sstevel@tonic-gate static void error(char *); 957c478bd9Sstevel@tonic-gate static void terminit(); 967c478bd9Sstevel@tonic-gate static void compact(); 977c478bd9Sstevel@tonic-gate static off_t getline(FILE *); 987c478bd9Sstevel@tonic-gate static int mrdchar(); 997c478bd9Sstevel@tonic-gate static off_t find(int, off_t); 1007c478bd9Sstevel@tonic-gate static int search(char *, off_t); 1017c478bd9Sstevel@tonic-gate static FILE *checkf(char *); 1027c478bd9Sstevel@tonic-gate static int skipf(int); 1037c478bd9Sstevel@tonic-gate static int readch(); 1047c478bd9Sstevel@tonic-gate static int ttyin(); 1057c478bd9Sstevel@tonic-gate static int number(); 1067c478bd9Sstevel@tonic-gate static int command(char *); 1077c478bd9Sstevel@tonic-gate static int screen(char *); 1087c478bd9Sstevel@tonic-gate static int fgetputc(); 1097c478bd9Sstevel@tonic-gate static char *pg_strchr(); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate struct line { /* how line addresses are stored */ 1137c478bd9Sstevel@tonic-gate off_t l_addr; /* file offset */ 1147c478bd9Sstevel@tonic-gate off_t l_no; /* line number in file */ 1157c478bd9Sstevel@tonic-gate }; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate typedef struct line LINE; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate static LINE *zero = NULL, /* first line */ 1207c478bd9Sstevel@tonic-gate *dot, /* current line */ 1217c478bd9Sstevel@tonic-gate *dol, /* last line */ 1227c478bd9Sstevel@tonic-gate *contig; /* where contiguous (non-aged) lines start */ 1237c478bd9Sstevel@tonic-gate static long nlall; /* room for how many LINEs in memory */ 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate static FILE *in_file, /* current input stream */ 1267c478bd9Sstevel@tonic-gate *tmp_fin, /* pipe temporary file in */ 1277c478bd9Sstevel@tonic-gate *tmp_fou; /* pipe temporary file out */ 1287c478bd9Sstevel@tonic-gate static char tmp_name[] = "/tmp/pgXXXXXX"; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate static short sign; /* sign of command input */ 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate static int fnum, /* which file argument we're in */ 1337c478bd9Sstevel@tonic-gate pipe_in, /* set when stdin is a pipe */ 1347c478bd9Sstevel@tonic-gate out_is_tty; /* set if stdout is a tty */ 1357c478bd9Sstevel@tonic-gate static gid_t my_pgid; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate static void on_brk(), 1387c478bd9Sstevel@tonic-gate end_it(); 1397c478bd9Sstevel@tonic-gate static short brk_hit; /* interrupt handling is pending flag */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static int window = 0; /* window size in lines */ 1427c478bd9Sstevel@tonic-gate static short eof_pause = 1; /* pause w/ prompt at end of files */ 1437c478bd9Sstevel@tonic-gate static short rmode = 0; /* deny shell escape in restricted mode */ 1447c478bd9Sstevel@tonic-gate static short soflag = 0; /* output all messages in standout mode */ 1457c478bd9Sstevel@tonic-gate static short promptlen; /* length of the current prompt */ 1467c478bd9Sstevel@tonic-gate static short firstf = 1; /* set before first file has been processed */ 1477c478bd9Sstevel@tonic-gate static short inwait, /* set while waiting for user input */ 1487c478bd9Sstevel@tonic-gate errors; /* set if error message has been printed. */ 1497c478bd9Sstevel@tonic-gate /* if so, need to erase it and prompt */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static char **fnames; 1527c478bd9Sstevel@tonic-gate static short status = 0; /* set > 0 if error detected */ 1537c478bd9Sstevel@tonic-gate static short fflag = 0; /* set if the f option is used */ 1547c478bd9Sstevel@tonic-gate static short nflag = 0; /* set for "no newline" input option */ 1557c478bd9Sstevel@tonic-gate static short clropt = 0; /* set if the clear option is used */ 1567c478bd9Sstevel@tonic-gate static int initopt = 0; /* set if the line option is used */ 1577c478bd9Sstevel@tonic-gate static int srchopt = 0; /* set if the search option is used */ 1587c478bd9Sstevel@tonic-gate static int initline; 1597c478bd9Sstevel@tonic-gate static char initbuf[BUFSIZ]; 1607c478bd9Sstevel@tonic-gate static wchar_t leave_search = L't'; 1617c478bd9Sstevel@tonic-gate /* where on the page to leave a found string */ 1627c478bd9Sstevel@tonic-gate static short nfiles; 1637c478bd9Sstevel@tonic-gate static char *shell; 1647c478bd9Sstevel@tonic-gate static char *promptstr = ":"; 1657c478bd9Sstevel@tonic-gate static off_t nchars; /* return from getline in find() */ 1667c478bd9Sstevel@tonic-gate static jmp_buf restore; 1677c478bd9Sstevel@tonic-gate static char Line[LINSIZ+2]; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate static int catch_susp; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate static void onsusp(); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate struct screen_stat { 1747c478bd9Sstevel@tonic-gate off_t first_line; 1757c478bd9Sstevel@tonic-gate off_t last_line; 1767c478bd9Sstevel@tonic-gate short is_eof; 1777c478bd9Sstevel@tonic-gate }; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static struct screen_stat old_ss = { 0, 0, 0 }; 1807c478bd9Sstevel@tonic-gate static struct screen_stat new_ss; 1817c478bd9Sstevel@tonic-gate static struct termio otty; /* to save old terminal settings */ 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate static short termflg = 0; /* set once terminal is initialized */ 1847c478bd9Sstevel@tonic-gate static short eoflag; /* set whenever at end of current file */ 1857c478bd9Sstevel@tonic-gate static short doliseof; /* set when last line of file is known */ 1867c478bd9Sstevel@tonic-gate static off_t eofl_no; /* what the last line of the file is */ 1877c478bd9Sstevel@tonic-gate static void usage(void); 1887c478bd9Sstevel@tonic-gate static FILE *pg_stdin; 1897c478bd9Sstevel@tonic-gate 190*4fce32e1Smuffin int 191*4fce32e1Smuffin main(int argc, char **argv) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate char *s; 1947c478bd9Sstevel@tonic-gate char *p; 1957c478bd9Sstevel@tonic-gate int prnames = 0; 1967c478bd9Sstevel@tonic-gate int opt; 1977c478bd9Sstevel@tonic-gate int i; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2007c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 2017c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 2027c478bd9Sstevel@tonic-gate #endif 2037c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* check for non-standard "-#" option */ 2067c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 2077c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "--") == 0) 2087c478bd9Sstevel@tonic-gate break; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if ((argv[i][0] == '-') && isdigit(argv[i][1])) { 2117c478bd9Sstevel@tonic-gate if (strlen(&argv[i][1]) != 2127c478bd9Sstevel@tonic-gate strspn(&argv[i][1], "0123456789")) { 2137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2147c478bd9Sstevel@tonic-gate "pg: Badly formed number\n")); 2157c478bd9Sstevel@tonic-gate usage(); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate window = (int)strtol(&argv[i][1], (char **)NULL, 10); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate while (i < argc) { 2217c478bd9Sstevel@tonic-gate argv[i] = argv[i + 1]; 2227c478bd9Sstevel@tonic-gate i++; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate i--; 2257c478bd9Sstevel@tonic-gate argc--; 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* check for non-standard + option */ 2307c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 2317c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "--") == 0) 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if (argv[i][0] == '+') { 2357c478bd9Sstevel@tonic-gate if (argv[i][1] == '/') { 2367c478bd9Sstevel@tonic-gate srchopt++; 2377c478bd9Sstevel@tonic-gate initopt = 0; 2387c478bd9Sstevel@tonic-gate for (s = &argv[i][2], p = initbuf; *s != '\0'; ) 2397c478bd9Sstevel@tonic-gate if (p < initbuf + sizeof (initbuf)) 2407c478bd9Sstevel@tonic-gate *p++ = *s++; 2417c478bd9Sstevel@tonic-gate else { 2427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2437c478bd9Sstevel@tonic-gate "pg: pattern too long\n")); 2447c478bd9Sstevel@tonic-gate return (1); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate *p = '\0'; 2477c478bd9Sstevel@tonic-gate } else { 2487c478bd9Sstevel@tonic-gate initopt++; 2497c478bd9Sstevel@tonic-gate srchopt = 0; 2507c478bd9Sstevel@tonic-gate s = &argv[i][2]; 2517c478bd9Sstevel@tonic-gate for (; isdigit(*s); s++) 2527c478bd9Sstevel@tonic-gate initline = initline*10 + *s -'0'; 2537c478bd9Sstevel@tonic-gate if (*s != '\0') 2547c478bd9Sstevel@tonic-gate usage(); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate while (i < argc) { 2587c478bd9Sstevel@tonic-gate argv[i] = argv[i + 1]; 2597c478bd9Sstevel@tonic-gate i++; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate i--; 2627c478bd9Sstevel@tonic-gate argc--; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "cefnrsp:")) != EOF) { 2677c478bd9Sstevel@tonic-gate switch (opt) { 2687c478bd9Sstevel@tonic-gate case 'c': 2697c478bd9Sstevel@tonic-gate clropt = 1; 2707c478bd9Sstevel@tonic-gate break; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate case 'e': 2737c478bd9Sstevel@tonic-gate eof_pause = 0; 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate case 'f': 2777c478bd9Sstevel@tonic-gate fflag = 1; 2787c478bd9Sstevel@tonic-gate break; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate case 'n': 2817c478bd9Sstevel@tonic-gate nflag = 1; 2827c478bd9Sstevel@tonic-gate break; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate case 'r': 2857c478bd9Sstevel@tonic-gate rmode = 1; /* restricted mode */ 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate case 's': 2897c478bd9Sstevel@tonic-gate soflag = 1; /* standout mode */ 2907c478bd9Sstevel@tonic-gate break; 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate case 'p': 2937c478bd9Sstevel@tonic-gate promptstr = setprompt(optarg); 2947c478bd9Sstevel@tonic-gate break; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate default: 2977c478bd9Sstevel@tonic-gate usage(); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate nfiles = argc - optind; 3027c478bd9Sstevel@tonic-gate fnames = &argv[optind]; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, end_it); 3057c478bd9Sstevel@tonic-gate (void) signal(SIGINT, end_it); 3067c478bd9Sstevel@tonic-gate out_is_tty = isatty(1); 3077c478bd9Sstevel@tonic-gate my_pgid = getpgrp(); 3087c478bd9Sstevel@tonic-gate if (out_is_tty) { 3097c478bd9Sstevel@tonic-gate terminit(); 3107c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, on_brk); 3117c478bd9Sstevel@tonic-gate (void) signal(SIGINT, on_brk); 3127c478bd9Sstevel@tonic-gate if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) { 3137c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, onsusp); 3147c478bd9Sstevel@tonic-gate catch_susp++; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate if (window == 0) 3187c478bd9Sstevel@tonic-gate window = lines - 1; 3197c478bd9Sstevel@tonic-gate if (window <= 1) 3207c478bd9Sstevel@tonic-gate window = 2; 3217c478bd9Sstevel@tonic-gate if (initline <= 0) 3227c478bd9Sstevel@tonic-gate initline = 1; 3237c478bd9Sstevel@tonic-gate if (nfiles > 1) 3247c478bd9Sstevel@tonic-gate prnames++; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (nfiles == 0) { 3277c478bd9Sstevel@tonic-gate fnames[0] = "-"; 3287c478bd9Sstevel@tonic-gate nfiles++; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate while (fnum < nfiles) { 3317c478bd9Sstevel@tonic-gate if (strcmp(fnames[fnum], "") == 0) 3327c478bd9Sstevel@tonic-gate fnames[fnum] = "-"; 333*4fce32e1Smuffin if ((in_file = checkf(fnames[fnum])) == NULL) { 3347c478bd9Sstevel@tonic-gate status = 2; 3357c478bd9Sstevel@tonic-gate fnum++; 3367c478bd9Sstevel@tonic-gate } else { 3377c478bd9Sstevel@tonic-gate status = 0; 3387c478bd9Sstevel@tonic-gate if (out_is_tty) 3397c478bd9Sstevel@tonic-gate fnum += screen(fnames[fnum]); 3407c478bd9Sstevel@tonic-gate else { 3417c478bd9Sstevel@tonic-gate if (prnames) { 3427c478bd9Sstevel@tonic-gate (void) fputs("::::::::::::::\n", 3437c478bd9Sstevel@tonic-gate stdout); 3447c478bd9Sstevel@tonic-gate (void) fputs(fnames[fnum], stdout); 3457c478bd9Sstevel@tonic-gate (void) fputs("\n::::::::::::::\n", 3467c478bd9Sstevel@tonic-gate stdout); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate copy_file(in_file, stdout); 3497c478bd9Sstevel@tonic-gate fnum++; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate (void) fflush(stdout); 3527c478bd9Sstevel@tonic-gate if (pipe_in) 3537c478bd9Sstevel@tonic-gate save_pipe(); 3547c478bd9Sstevel@tonic-gate else 3557c478bd9Sstevel@tonic-gate if (in_file != tmp_fin) 3567c478bd9Sstevel@tonic-gate (void) fclose(in_file); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate end_it(); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3627c478bd9Sstevel@tonic-gate return (0); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate static char * 3667c478bd9Sstevel@tonic-gate setprompt(s) 3677c478bd9Sstevel@tonic-gate char *s; 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate int i = 0; 3707c478bd9Sstevel@tonic-gate int pct_d = 0; 3717c478bd9Sstevel@tonic-gate static char pstr[PROMPTSIZE]; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate while (i < PROMPTSIZE - 2) 3747c478bd9Sstevel@tonic-gate switch (pstr[i++] = *s++) { 3757c478bd9Sstevel@tonic-gate case '\0': 3767c478bd9Sstevel@tonic-gate return (pstr); 3777c478bd9Sstevel@tonic-gate case '%': 3787c478bd9Sstevel@tonic-gate if (*s == 'd' && !pct_d) { 3797c478bd9Sstevel@tonic-gate pct_d++; 3807c478bd9Sstevel@tonic-gate } else if (*s != '%') 3817c478bd9Sstevel@tonic-gate pstr[i++] = '%'; 3827c478bd9Sstevel@tonic-gate if ((pstr[i++] = *s++) == '\0') 3837c478bd9Sstevel@tonic-gate return (pstr); 3847c478bd9Sstevel@tonic-gate break; 3857c478bd9Sstevel@tonic-gate default: 3867c478bd9Sstevel@tonic-gate break; 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("pg: prompt too long\n")); 3897c478bd9Sstevel@tonic-gate exit(1); 3907c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Print out the contents of the file f, one screenful at a time. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate static int 3997c478bd9Sstevel@tonic-gate screen(file_name) 4007c478bd9Sstevel@tonic-gate char *file_name; 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate int cmd_ret = 0; 4037c478bd9Sstevel@tonic-gate off_t start; 4047c478bd9Sstevel@tonic-gate short hadchance = 0; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate old_ss.is_eof = 0; 4077c478bd9Sstevel@tonic-gate old_ss.first_line = 0; 4087c478bd9Sstevel@tonic-gate old_ss.last_line = 0; 4097c478bd9Sstevel@tonic-gate new_ss = old_ss; 4107c478bd9Sstevel@tonic-gate if (!firstf) 4117c478bd9Sstevel@tonic-gate cmd_ret = command(file_name); 4127c478bd9Sstevel@tonic-gate else { 4137c478bd9Sstevel@tonic-gate firstf = 0; 4147c478bd9Sstevel@tonic-gate if (initopt) { 4157c478bd9Sstevel@tonic-gate initopt = 0; 4167c478bd9Sstevel@tonic-gate new_ss.first_line = initline; 4177c478bd9Sstevel@tonic-gate new_ss.last_line = initline + (off_t)window - 1; 4187c478bd9Sstevel@tonic-gate } else if (srchopt) { 4197c478bd9Sstevel@tonic-gate srchopt = 0; 4207c478bd9Sstevel@tonic-gate if (!search(initbuf, (off_t)1)) 4217c478bd9Sstevel@tonic-gate cmd_ret = command(file_name); 4227c478bd9Sstevel@tonic-gate } else { 4237c478bd9Sstevel@tonic-gate new_ss.first_line = 1; 4247c478bd9Sstevel@tonic-gate new_ss.last_line = (off_t)window; 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate for (;;) { 4297c478bd9Sstevel@tonic-gate if (cmd_ret) 4307c478bd9Sstevel@tonic-gate return (cmd_ret); 4317c478bd9Sstevel@tonic-gate if (hadchance && new_ss.last_line >= eofl_no) 4327c478bd9Sstevel@tonic-gate return (1); 4337c478bd9Sstevel@tonic-gate hadchance = 0; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if (new_ss.last_line < (off_t)window) 4367c478bd9Sstevel@tonic-gate new_ss.last_line = (off_t)window; 4377c478bd9Sstevel@tonic-gate if (find(0, new_ss.last_line + 1) != EOF) 4387c478bd9Sstevel@tonic-gate new_ss.is_eof = 0; 4397c478bd9Sstevel@tonic-gate else { 4407c478bd9Sstevel@tonic-gate new_ss.is_eof = 1; 4417c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 4427c478bd9Sstevel@tonic-gate new_ss.first_line = new_ss.last_line - 4437c478bd9Sstevel@tonic-gate (off_t)window + 1; 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate if (new_ss.first_line < 1) 4477c478bd9Sstevel@tonic-gate new_ss.first_line = 1; 4487c478bd9Sstevel@tonic-gate if (clropt) { 4497c478bd9Sstevel@tonic-gate doclear(); 4507c478bd9Sstevel@tonic-gate start = new_ss.first_line; 4517c478bd9Sstevel@tonic-gate } else { 4527c478bd9Sstevel@tonic-gate if (new_ss.first_line == old_ss.last_line) 4537c478bd9Sstevel@tonic-gate start = new_ss.first_line + 1; 4547c478bd9Sstevel@tonic-gate else 4557c478bd9Sstevel@tonic-gate if (new_ss.first_line > old_ss.last_line) 4567c478bd9Sstevel@tonic-gate start = new_ss.first_line; 4577c478bd9Sstevel@tonic-gate else 4587c478bd9Sstevel@tonic-gate if (old_ss.first_line < new_ss.first_line) 4597c478bd9Sstevel@tonic-gate start = old_ss.last_line + 1; 4607c478bd9Sstevel@tonic-gate else 4617c478bd9Sstevel@tonic-gate start = new_ss.first_line; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate if (start < old_ss.first_line) 4647c478bd9Sstevel@tonic-gate sopr(gettext("...skipping backward\n"), 0); 4657c478bd9Sstevel@tonic-gate else 4667c478bd9Sstevel@tonic-gate if (start > old_ss.last_line + 1) 4677c478bd9Sstevel@tonic-gate sopr(gettext("...skipping forward\n"), 0); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate for (; start <= new_ss.last_line; start++) { 4717c478bd9Sstevel@tonic-gate (void) find(0, start); 4727c478bd9Sstevel@tonic-gate (void) fputs(Line, stdout); 4737c478bd9Sstevel@tonic-gate if (brk_hit) { 4747c478bd9Sstevel@tonic-gate new_ss.last_line = find(1, 0); 4757c478bd9Sstevel@tonic-gate new_ss.is_eof = 0; 4767c478bd9Sstevel@tonic-gate break; 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate brk_hit = 0; 4817c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4827c478bd9Sstevel@tonic-gate if (new_ss.is_eof) { 4837c478bd9Sstevel@tonic-gate if (!eof_pause || eofl_no == 1) 4847c478bd9Sstevel@tonic-gate return (1); 4857c478bd9Sstevel@tonic-gate hadchance++; 4867c478bd9Sstevel@tonic-gate error("(EOF)"); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate old_ss = new_ss; 4897c478bd9Sstevel@tonic-gate cmd_ret = command((char *)NULL); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate static char cmdbuf[LINSIZ], *cmdptr; 4947c478bd9Sstevel@tonic-gate #define BEEP() if (bell) { (void) putp(bell); (void) fflush(stdout); } 4957c478bd9Sstevel@tonic-gate #define BLANKS(p) while (*p == ' ' || *p == '\t') p++ 4967c478bd9Sstevel@tonic-gate #define CHECKEND() BLANKS(cmdptr); if (*cmdptr) { BEEP(); break; } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* 4997c478bd9Sstevel@tonic-gate * Read a command and do it. A command consists of an optional integer 5007c478bd9Sstevel@tonic-gate * argument followed by the command character. Return the number of files 5017c478bd9Sstevel@tonic-gate * to skip, 0 if we're still talking about the same file. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate static int 5057c478bd9Sstevel@tonic-gate command(filename) 5067c478bd9Sstevel@tonic-gate char *filename; 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate off_t nlines; 5097c478bd9Sstevel@tonic-gate FILE *sf; 5107c478bd9Sstevel@tonic-gate char *cmdend; 5117c478bd9Sstevel@tonic-gate pid_t id; 5127c478bd9Sstevel@tonic-gate int skip; 5137c478bd9Sstevel@tonic-gate int len; 5147c478bd9Sstevel@tonic-gate wchar_t wc; 5157c478bd9Sstevel@tonic-gate wchar_t wc_e; 5167c478bd9Sstevel@tonic-gate wchar_t wc_e1; 5177c478bd9Sstevel@tonic-gate char *p; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate for (;;) { 5207c478bd9Sstevel@tonic-gate /* 5217c478bd9Sstevel@tonic-gate * Wait for output to drain before going on. 5227c478bd9Sstevel@tonic-gate * This is done so that the user will not hit 5237c478bd9Sstevel@tonic-gate * break and quit before he has seen the prompt. 5247c478bd9Sstevel@tonic-gate */ 5257c478bd9Sstevel@tonic-gate (void) ioctl(1, TCSBRK, 1); 5267c478bd9Sstevel@tonic-gate if (setjmp(restore) > 0) 5277c478bd9Sstevel@tonic-gate end_it(); 5287c478bd9Sstevel@tonic-gate inwait = 1; 5297c478bd9Sstevel@tonic-gate brk_hit = 0; 5307c478bd9Sstevel@tonic-gate if (errors) 5317c478bd9Sstevel@tonic-gate errors = 0; 5327c478bd9Sstevel@tonic-gate else { 5337c478bd9Sstevel@tonic-gate kill_line(); 5347c478bd9Sstevel@tonic-gate prompt(filename); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate (void) fflush(stdout); 5377c478bd9Sstevel@tonic-gate if (ttyin()) 5387c478bd9Sstevel@tonic-gate continue; 5397c478bd9Sstevel@tonic-gate cmdptr = cmdbuf; 5407c478bd9Sstevel@tonic-gate nlines = number(); 5417c478bd9Sstevel@tonic-gate BLANKS(cmdptr); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, cmdptr, MB_CUR_MAX)) <= 0) { 5447c478bd9Sstevel@tonic-gate wc = *cmdptr; 5457c478bd9Sstevel@tonic-gate len = 1; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate cmdptr += len; 5487c478bd9Sstevel@tonic-gate switch (wc) { 5497c478bd9Sstevel@tonic-gate case 'h': 5507c478bd9Sstevel@tonic-gate CHECKEND(); 5517c478bd9Sstevel@tonic-gate help(); 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate case '\014': /* ^L */ 5547c478bd9Sstevel@tonic-gate case '.': /* redisplay current window */ 5557c478bd9Sstevel@tonic-gate CHECKEND(); 5567c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line; 5577c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line; 5587c478bd9Sstevel@tonic-gate inwait = 0; 5597c478bd9Sstevel@tonic-gate return (0); 5607c478bd9Sstevel@tonic-gate case 'w': /* set window size */ 5617c478bd9Sstevel@tonic-gate case 'z': 5627c478bd9Sstevel@tonic-gate if (sign == -1) { 5637c478bd9Sstevel@tonic-gate BEEP(); 5647c478bd9Sstevel@tonic-gate break; 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate CHECKEND(); 5677c478bd9Sstevel@tonic-gate if (nlines == 0) 5687c478bd9Sstevel@tonic-gate nlines = (off_t)window; 5697c478bd9Sstevel@tonic-gate else 5707c478bd9Sstevel@tonic-gate if (nlines > 1) 5717c478bd9Sstevel@tonic-gate window = (int)nlines; 5727c478bd9Sstevel@tonic-gate else { 5737c478bd9Sstevel@tonic-gate BEEP(); 5747c478bd9Sstevel@tonic-gate break; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line; 5777c478bd9Sstevel@tonic-gate new_ss.last_line = new_ss.first_line + 5787c478bd9Sstevel@tonic-gate (off_t)window - 1; 5797c478bd9Sstevel@tonic-gate inwait = 0; 5807c478bd9Sstevel@tonic-gate return (0); 5817c478bd9Sstevel@tonic-gate case '\004': /* ^D */ 5827c478bd9Sstevel@tonic-gate case 'd': 5837c478bd9Sstevel@tonic-gate CHECKEND(); 5847c478bd9Sstevel@tonic-gate if (sign == 0) 5857c478bd9Sstevel@tonic-gate sign = 1; 5867c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line + 5877c478bd9Sstevel@tonic-gate (off_t)sign*window/2; 5887c478bd9Sstevel@tonic-gate new_ss.first_line = new_ss.last_line - 5897c478bd9Sstevel@tonic-gate (off_t)window + 1; 5907c478bd9Sstevel@tonic-gate inwait = 0; 5917c478bd9Sstevel@tonic-gate return (0); 5927c478bd9Sstevel@tonic-gate case 's': 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * save input in filename. 5957c478bd9Sstevel@tonic-gate * Check for filename, access, etc. 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate BLANKS(cmdptr); 5987c478bd9Sstevel@tonic-gate if (!*cmdptr) { 5997c478bd9Sstevel@tonic-gate BEEP(); 6007c478bd9Sstevel@tonic-gate break; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if (setjmp(restore) > 0) { 6037c478bd9Sstevel@tonic-gate BEEP(); 6047c478bd9Sstevel@tonic-gate } else { 6057c478bd9Sstevel@tonic-gate char outstr[PROMPTSIZE]; 6067c478bd9Sstevel@tonic-gate if ((sf = fopen(cmdptr, "w")) == NULL) { 6077c478bd9Sstevel@tonic-gate error("cannot open save file"); 6087c478bd9Sstevel@tonic-gate break; 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate kill_line(); 6117c478bd9Sstevel@tonic-gate (void) sprintf(outstr, gettext( 6127c478bd9Sstevel@tonic-gate "saving file %s"), cmdptr); 6137c478bd9Sstevel@tonic-gate sopr(outstr, 1); 6147c478bd9Sstevel@tonic-gate (void) fflush(stdout); 6157c478bd9Sstevel@tonic-gate save_input(sf); 6167c478bd9Sstevel@tonic-gate error("saved"); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate (void) fclose(sf); 6197c478bd9Sstevel@tonic-gate break; 6207c478bd9Sstevel@tonic-gate case 'q': 6217c478bd9Sstevel@tonic-gate case 'Q': 6227c478bd9Sstevel@tonic-gate CHECKEND(); 6237c478bd9Sstevel@tonic-gate inwait = 0; 6247c478bd9Sstevel@tonic-gate end_it(); 6257c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate case 'f': /* skip forward screenfuls */ 6287c478bd9Sstevel@tonic-gate CHECKEND(); 6297c478bd9Sstevel@tonic-gate if (sign == 0) 6307c478bd9Sstevel@tonic-gate sign++; /* skips are always relative */ 6317c478bd9Sstevel@tonic-gate if (nlines == 0) 6327c478bd9Sstevel@tonic-gate nlines++; 6337c478bd9Sstevel@tonic-gate nlines = nlines * (window - 1); 6347c478bd9Sstevel@tonic-gate if (sign == 1) 6357c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line + nlines; 6367c478bd9Sstevel@tonic-gate else 6377c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line - nlines; 6387c478bd9Sstevel@tonic-gate new_ss.last_line = new_ss.first_line + 6397c478bd9Sstevel@tonic-gate (off_t)window - 1; 6407c478bd9Sstevel@tonic-gate inwait = 0; 6417c478bd9Sstevel@tonic-gate return (0); 6427c478bd9Sstevel@tonic-gate case 'l': /* get a line */ 6437c478bd9Sstevel@tonic-gate CHECKEND(); 6447c478bd9Sstevel@tonic-gate if (nlines == 0) { 6457c478bd9Sstevel@tonic-gate nlines++; 6467c478bd9Sstevel@tonic-gate if (sign == 0) 6477c478bd9Sstevel@tonic-gate sign = 1; 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate switch (sign) { 6507c478bd9Sstevel@tonic-gate case 1: 6517c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.last_line + nlines; 6527c478bd9Sstevel@tonic-gate new_ss.first_line = 6537c478bd9Sstevel@tonic-gate new_ss.last_line - (off_t)window + 1; 6547c478bd9Sstevel@tonic-gate break; 6557c478bd9Sstevel@tonic-gate case 0: /* leave addressed line at top */ 6567c478bd9Sstevel@tonic-gate new_ss.first_line = nlines; 6577c478bd9Sstevel@tonic-gate new_ss.last_line = nlines + (off_t)window - 1; 6587c478bd9Sstevel@tonic-gate break; 6597c478bd9Sstevel@tonic-gate case -1: 6607c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.first_line - nlines; 6617c478bd9Sstevel@tonic-gate new_ss.last_line = 6627c478bd9Sstevel@tonic-gate new_ss.first_line + (off_t)window - 1; 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate inwait = 0; 6667c478bd9Sstevel@tonic-gate return (0); 6677c478bd9Sstevel@tonic-gate case '\0': /* \n or blank */ 6687c478bd9Sstevel@tonic-gate if (nlines == 0) { 6697c478bd9Sstevel@tonic-gate nlines++; 6707c478bd9Sstevel@tonic-gate if (sign == 0) 6717c478bd9Sstevel@tonic-gate sign = 1; 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate nlines = (nlines - 1) * (window - 1); 6747c478bd9Sstevel@tonic-gate switch (sign) { 6757c478bd9Sstevel@tonic-gate case 1: 6767c478bd9Sstevel@tonic-gate new_ss.first_line = old_ss.last_line + nlines; 6777c478bd9Sstevel@tonic-gate new_ss.last_line = 6787c478bd9Sstevel@tonic-gate new_ss.first_line + (off_t)window - 1; 6797c478bd9Sstevel@tonic-gate break; 6807c478bd9Sstevel@tonic-gate case 0: 6817c478bd9Sstevel@tonic-gate new_ss.first_line = nlines + 1; 6827c478bd9Sstevel@tonic-gate new_ss.last_line = nlines + (off_t)window; 6837c478bd9Sstevel@tonic-gate /* 6847c478bd9Sstevel@tonic-gate * This if statement is to fix the obscure bug 6857c478bd9Sstevel@tonic-gate * where you have a file that has less lines 6867c478bd9Sstevel@tonic-gate * than a screen holds, and the user types '1', 6877c478bd9Sstevel@tonic-gate * expecting to have the 1st page (re)displayed. 6887c478bd9Sstevel@tonic-gate * If we didn't set the new last_line to 6897c478bd9Sstevel@tonic-gate * eofl_no-1, the screen() routine 6907c478bd9Sstevel@tonic-gate * would cause pg to exit. 6917c478bd9Sstevel@tonic-gate */ 6927c478bd9Sstevel@tonic-gate if (new_ss.first_line == 1 && 6937c478bd9Sstevel@tonic-gate new_ss.last_line >= eofl_no) 6947c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 6957c478bd9Sstevel@tonic-gate break; 6967c478bd9Sstevel@tonic-gate case -1: 6977c478bd9Sstevel@tonic-gate new_ss.last_line = old_ss.first_line - nlines; 6987c478bd9Sstevel@tonic-gate new_ss.first_line = 6997c478bd9Sstevel@tonic-gate new_ss.last_line - (off_t)window + 1; 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate inwait = 0; 7037c478bd9Sstevel@tonic-gate return (0); 7047c478bd9Sstevel@tonic-gate case 'n': /* switch to next file in arglist */ 7057c478bd9Sstevel@tonic-gate CHECKEND(); 7067c478bd9Sstevel@tonic-gate if (sign == 0) 7077c478bd9Sstevel@tonic-gate sign = 1; 7087c478bd9Sstevel@tonic-gate if (nlines == 0) 7097c478bd9Sstevel@tonic-gate nlines++; 7107c478bd9Sstevel@tonic-gate if ((skip = skipf(sign *nlines)) == 0) { 7117c478bd9Sstevel@tonic-gate BEEP(); 7127c478bd9Sstevel@tonic-gate break; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate inwait = 0; 7157c478bd9Sstevel@tonic-gate return (skip); 7167c478bd9Sstevel@tonic-gate case 'p': /* switch to previous file in arglist */ 7177c478bd9Sstevel@tonic-gate CHECKEND(); 7187c478bd9Sstevel@tonic-gate if (sign == 0) 7197c478bd9Sstevel@tonic-gate sign = 1; 7207c478bd9Sstevel@tonic-gate if (nlines == 0) 7217c478bd9Sstevel@tonic-gate nlines++; 7227c478bd9Sstevel@tonic-gate if ((skip = skipf(-sign * nlines)) == 0) { 7237c478bd9Sstevel@tonic-gate BEEP(); 7247c478bd9Sstevel@tonic-gate break; 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate inwait = 0; 7277c478bd9Sstevel@tonic-gate return (skip); 7287c478bd9Sstevel@tonic-gate case '$': /* go to end of file */ 7297c478bd9Sstevel@tonic-gate CHECKEND(); 7307c478bd9Sstevel@tonic-gate sign = 1; 7317c478bd9Sstevel@tonic-gate while (find(1, (off_t)10000) != EOF) 7327c478bd9Sstevel@tonic-gate /* any large number will do */; 7337c478bd9Sstevel@tonic-gate new_ss.last_line = eofl_no - 1; 7347c478bd9Sstevel@tonic-gate new_ss.first_line = eofl_no - (off_t)window; 7357c478bd9Sstevel@tonic-gate inwait = 0; 7367c478bd9Sstevel@tonic-gate return (0); 7377c478bd9Sstevel@tonic-gate case '/': /* search forward for r.e. */ 7387c478bd9Sstevel@tonic-gate case '?': /* " backwards */ 7397c478bd9Sstevel@tonic-gate case '^': /* this ones a ? for regent100s */ 7407c478bd9Sstevel@tonic-gate if (sign < 0) { 7417c478bd9Sstevel@tonic-gate BEEP(); 7427c478bd9Sstevel@tonic-gate break; 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate if (nlines == 0) 7457c478bd9Sstevel@tonic-gate nlines++; 7467c478bd9Sstevel@tonic-gate cmdptr--; 7477c478bd9Sstevel@tonic-gate cmdend = cmdptr + (strlen(cmdptr) - 1); 7487c478bd9Sstevel@tonic-gate wc_e1 = -1; 7497c478bd9Sstevel@tonic-gate wc_e = -1; 7507c478bd9Sstevel@tonic-gate for (p = cmdptr; p <= cmdend; p += len) { 7517c478bd9Sstevel@tonic-gate wc_e1 = wc_e; 7527c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc_e, p, MB_CUR_MAX)) <= 0) { 7537c478bd9Sstevel@tonic-gate wc_e = *p; 7547c478bd9Sstevel@tonic-gate len = 1; 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (cmdend > cmdptr + 1) { 7597c478bd9Sstevel@tonic-gate if ((wc_e1 == *cmdptr) && 7607c478bd9Sstevel@tonic-gate ((wc_e == L't') || 7617c478bd9Sstevel@tonic-gate (wc_e == L'm') || (wc_e == L'b'))) { 7627c478bd9Sstevel@tonic-gate leave_search = wc_e; 7637c478bd9Sstevel@tonic-gate wc_e = wc_e1; 7647c478bd9Sstevel@tonic-gate cmdend--; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate if ((cmdptr < cmdend) && (wc_e == *cmdptr)) 7687c478bd9Sstevel@tonic-gate *cmdend = '\0'; 7697c478bd9Sstevel@tonic-gate if (*cmdptr != '/') /* signify back search by - */ 7707c478bd9Sstevel@tonic-gate nlines = -nlines; 7717c478bd9Sstevel@tonic-gate if (!search(++cmdptr, (off_t)nlines)) 7727c478bd9Sstevel@tonic-gate break; 7737c478bd9Sstevel@tonic-gate else { 7747c478bd9Sstevel@tonic-gate inwait = 0; 7757c478bd9Sstevel@tonic-gate return (0); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate case '!': /* shell escape */ 7787c478bd9Sstevel@tonic-gate if (rmode) { /* restricted mode */ 7797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7807c478bd9Sstevel@tonic-gate "!command not allowed in restricted mode.\n")); 7817c478bd9Sstevel@tonic-gate break; 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate if (!hard_copy) { /* redisplay the command */ 7847c478bd9Sstevel@tonic-gate (void) fputs(cmdbuf, stdout); 7857c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate if ((id = fork()) < 0) { 7887c478bd9Sstevel@tonic-gate error("cannot fork, try again later"); 7897c478bd9Sstevel@tonic-gate break; 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate if (id == (pid_t)0) { 7927c478bd9Sstevel@tonic-gate /* 7937c478bd9Sstevel@tonic-gate * if stdin is a pipe, need to close it so 7947c478bd9Sstevel@tonic-gate * that the terminal is really stdin for 7957c478bd9Sstevel@tonic-gate * the command 7967c478bd9Sstevel@tonic-gate */ 7977c478bd9Sstevel@tonic-gate (void) fclose(stdin); 7987c478bd9Sstevel@tonic-gate (void) fclose(pg_stdin); 7997c478bd9Sstevel@tonic-gate (void) dup(fileno(stdout)); 8007c478bd9Sstevel@tonic-gate (void) execl(shell, shell, "-c", cmdptr, 0); 8017c478bd9Sstevel@tonic-gate (void) perror("exec"); 8027c478bd9Sstevel@tonic-gate exit(1); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 8057c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 8067c478bd9Sstevel@tonic-gate if (catch_susp) 8077c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 8087c478bd9Sstevel@tonic-gate while (wait((int *)0) != id); 8097c478bd9Sstevel@tonic-gate { 8107c478bd9Sstevel@tonic-gate if (errno == ECHILD) 8117c478bd9Sstevel@tonic-gate break; 8127c478bd9Sstevel@tonic-gate else 8137c478bd9Sstevel@tonic-gate errno = 0; 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate (void) fputs("!\n", stdout); 8167c478bd9Sstevel@tonic-gate (void) fflush(stdout); 8177c478bd9Sstevel@tonic-gate (void) signal(SIGINT, on_brk); 8187c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, on_brk); 8197c478bd9Sstevel@tonic-gate if (catch_susp) 8207c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, onsusp); 8217c478bd9Sstevel@tonic-gate break; 8227c478bd9Sstevel@tonic-gate default: 8237c478bd9Sstevel@tonic-gate BEEP(); 8247c478bd9Sstevel@tonic-gate break; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate static int 8307c478bd9Sstevel@tonic-gate number() 8317c478bd9Sstevel@tonic-gate { 8327c478bd9Sstevel@tonic-gate int i; 8337c478bd9Sstevel@tonic-gate char *p; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate i = 0; 8367c478bd9Sstevel@tonic-gate sign = 0; 8377c478bd9Sstevel@tonic-gate p = cmdptr; 8387c478bd9Sstevel@tonic-gate BLANKS(p); 8397c478bd9Sstevel@tonic-gate if (*p == '+') { 8407c478bd9Sstevel@tonic-gate p++; 8417c478bd9Sstevel@tonic-gate sign = 1; 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate else 8447c478bd9Sstevel@tonic-gate if (*p == '-') { 8457c478bd9Sstevel@tonic-gate p++; 8467c478bd9Sstevel@tonic-gate sign = -1; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate while (isdigit(*p)) 8497c478bd9Sstevel@tonic-gate i = i * 10 + *p++ - '0'; 8507c478bd9Sstevel@tonic-gate cmdptr = p; 8517c478bd9Sstevel@tonic-gate return (i); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate static int 8557c478bd9Sstevel@tonic-gate ttyin() 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate char *sptr, *p; 8587c478bd9Sstevel@tonic-gate wchar_t ch; 8597c478bd9Sstevel@tonic-gate int slash = 0; 8607c478bd9Sstevel@tonic-gate int state = 0; 8617c478bd9Sstevel@tonic-gate int width, length; 8627c478bd9Sstevel@tonic-gate char multic[MB_LEN_MAX]; 8637c478bd9Sstevel@tonic-gate static int readch(); 8647c478bd9Sstevel@tonic-gate int len; 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate (void) fixterm(); 8677c478bd9Sstevel@tonic-gate /* initialize state processing */ 8687c478bd9Sstevel@tonic-gate (void) set_state(&state, ' ', (char *)0); 8697c478bd9Sstevel@tonic-gate sptr = cmdbuf; 8707c478bd9Sstevel@tonic-gate while (state != 10) { 8717c478bd9Sstevel@tonic-gate if ((ch = readch()) < 0 || !iswascii(ch) && !iswprint(ch)) { 8727c478bd9Sstevel@tonic-gate BEEP(); 8737c478bd9Sstevel@tonic-gate continue; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if ((length = wctomb(multic, ch)) < 0) 8777c478bd9Sstevel@tonic-gate length = 0; 8787c478bd9Sstevel@tonic-gate multic[length] = 0; 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate if (ch == '\n' && !slash) 8817c478bd9Sstevel@tonic-gate break; 8827c478bd9Sstevel@tonic-gate if (ch == erasechar() && !slash) { 8837c478bd9Sstevel@tonic-gate if (sptr > cmdbuf) { 8847c478bd9Sstevel@tonic-gate char *oldp = cmdbuf; 8857c478bd9Sstevel@tonic-gate wchar_t wchar; 8867c478bd9Sstevel@tonic-gate p = cmdbuf; 8877c478bd9Sstevel@tonic-gate while (p < sptr) { 8887c478bd9Sstevel@tonic-gate oldp = p; 8897c478bd9Sstevel@tonic-gate len = mbtowc(&wchar, p, MB_CUR_MAX); 8907c478bd9Sstevel@tonic-gate if (len <= 0) { 8917c478bd9Sstevel@tonic-gate wchar = (unsigned char)*p; 8927c478bd9Sstevel@tonic-gate len = 1; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate p += len; 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate if ((width = wcwidth(wchar)) <= 0) 8977c478bd9Sstevel@tonic-gate /* ascii control character */ 8987c478bd9Sstevel@tonic-gate width = 2; 8997c478bd9Sstevel@tonic-gate promptlen -= width; 9007c478bd9Sstevel@tonic-gate while (width--) 9017c478bd9Sstevel@tonic-gate (void) fputs("\b \b", stdout); 9027c478bd9Sstevel@tonic-gate sptr = oldp; 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate (void) set_state(&state, ch, sptr); 9057c478bd9Sstevel@tonic-gate (void) fflush(stdout); 9067c478bd9Sstevel@tonic-gate continue; 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate else 9097c478bd9Sstevel@tonic-gate if (ch == killchar() && !slash) { 9107c478bd9Sstevel@tonic-gate if (hard_copy) 9117c478bd9Sstevel@tonic-gate (void) putwchar(ch); 9127c478bd9Sstevel@tonic-gate (void) resetterm(); 9137c478bd9Sstevel@tonic-gate return (1); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate if (ch < ' ') 9167c478bd9Sstevel@tonic-gate width = 2; 9177c478bd9Sstevel@tonic-gate else 9187c478bd9Sstevel@tonic-gate if ((width = wcwidth(ch)) <= 0) 9197c478bd9Sstevel@tonic-gate width = 0; 9207c478bd9Sstevel@tonic-gate if (slash) { 9217c478bd9Sstevel@tonic-gate slash = 0; 9227c478bd9Sstevel@tonic-gate (void) fputs("\b \b", stdout); 9237c478bd9Sstevel@tonic-gate sptr--; 9247c478bd9Sstevel@tonic-gate promptlen--; 9257c478bd9Sstevel@tonic-gate } else /* is there room to keep this character? */ 9267c478bd9Sstevel@tonic-gate if (sptr >= cmdbuf + sizeof (cmdbuf) || 9277c478bd9Sstevel@tonic-gate promptlen + width >= columns) { 9287c478bd9Sstevel@tonic-gate BEEP(); 9297c478bd9Sstevel@tonic-gate continue; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate else 9327c478bd9Sstevel@tonic-gate if (ch == '\\') 9337c478bd9Sstevel@tonic-gate slash++; 9347c478bd9Sstevel@tonic-gate if (set_state(&state, ch, sptr) == 0) { 9357c478bd9Sstevel@tonic-gate BEEP(); 9367c478bd9Sstevel@tonic-gate continue; 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate (void) strncpy(sptr, multic, (size_t)length); 9397c478bd9Sstevel@tonic-gate sptr += length; 9407c478bd9Sstevel@tonic-gate if (ch < ' ') { 9417c478bd9Sstevel@tonic-gate ch += 0100; 9427c478bd9Sstevel@tonic-gate multic[0] = '^'; 9437c478bd9Sstevel@tonic-gate multic[1] = ch; 9447c478bd9Sstevel@tonic-gate length = 2; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate p = multic; 9477c478bd9Sstevel@tonic-gate while (length--) 9487c478bd9Sstevel@tonic-gate (void) putchar(*p++); 9497c478bd9Sstevel@tonic-gate promptlen += width; 9507c478bd9Sstevel@tonic-gate (void) fflush(stdout); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate *sptr = '\0'; 9547c478bd9Sstevel@tonic-gate kill_line(); 9557c478bd9Sstevel@tonic-gate (void) fflush(stdout); 9567c478bd9Sstevel@tonic-gate (void) resetterm(); 9577c478bd9Sstevel@tonic-gate return (0); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate static int 9617c478bd9Sstevel@tonic-gate set_state(pstate, c, pc) 9627c478bd9Sstevel@tonic-gate int *pstate; 9637c478bd9Sstevel@tonic-gate wchar_t c; 9647c478bd9Sstevel@tonic-gate char *pc; 9657c478bd9Sstevel@tonic-gate { 9667c478bd9Sstevel@tonic-gate static char *psign; 9677c478bd9Sstevel@tonic-gate static char *pnumber; 9687c478bd9Sstevel@tonic-gate static char *pcommand; 9697c478bd9Sstevel@tonic-gate static int slash; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate if (*pstate == 0) { 9727c478bd9Sstevel@tonic-gate psign = (char *)NULL; 9737c478bd9Sstevel@tonic-gate pnumber = (char *)NULL; 9747c478bd9Sstevel@tonic-gate pcommand = (char *)NULL; 9757c478bd9Sstevel@tonic-gate *pstate = 1; 9767c478bd9Sstevel@tonic-gate slash = 0; 9777c478bd9Sstevel@tonic-gate return (1); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate if (c == '\\' && !slash) { 9807c478bd9Sstevel@tonic-gate slash++; 9817c478bd9Sstevel@tonic-gate return (1); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate if (c == erasechar() && !slash) 9847c478bd9Sstevel@tonic-gate switch (*pstate) { 9857c478bd9Sstevel@tonic-gate case 4: 9867c478bd9Sstevel@tonic-gate if (pc > pcommand) 9877c478bd9Sstevel@tonic-gate return (1); 9887c478bd9Sstevel@tonic-gate pcommand = (char *)NULL; 9897c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate case 3: 9927c478bd9Sstevel@tonic-gate if (pnumber && pc > pnumber) { 9937c478bd9Sstevel@tonic-gate *pstate = 3; 9947c478bd9Sstevel@tonic-gate return (1); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate pnumber = (char *)NULL; 9977c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate case 2: 10007c478bd9Sstevel@tonic-gate if (psign && pc > psign) { 10017c478bd9Sstevel@tonic-gate *pstate = 2; 10027c478bd9Sstevel@tonic-gate return (1); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate psign = (char *)NULL; 10057c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate case 1: 10087c478bd9Sstevel@tonic-gate *pstate = 1; 10097c478bd9Sstevel@tonic-gate return (1); 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate slash = 0; 10137c478bd9Sstevel@tonic-gate switch (*pstate) { 10147c478bd9Sstevel@tonic-gate case 1: /* before recieving anything interesting */ 10157c478bd9Sstevel@tonic-gate if (c == '\t' || (!nflag && c == ' ')) 10167c478bd9Sstevel@tonic-gate return (1); 10177c478bd9Sstevel@tonic-gate if (c == '+' || c == '-') { 10187c478bd9Sstevel@tonic-gate psign = pc; 10197c478bd9Sstevel@tonic-gate *pstate = 2; 10207c478bd9Sstevel@tonic-gate return (1); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate case 2: /* recieved sign, waiting for digit */ 10257c478bd9Sstevel@tonic-gate if (iswascii(c) && isdigit(c)) { 10267c478bd9Sstevel@tonic-gate pnumber = pc; 10277c478bd9Sstevel@tonic-gate *pstate = 3; 10287c478bd9Sstevel@tonic-gate return (1); 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate case 3: /* recieved digit, waiting for the rest of the number */ 10337c478bd9Sstevel@tonic-gate if (iswascii(c) && isdigit(c)) 10347c478bd9Sstevel@tonic-gate return (1); 10357c478bd9Sstevel@tonic-gate if (iswascii(c) && pg_strchr("h\014.wz\004dqQfl np$", c)) { 10367c478bd9Sstevel@tonic-gate pcommand = pc; 10377c478bd9Sstevel@tonic-gate if (nflag) 10387c478bd9Sstevel@tonic-gate *pstate = 10; 10397c478bd9Sstevel@tonic-gate else 10407c478bd9Sstevel@tonic-gate *pstate = 4; 10417c478bd9Sstevel@tonic-gate return (1); 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate if (iswascii(c) && pg_strchr("s/^?!", c)) { 10447c478bd9Sstevel@tonic-gate pcommand = pc; 10457c478bd9Sstevel@tonic-gate *pstate = 4; 10467c478bd9Sstevel@tonic-gate return (1); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate return (0); 10497c478bd9Sstevel@tonic-gate case 4: 10507c478bd9Sstevel@tonic-gate return (1); 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate return (0); 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate static int 10567c478bd9Sstevel@tonic-gate readch() 10577c478bd9Sstevel@tonic-gate { 10587c478bd9Sstevel@tonic-gate return (fgetwc(pg_stdin)); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate static void 10627c478bd9Sstevel@tonic-gate help() 10637c478bd9Sstevel@tonic-gate { 10647c478bd9Sstevel@tonic-gate if (clropt) 10657c478bd9Sstevel@tonic-gate doclear(); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate (void) fputs(gettext( 10687c478bd9Sstevel@tonic-gate "-------------------------------------------------------\n" 10697c478bd9Sstevel@tonic-gate " h help\n" 10707c478bd9Sstevel@tonic-gate " q or Q quit\n" 10717c478bd9Sstevel@tonic-gate " <blank> or <newline> next page\n" 10727c478bd9Sstevel@tonic-gate " l next line\n" 10737c478bd9Sstevel@tonic-gate " d or <^D> display half a page more\n" 10747c478bd9Sstevel@tonic-gate " . or <^L> redisplay current page\n" 10757c478bd9Sstevel@tonic-gate " f skip the next page forward\n" 10767c478bd9Sstevel@tonic-gate " n next file\n" 10777c478bd9Sstevel@tonic-gate " p previous file\n" 10787c478bd9Sstevel@tonic-gate " $ last page\n" 10797c478bd9Sstevel@tonic-gate " w or z set window size and display next page\n" 10807c478bd9Sstevel@tonic-gate " s savefile save current file in savefile\n" 10817c478bd9Sstevel@tonic-gate " /pattern/ search forward for pattern\n" 10827c478bd9Sstevel@tonic-gate " ?pattern? or\n" 10837c478bd9Sstevel@tonic-gate " ^pattern^ search backward for pattern\n" 10847c478bd9Sstevel@tonic-gate " !command execute command\n" 10857c478bd9Sstevel@tonic-gate "\n" 10867c478bd9Sstevel@tonic-gate "Most commands can be preceeded by a number, as in:\n" 10877c478bd9Sstevel@tonic-gate "+1<newline> (next page); -1<newline> (previous page); 1<newline> (page 1).\n" 10887c478bd9Sstevel@tonic-gate "\n" 10897c478bd9Sstevel@tonic-gate "See the manual page for more detail.\n" 10907c478bd9Sstevel@tonic-gate "-------------------------------------------------------\n"), 10917c478bd9Sstevel@tonic-gate stdout); 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate /* 10957c478bd9Sstevel@tonic-gate * Skip nskip files in the file list (from the command line). Nskip may be 10967c478bd9Sstevel@tonic-gate * negative. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate static int 11007c478bd9Sstevel@tonic-gate skipf(nskip) 11017c478bd9Sstevel@tonic-gate int nskip; 11027c478bd9Sstevel@tonic-gate { 11037c478bd9Sstevel@tonic-gate if (fnum + nskip < 0) { 11047c478bd9Sstevel@tonic-gate nskip = -fnum; 11057c478bd9Sstevel@tonic-gate if (nskip == 0) 11067c478bd9Sstevel@tonic-gate error("No previous file"); 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate else 11097c478bd9Sstevel@tonic-gate if (fnum + nskip > nfiles - 1) { 11107c478bd9Sstevel@tonic-gate nskip = (nfiles - 1) - fnum; 11117c478bd9Sstevel@tonic-gate if (nskip == 0) 11127c478bd9Sstevel@tonic-gate error("No next file"); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate return (nskip); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate /* 11187c478bd9Sstevel@tonic-gate * Check whether the file named by fs is a file which the user may 11197c478bd9Sstevel@tonic-gate * access. If it is, return the opened file. Otherwise return NULL. 11207c478bd9Sstevel@tonic-gate */ 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate static FILE * 11237c478bd9Sstevel@tonic-gate checkf(fs) 11247c478bd9Sstevel@tonic-gate char *fs; 11257c478bd9Sstevel@tonic-gate { 11267c478bd9Sstevel@tonic-gate struct stat stbuf; 11277c478bd9Sstevel@tonic-gate FILE *f; 11287c478bd9Sstevel@tonic-gate int fd; 11297c478bd9Sstevel@tonic-gate int f_was_opened; 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate pipe_in = 0; 11327c478bd9Sstevel@tonic-gate if (strcmp(fs, "-") == 0) { 11337c478bd9Sstevel@tonic-gate if (tmp_fin == NULL) 11347c478bd9Sstevel@tonic-gate f = stdin; 11357c478bd9Sstevel@tonic-gate else { 11367c478bd9Sstevel@tonic-gate rewind(tmp_fin); 11377c478bd9Sstevel@tonic-gate f = tmp_fin; 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate f_was_opened = 0; 11407c478bd9Sstevel@tonic-gate } else { 11417c478bd9Sstevel@tonic-gate if ((f = fopen(fs, "r")) == (FILE *)NULL) { 11427c478bd9Sstevel@tonic-gate (void) fflush(stdout); 11437c478bd9Sstevel@tonic-gate perror(fs); 11447c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate f_was_opened = 1; 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate if (fstat(fileno(f), &stbuf) == -1) { 11497c478bd9Sstevel@tonic-gate if (f_was_opened) 11507c478bd9Sstevel@tonic-gate (void) fclose(f); 11517c478bd9Sstevel@tonic-gate (void) fflush(stdout); 11527c478bd9Sstevel@tonic-gate perror(fs); 11537c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 11567c478bd9Sstevel@tonic-gate if (f_was_opened) 11577c478bd9Sstevel@tonic-gate (void) fclose(f); 11587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pg: "); 11597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s is a directory\n"), fs); 11607c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate if ((stbuf.st_mode & S_IFMT) == S_IFREG) { 11637c478bd9Sstevel@tonic-gate if (f == stdin) /* It may have been read from */ 11647c478bd9Sstevel@tonic-gate rewind(f); /* already, and not reopened */ 11657c478bd9Sstevel@tonic-gate } else { 11667c478bd9Sstevel@tonic-gate if (f != stdin) { 11677c478bd9Sstevel@tonic-gate if (f_was_opened) 11687c478bd9Sstevel@tonic-gate (void) fclose(f); 11697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pg: "); 11707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 11717c478bd9Sstevel@tonic-gate "special files only handled as standard input\n")); 11727c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11737c478bd9Sstevel@tonic-gate } else { 11747c478bd9Sstevel@tonic-gate if ((fd = mkstemp(tmp_name)) < 0) { 11757c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 11767c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate (void) close(fd); 11797c478bd9Sstevel@tonic-gate if ((tmp_fou = fopen(tmp_name, "w")) == NULL) { 11807c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 11817c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate if ((tmp_fin = fopen(tmp_name, "r")) == NULL) { 11847c478bd9Sstevel@tonic-gate (void) perror(tmp_name); 11857c478bd9Sstevel@tonic-gate return ((FILE *)NULL); 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate pipe_in = 1; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate lineset(BOF); 11917c478bd9Sstevel@tonic-gate return (f); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate static void 11957c478bd9Sstevel@tonic-gate copy_file(f, out) 11967c478bd9Sstevel@tonic-gate FILE *f, *out; 11977c478bd9Sstevel@tonic-gate { 11987c478bd9Sstevel@tonic-gate int c; 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate while ((c = getc(f)) != EOF) 12017c478bd9Sstevel@tonic-gate (void) putc(c, out); 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate static void 12067c478bd9Sstevel@tonic-gate re_error(i) 12077c478bd9Sstevel@tonic-gate int i; 12087c478bd9Sstevel@tonic-gate { 12097c478bd9Sstevel@tonic-gate int j; 12107c478bd9Sstevel@tonic-gate static struct messages { 12117c478bd9Sstevel@tonic-gate char *message; 12127c478bd9Sstevel@tonic-gate int number; 12137c478bd9Sstevel@tonic-gate } re_errmsg[] = { 12147c478bd9Sstevel@tonic-gate "Pattern not found", 1, 12157c478bd9Sstevel@tonic-gate "Range endpoint too large", 11, 12167c478bd9Sstevel@tonic-gate "Bad number", 16, 12177c478bd9Sstevel@tonic-gate "`\\digit' out of range", 25, 12187c478bd9Sstevel@tonic-gate "No remembered search string", 41, 12197c478bd9Sstevel@tonic-gate "\\( \\) imbalance", 42, 12207c478bd9Sstevel@tonic-gate "Too many \\(", 43, 12217c478bd9Sstevel@tonic-gate "More than two numbers given in \\{ \\}", 44, 12227c478bd9Sstevel@tonic-gate "} expected after \\", 45, 12237c478bd9Sstevel@tonic-gate "First number exceeds second in \\{ \\}", 46, 12247c478bd9Sstevel@tonic-gate "[] imbalance", 49, 12257c478bd9Sstevel@tonic-gate "Regular expression overflow", 50, 12267c478bd9Sstevel@tonic-gate "Illegal byte sequence", 67, 12277c478bd9Sstevel@tonic-gate "Bad regular expression", 0 12287c478bd9Sstevel@tonic-gate }; 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate for (j = 0; re_errmsg[j].number != 0; j++) 12317c478bd9Sstevel@tonic-gate if (re_errmsg[j].number == i) 12327c478bd9Sstevel@tonic-gate break; 12337c478bd9Sstevel@tonic-gate error(re_errmsg[j].message); 12347c478bd9Sstevel@tonic-gate longjmp(restore, 1); /* restore to search() */ 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate /* 12387c478bd9Sstevel@tonic-gate * Search for nth ocurrence of regular expression contained in buf in the file 12397c478bd9Sstevel@tonic-gate * negative n implies backward search 12407c478bd9Sstevel@tonic-gate * n 'guaranteed' non-zero 12417c478bd9Sstevel@tonic-gate */ 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate static int 12457c478bd9Sstevel@tonic-gate search(buf, n) 12467c478bd9Sstevel@tonic-gate char buf[]; 12477c478bd9Sstevel@tonic-gate off_t n; 12487c478bd9Sstevel@tonic-gate { 12497c478bd9Sstevel@tonic-gate int direction; 12507c478bd9Sstevel@tonic-gate static char *expbuf; 12517c478bd9Sstevel@tonic-gate char *nexpbuf; 12527c478bd9Sstevel@tonic-gate int END_COND; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if (setjmp(restore) <= 0) { 12557c478bd9Sstevel@tonic-gate nexpbuf = compile(buf, (char *)0, (char *)0); 12567c478bd9Sstevel@tonic-gate if (regerrno) { 12577c478bd9Sstevel@tonic-gate if (regerrno != 41 || expbuf == NULL) 12587c478bd9Sstevel@tonic-gate re_error(regerrno); 12597c478bd9Sstevel@tonic-gate } else { 12607c478bd9Sstevel@tonic-gate if (expbuf) 12617c478bd9Sstevel@tonic-gate free(expbuf); 12627c478bd9Sstevel@tonic-gate expbuf = nexpbuf; 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate if (n < 0) { /* search back */ 12667c478bd9Sstevel@tonic-gate direction = -1; 12677c478bd9Sstevel@tonic-gate (void) find(0, old_ss.first_line); 12687c478bd9Sstevel@tonic-gate END_COND = BOF; 12697c478bd9Sstevel@tonic-gate } else { 12707c478bd9Sstevel@tonic-gate direction = 1; 12717c478bd9Sstevel@tonic-gate (void) find(0, old_ss.last_line); 12727c478bd9Sstevel@tonic-gate END_COND = EOF; 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate while (find(1, direction) != END_COND) { 12767c478bd9Sstevel@tonic-gate if (brk_hit) 12777c478bd9Sstevel@tonic-gate break; 12787c478bd9Sstevel@tonic-gate if (step(Line, expbuf)) 12797c478bd9Sstevel@tonic-gate if ((n -= direction) == 0) { 12807c478bd9Sstevel@tonic-gate switch (leave_search) { 12817c478bd9Sstevel@tonic-gate case 't': 12827c478bd9Sstevel@tonic-gate new_ss.first_line = 12837c478bd9Sstevel@tonic-gate find(1, (off_t)0); 12847c478bd9Sstevel@tonic-gate new_ss.last_line = 12857c478bd9Sstevel@tonic-gate new_ss.first_line + 12867c478bd9Sstevel@tonic-gate (off_t)window 12877c478bd9Sstevel@tonic-gate - 1; 12887c478bd9Sstevel@tonic-gate break; 12897c478bd9Sstevel@tonic-gate case 'b': 12907c478bd9Sstevel@tonic-gate new_ss.last_line = 12917c478bd9Sstevel@tonic-gate find(1, (off_t)0); 12927c478bd9Sstevel@tonic-gate new_ss.first_line = 12937c478bd9Sstevel@tonic-gate new_ss.last_line - 12947c478bd9Sstevel@tonic-gate (off_t)window 12957c478bd9Sstevel@tonic-gate + 1; 12967c478bd9Sstevel@tonic-gate break; 12977c478bd9Sstevel@tonic-gate case 'm': 12987c478bd9Sstevel@tonic-gate new_ss.first_line = 12997c478bd9Sstevel@tonic-gate find(1, (off_t)0) - 13007c478bd9Sstevel@tonic-gate ((off_t)window - 1)/2; 13017c478bd9Sstevel@tonic-gate new_ss.last_line = 13027c478bd9Sstevel@tonic-gate new_ss.first_line + 13037c478bd9Sstevel@tonic-gate (off_t)window 13047c478bd9Sstevel@tonic-gate - 1; 13057c478bd9Sstevel@tonic-gate break; 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate return (1); 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate re_error(1); /* Pattern not found */ 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate BEEP(); 13137c478bd9Sstevel@tonic-gate return (0); 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate /* 13177c478bd9Sstevel@tonic-gate * find -- find line in file f, subject to certain constraints. 13187c478bd9Sstevel@tonic-gate * 13197c478bd9Sstevel@tonic-gate * This is the reason for all the funny stuff with sign and nlines. 13207c478bd9Sstevel@tonic-gate * We need to be able to differentiate between relative and abosolute 13217c478bd9Sstevel@tonic-gate * address specifications. 13227c478bd9Sstevel@tonic-gate * 13237c478bd9Sstevel@tonic-gate * So...there are basically three cases that this routine 13247c478bd9Sstevel@tonic-gate * handles. Either line is zero, which means there is to be 13257c478bd9Sstevel@tonic-gate * no motion (because line numbers start at one), or 13267c478bd9Sstevel@tonic-gate * how and line specify a number, or line itself is negative, 13277c478bd9Sstevel@tonic-gate * which is the same as having how == -1 and line == abs(line). 13287c478bd9Sstevel@tonic-gate * 13297c478bd9Sstevel@tonic-gate * Then, figure where exactly it is that we are going (an absolute 13307c478bd9Sstevel@tonic-gate * line number). Find out if it is within what we have read, 13317c478bd9Sstevel@tonic-gate * if so, go there without further ado. Otherwise, do some 13327c478bd9Sstevel@tonic-gate * magic to get there, saving all the intervening lines, 13337c478bd9Sstevel@tonic-gate * in case the user wants to see them some time later. 13347c478bd9Sstevel@tonic-gate * 13357c478bd9Sstevel@tonic-gate * In any case, return the line number that we end up at. 13367c478bd9Sstevel@tonic-gate * (This is used by search() and screen()). If we go past EOF, 13377c478bd9Sstevel@tonic-gate * return EOF. 13387c478bd9Sstevel@tonic-gate * This EOF will go away eventually, as pg is expanded to 13397c478bd9Sstevel@tonic-gate * handle multiple files as one huge one. Then EOF will 13407c478bd9Sstevel@tonic-gate * mean we have run off the file list. 13417c478bd9Sstevel@tonic-gate * If the requested line number is too far back, return BOF. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate static off_t 13457c478bd9Sstevel@tonic-gate find(how, line) /* find the line and seek there */ 13467c478bd9Sstevel@tonic-gate int how; 13477c478bd9Sstevel@tonic-gate off_t line; 13487c478bd9Sstevel@tonic-gate { 13497c478bd9Sstevel@tonic-gate /* no compacted memory yet */ 13507c478bd9Sstevel@tonic-gate FILE *f = in_file; 13517c478bd9Sstevel@tonic-gate off_t where; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (how == 0) 13547c478bd9Sstevel@tonic-gate where = line; 13557c478bd9Sstevel@tonic-gate else 13567c478bd9Sstevel@tonic-gate if (dot == zero - 1) 13577c478bd9Sstevel@tonic-gate where = how * line; 13587c478bd9Sstevel@tonic-gate else 13597c478bd9Sstevel@tonic-gate where = how * line + dot->l_no; 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate /* now, where is either at, before, or after dol */ 13627c478bd9Sstevel@tonic-gate /* most likely case is after, so do it first */ 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate eoflag = 0; 13657c478bd9Sstevel@tonic-gate if (where >= dol->l_no) { 13667c478bd9Sstevel@tonic-gate if (doliseof) { 13677c478bd9Sstevel@tonic-gate dot = dol; 13687c478bd9Sstevel@tonic-gate eoflag++; 13697c478bd9Sstevel@tonic-gate return (EOF); 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate if (pipe_in) 13727c478bd9Sstevel@tonic-gate in_file = f = stdin; 13737c478bd9Sstevel@tonic-gate else 13747c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)dol->l_addr, SEEK_SET); 13757c478bd9Sstevel@tonic-gate dot = dol - 1; 13767c478bd9Sstevel@tonic-gate while ((nchars = getline(f)) != EOF) { 13777c478bd9Sstevel@tonic-gate dot++; 13787c478bd9Sstevel@tonic-gate newdol(f); 13797c478bd9Sstevel@tonic-gate if (where == dot->l_no || brk_hit) 13807c478bd9Sstevel@tonic-gate break; 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate if (nchars != EOF) 13837c478bd9Sstevel@tonic-gate return (dot->l_no); 13847c478bd9Sstevel@tonic-gate else { /* EOF */ 13857c478bd9Sstevel@tonic-gate dot = dol; 13867c478bd9Sstevel@tonic-gate eoflag++; 13877c478bd9Sstevel@tonic-gate doliseof++; 13887c478bd9Sstevel@tonic-gate eofl_no = dol->l_no; 13897c478bd9Sstevel@tonic-gate return (EOF); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate } else { /* where < dol->l_no */ 13927c478bd9Sstevel@tonic-gate if (pipe_in) { 13937c478bd9Sstevel@tonic-gate (void) fflush(tmp_fou); 13947c478bd9Sstevel@tonic-gate in_file = f = tmp_fin; 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate if (where < zero->l_no) { 13977c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)zero->l_addr, SEEK_SET); 13987c478bd9Sstevel@tonic-gate dot = zero - 1; 13997c478bd9Sstevel@tonic-gate return (BOF); 14007c478bd9Sstevel@tonic-gate } else { 14017c478bd9Sstevel@tonic-gate dot = zero + where - 1; 14027c478bd9Sstevel@tonic-gate (void) fseeko(f, (off_t)dot->l_addr, SEEK_SET); 14037c478bd9Sstevel@tonic-gate nchars = getline(f); 14047c478bd9Sstevel@tonic-gate return (dot->l_no); 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate static FILE *fileptr; 14107c478bd9Sstevel@tonic-gate static int (*rdchar)(); 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate static int 14137c478bd9Sstevel@tonic-gate mrdchar() 14147c478bd9Sstevel@tonic-gate { 14157c478bd9Sstevel@tonic-gate return (rdchar(fileptr)); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate /* 14197c478bd9Sstevel@tonic-gate * Get a logical line 14207c478bd9Sstevel@tonic-gate */ 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate static off_t 14237c478bd9Sstevel@tonic-gate getline(f) 14247c478bd9Sstevel@tonic-gate FILE *f; 14257c478bd9Sstevel@tonic-gate { 14267c478bd9Sstevel@tonic-gate char *p; 14277c478bd9Sstevel@tonic-gate int column; 14287c478bd9Sstevel@tonic-gate static char multic[MB_LEN_MAX]; 14297c478bd9Sstevel@tonic-gate static int savlength; 14307c478bd9Sstevel@tonic-gate wchar_t c; 14317c478bd9Sstevel@tonic-gate int length, width; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate if (pipe_in && f == stdin) 14347c478bd9Sstevel@tonic-gate rdchar = fgetputc; 14357c478bd9Sstevel@tonic-gate else 14367c478bd9Sstevel@tonic-gate rdchar = (int (*)())fgetwc; 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate fileptr = f; 14397c478bd9Sstevel@tonic-gate /* copy overlap from previous call to getline */ 14407c478bd9Sstevel@tonic-gate if (savlength) 14417c478bd9Sstevel@tonic-gate (void) strncpy(Line, multic, (size_t)savlength); 14427c478bd9Sstevel@tonic-gate for (column = 0, p = Line + savlength; ; ) { 14437c478bd9Sstevel@tonic-gate if ((c = mrdchar()) <= 0) { 14447c478bd9Sstevel@tonic-gate clearerr(f); 14457c478bd9Sstevel@tonic-gate if (p > Line) { /* last line doesn't have '\n', */ 14467c478bd9Sstevel@tonic-gate *p++ = '\n'; 14477c478bd9Sstevel@tonic-gate *p = '\0'; /* print it any way */ 14487c478bd9Sstevel@tonic-gate return (column); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate return (EOF); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate length = wctomb(multic, c); 14537c478bd9Sstevel@tonic-gate if (length < 0) { 14547c478bd9Sstevel@tonic-gate length = -length; 14557c478bd9Sstevel@tonic-gate c = 0; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate if ((width = wcwidth(c)) < 0) 14587c478bd9Sstevel@tonic-gate width = 0; 14597c478bd9Sstevel@tonic-gate if (column + width > columns && !fflag) 14607c478bd9Sstevel@tonic-gate break; 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate if (p + length > &Line[LINSIZ - 2] && c != '\n') 14637c478bd9Sstevel@tonic-gate break; 14647c478bd9Sstevel@tonic-gate (void) strncpy(p, multic, (size_t)length); 14657c478bd9Sstevel@tonic-gate p += length; 14667c478bd9Sstevel@tonic-gate column += width; 14677c478bd9Sstevel@tonic-gate /* don't have any overlap here */ 14687c478bd9Sstevel@tonic-gate length = 0; 14697c478bd9Sstevel@tonic-gate switch (c) { 14707c478bd9Sstevel@tonic-gate case '\t': /* just a guess */ 14717c478bd9Sstevel@tonic-gate column = 1 + (column | 7); 14727c478bd9Sstevel@tonic-gate break; 14737c478bd9Sstevel@tonic-gate case '\b': 14747c478bd9Sstevel@tonic-gate if (column > 0) 14757c478bd9Sstevel@tonic-gate column--; 14767c478bd9Sstevel@tonic-gate break; 14777c478bd9Sstevel@tonic-gate case '\r': 14787c478bd9Sstevel@tonic-gate column = 0; 14797c478bd9Sstevel@tonic-gate break; 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate if (c == '\n') 14827c478bd9Sstevel@tonic-gate break; 14837c478bd9Sstevel@tonic-gate if (column >= columns && !fflag) 14847c478bd9Sstevel@tonic-gate break; 14857c478bd9Sstevel@tonic-gate } 14867c478bd9Sstevel@tonic-gate if (c != '\n') { /* We're stopping in the middle of the line */ 14877c478bd9Sstevel@tonic-gate if (column != columns || !auto_right_margin) 14887c478bd9Sstevel@tonic-gate *p++ = '\n'; /* for the display */ 14897c478bd9Sstevel@tonic-gate /* save overlap for next call to getline */ 14907c478bd9Sstevel@tonic-gate savlength = length; 14917c478bd9Sstevel@tonic-gate if (savlength == 0) { 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate * check if following byte is newline and get 14947c478bd9Sstevel@tonic-gate * it if it is 14957c478bd9Sstevel@tonic-gate */ 14967c478bd9Sstevel@tonic-gate c = fgetwc(f); 14977c478bd9Sstevel@tonic-gate if (c == '\n') { 14987c478bd9Sstevel@tonic-gate /* gobble and copy (if necessary) newline */ 14997c478bd9Sstevel@tonic-gate (void) ungetwc(c, f); 15007c478bd9Sstevel@tonic-gate (void) (*rdchar)(f); 15017c478bd9Sstevel@tonic-gate } else if (c == EOF) 15027c478bd9Sstevel@tonic-gate clearerr(f); 15037c478bd9Sstevel@tonic-gate else 15047c478bd9Sstevel@tonic-gate (void) ungetwc(c, f); 15057c478bd9Sstevel@tonic-gate } 15067c478bd9Sstevel@tonic-gate } else 15077c478bd9Sstevel@tonic-gate savlength = 0; 15087c478bd9Sstevel@tonic-gate *p = 0; 15097c478bd9Sstevel@tonic-gate return (column); 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate static void 15137c478bd9Sstevel@tonic-gate save_input(f) 15147c478bd9Sstevel@tonic-gate FILE *f; 15157c478bd9Sstevel@tonic-gate { 15167c478bd9Sstevel@tonic-gate if (pipe_in) { 15177c478bd9Sstevel@tonic-gate save_pipe(); 15187c478bd9Sstevel@tonic-gate in_file = tmp_fin; 15197c478bd9Sstevel@tonic-gate pipe_in = 0; 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate (void) fseeko(in_file, (off_t)0, SEEK_SET); 15227c478bd9Sstevel@tonic-gate copy_file(in_file, f); 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate static void 15267c478bd9Sstevel@tonic-gate save_pipe() 15277c478bd9Sstevel@tonic-gate { 15287c478bd9Sstevel@tonic-gate if (!doliseof) 15297c478bd9Sstevel@tonic-gate while (fgetputc(stdin) != EOF) 15307c478bd9Sstevel@tonic-gate if (brk_hit) { 15317c478bd9Sstevel@tonic-gate brk_hit = 0; 15327c478bd9Sstevel@tonic-gate error("Piped input only partially saved"); 15337c478bd9Sstevel@tonic-gate break; 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate (void) fclose(tmp_fou); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate static int 15397c478bd9Sstevel@tonic-gate fgetputc(f) /* copy anything read from a pipe to tmp_fou */ 15407c478bd9Sstevel@tonic-gate FILE *f; 15417c478bd9Sstevel@tonic-gate { 15427c478bd9Sstevel@tonic-gate int c; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate if ((c = fgetwc(f)) != EOF) 15457c478bd9Sstevel@tonic-gate (void) fputwc(c, tmp_fou); 15467c478bd9Sstevel@tonic-gate return (c); 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate static void 15507c478bd9Sstevel@tonic-gate lineset(how) /* initialize line memory */ 15517c478bd9Sstevel@tonic-gate int how; 15527c478bd9Sstevel@tonic-gate { 15537c478bd9Sstevel@tonic-gate if (zero == NULL) { 15547c478bd9Sstevel@tonic-gate nlall = 128; 15557c478bd9Sstevel@tonic-gate zero = (LINE *) malloc(nlall * sizeof (LINE)); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate dol = contig = zero; 15587c478bd9Sstevel@tonic-gate zero->l_no = 1; 15597c478bd9Sstevel@tonic-gate zero->l_addr = 0l; 15607c478bd9Sstevel@tonic-gate if (how == BOF) { 15617c478bd9Sstevel@tonic-gate dot = zero - 1; 15627c478bd9Sstevel@tonic-gate eoflag = 0; 15637c478bd9Sstevel@tonic-gate doliseof = 0; 15647c478bd9Sstevel@tonic-gate eofl_no = -1; 15657c478bd9Sstevel@tonic-gate } else { 15667c478bd9Sstevel@tonic-gate dot = dol; 15677c478bd9Sstevel@tonic-gate eoflag = 1; 15687c478bd9Sstevel@tonic-gate doliseof = 1; 15697c478bd9Sstevel@tonic-gate eofl_no = 1; 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate static void 15747c478bd9Sstevel@tonic-gate newdol(f) /* add address of new 'dol' */ 15757c478bd9Sstevel@tonic-gate /* assumes that f is currently at beginning of said line */ 15767c478bd9Sstevel@tonic-gate /* updates dol */ 15777c478bd9Sstevel@tonic-gate FILE *f; 15787c478bd9Sstevel@tonic-gate { 15797c478bd9Sstevel@tonic-gate int diff; 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate if ((dol - zero) + 1 >= nlall) { 15827c478bd9Sstevel@tonic-gate LINE *ozero = zero; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate nlall += 512; 15857c478bd9Sstevel@tonic-gate if ((zero = (LINE *)realloc((char *)zero, 15867c478bd9Sstevel@tonic-gate (unsigned)(nlall * sizeof (LINE)))) == NULL) { 15877c478bd9Sstevel@tonic-gate zero = ozero; 15887c478bd9Sstevel@tonic-gate compact(); 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate diff = (int)((int)zero - (int)ozero); 15917c478bd9Sstevel@tonic-gate dot = (LINE *)((int)dot + diff); 15927c478bd9Sstevel@tonic-gate dol = (LINE *)((int)dol + diff); 15937c478bd9Sstevel@tonic-gate contig = (LINE *)((int)contig + diff); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate dol++; 15967c478bd9Sstevel@tonic-gate if (!pipe_in) 15977c478bd9Sstevel@tonic-gate dol->l_addr = (off_t)ftello(f); 15987c478bd9Sstevel@tonic-gate else { 15997c478bd9Sstevel@tonic-gate (void) fflush(tmp_fou); 16007c478bd9Sstevel@tonic-gate dol->l_addr = (off_t)ftello(tmp_fou); 16017c478bd9Sstevel@tonic-gate } 16027c478bd9Sstevel@tonic-gate dol->l_no = (dol-1)->l_no + 1; 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate static void 16067c478bd9Sstevel@tonic-gate compact() 16077c478bd9Sstevel@tonic-gate { 16087c478bd9Sstevel@tonic-gate (void) perror("realloc"); 16097c478bd9Sstevel@tonic-gate end_it(); 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate static void 16147c478bd9Sstevel@tonic-gate terminit() /* set up terminal dependencies from termlib */ 16157c478bd9Sstevel@tonic-gate { 16167c478bd9Sstevel@tonic-gate int err_ret; 16177c478bd9Sstevel@tonic-gate struct termio ntty; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate for (;;) { 16207c478bd9Sstevel@tonic-gate gid_t my_tgid; 16217c478bd9Sstevel@tonic-gate my_tgid = (gid_t)tcgetpgrp(1); 16227c478bd9Sstevel@tonic-gate if (my_tgid < (gid_t)0 || my_tgid == my_pgid) 16237c478bd9Sstevel@tonic-gate break; 16247c478bd9Sstevel@tonic-gate (void) kill(-my_pgid, SIGTTOU); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate if ((freopen("/dev/tty", "r+", stdout)) == NULL) { 16287c478bd9Sstevel@tonic-gate (void) perror("open"); 16297c478bd9Sstevel@tonic-gate exit(1); 16307c478bd9Sstevel@tonic-gate } 16317c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCGETA, &otty); 16327c478bd9Sstevel@tonic-gate termflg = 1; 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate (void) setupterm(0, fileno(stdout), &err_ret); 16357c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCGETA, &ntty); 16367c478bd9Sstevel@tonic-gate ntty.c_lflag &= ~(ECHONL | ECHO | ICANON); 16377c478bd9Sstevel@tonic-gate ntty.c_cc[VMIN] = 1; 16387c478bd9Sstevel@tonic-gate ntty.c_cc[VTIME] = 1; 16397c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCSETAW, &ntty); 16407c478bd9Sstevel@tonic-gate pg_stdin = fdopen(dup(fileno(stdout)), "r"); 16417c478bd9Sstevel@tonic-gate (void) saveterm(); 16427c478bd9Sstevel@tonic-gate (void) resetterm(); 16437c478bd9Sstevel@tonic-gate if (lines <= 0 || hard_copy) { 16447c478bd9Sstevel@tonic-gate hard_copy = 1; 16457c478bd9Sstevel@tonic-gate lines = 24; 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate if (columns <= 0) 16487c478bd9Sstevel@tonic-gate columns = 80; 16497c478bd9Sstevel@tonic-gate if (clropt && !clear_screen) 16507c478bd9Sstevel@tonic-gate clropt = 0; 16517c478bd9Sstevel@tonic-gate if ((shell = getenv("SHELL")) == (char *)NULL) 16527c478bd9Sstevel@tonic-gate shell = "/usr/bin/sh"; 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate static void 16567c478bd9Sstevel@tonic-gate error(mess) 16577c478bd9Sstevel@tonic-gate char *mess; 16587c478bd9Sstevel@tonic-gate { 16597c478bd9Sstevel@tonic-gate kill_line(); 16607c478bd9Sstevel@tonic-gate sopr(gettext(mess), 1); 16617c478bd9Sstevel@tonic-gate prompt((char *)NULL); 16627c478bd9Sstevel@tonic-gate errors++; 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate static void 16667c478bd9Sstevel@tonic-gate prompt(filename) 16677c478bd9Sstevel@tonic-gate char *filename; 16687c478bd9Sstevel@tonic-gate { 16697c478bd9Sstevel@tonic-gate char outstr[PROMPTSIZE+6]; 16707c478bd9Sstevel@tonic-gate int pagenum; 16717c478bd9Sstevel@tonic-gate if (filename != NULL) { 16727c478bd9Sstevel@tonic-gate /* 16737c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 16747c478bd9Sstevel@tonic-gate * %s is a filename. 16757c478bd9Sstevel@tonic-gate */ 16767c478bd9Sstevel@tonic-gate (void) sprintf(outstr, gettext("(Next file: %s)"), filename); 16777c478bd9Sstevel@tonic-gate } else { 16787c478bd9Sstevel@tonic-gate if ((pagenum = (int)((new_ss.last_line-2)/(window-1)+1)) 16797c478bd9Sstevel@tonic-gate > 999999) 16807c478bd9Sstevel@tonic-gate pagenum = 999999; 16817c478bd9Sstevel@tonic-gate (void) sprintf(outstr, promptstr, pagenum); 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate sopr(outstr, 1); 16847c478bd9Sstevel@tonic-gate (void) fflush(stdout); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate /* 16887c478bd9Sstevel@tonic-gate * sopr puts out the message (please no \n's) surrounded by standout 16897c478bd9Sstevel@tonic-gate * begins and ends 16907c478bd9Sstevel@tonic-gate */ 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate static void 16937c478bd9Sstevel@tonic-gate sopr(m, count) 16947c478bd9Sstevel@tonic-gate char *m; 16957c478bd9Sstevel@tonic-gate int count; 16967c478bd9Sstevel@tonic-gate { 16977c478bd9Sstevel@tonic-gate wchar_t wc; 16987c478bd9Sstevel@tonic-gate int len, n; 16997c478bd9Sstevel@tonic-gate char *p; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate if (count) { 17027c478bd9Sstevel@tonic-gate p = m; 17037c478bd9Sstevel@tonic-gate for (; *p; p += len) { 17047c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, p, MB_CUR_MAX)) <= 0) { 17057c478bd9Sstevel@tonic-gate len = 1; 17067c478bd9Sstevel@tonic-gate continue; 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate if ((n = wcwidth(wc)) > 0) 17097c478bd9Sstevel@tonic-gate promptlen += n; 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate if (soflag && enter_standout_mode && exit_standout_mode) { 17137c478bd9Sstevel@tonic-gate (void) putp(enter_standout_mode); 17147c478bd9Sstevel@tonic-gate (void) fputs(m, stdout); 17157c478bd9Sstevel@tonic-gate (void) putp(exit_standout_mode); 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate else 17187c478bd9Sstevel@tonic-gate (void) fputs(m, stdout); 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate static void 17227c478bd9Sstevel@tonic-gate doclear() 17237c478bd9Sstevel@tonic-gate { 17247c478bd9Sstevel@tonic-gate if (clear_screen) 17257c478bd9Sstevel@tonic-gate (void) putp(clear_screen); 17267c478bd9Sstevel@tonic-gate (void) putchar('\r'); /* this resets the terminal drivers character */ 17277c478bd9Sstevel@tonic-gate /* count in case it is trying to expand tabs */ 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate static void 17327c478bd9Sstevel@tonic-gate kill_line() 17337c478bd9Sstevel@tonic-gate { 17347c478bd9Sstevel@tonic-gate erase_line(0); 17357c478bd9Sstevel@tonic-gate if (!clr_eol) (void) putchar('\r'); 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate /* erase from after col to end of prompt */ 17407c478bd9Sstevel@tonic-gate static void 17417c478bd9Sstevel@tonic-gate erase_line(col) 17427c478bd9Sstevel@tonic-gate int col; 17437c478bd9Sstevel@tonic-gate { 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate if (promptlen == 0) 17467c478bd9Sstevel@tonic-gate return; 17477c478bd9Sstevel@tonic-gate if (hard_copy) 17487c478bd9Sstevel@tonic-gate (void) putchar('\n'); 17497c478bd9Sstevel@tonic-gate else { 17507c478bd9Sstevel@tonic-gate if (col == 0) 17517c478bd9Sstevel@tonic-gate (void) putchar('\r'); 17527c478bd9Sstevel@tonic-gate if (clr_eol) { 17537c478bd9Sstevel@tonic-gate (void) putp(clr_eol); 17547c478bd9Sstevel@tonic-gate /* for the terminal driver again */ 17557c478bd9Sstevel@tonic-gate (void) putchar('\r'); 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate else 17587c478bd9Sstevel@tonic-gate for (col = promptlen - col; col > 0; col--) 17597c478bd9Sstevel@tonic-gate (void) putchar(' '); 17607c478bd9Sstevel@tonic-gate } 17617c478bd9Sstevel@tonic-gate promptlen = 0; 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate /* 17657c478bd9Sstevel@tonic-gate * Come here if a quit or interrupt signal is received 17667c478bd9Sstevel@tonic-gate */ 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate static void 17697c478bd9Sstevel@tonic-gate on_brk(sno) 17707c478bd9Sstevel@tonic-gate int sno; /* signal number generated */ 17717c478bd9Sstevel@tonic-gate { 17727c478bd9Sstevel@tonic-gate (void) signal(sno, on_brk); 17737c478bd9Sstevel@tonic-gate if (!inwait) { 17747c478bd9Sstevel@tonic-gate BEEP(); 17757c478bd9Sstevel@tonic-gate brk_hit = 1; 17767c478bd9Sstevel@tonic-gate } else { 17777c478bd9Sstevel@tonic-gate brk_hit = 0; 17787c478bd9Sstevel@tonic-gate longjmp(restore, 1); 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate /* 17837c478bd9Sstevel@tonic-gate * Clean up terminal state and exit. 17847c478bd9Sstevel@tonic-gate */ 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate void 17877c478bd9Sstevel@tonic-gate end_it() 17887c478bd9Sstevel@tonic-gate { 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if (out_is_tty) { 17917c478bd9Sstevel@tonic-gate kill_line(); 17927c478bd9Sstevel@tonic-gate (void) resetterm(); 17937c478bd9Sstevel@tonic-gate if (termflg) 17947c478bd9Sstevel@tonic-gate (void) ioctl(fileno(stdout), TCSETAW, &otty); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate if (tmp_fin) 17977c478bd9Sstevel@tonic-gate (void) fclose(tmp_fin); 17987c478bd9Sstevel@tonic-gate if (tmp_fou) 17997c478bd9Sstevel@tonic-gate (void) fclose(tmp_fou); 18007c478bd9Sstevel@tonic-gate if (tmp_fou || tmp_fin) 18017c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 18027c478bd9Sstevel@tonic-gate exit(status); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate void 18067c478bd9Sstevel@tonic-gate onsusp() 18077c478bd9Sstevel@tonic-gate { 18087c478bd9Sstevel@tonic-gate int ttou_is_dfl; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate /* ignore SIGTTOU so following resetterm and flush works */ 18117c478bd9Sstevel@tonic-gate ttou_is_dfl = (signal(SIGTTOU, SIG_IGN) == SIG_DFL); 18127c478bd9Sstevel@tonic-gate (void) resetterm(); 18137c478bd9Sstevel@tonic-gate (void) fflush(stdout); 18147c478bd9Sstevel@tonic-gate if (ttou_is_dfl) 18157c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_DFL); 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate /* send SIGTSTP to stop this process group */ 18187c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 18197c478bd9Sstevel@tonic-gate (void) kill(-my_pgid, SIGTSTP); 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate /* continued - reset the terminal */ 18227c478bd9Sstevel@tonic-gate #ifdef __STDC__ 18237c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, (void (*)(int))onsusp); 18247c478bd9Sstevel@tonic-gate #else 18257c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, (void (*))onsusp); 18267c478bd9Sstevel@tonic-gate #endif 18277c478bd9Sstevel@tonic-gate (void) resetterm(); 18287c478bd9Sstevel@tonic-gate if (inwait) 18297c478bd9Sstevel@tonic-gate longjmp(restore, -1); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate } 18327c478bd9Sstevel@tonic-gate 18337c478bd9Sstevel@tonic-gate static char * 18347c478bd9Sstevel@tonic-gate pg_strchr(str, c) 18357c478bd9Sstevel@tonic-gate char *str; 18367c478bd9Sstevel@tonic-gate wchar_t c; 18377c478bd9Sstevel@tonic-gate { 18387c478bd9Sstevel@tonic-gate while (*str) { 18397c478bd9Sstevel@tonic-gate if (c == *str) 18407c478bd9Sstevel@tonic-gate return (str); 18417c478bd9Sstevel@tonic-gate str++; 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate return (0); 18447c478bd9Sstevel@tonic-gate } 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate void 18477c478bd9Sstevel@tonic-gate usage() 18487c478bd9Sstevel@tonic-gate { 18497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 18507c478bd9Sstevel@tonic-gate "Usage: pg [-number] [-p string] [-cefnrs] [+line] [+/pattern/] files\n")); 18517c478bd9Sstevel@tonic-gate exit(1); 18527c478bd9Sstevel@tonic-gate } 1853