1: #ifndef lint 2: static char sccsid[] = "@(#)man.c 1.10 (Berkeley) 9/19/83"; 3: #endif 4: 5: #include <whoami.h> 6: #include <stdio.h> 7: #include <ctype.h> 8: #include <sgtty.h> 9: #include <sys/types.h> 10: #include <stat.h> 11: #include <signal.h> 12: /* 13: * man 14: * link also to apropos and whatis 15: * This version uses cat -s for eliminating multiple blank lines, 16: * and more for underlining and paging. 17: */ 18: #define MANDIR "/usr/man" /* this is deeply embedded */ 19: #define NROFFCAT "nroff -man" /* for nroffing to cat file */ 20: #define SSP "cat -s" /* compression for cat file */ 21: #define NROFF "nroff -man" /* for nroffing to tty */ 22: #define MORE "more -s" /* paging filter */ 23: #define CAT "cat" /* for '-' opt (no more) */ 24: #define TROFF1 "troff -man" /* for -t option */ 25: #define TROFF2 "" /* for troff to pipe to */ 26: /* for vtroff: 27: #define TROFF1 "troff -t -man /usr/lib/tmac/tmac.vcat" 28: #define TROFF2 "| /usr/lib/rvsort |/usr/lib/vpr -t" 29: */ 30: 31: #define ALLSECT "1unl6823457p" /* order to look through sections */ 32: #define SECT1 "1unl" /* sections to look at if 1 is specified */ 33: #define SUBSEC1 "mcg" /* subsections to look for in sect. 1 */ 34: #define SUBSEC2 "jv" /* subsections, section 2 */ 35: #define SUBSEC3 "jxmsf" /* subsections, section 3 */ 36: 37: #if !defined(VMUNIX) && !defined(VIRUS_VFORK) 38: #define vfork fork 39: #endif 40: 41: int nomore; 42: char *strcpy(); 43: char *strcat(); 44: char *trim(); 45: int remove(); 46: int section; 47: int subsec; 48: int troffit; 49: 50: #define eq(a,b) (strcmp(a,b) == 0) 51: 52: main(argc, argv) 53: int argc; 54: char *argv[]; 55: { 56: 57: if (signal(SIGINT, SIG_IGN) == SIG_DFL) { 58: signal(SIGINT, remove); 59: signal(SIGQUIT, remove); 60: signal(SIGTERM, remove); 61: } 62: umask(0); 63: if (chdir(MANDIR) < 0) { 64: fprintf(stderr, "Can't chdir to %s.\n", MANDIR); 65: exit(1); 66: } 67: if (strcmp(argv[0], "apropos") == 0) { 68: apropos(argc-1, argv+1); 69: exit(0); 70: } 71: if (strcmp(argv[0], "whatis") == 0) { 72: whatis(argc-1, argv+1); 73: exit(0); 74: } 75: if (argc <= 1) { 76: fprintf(stderr, "Usage: man [ section ] name ...\n"); 77: exit(1); 78: } 79: argc--, argv++; 80: while (argc > 0 && argv[0][0] == '-') { 81: switch(argv[0][1]) { 82: 83: case 0: 84: nomore++; 85: break; 86: 87: case 't': 88: troffit++; 89: break; 90: 91: case 'k': 92: apropos(argc-1, argv+1); 93: exit(0); 94: 95: case 'f': 96: whatis(argc-1, argv+1); 97: exit(0); 98: } 99: argc--, argv++; 100: } 101: if (troffit == 0 && nomore == 0 && !isatty(1)) 102: nomore++; 103: section = 0; 104: do { 105: if (eq(argv[0], "local")) { 106: section = 'l'; 107: goto sectin; 108: } else if (eq(argv[0], "new")) { 109: section = 'n'; 110: goto sectin; 111: } else if (eq(argv[0], "public")) { 112: section = 'p'; 113: goto sectin; 114: } else if (eq(argv[0], "ucb")) { 115: section = 'u'; 116: goto sectin; 117: } else if (argv[0][0] >= '0' && argv[0][0] <= '9' && (argv[0][1] == 0 || argv[0][2] == 0)) { 118: section = argv[0][0]; 119: subsec = argv[0][1]; 120: sectin: 121: argc--, argv++; 122: if (argc == 0) { 123: fprintf(stderr, "But what do you want from section %s?\n", argv[-1]); 124: exit(1); 125: } 126: continue; 127: } 128: manual(section, argv[0]); 129: argc--, argv++; 130: } while (argc > 0); 131: exit(0); 132: } 133: 134: manual(sec, name) 135: char sec; 136: char *name; 137: { 138: char section = sec; 139: char work[100], work2[100], cmdbuf[150]; 140: struct stat stbuf, stbuf2; 141: int last; 142: char *sp = ALLSECT; 143: 144: strcpy(work, "manx/"); 145: strcat(work, name); 146: strcat(work, ".x"); 147: last = strlen(work) - 1; 148: if (section == '1') { 149: sp = SECT1; 150: section = 0; 151: } 152: if (section == 0) { 153: for (section = *sp++; section; section = *sp++) { 154: work[3] = section; 155: work[last] = section; 156: work[last+1] = 0; 157: work[last+2] = 0; 158: if (stat(work, &stbuf) >= 0) 159: break; 160: if (work[last] >= '1' && work[last] <= '3') { 161: char *cp; 162: search: 163: switch (work[last]) { 164: case '1': cp = SUBSEC1; break; 165: case '2': cp = SUBSEC2; break; 166: case '3': cp = SUBSEC3; break; 167: } 168: while (*cp) { 169: work[last+1] = *cp++; 170: if (stat(work, &stbuf) >= 0) 171: goto found; 172: } 173: work[last+1] = 0; 174: } 175: } 176: if (section == 0) { 177: if (sec == 0) 178: printf("No manual entry for %s.\n", name); 179: else 180: printf("No entry for %s in section %c of the manual.\n", name, sec); 181: return; 182: } 183: } else { 184: work[3] = section; 185: work[last] = section; 186: work[last+1] = subsec; 187: work[last+2] = 0; 188: if (stat(work, &stbuf) < 0) { 189: if ((section >= '1' && section <= '3') && subsec == 0) { 190: sp = "\0"; 191: goto search; 192: } 193: printf("No entry for %s in section %c", name, section); 194: if (subsec) 195: putchar(subsec); 196: printf(" of the manual.\n"); 197: return; 198: } 199: } 200: found: 201: if (troffit) 202: troff(work); 203: else { 204: FILE *it; 205: char abuf[BUFSIZ]; 206: 207: if (!nomore) { 208: it = fopen(work, "r"); 209: if (fgets(abuf, BUFSIZ-1, it) && 210: abuf[0] == '.' && abuf[1] == 's' && 211: abuf[2] == 'o' && abuf[3] == ' ') { 212: register char *cp = abuf+strlen(".so "); 213: char *dp; 214: 215: while (*cp && *cp != '\n') 216: cp++; 217: *cp = 0; 218: while (cp > abuf && *--cp != '/') 219: ; 220: dp = ".so /usr/man/man"; 221: if (cp != abuf+strlen(dp)+1) { 222: tohard: 223: strcpy(work, abuf+4); 224: goto hardway; 225: } 226: for (cp = abuf; *cp == *dp && *cp; cp++, dp++) 227: ; 228: if (*dp) 229: goto tohard; 230: strcpy(work, cp-3); 231: (void) stat(abuf+strlen(".so "), &stbuf); 232: } 233: fclose(it); 234: strcpy(work2, "cat"); 235: strcpy(work2+3, work+3); 236: work2[4] = 0; 237: if (stat(work2, &stbuf2) < 0) 238: goto hardway; 239: strcpy(work2+3, work+3); 240: if (stat(work2, &stbuf2) < 0 241: || stbuf2.st_mtime < stbuf.st_mtime) { 242: printf("Reformatting page. Wait..."); 243: fflush(stdout); 244: unlink(work2); 245: sprintf(cmdbuf, 246: "%s %s |%s> /tmp/man%d; trap '' 1 15; mv /tmp/man%d %s", 247: NROFFCAT, work, SSP, getpid(), getpid(), work2); 248: if (system(cmdbuf)) { 249: printf(" aborted (sorry)\n"); 250: remove(); 251: /*NOTREACHED*/ 252: } 253: printf(" done\n"); 254: } 255: strcpy(work, work2); 256: } 257: hardway: 258: nroff(work); 259: } 260: } 261: 262: nroff(cp) 263: char *cp; 264: { 265: char cmd[BUFSIZ]; 266: 267: if (cp[0] == 'c') 268: sprintf(cmd, "%s %s", nomore? CAT : MORE, cp); 269: else 270: sprintf(cmd, nomore? "%s %s" : "%s %s|%s", NROFF, cp, MORE); 271: system(cmd); 272: } 273: 274: troff(cp) 275: char *cp; 276: { 277: char cmdbuf[BUFSIZ]; 278: 279: sprintf(cmdbuf, "%s %s %s", TROFF1, cp, TROFF2); 280: system(cmdbuf); 281: } 282: 283: any(c, sp) 284: register int c; 285: register char *sp; 286: { 287: register int d; 288: 289: while (d = *sp++) 290: if (c == d) 291: return (1); 292: return (0); 293: } 294: 295: remove() 296: { 297: char name[15]; 298: 299: sprintf(name, "/tmp/man%d", getpid()); 300: unlink(name); 301: exit(1); 302: } 303: 304: apropos(argc, argv) 305: int argc; 306: char **argv; 307: { 308: char buf[BUFSIZ]; 309: char *gotit; 310: register char **vp; 311: 312: if (argc == 0) { 313: fprintf(stderr, "apropos what?\n"); 314: exit(1); 315: } 316: if (freopen("/usr/lib/whatis", "r", stdin) == NULL) { 317: perror("/usr/lib/whatis"); 318: exit (1); 319: } 320: gotit = (char *) calloc(1, blklen(argv)); 321: while (fgets(buf, sizeof buf, stdin) != NULL) 322: for (vp = argv; *vp; vp++) 323: if (match(buf, *vp)) { 324: printf("%s", buf); 325: gotit[vp - argv] = 1; 326: for (vp++; *vp; vp++) 327: if (match(buf, *vp)) 328: gotit[vp - argv] = 1; 329: break; 330: } 331: for (vp = argv; *vp; vp++) 332: if (gotit[vp - argv] == 0) 333: printf("%s: nothing apropriate\n", *vp); 334: } 335: 336: match(buf, str) 337: char *buf, *str; 338: { 339: register char *bp; 340: 341: bp = buf; 342: for (;;) { 343: if (*bp == 0) 344: return (0); 345: if (amatch(bp, str)) 346: return (1); 347: bp++; 348: } 349: } 350: 351: amatch(cp, dp) 352: register char *cp, *dp; 353: { 354: 355: while (*cp && *dp && lmatch(*cp, *dp)) 356: cp++, dp++; 357: if (*dp == 0) 358: return (1); 359: return (0); 360: } 361: 362: lmatch(c, d) 363: char c, d; 364: { 365: 366: if (c == d) 367: return (1); 368: if (!isalpha(c) || !isalpha(d)) 369: return (0); 370: if (islower(c)) 371: c = toupper(c); 372: if (islower(d)) 373: d = toupper(d); 374: return (c == d); 375: } 376: 377: blklen(ip) 378: register char **ip; 379: { 380: register int i = 0; 381: 382: while (*ip++) 383: i++; 384: return (i); 385: } 386: 387: whatis(argc, argv) 388: int argc; 389: char **argv; 390: { 391: register char **avp; 392: 393: if (argc == 0) { 394: fprintf(stderr, "whatis what?\n"); 395: exit(1); 396: } 397: if (freopen("/usr/lib/whatis", "r", stdin) == NULL) { 398: perror("/usr/lib/whatis"); 399: exit (1); 400: } 401: for (avp = argv; *avp; avp++) 402: *avp = trim(*avp); 403: whatisit(argv); 404: exit(0); 405: } 406: 407: whatisit(argv) 408: char **argv; 409: { 410: char buf[BUFSIZ]; 411: register char *gotit; 412: register char **vp; 413: 414: gotit = (char *)calloc(1, blklen(argv)); 415: while (fgets(buf, sizeof buf, stdin) != NULL) 416: for (vp = argv; *vp; vp++) 417: if (wmatch(buf, *vp)) { 418: printf("%s", buf); 419: gotit[vp - argv] = 1; 420: for (vp++; *vp; vp++) 421: if (wmatch(buf, *vp)) 422: gotit[vp - argv] = 1; 423: break; 424: } 425: for (vp = argv; *vp; vp++) 426: if (gotit[vp - argv] == 0) 427: printf("%s: not found\n", *vp); 428: } 429: 430: wmatch(buf, str) 431: char *buf, *str; 432: { 433: register char *bp, *cp; 434: 435: bp = buf; 436: again: 437: cp = str; 438: while (*bp && *cp && lmatch(*bp, *cp)) 439: bp++, cp++; 440: if (*cp == 0 && (*bp == '(' || *bp == ',' || *bp == '\t' || *bp == ' ')) 441: return (1); 442: while (isalpha(*bp) || isdigit(*bp)) 443: bp++; 444: if (*bp != ',') 445: return (0); 446: bp++; 447: while (isspace(*bp)) 448: bp++; 449: goto again; 450: } 451: 452: char * 453: trim(cp) 454: register char *cp; 455: { 456: register char *dp; 457: 458: for (dp = cp; *dp; dp++) 459: if (*dp == '/') 460: cp = dp + 1; 461: if (cp[0] != '.') { 462: if (cp + 3 <= dp && dp[-2] == '.' && any(dp[-1], "cosa12345678npP")) 463: dp[-2] = 0; 464: if (cp + 4 <= dp && dp[-3] == '.' && any(dp[-2], "13") && isalpha(dp[-1])) 465: dp[-3] = 0; 466: } 467: return (cp); 468: } 469: 470: system(s) 471: char *s; 472: { 473: int status, pid, w; 474: 475: if ((pid = vfork()) == 0) { 476: execl("/bin/sh", "sh", "-c", s, 0); 477: _exit(127); 478: } 479: while ((w = wait(&status)) != pid && w != -1) 480: ; 481: if (w == -1) 482: status = -1; 483: return (status); 484: }