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. */
6 /* Also readmail() and doshell(), and generally the things that
7 contact the outside world. */
10 #include <sys/signal.h>
15 extern int CO, LI; /* usually COLNO and ROWNO+2 */
17 extern char quitchars[];
24 char *buf = &bufr[6], *ep, q;
25 extern char readchar();
27 if(!(fp = fopen(DATAFILE, "r")))
28 pline("Cannot open data file!");
30 pline("Specify what? ");
33 while(fgets(buf,BUFSZ,fp))
35 ep = index(buf, '\n');
37 /* else: bad data file */
38 /* Expand tab 'by hand' */
42 (void) strncpy(buf+1, " ", 7);
47 if(readchar() == 'y') {
48 page_more(fp,1); /* does fclose() */
52 (void) fclose(fp); /* kopper@psuvax1 */
55 pline("I've never heard of such things.");
61 /* make the paging of a file interruptible */
62 static int got_intrup;
69 /* simple pager, also used from dohelp() */
72 int strip; /* nr of chars to be stripped from each line (0 or 1) */
75 sig_t prevsig = signal(SIGINT, intruph);
78 bufr = (char *) alloc((unsigned) CO);
80 while(fgets(bufr,CO-1,fp) && (!strip || *bufr == '\t') && !got_intrup){
81 ep = index(bufr, '\n');
84 if(page_line(bufr+strip)) {
93 (void) signal(SIGINT, prevsig);
97 static boolean whole_screen = TRUE;
98 #define PAGMIN 12 /* minimum # of lines for page below level map */
100 set_whole_screen() { /* called in termcap as soon as LI is known */
101 whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
108 whole_screen = TRUE; /* force a docrt(), our first */
109 ret = page_file(NEWS, TRUE);
111 return(ret); /* report whether we did docrt() */
116 int mode; /* 0: open 1: wait+close 2: close */
123 /* use part of screen below level map */
145 page_line(s) /* returns 1 if we should quit */
152 return(0); /* suppress blank lines at top */
173 * Flexible pager: feed it with a number of lines and it will decide
174 * whether these should be fed to the pager above, or displayed in a
177 * cornline(0, title or 0) : initialize
178 * cornline(1, text) : add text to the chain of texts
179 * cornline(2, morcs) : output everything and cleanup
180 * cornline(3, 0) : cleanup
188 struct line *next_line;
190 } *texthead, *texttail;
200 cornline(1, text); /* title */
201 cornline(1, ""); /* blank line */
209 if(!text) return; /* superfluous, just to be sure */
215 alloc((unsigned)(len + sizeof(struct line) + 1));
217 tl->line_text = (char *)(tl + 1);
218 (void) strcpy(tl->line_text, text);
222 texttail->next_line = tl;
227 /* --- now we really do it --- */
228 if(mode == 2 && linect == 1) /* topline only */
229 pline(texthead->line_text);
234 if(flags.toplin == 1) more(); /* ab@unido */
237 lth = CO - maxlen - 2; /* Use full screen width */
238 if (linect < LI && lth >= 10) { /* in a corner */
243 for (tl = texthead; tl; tl = tl->next_line) {
248 putstr (tl->line_text);
256 docorner (lth, curline-1);
257 } else { /* feed to pager */
259 for (tl = texthead; tl; tl = tl->next_line) {
260 if (page_line (tl->line_text)) {
274 while(tl = texthead) {
275 texthead = tl->next_line;
284 pline ("Long or short help? ");
285 while (((c = readchar ()) != 'l') && (c != 's') && !index(quitchars,c))
287 if (!index(quitchars, c))
288 (void) page_file((c == 'l') ? HELP : SHELP, FALSE);
292 page_file(fnam, silent) /* return: 0 - cannot open fnam; 1 - otherwise */
296 #ifdef DEF_PAGER /* this implies that UNIX is defined */
298 /* use external pager; this may give security problems */
300 int fd = open(fnam, 0);
303 if(!silent) pline("Cannot open %s.", fnam);
307 extern char *catmore;
309 /* Now that child() does a setuid(getuid()) and a chdir(),
310 we may not be able to open file fnam anymore, so make
314 if(!silent) printf("Cannot open %s as stdin.\n", fnam);
316 execl(catmore, "page", (char *) 0);
317 if(!silent) printf("Cannot exec %s.\n", catmore);
325 FILE *f; /* free after Robert Viduya */
327 if ((f = fopen (fnam, "r")) == (FILE *) 0) {
329 home(); perror (fnam); flags.toplin = 1;
330 pline ("Cannot open %s.", fnam);
346 if(str = getenv("SHELL"))
347 execl(str, str, (char *) 0);
349 execl("/bin/sh", "sh", (char *) 0);
350 pline("sh: cannot execute.");
358 union wait { /* used only for the cast (union wait *) 0 */
361 unsigned short w_Termsig:7;
362 unsigned short w_Coredump:1;
363 unsigned short w_Retcode:8;
370 #include <sys/wait.h>
381 if(f == 0){ /* child */
382 settty((char *) 0); /* also calls end_screen() */
386 (void) chdir(getenv("HOME"));
390 if(f == -1) { /* cannot fork */
391 pline("Fork failed. Try again.");
394 /* fork succeeded; wait for child to exit */
395 (void) signal(SIGINT,SIG_IGN);
396 (void) signal(SIGQUIT,SIG_IGN);
397 (void) wait(&status);
400 (void) signal(SIGINT,done1);
402 if(wizard) (void) signal(SIGQUIT,SIG_DFL);