# 2.11BSD#431 - /usr/src/games/hack/hack.pager.c

##### Functions

    child             X
    cornline          X
    dohelp            X
    dosh              X
    dowhatis          X
    intruph           X
    page_file         X
    page_line         X
    page_more         X
    readnews          X
    set_pager         X
    set_whole_screen  X

##### Macros

    PAGMIN            X

##### struct's

    line              X

##### unions's

    wait              X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
       2: /* hack.pager.c - version 1.0.4 */
       3:
       4: /* This file contains the command routine dowhatis() and a pager. */
       5: /* Also readmail() and doshell(), and generally the things that
       6:    contact the outside world. */
       7:
       8: #include    <stdio.h>
       9: #include    <signal.h>
      10: #include    <stdlib.h>
      11: #include "hack.h"
      12: extern int CO, LI;  /* usually COLNO and ROWNO+2 */
      13: extern char *CD;
      14: extern char quitchars[];
      15: int done1();
      16:
      17: dowhatis()
      18: {
      19:     FILE *fp;
      20:     char bufr[BUFSZ+6];
      21:     register char *buf = &bufr[6], *ep, q;
      22:     extern char readchar();
      23:
      24:     if(!(fp = fopen(DATAFILE, "r")))
      25:         pline("Cannot open data file!");
      26:     else {
      27:         pline("Specify what? ");
      28:         q = readchar();
      29:         if(q != '\t')
      30:         while(fgets(buf,BUFSZ,fp))
      31:             if(*buf == q) {
      32:             ep = index(buf, '\n');
      33:             if(ep) *ep = 0;
      34:             /* else: bad data file */
      35:             /* Expand tab 'by hand' */
      36:             if(buf[1] == '\t'){
      37:                 buf = bufr;
      38:                 buf[0] = q;
      39:                 (void) strncpy(buf+1, "       ", 7);
      40:             }
      41:             pline(buf);
      42:             if(ep[-1] == ';') {
      43:                 pline("More info? ");
      44:                 if(readchar() == 'y') {
      45:                     page_more(fp,1); /* does fclose() */
      46:                     return(0);
      47:                 }
      48:             }
      49:             (void) fclose(fp);  /* kopper@psuvax1 */
      50:             return(0);
      51:             }
      52:         pline("I've never heard of such things.");
      53:         (void) fclose(fp);
      54:     }
      55:     return(0);
      56: }
      57:
      58: /* make the paging of a file interruptible */
      59: static int got_intrup;
      60:
      61: intruph(){
      62:     got_intrup++;
      63: }
      64:
      65: /* simple pager, also used from dohelp() */
      66: page_more(fp,strip)
      67: FILE *fp;
      68: int strip;  /* nr of chars to be stripped from each line (0 or 1) */
      69: {
      70:     register char *bufr, *ep;
      71:     int (*prevsig)() = signal(SIGINT, intruph);
      72:
      73:     set_pager(0);
      74:     bufr = (char *) alloc((unsigned) CO);
      75:     bufr[CO-1] = 0;
      76:     while(fgets(bufr,CO-1,fp) && (!strip || *bufr == '\t') && !got_intrup){
      77:         ep = index(bufr, '\n');
      78:         if(ep)
      79:             *ep = 0;
      80:         if(page_line(bufr+strip)) {
      81:             set_pager(2);
      82:             goto ret;
      83:         }
      84:     }
      85:     set_pager(1);
      86: ret:
      87:     free(bufr);
      88:     (void) fclose(fp);
      89:     (void) signal(SIGINT, prevsig);
      90:     got_intrup = 0;
      91: }
      92:
      93: static boolean whole_screen = TRUE;
      94: #define PAGMIN  12  /* minimum # of lines for page below level map */
      95:
      96: set_whole_screen() {    /* called in termcap as soon as LI is known */
      97:     whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
      98: }
      99:
     100: #ifdef NEWS
     101: readnews() {
     102:     register int ret;
     103:
     104:     whole_screen = TRUE;    /* force a docrt(), our first */
     105:     ret = page_file(NEWS, TRUE);
     106:     set_whole_screen();
     107:     return(ret);        /* report whether we did docrt() */
     108: }
     109: #endif NEWS
     110:
     111: set_pager(mode)
     112: register int mode;  /* 0: open  1: wait+close  2: close */
     113: {
     114:     static boolean so;
     115:     if(mode == 0) {
     116:         if(!whole_screen) {
     117:             /* clear topline */
     118:             clrlin();
     119:             /* use part of screen below level map */
     120:             curs(1, ROWNO+4);
     121:         } else {
     122:             cls();
     123:         }
     124:         so = flags.standout;
     125:         flags.standout = 1;
     126:     } else {
     127:         if(mode == 1) {
     128:             curs(1, LI);
     129:             more();
     130:         }
     131:         flags.standout = so;
     132:         if(whole_screen)
     133:             docrt();
     134:         else {
     135:             curs(1, ROWNO+4);
     136:             cl_eos();
     137:         }
     138:     }
     139: }
     140:
     141: page_line(s)        /* returns 1 if we should quit */
     142: register char *s;
     143: {
     144:     extern char morc;
     145:
     146:     if(cury == LI-1) {
     147:         if(!*s)
     148:             return(0);  /* suppress blank lines at top */
     149:         putchar('\n');
     150:         cury++;
     151:         cmore("q\033");
     152:         if(morc) {
     153:             morc = 0;
     154:             return(1);
     155:         }
     156:         if(whole_screen)
     157:             cls();
     158:         else {
     159:             curs(1, ROWNO+4);
     160:             cl_eos();
     161:         }
     162:     }
     163:     puts(s);
     164:     cury++;
     165:     return(0);
     166: }
     167:
     168: /*
     169:  * Flexible pager: feed it with a number of lines and it will decide
     170:  * whether these should be fed to the pager above, or displayed in a
     171:  * corner.
     172:  * Call:
     173:  *	cornline(0, title or 0)	: initialize
     174:  *	cornline(1, text)	: add text to the chain of texts
     175:  *	cornline(2, morcs)	: output everything and cleanup
     176:  *	cornline(3, 0)		: cleanup
     177:  */
     178:
     179: cornline(mode, text)
     180: int mode;
     181: char *text;
     182: {
     183:     static struct line {
     184:         struct line *next_line;
     185:         char *line_text;
     186:     } *texthead, *texttail;
     187:     static int maxlen;
     188:     static int linect;
     189:     register struct line *tl;
     190:
     191:     if(mode == 0) {
     192:         texthead = 0;
     193:         maxlen = 0;
     194:         linect = 0;
     195:         if(text) {
     196:             cornline(1, text);  /* title */
     197:             cornline(1, "");    /* blank line */
     198:         }
     199:         return;
     200:     }
     201:
     202:     if(mode == 1) {
     203:         register int len;
     204:
     205:         if(!text) return;   /* superfluous, just to be sure */
     206:         linect++;
     207:         len = strlen(text);
     208:         if(len > maxlen)
     209:         maxlen = len;
     210:         tl = (struct line *)
     211:         alloc((unsigned)(len + sizeof(struct line) + 1));
     212:         tl->next_line = 0;
     213:         tl->line_text = (char *)(tl + 1);
     214:         (void) strcpy(tl->line_text, text);
     215:         if(!texthead)
     216:         texthead = tl;
     217:         else
     218:         texttail->next_line = tl;
     219:         texttail = tl;
     220:         return;
     221:     }
     222:
     223:     /* --- now we really do it --- */
     224:     if(mode == 2 && linect == 1)                /* topline only */
     225:         pline(texthead->line_text);
     226:     else
     227:     if(mode == 2) {
     228:         register int curline, lth;
     229:
     230:         if(flags.toplin == 1) more();   /* ab@unido */
     231:         remember_topl();
     232:
     233:         lth = CO - maxlen - 2;         /* Use full screen width */
     234:         if (linect < LI && lth >= 10) {          /* in a corner */
     235:         home ();
     236:         cl_end ();
     237:         flags.toplin = 0;
     238:         curline = 1;
     239:         for (tl = texthead; tl; tl = tl->next_line) {
     240:             curs (lth, curline);
     241:             if(curline > 1)
     242:             cl_end ();
     243:             putsym(' ');
     244:             putstr (tl->line_text);
     245:             curline++;
     246:         }
     247:         curs (lth, curline);
     248:         cl_end ();
     249:         cmore (text);
     250:         home ();
     251:         cl_end ();
     252:         docorner (lth, curline-1);
     253:         } else {                    /* feed to pager */
     254:         set_pager(0);
     255:         for (tl = texthead; tl; tl = tl->next_line) {
     256:             if (page_line (tl->line_text)) {
     257:             set_pager(2);
     258:             goto cleanup;
     259:             }
     260:         }
     261:         if(text) {
     262:             cgetret(text);
     263:             set_pager(2);
     264:         } else
     265:             set_pager(1);
     266:         }
     267:     }
     268:
     269: cleanup:
     270:     while(tl = texthead) {
     271:         texthead = tl->next_line;
     272:         free((char *) tl);
     273:     }
     274: }
     275:
     276: dohelp()
     277: {
     278:     char c;
     279:
     280:     pline ("Long or short help? ");
     281:     while (((c = readchar ()) != 'l') && (c != 's') && !index(quitchars,c))
     282:         bell ();
     283:     if (!index(quitchars, c))
     284:         (void) page_file((c == 'l') ? HELP : SHELP, FALSE);
     285:     return(0);
     286: }
     287:
     288: page_file(fnam, silent) /* return: 0 - cannot open fnam; 1 - otherwise */
     289: register char *fnam;
     290: boolean silent;
     291: {
     292: #ifdef DEF_PAGER            /* this implies that UNIX is defined */
     293:       {
     294:     /* use external pager; this may give security problems */
     295:
     296:     register int fd = open(fnam, 0);
     297:
     298:     if(fd < 0) {
     299:         if(!silent) pline("Cannot open %s.", fnam);
     300:         return(0);
     301:     }
     302:     if(child(1)){
     303:         extern char *catmore;
     304:
     305:         /* Now that child() does a setuid(getuid()) and a chdir(),
     306: 		   we may not be able to open file fnam anymore, so make
     307: 		   it stdin. */
     308:         (void) close(0);
     309:         if(dup(fd)) {
     310:             if(!silent) printf("Cannot open %s as stdin.\n", fnam);
     311:         } else {
     312:             execl(catmore, "page", (char *) 0);
     313:             if(!silent) printf("Cannot exec %s.\n", catmore);
     314:         }
     315:         exit(1);
     316:     }
     317:     (void) close(fd);
     318:       }
     319: #else DEF_PAGER
     320:       {
     321:     FILE *f;            /* free after Robert Viduya */
     322:
     323:     if ((f = fopen (fnam, "r")) == (FILE *) 0) {
     324:         if(!silent) {
     325:             home(); perror (fnam); flags.toplin = 1;
     326:             pline ("Cannot open %s.", fnam);
     327:         }
     328:         return(0);
     329:     }
     330:     page_more(f, 0);
     331:       }
     332: #endif DEF_PAGER
     333:
     334:     return(1);
     335: }
     336:
     337: #ifdef UNIX
     338: #ifdef SHELL
     339: dosh(){
     340: register char *str;
     341:     if(child(0)) {
     342:         if(str = getenv("SHELL"))
     343:             execl(str, str, (char *) 0);
     344:         else
     345:             execl("/bin/sh", "sh", (char *) 0);
     346:         pline("sh: cannot execute.");
     347:         exit(1);
     348:     }
     349:     return(0);
     350: }
     351: #endif SHELL
     352:
     353: #ifdef NOWAITINCLUDE
     354: union wait {        /* used only for the cast  (union wait *) 0  */
     355:     int w_status;
     356:     struct {
     357:         unsigned short w_Termsig:7;
     358:         unsigned short w_Coredump:1;
     359:         unsigned short w_Retcode:8;
     360:     } w_T;
     361: };
     362:
     363: #else
     364:
     365: #ifdef BSD
     366: #include    <sys/wait.h>
     367: #else
     368: #include    <wait.h>
     369: #endif BSD
     370: #endif NOWAITINCLUDE
     371:
     372: child(wt) {
     373: register int f = fork();
     374:     if(f == 0){     /* child */
     375:         settty((char *) 0);     /* also calls end_screen() */
     376:         (void) setuid(getuid());
     377:         (void) setgid(getgid());
     378: #ifdef CHDIR
     379:         (void) chdir(getenv("HOME"));
     380: #endif CHDIR
     381:         return(1);
     382:     }
     383:     if(f == -1) {   /* cannot fork */
     384:         pline("Fork failed. Try again.");
     385:         return(0);
     386:     }
     387:     /* fork succeeded; wait for child to exit */
     388:     (void) signal(SIGINT,SIG_IGN);
     389:     (void) signal(SIGQUIT,SIG_IGN);
     390:     (void) wait((union wait *) 0);
     391:     gettty();
     392:     setftty();
     393:     (void) signal(SIGINT,done1);
     394: #ifdef WIZARD
     395:     if(wizard) (void) signal(SIGQUIT,SIG_DFL);
     396: #endif WIZARD
     397:     if(wt) getret();
     398:     docrt();
     399:     return(0);
     400: }
     401: #endif UNIX

