Annotation of 43BSDTahoe/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: 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

unix.superglobalmegacorp.com

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