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