#### Defined functions

child defined in line 372; used 3 times

- in line 302, 341
- in /usr/src/games/hack/hack.unix.c line 410

cornline defined in line 179; used 14 times

- in line 196-197(2)
- in /usr/src/games/hack/hack.invent.c line 614-619(2), 625, 723-727(2), 745-753(3)
- in /usr/src/games/hack/hack.o_init.c line 135, 141-148(3)

dohelp defined in line 276; used 2 times

- in /usr/src/games/hack/hack.cmd.c line 10, 66

dosh defined in line 339; used 2 times

- in /usr/src/games/hack/hack.cmd.c line 14, 68

dowhatis defined in line 17; used 2 times

- in /usr/src/games/hack/hack.cmd.c line 9, 65

intruph defined in line 61; used 1 times

- in line 71

page_file defined in line 288; used 3 times

- in line 105, 284
- in /usr/src/games/hack/hack.unix.c line 415

page_line defined in line 141; used 7 times

- in line 80, 256
- in /usr/src/games/hack/hack.shk.c line 647(2), 676-681(3)

page_more defined in line 66; used 2 times

- in line 45, 330

readnews defined in line 101; used 1 times

- in /usr/src/games/hack/hack.main.c line 275

set_pager defined in line 111; used 10 times

- in line 73, 81-85(2), 254-257(2), 263-265(2)
- in /usr/src/games/hack/hack.shk.c line 646, 683-686(2)

set_whole_screen defined in line 96; used 2 times

- in line 106
- in /usr/src/games/hack/hack.termcap.c line 75

#### Defined variables

got_intrup defined in line 59; used 3 times

- in line 62, 76, 90

whole_screen defined in line 93; used 5 times

- in line 97, 104, 116, 132, 156

#### Defined struct's

line defined in line 183; used 8 times

- in line 184-189(4), 210-211(4)

#### Defined union's

wait defined in line 354; used 2 times

- in line 390(2)

#### Defined macros

PAGMIN defined in line 94; used 1 times

- in line 97

Last modified: 1997-10-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1435 |