Annotation of 43BSDReno/games/hack/hack.pager.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.