1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.pager.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.pager.c,v 1.7 1999/11/16 02:57:09 billf Exp $ */
5 /* This file contains the command routine dowhatis() and a pager. */
7 * Also readmail() and doshell(), and generally the things that contact the
11 #include <sys/types.h>
14 extern int CO
, LI
; /* usually COLNO and ROWNO+2 */
16 extern char quitchars
[];
18 static void intruph(int);
19 static void page_more(FILE *, int);
26 char *buf
= &bufr
[6], *ep
, q
;
28 if (!(fp
= fopen(DATAFILE
, "r")))
29 pline("Cannot open data file!");
31 pline("Specify what? ");
34 while (fgets(buf
, BUFSZ
, fp
))
36 ep
= strchr(buf
, '\n');
39 /* else: bad data file */
40 /* Expand tab 'by hand' */
44 memcpy(buf
+ 1, " ", 7);
49 if (readchar() == 'y') {
50 page_more(fp
, 1); /* does fclose() */
54 fclose(fp
); /* kopper@psuvax1 */
57 pline("I've never heard of such things.");
63 /* make the paging of a file interruptible */
64 static int got_intrup
;
67 intruph(int unused __unused
)
72 /* simple pager, also used from dohelp() */
73 /* strip: nr of chars to be stripped from each line (0 or 1) */
75 page_more(FILE *fp
, int strip
)
78 sig_t prevsig
= signal(SIGINT
, intruph
);
81 bufr
= alloc((unsigned)CO
);
83 while (fgets(bufr
, CO
- 1, fp
) && (!strip
|| *bufr
== '\t') && !got_intrup
) {
84 ep
= strchr(bufr
, '\n');
87 if (page_line(bufr
+ strip
)) {
96 signal(SIGINT
, prevsig
);
100 static boolean whole_screen
= TRUE
;
101 #define PAGMIN 12 /* minimum # of lines for page below level map */
104 set_whole_screen(void) /* called in termcap as soon as LI is known */
106 whole_screen
= (LI
- ROWNO
- 2 <= PAGMIN
|| !CD
);
115 whole_screen
= TRUE
; /* force a docrt(), our first */
116 ret
= page_file(NEWS
, TRUE
);
118 return (ret
); /* report whether we did docrt() */
123 set_pager(int mode
) /* 0: open 1: wait+close 2: close */
131 /* use part of screen below level map */
154 page_line(const char *s
) /* returns 1 if we should quit */
156 if (cury
== LI
- 1) {
158 return (0); /* suppress blank lines at top */
179 * Flexible pager: feed it with a number of lines and it will decide
180 * whether these should be fed to the pager above, or displayed in a
183 * cornline(0, title or 0) : initialize
184 * cornline(1, text) : add text to the chain of texts
185 * cornline(2, morcs) : output everything and cleanup
186 * cornline(3, 0) : cleanup
190 cornline(int mode
, const char *text
)
193 struct line
*next_line
;
195 } *texthead
, *texttail
;
205 cornline(1, text
); /* title */
206 cornline(1, ""); /* blank line */
214 if (!text
) /* superfluous, just to be sure */
220 tl
= alloc((unsigned)(len
+ sizeof(struct line
) + 1));
221 tl
->next_line
= NULL
;
222 tl
->line_text
= (char *)(tl
+ 1);
223 strcpy(tl
->line_text
, text
);
227 texttail
->next_line
= tl
;
232 /* --- now we really do it --- */
233 if (mode
== 2 && linect
== 1) /* topline only */
234 pline("%s", texthead
->line_text
);
235 else if (mode
== 2) {
238 if (flags
.toplin
== 1) /* ab@unido */
242 lth
= CO
- maxlen
- 2; /* Use full screen width */
243 if (linect
< LI
&& lth
>= 10) { /* in a corner */
248 for (tl
= texthead
; tl
; tl
= tl
->next_line
) {
253 putstr(tl
->line_text
);
261 docorner(lth
, curline
- 1);
262 } else { /* feed to pager */
264 for (tl
= texthead
; tl
; tl
= tl
->next_line
) {
265 if (page_line(tl
->line_text
)) {
279 while ((tl
= texthead
) != NULL
) {
280 texthead
= tl
->next_line
;
290 pline("Long or short help? ");
291 while (((c
= readchar()) != 'l') && (c
!= 's') && !strchr(quitchars
, c
))
293 if (!strchr(quitchars
, c
))
294 page_file((c
== 'l') ? HELP
: SHELP
, FALSE
);
298 /* return: 0 - cannot open fnam; 1 - otherwise */
300 page_file(const char *fnam
, bool silent
)
302 #ifdef DEF_PAGER /* this implies that UNIX is defined */
303 /* use external pager; this may give security problems */
304 int fd
= open(fnam
, O_RDONLY
);
308 pline("Cannot open %s.", fnam
);
312 extern char *catmore
;
315 * Now that child() does a setuid(getuid()) and a
316 * chdir(), we may not be able to open file fnam
317 * anymore, so make it stdin.
322 printf("Cannot open %s as stdin.\n", fnam
);
324 execl(catmore
, "page", NULL
);
326 printf("Cannot exec %s.\n", catmore
);
331 #else /* DEF_PAGER */
332 FILE *f
; /* free after Robert Viduya */
334 if ((f
= fopen(fnam
, "r")) == NULL
) {
339 pline("Cannot open %s.", fnam
);
344 #endif /* DEF_PAGER */
357 if ((str
= getenv("SHELL")) != NULL
)
358 execl(str
, str
, NULL
);
360 execl("/bin/sh", "sh", NULL
);
361 pline("sh: cannot execute.");
369 union wait
{ /* used only for the cast (union wait *)0 */
372 unsigned short w_Termsig
:7;
373 unsigned short w_Coredump
:1;
374 unsigned short w_Retcode
:8;
379 #include <sys/wait.h>
380 #endif /* NOWAITINCLUDE */
389 if (f
== 0) { /* child */
390 settty(NULL
); /* also calls end_screen() */
394 chdir(getenv("HOME"));
398 if (f
== -1) { /* cannot fork */
399 pline("Fork failed. Try again.");
402 /* fork succeeded; wait for child to exit */
403 signal(SIGINT
, SIG_IGN
);
404 signal(SIGQUIT
, SIG_IGN
);
408 signal(SIGINT
, done1
);
411 signal(SIGQUIT
, SIG_DFL
);