1 /* $NetBSD: hack.pager.c,v 1.12 2009/06/07 18:30:39 dholland Exp $ */
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
66 __RCSID("$NetBSD: hack.pager.c,v 1.12 2009/06/07 18:30:39 dholland Exp $");
69 /* This file contains the command routine dowhatis() and a pager. */
71 * Also readmail() and doshell(), and generally the things that contact the
75 #include <sys/types.h>
82 static void intruph(int);
83 static void page_more(FILE *, int);
84 static int page_file(const char *, boolean
);
85 static int child(int);
92 char *buf
= &bufr
[6], *ep
, q
;
94 if (!(fp
= fopen(DATAFILE
, "r")))
95 pline("Cannot open data file!");
97 pline("Specify what? ");
100 while (fgets(buf
, BUFSZ
, fp
))
102 ep
= strchr(buf
, '\n');
105 /* else: bad data file */
107 pline("Bad data file!");
111 /* Expand tab 'by hand' */
112 if (buf
[1] == '\t') {
115 (void) strncpy(buf
+ 1, " ", 7);
119 pline("More info? ");
120 if (readchar() == 'y') {
121 page_more(fp
, 1); /* does fclose() */
125 (void) fclose(fp
); /* kopper@psuvax1 */
128 pline("I've never heard of such things.");
134 /* make the paging of a file interruptible */
135 static int got_intrup
;
138 intruph(int n __unused
)
143 /* simple pager, also used from dohelp() */
144 /* strip: nr of chars to be stripped from each line (0 or 1) */
146 page_more(FILE *fp
, int strip
)
149 sig_t prevsig
= signal(SIGINT
, intruph
);
152 bufr
= (char *) alloc((unsigned) CO
);
154 while (fgets(bufr
, CO
- 1, fp
) && (!strip
|| *bufr
== '\t') && !got_intrup
) {
155 ep
= strchr(bufr
, '\n');
158 if (page_line(bufr
+ strip
)) {
167 (void) signal(SIGINT
, prevsig
);
171 static boolean whole_screen
= TRUE
;
172 #define PAGMIN 12 /* minimum # of lines for page below level
176 set_whole_screen(void)
177 { /* called in termcap as soon as LI is known */
178 whole_screen
= (LI
- ROWNO
- 2 <= PAGMIN
|| !CD
);
187 whole_screen
= TRUE
; /* force a docrt(), our first */
188 ret
= page_file(NEWS
, TRUE
);
190 return (ret
); /* report whether we did docrt() */
194 /* mode: 0: open 1: wait+close 2: close */
203 /* use part of screen below level map */
226 page_line(const char *s
) /* returns 1 if we should quit */
228 if (cury
== LI
- 1) {
230 return (0); /* suppress blank lines at top */
251 * Flexible pager: feed it with a number of lines and it will decide
252 * whether these should be fed to the pager above, or displayed in a
255 * cornline(0, title or 0) : initialize
256 * cornline(1, text) : add text to the chain of texts
257 * cornline(2, morcs) : output everything and cleanup
258 * cornline(3, 0) : cleanup
262 cornline(int mode
, const char *text
)
265 struct line
*next_line
;
267 } *texthead
, *texttail
;
277 cornline(1, text
); /* title */
278 cornline(1, ""); /* blank line */
286 return; /* superfluous, just to be sure */
292 alloc((unsigned) (len
+ sizeof(struct line
) + 1));
294 tl
->line_text
= (char *) (tl
+ 1);
295 (void) strcpy(tl
->line_text
, text
);
299 texttail
->next_line
= tl
;
303 /* --- now we really do it --- */
304 if (mode
== 2 && linect
== 1) /* topline only */
305 pline(texthead
->line_text
);
306 else if (mode
== 2) {
309 if (flags
.toplin
== 1)
310 more(); /* ab@unido */
313 lth
= CO
- maxlen
- 2; /* Use full screen width */
314 if (linect
< LI
&& lth
>= 10) { /* in a corner */
319 for (tl
= texthead
; tl
; tl
= tl
->next_line
) {
324 putstr(tl
->line_text
);
332 docorner(lth
, curline
- 1);
333 } else { /* feed to pager */
335 for (tl
= texthead
; tl
; tl
= tl
->next_line
) {
336 if (page_line(tl
->line_text
)) {
349 while ((tl
= texthead
) != NULL
) {
350 texthead
= tl
->next_line
;
360 pline("Long or short help? ");
361 while (((c
= readchar()) != 'l') && (c
!= 's') && !strchr(quitchars
, c
))
363 if (!strchr(quitchars
, c
))
364 (void) page_file((c
== 'l') ? HELP
: SHELP
, FALSE
);
368 /* return: 0 - cannot open fnam; 1 - otherwise */
370 page_file(const char *fnam
, boolean silent
)
372 #ifdef DEF_PAGER /* this implies that UNIX is defined */
374 /* use external pager; this may give security problems */
376 int fd
= open(fnam
, O_RDONLY
);
380 pline("Cannot open %s.", fnam
);
386 * Now that child() does a setuid(getuid()) and a
387 * chdir(), we may not be able to open file fnam
388 * anymore, so make it stdin.
393 printf("Cannot open %s as stdin.\n", fnam
);
395 execl(catmore
, "page", (char *) 0);
397 printf("Cannot exec %s.\n", catmore
);
403 #else /* DEF_PAGER */
405 FILE *f
; /* free after Robert Viduya */
407 if ((f
= fopen(fnam
, "r")) == (FILE *) 0) {
412 pline("Cannot open %s.", fnam
);
418 #endif /* DEF_PAGER */
430 if ((str
= getenv("SHELL")) != NULL
)
431 execl(str
, str
, (char *) 0);
433 execl("/bin/sh", "sh", (char *) 0);
434 pline("sh: cannot execute.");
442 union wait
{ /* used only for the cast (union wait *) 0 */
445 unsigned short w_Termsig
:7;
446 unsigned short w_Coredump
:1;
447 unsigned short w_Retcode
:8;
454 #include <sys/wait.h>
458 #endif /* NOWAITINCLUDE */
467 if (f
== 0) { /* child */
468 settty((char *) 0); /* also calls end_screen() */
469 (void) setuid(getuid());
470 (void) setgid(getgid());
472 (void) chdir(getenv("HOME"));
476 if (f
== -1) { /* cannot fork */
477 pline("Fork failed. Try again.");
480 /* fork succeeded; wait for child to exit */
481 (void) signal(SIGINT
, SIG_IGN
);
482 (void) signal(SIGQUIT
, SIG_IGN
);
483 (void) wait(&status
);
486 (void) signal(SIGINT
, done1
);
489 (void) signal(SIGQUIT
, SIG_DFL
);