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 $ */
4 /* $DragonFly: src/games/hack/hack.pager.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */
6 /* This file contains the command routine dowhatis() and a pager. */
8 * Also readmail() and doshell(), and generally the things that contact the
12 #include <sys/types.h>
15 extern int CO, LI; /* usually COLNO and ROWNO+2 */
17 extern char quitchars[];
19 static void intruph(int);
20 static void page_more(FILE *, int);
27 char *buf = &bufr[6], *ep, q;
29 if (!(fp = fopen(DATAFILE, "r")))
30 pline("Cannot open data file!");
32 pline("Specify what? ");
35 while (fgets(buf, BUFSZ, fp))
37 ep = strchr(buf, '\n');
40 /* else: bad data file */
41 /* Expand tab 'by hand' */
45 strncpy(buf + 1, " ", 7);
50 if (readchar() == 'y') {
51 page_more(fp, 1); /* does fclose() */
55 fclose(fp); /* kopper@psuvax1 */
58 pline("I've never heard of such things.");
64 /* make the paging of a file interruptible */
65 static int got_intrup;
68 intruph(int unused __unused)
73 /* simple pager, also used from dohelp() */
74 /* strip: nr of chars to be stripped from each line (0 or 1) */
76 page_more(FILE *fp, int strip)
79 sig_t prevsig = signal(SIGINT, intruph);
82 bufr = alloc((unsigned)CO);
84 while (fgets(bufr, CO - 1, fp) && (!strip || *bufr == '\t') && !got_intrup) {
85 ep = strchr(bufr, '\n');
88 if (page_line(bufr + strip)) {
97 signal(SIGINT, prevsig);
101 static boolean whole_screen = TRUE;
102 #define PAGMIN 12 /* minimum # of lines for page below level map */
105 set_whole_screen(void) /* called in termcap as soon as LI is known */
107 whole_screen = (LI - ROWNO - 2 <= PAGMIN || !CD);
116 whole_screen = TRUE; /* force a docrt(), our first */
117 ret = page_file(NEWS, TRUE);
119 return (ret); /* report whether we did docrt() */
124 set_pager(int mode) /* 0: open 1: wait+close 2: close */
132 /* use part of screen below level map */
155 page_line(const char *s) /* returns 1 if we should quit */
157 if (cury == LI - 1) {
159 return (0); /* suppress blank lines at top */
180 * Flexible pager: feed it with a number of lines and it will decide
181 * whether these should be fed to the pager above, or displayed in a
184 * cornline(0, title or 0) : initialize
185 * cornline(1, text) : add text to the chain of texts
186 * cornline(2, morcs) : output everything and cleanup
187 * cornline(3, 0) : cleanup
191 cornline(int mode, const char *text)
194 struct line *next_line;
196 } *texthead, *texttail;
206 cornline(1, text); /* title */
207 cornline(1, ""); /* blank line */
215 if (!text) /* superfluous, just to be sure */
221 tl = alloc((unsigned)(len + sizeof(struct line) + 1));
223 tl->line_text = (char *)(tl + 1);
224 strcpy(tl->line_text, text);
228 texttail->next_line = tl;
233 /* --- now we really do it --- */
234 if (mode == 2 && linect == 1) /* topline only */
235 pline(texthead->line_text);
236 else if (mode == 2) {
239 if (flags.toplin == 1) /* ab@unido */
243 lth = CO - maxlen - 2; /* Use full screen width */
244 if (linect < LI && lth >= 10) { /* in a corner */
249 for (tl = texthead; tl; tl = tl->next_line) {
254 putstr(tl->line_text);
262 docorner(lth, curline - 1);
263 } else { /* feed to pager */
265 for (tl = texthead; tl; tl = tl->next_line) {
266 if (page_line(tl->line_text)) {
280 while ((tl = texthead) != NULL) {
281 texthead = tl->next_line;
291 pline("Long or short help? ");
292 while (((c = readchar()) != 'l') && (c != 's') && !strchr(quitchars, c))
294 if (!strchr(quitchars, c))
295 page_file((c == 'l') ? HELP : SHELP, FALSE);
299 /* return: 0 - cannot open fnam; 1 - otherwise */
301 page_file(const char *fnam, bool silent)
303 #ifdef DEF_PAGER /* this implies that UNIX is defined */
304 /* use external pager; this may give security problems */
305 int fd = open(fnam, O_RDONLY);
309 pline("Cannot open %s.", fnam);
313 extern char *catmore;
316 * Now that child() does a setuid(getuid()) and a
317 * chdir(), we may not be able to open file fnam
318 * anymore, so make it stdin.
323 printf("Cannot open %s as stdin.\n", fnam);
325 execl(catmore, "page", NULL);
327 printf("Cannot exec %s.\n", catmore);
332 #else /* DEF_PAGER */
333 FILE *f; /* free after Robert Viduya */
335 if ((f = fopen(fnam, "r")) == NULL) {
340 pline("Cannot open %s.", fnam);
345 #endif /* DEF_PAGER */
358 if ((str = getenv("SHELL")) != NULL)
359 execl(str, str, NULL);
361 execl("/bin/sh", "sh", NULL);
362 pline("sh: cannot execute.");
370 union wait { /* used only for the cast (union wait *)0 */
373 unsigned short w_Termsig:7;
374 unsigned short w_Coredump:1;
375 unsigned short w_Retcode:8;
380 #include <sys/wait.h>
381 #endif /* NOWAITINCLUDE */
390 if (f == 0) { /* child */
391 settty(NULL); /* also calls end_screen() */
395 chdir(getenv("HOME"));
399 if (f == -1) { /* cannot fork */
400 pline("Fork failed. Try again.");
403 /* fork succeeded; wait for child to exit */
404 signal(SIGINT, SIG_IGN);
405 signal(SIGQUIT, SIG_IGN);
409 signal(SIGINT, done1);
412 signal(SIGQUIT, SIG_DFL);