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
cornline defined in line 179; used 14 times
dohelp defined in line 276; used 2 times
dosh defined in line 339; used 2 times
dowhatis defined in line 17; used 2 times
intruph defined in line 61; used 1 times
  • in line 71
page_file defined in line 288; used 3 times
page_line defined in line 141; used 7 times
page_more defined in line 66; used 2 times
readnews defined in line 101; used 1 times
set_pager defined in line 111; used 10 times
set_whole_screen defined in line 96; used 2 times

Defined variables

got_intrup defined in line 59; used 3 times
whole_screen defined in line 93; used 5 times

Defined struct's

line defined in line 183; used 8 times

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: 1454
Valid CSS Valid XHTML 1.0 Strict