|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.