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