Annotation of 43BSD/ucb/man.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: char copyright[] =
        !             9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)man.c      5.12 (Berkeley) 3/20/86";
        !            15: #endif not lint
        !            16: 
        !            17: #include <stdio.h>
        !            18: #include <ctype.h>
        !            19: #include <sgtty.h>
        !            20: #include <sys/param.h>
        !            21: #include <sys/stat.h>
        !            22: #include <signal.h>
        !            23: #include <strings.h>
        !            24: 
        !            25: /*
        !            26:  * man
        !            27:  * link also to apropos and whatis
        !            28:  * This version uses more for underlining and paging.
        !            29:  */
        !            30: #define        NROFFCAT "nroff -h -man"        /* for nroffing to cat file */
        !            31: #define        NROFF   "nroff -man"            /* for nroffing to tty */
        !            32: #define        MORE    "more -s"               /* paging filter */
        !            33: #define        CAT_    "/bin/cat"              /* for when output is not a tty */
        !            34: #define        CAT_S   "/bin/cat -s"           /* for '-' opt (no more) */
        !            35: 
        !            36: #define TROFFCMD "vtroff -man %s"
        !            37: 
        !            38: #define        ALLSECT "1nl6823457po"  /* order to look through sections */
        !            39: #define        SECT1   "1nlo"          /* sections to look at if 1 is specified */
        !            40: #define        SUBSEC1 "cg"            /* subsections to try in section 1 */
        !            41: #define        SUBSEC3 "sxmncf"
        !            42: #define        SUBSEC4 "pfn"
        !            43: #define        SUBSEC8 "cv"
        !            44: 
        !            45: #define        WHATIS  "whatis"
        !            46: 
        !            47: int    nomore;
        !            48: char   *CAT    = CAT_;
        !            49: char   *manpath = "/usr/man";
        !            50: char   *strcpy();
        !            51: char   *strcat();
        !            52: char   *getenv();
        !            53: char   *calloc();
        !            54: char   *trim();
        !            55: int    remove();
        !            56: int    apropos();
        !            57: int    whatis();
        !            58: int    section;
        !            59: int    subsec;
        !            60: int    troffit;
        !            61: int    mypid;
        !            62: 
        !            63: #define        eq(a,b) (strcmp(a,b) == 0)
        !            64: 
        !            65: main(argc, argv)
        !            66:        int argc;
        !            67:        char *argv[];
        !            68: {
        !            69:        char *mp;
        !            70: 
        !            71:        if ((mp = getenv("MANPATH")) != NULL)
        !            72:                manpath = mp;
        !            73:        umask(0);
        !            74:        mypid = getpid();
        !            75:        if (strcmp(argv[0], "apropos") == 0) {
        !            76:                runpath(argc-1, argv+1, apropos);
        !            77:                exit(0);
        !            78:        }
        !            79:        if (strcmp(argv[0], "whatis") == 0) {
        !            80:                runpath(argc-1, argv+1, whatis);
        !            81:                exit(0);
        !            82:        }
        !            83:        if (argc <= 1) {
        !            84:                fprintf(stderr, "Usage: man [ section ] name ...\n");
        !            85:                exit(1);
        !            86:        }
        !            87:        argc--, argv++;
        !            88:        while (argc > 0 && argv[0][0] == '-') {
        !            89:                switch(argv[0][1]) {
        !            90: 
        !            91:                case 0:
        !            92:                        nomore++;
        !            93:                        CAT = CAT_S;
        !            94:                        break;
        !            95: 
        !            96:                case 't':
        !            97:                        troffit++;
        !            98:                        break;
        !            99: 
        !           100:                case 'k':
        !           101:                        apropos(argc-1, argv+1);
        !           102:                        exit(0);
        !           103: 
        !           104:                case 'f':
        !           105:                        whatis(argc-1, argv+1);
        !           106:                        exit(0);
        !           107: 
        !           108:                case 'P':               /* backwards compatibility */
        !           109:                case 'M':
        !           110:                        if (argc < 2) {
        !           111:                                fprintf(stderr, "%s: missing path\n", *argv);
        !           112:                                exit(1);
        !           113:                        }
        !           114:                        argc--, argv++;
        !           115:                        manpath = *argv;
        !           116:                        break;
        !           117:                }
        !           118:                argc--, argv++;
        !           119:        }
        !           120:        if (troffit == 0 && nomore == 0 && !isatty(1))
        !           121:                nomore++;
        !           122:        section = 0;
        !           123:        do {
        !           124:                if (eq(argv[0], "local")) {
        !           125:                        section = 'l';
        !           126:                        goto sectin;
        !           127:                } else if (eq(argv[0], "new")) {
        !           128:                        section = 'n';
        !           129:                        goto sectin;
        !           130:                } else if (eq(argv[0], "old")) {
        !           131:                        section = 'o';
        !           132:                        goto sectin;
        !           133:                } else if (eq(argv[0], "public")) {
        !           134:                        section = 'p';
        !           135:                        goto sectin;
        !           136:                } else if (isdigit(argv[0][0]) &&
        !           137:                    (argv[0][1] == 0 || argv[0][2] == 0)) {
        !           138:                        section = argv[0][0];
        !           139:                        subsec = argv[0][1];
        !           140: sectin:
        !           141:                        argc--, argv++;
        !           142:                        if (argc == 0) {
        !           143:                                fprintf(stderr,
        !           144:                                    "But what do you want from section %s?\n",
        !           145:                                    argv[-1]);
        !           146:                                exit(1);
        !           147:                        }
        !           148:                        continue;
        !           149:                }
        !           150:                manual(section, argv[0]);
        !           151:                argc--, argv++;
        !           152:        } while (argc > 0);
        !           153:        exit(0);
        !           154: }
        !           155: 
        !           156: runpath(ac, av, f)
        !           157:        int ac;
        !           158:        char *av[];
        !           159:        int (*f)();
        !           160: {
        !           161: 
        !           162:        if (ac > 0 && strcmp(av[0], "-M") == 0 || strcmp(av[0], "-P") == 0) {
        !           163:                if (ac < 2) {
        !           164:                        fprintf(stderr, "%s: missing path\n", av[0]);
        !           165:                        exit(1);
        !           166:                }
        !           167:                manpath = av[1];
        !           168:                ac -= 2, av += 2;
        !           169:        }
        !           170:        (*f)(ac, av);
        !           171:        exit(0);
        !           172: }
        !           173: 
        !           174: manual(sec, name)
        !           175:        char sec, *name;
        !           176: {
        !           177:        char section = sec;
        !           178:        char work[100], work2[100];
        !           179:        char path[MAXPATHLEN+1], realname[MAXPATHLEN+1];
        !           180:        char cmdbuf[150];
        !           181:        int ss = 0;
        !           182:        struct stat stbuf, stbuf2;
        !           183:        int last;
        !           184:        char *sp = ALLSECT;
        !           185:        FILE *it;
        !           186:        char abuf[BUFSIZ];
        !           187: 
        !           188:        strcpy(work, "manx/");
        !           189:        strcat(work, name);
        !           190:        strcat(work, ".x");
        !           191:        last = strlen(work) - 1;
        !           192:        if (section == '1') {
        !           193:                sp = SECT1;
        !           194:                section = 0;
        !           195:        }
        !           196:        if (section == 0) {             /* no section or section 1 given */
        !           197:                for (section = *sp++; section; section = *sp++) {
        !           198:                        work[3] = section;
        !           199:                        work[last] = section;
        !           200:                        work[last+1] = 0;
        !           201:                        work[last+2] = 0;
        !           202:                        if (pathstat(work, path, &stbuf))
        !           203:                                break;
        !           204:                        if (work[last] >= '1' && work[last] <= '8') {
        !           205:                                char *cp;
        !           206: search:
        !           207:                                switch (work[last]) {
        !           208:                                case '1': cp = SUBSEC1; break;
        !           209:                                case '3': cp = SUBSEC3; break;
        !           210:                                case '4': cp = SUBSEC4; break;
        !           211:                                case '8': cp = SUBSEC8; break;
        !           212:                                default:  cp = ""; break;
        !           213:                                }
        !           214:                                while (*cp) {
        !           215:                                        work[last+1] = *cp++;
        !           216:                                        if (pathstat(work, path, &stbuf)) {
        !           217:                                                ss = work[last+1];
        !           218:                                                goto found;
        !           219:                                        }
        !           220:                                }
        !           221:                                if (ss == 0)
        !           222:                                        work[last+1] = 0;
        !           223:                        }
        !           224:                }
        !           225:                if (section == 0) {
        !           226:                        if (sec == 0)
        !           227:                                printf("No manual entry for %s.\n", name);
        !           228:                        else
        !           229:                                printf("No entry for %s in section %c%s.\n",
        !           230:                                   name, sec, " of the manual");
        !           231:                        return;
        !           232:                }
        !           233:        } else {                        /* section given */
        !           234:                work[3] = section;
        !           235:                work[last] = section;
        !           236:                work[last+1] = subsec;
        !           237:                work[last+2] = 0;
        !           238:                if (!pathstat(work, path, &stbuf)) {
        !           239:                        if ((section >= '1' && section <= '8') && subsec == 0) {
        !           240:                                sp = "\0";
        !           241:                                goto search;
        !           242:                        }
        !           243:                        else if (section == 'o') {      /* XXX */
        !           244:                                char *cp;
        !           245:                                char sec;
        !           246:                                for (sec = '0'; sec <= '8'; sec++) {
        !           247:                                        work[last] = sec;
        !           248:                                        if (pathstat(work, path, &stbuf))
        !           249:                                                goto found;
        !           250:                                        switch (work[last]) {
        !           251:                                        case '1': cp = SUBSEC1; break;
        !           252:                                        case '3': cp = SUBSEC3; break;
        !           253:                                        case '4': cp = SUBSEC4; break;
        !           254:                                        case '8': cp = SUBSEC8; break;
        !           255:                                        default:  cp = ""; break;
        !           256:                                        }
        !           257:                                        while (*cp) {
        !           258:                                                work[last+1] = *cp++;
        !           259:                                                if (pathstat(work, path, &stbuf)) {
        !           260:                                                        ss = work[last+1];
        !           261:                                                        goto found;
        !           262:                                                }
        !           263:                                        }
        !           264:                                        if (ss == 0)
        !           265:                                                work[last+1] = 0;
        !           266:                                }
        !           267:                        }
        !           268:                        printf("No entry for %s in section %c", name, section);
        !           269:                        if (subsec)
        !           270:                                putchar(subsec);
        !           271:                        printf(" of the manual.\n");
        !           272:                        return;
        !           273:                }
        !           274:        }
        !           275: found:
        !           276:        sprintf(realname, "%s/%s", path, work);
        !           277:        if (troffit) {
        !           278:                troff(path, work);
        !           279:                return;
        !           280:        }
        !           281:        if (!nomore) {
        !           282:                if ((it = fopen(realname, "r")) == NULL) {
        !           283:                        goto catit;
        !           284:                }
        !           285:                if (fgets(abuf, BUFSIZ-1, it) &&
        !           286:                   strncmp(abuf, ".so ", 4) == 0) {
        !           287:                        register char *cp = abuf+4;
        !           288:                        char *dp;
        !           289: 
        !           290:                        while (*cp && *cp != '\n')
        !           291:                                cp++;
        !           292:                        *cp = 0;
        !           293:                        while (cp > abuf && *--cp != '/')
        !           294:                                ;
        !           295:                        dp = ".so man";
        !           296:                        if (cp != abuf+strlen(dp)+1) {
        !           297: tohard:
        !           298:                                fclose(it);
        !           299:                                nomore = 1;
        !           300:                                strcpy(work, abuf+4);
        !           301:                                goto hardway;
        !           302:                        }
        !           303:                        for (cp = abuf; *cp == *dp && *cp; cp++, dp++)
        !           304:                                ;
        !           305:                        if (*dp)
        !           306:                                goto tohard;
        !           307:                        strcpy(work, cp-3);
        !           308:                }
        !           309:                fclose(it);
        !           310:        }
        !           311: catit:
        !           312:        strcpy(work2, "cat");
        !           313:        work2[3] = work[3];
        !           314:        work2[4] = 0;
        !           315:        sprintf(realname, "%s/%s", path, work2);
        !           316:        if (stat(realname, &stbuf2) < 0)
        !           317:                goto hardway;
        !           318:        strcpy(work2+4, work+4);
        !           319:        sprintf(realname, "%s/%s", path, work2);
        !           320:        if (stat(realname, &stbuf2) < 0 || stbuf2.st_mtime < stbuf.st_mtime) {
        !           321:                if (nomore)
        !           322:                        goto hardway;
        !           323:                printf("Reformatting page.  Wait...");
        !           324:                fflush(stdout);
        !           325:                unlink(work2);
        !           326:                if (signal(SIGINT, SIG_IGN) == SIG_DFL) {
        !           327:                        (void) signal(SIGINT, remove);
        !           328:                        (void) signal(SIGQUIT, remove);
        !           329:                        (void) signal(SIGTERM, remove);
        !           330:                }
        !           331:                sprintf(cmdbuf, "%s %s/%s > /tmp/man%d; trap '' 1 15",
        !           332:                        NROFFCAT, path, work, mypid);
        !           333:                if (system(cmdbuf)) {
        !           334:                        printf(" aborted (sorry)\n");
        !           335:                        remove();
        !           336:                        /*NOTREACHED*/
        !           337:                }
        !           338:                sprintf(cmdbuf, "/bin/mv -f /tmp/man%d %s/%s 2>/dev/null",
        !           339:                        mypid, path, work2);
        !           340:                if (system(cmdbuf)) {
        !           341:                        sprintf(path,  "/");
        !           342:                        sprintf(work2, "tmp/man%d", mypid);
        !           343:                }
        !           344:                printf(" done\n");
        !           345:        }
        !           346:        strcpy(work, work2);
        !           347: hardway:
        !           348:        nroff(path, work);
        !           349:        if (work2[0] == 't')
        !           350:                remove();
        !           351: }
        !           352: 
        !           353: /*
        !           354:  * Use the manpath to look for
        !           355:  * the file name.  The result of
        !           356:  * stat is returned in stbuf, the
        !           357:  * successful path in path.
        !           358:  */
        !           359: pathstat(name, path, stbuf)
        !           360:        char *name, path[];
        !           361:        struct stat *stbuf;
        !           362: {
        !           363:        char *cp, *tp, *ep;
        !           364:        char **cpp;
        !           365:        static char *manpaths[] = {"man", "cat", 0};
        !           366:        static char *nopaths[]  = {"", 0};
        !           367: 
        !           368:        if (strncmp(name, "man", 3) == 0)
        !           369:                cpp = manpaths;
        !           370:        else
        !           371:                cpp = nopaths;
        !           372:        for ( ; *cpp ; cpp++) {
        !           373:                for (cp = manpath; cp && *cp; cp = tp) {
        !           374:                        tp = index(cp, ':');
        !           375:                        if (tp) {
        !           376:                                if (tp == cp) {
        !           377:                                        sprintf(path, "%s%s", *cpp,
        !           378:                                                name+strlen(*cpp));
        !           379:                                }
        !           380:                                else {
        !           381:                                        sprintf(path, "%.*s/%s%s", tp-cp, cp, 
        !           382:                                                *cpp, name+strlen(*cpp));
        !           383:                                }
        !           384:                                ep = path + (tp-cp);
        !           385:                                tp++;
        !           386:                        } else {
        !           387:                                sprintf(path, "%s/%s%s", cp, *cpp,
        !           388:                                        name+strlen(*cpp));
        !           389:                                ep = path + strlen(cp);
        !           390:                        }
        !           391:                        if (stat(path, stbuf) >= 0) {
        !           392:                                *ep = '\0';
        !           393:                                return (1);
        !           394:                        }
        !           395:                }
        !           396:        }
        !           397:        return (0);
        !           398: }
        !           399: 
        !           400: nroff(pp, wp)
        !           401:        char *pp, *wp;
        !           402: {
        !           403:        char cmd[BUFSIZ];
        !           404: 
        !           405:        chdir(pp);
        !           406:        if (wp[0] == 'c' || wp[0] == 't')
        !           407:                sprintf(cmd, "%s %s", nomore? CAT : MORE, wp);
        !           408:        else
        !           409:                sprintf(cmd, nomore? "%s %s" : "%s %s|%s", NROFF, wp, MORE);
        !           410:        (void) system(cmd);
        !           411: }
        !           412: 
        !           413: troff(pp, wp)
        !           414:        char *pp, *wp;
        !           415: {
        !           416:        char cmdbuf[BUFSIZ];
        !           417: 
        !           418:        chdir(pp);
        !           419:        sprintf(cmdbuf, TROFFCMD, wp);
        !           420:        (void) system(cmdbuf);
        !           421: }
        !           422: 
        !           423: any(c, sp)
        !           424:        register int c;
        !           425:        register char *sp;
        !           426: {
        !           427:        register int d;
        !           428: 
        !           429:        while (d = *sp++)
        !           430:                if (c == d)
        !           431:                        return (1);
        !           432:        return (0);
        !           433: }
        !           434: 
        !           435: remove()
        !           436: {
        !           437:        char name[15];
        !           438: 
        !           439:        sprintf(name, "/tmp/man%d", mypid);
        !           440:        unlink(name);
        !           441:        exit(1);
        !           442: }
        !           443: 
        !           444: unsigned int
        !           445: blklen(ip)
        !           446:        register char **ip;
        !           447: {
        !           448:        register unsigned int i = 0;
        !           449: 
        !           450:        while (*ip++)
        !           451:                i++;
        !           452:        return (i);
        !           453: }
        !           454: 
        !           455: apropos(argc, argv)
        !           456:        int argc;
        !           457:        char **argv;
        !           458: {
        !           459:        char buf[BUFSIZ], file[MAXPATHLEN+1];
        !           460:        char *gotit, *cp, *tp;
        !           461:        register char **vp;
        !           462: 
        !           463:        if (argc == 0) {
        !           464:                fprintf(stderr, "apropos what?\n");
        !           465:                exit(1);
        !           466:        }
        !           467:        gotit = calloc(1, blklen(argv));
        !           468:        for (cp = manpath; cp; cp = tp) {
        !           469:                tp = index(cp, ':');
        !           470:                if (tp) {
        !           471:                        if (tp == cp)
        !           472:                                strcpy(file, WHATIS);
        !           473:                        else
        !           474:                                sprintf(file, "%.*s/%s", tp-cp, cp, WHATIS);
        !           475:                        tp++;
        !           476:                } else
        !           477:                        sprintf(file, "%s/%s", cp, WHATIS);
        !           478:                if (freopen(file, "r", stdin) == NULL)
        !           479:                        continue;
        !           480:                while (fgets(buf, sizeof buf, stdin) != NULL)
        !           481:                        for (vp = argv; *vp; vp++)
        !           482:                                if (match(buf, *vp)) {
        !           483:                                        printf("%s", buf);
        !           484:                                        gotit[vp - argv] = 1;
        !           485:                                        for (vp++; *vp; vp++)
        !           486:                                                if (match(buf, *vp))
        !           487:                                                        gotit[vp - argv] = 1;
        !           488:                                        break;
        !           489:                                }
        !           490:        }
        !           491:        for (vp = argv; *vp; vp++)
        !           492:                if (gotit[vp - argv] == 0)
        !           493:                        printf("%s: nothing appropriate\n", *vp);
        !           494: }
        !           495: 
        !           496: match(bp, str)
        !           497:        register char *bp;
        !           498:        char *str;
        !           499: {
        !           500: 
        !           501:        for (;;) {
        !           502:                if (*bp == 0)
        !           503:                        return (0);
        !           504:                if (amatch(bp, str))
        !           505:                        return (1);
        !           506:                bp++;
        !           507:        }
        !           508: }
        !           509: 
        !           510: amatch(cp, dp)
        !           511:        register char *cp, *dp;
        !           512: {
        !           513: 
        !           514:        while (*cp && *dp && lmatch(*cp, *dp))
        !           515:                cp++, dp++;
        !           516:        if (*dp == 0)
        !           517:                return (1);
        !           518:        return (0);
        !           519: }
        !           520: 
        !           521: lmatch(c, d)
        !           522:        register int c, d;
        !           523: {
        !           524: 
        !           525:        if (c == d)
        !           526:                return (1);
        !           527:        if (!isalpha(c) || !isalpha(d))
        !           528:                return (0);
        !           529:        if (islower(c))
        !           530:                c = toupper(c);
        !           531:        if (islower(d))
        !           532:                d = toupper(d);
        !           533:        return (c == d);
        !           534: }
        !           535: 
        !           536: whatis(argc, argv)
        !           537:        int argc;
        !           538:        char **argv;
        !           539: {
        !           540:        register char *gotit, **vp;
        !           541:        char buf[BUFSIZ], file[MAXPATHLEN+1], *cp, *tp;
        !           542: 
        !           543:        if (argc == 0) {
        !           544:                fprintf(stderr, "whatis what?\n");
        !           545:                exit(1);
        !           546:        }
        !           547:        for (vp = argv; *vp; vp++)
        !           548:                *vp = trim(*vp);
        !           549:        gotit = calloc(1, blklen(argv));
        !           550:        for (cp = manpath; cp; cp = tp) {
        !           551:                tp = index(cp, ':');
        !           552:                if (tp) {
        !           553:                        if (tp == cp)
        !           554:                                strcpy(file, WHATIS);
        !           555:                        else
        !           556:                                sprintf(file, "%.*s/%s", tp-cp, cp, WHATIS);
        !           557:                        tp++;
        !           558:                } else
        !           559:                        sprintf(file, "%s/%s", cp, WHATIS);
        !           560:                if (freopen(file, "r", stdin) == NULL)
        !           561:                        continue;
        !           562:                while (fgets(buf, sizeof buf, stdin) != NULL)
        !           563:                        for (vp = argv; *vp; vp++)
        !           564:                                if (wmatch(buf, *vp)) {
        !           565:                                        printf("%s", buf);
        !           566:                                        gotit[vp - argv] = 1;
        !           567:                                        for (vp++; *vp; vp++)
        !           568:                                                if (wmatch(buf, *vp))
        !           569:                                                        gotit[vp - argv] = 1;
        !           570:                                        break;
        !           571:                                }
        !           572:        }
        !           573:        for (vp = argv; *vp; vp++)
        !           574:                if (gotit[vp - argv] == 0)
        !           575:                        printf("%s: not found\n", *vp);
        !           576: }
        !           577: 
        !           578: wmatch(buf, str)
        !           579:        char *buf, *str;
        !           580: {
        !           581:        register char *bp, *cp;
        !           582: 
        !           583:        bp = buf;
        !           584: again:
        !           585:        cp = str;
        !           586:        while (*bp && *cp && lmatch(*bp, *cp))
        !           587:                bp++, cp++;
        !           588:        if (*cp == 0 && (*bp == '(' || *bp == ',' || *bp == '\t' || *bp == ' '))
        !           589:                return (1);
        !           590:        while (isalpha(*bp) || isdigit(*bp))
        !           591:                bp++;
        !           592:        if (*bp != ',')
        !           593:                return (0);
        !           594:        bp++;
        !           595:        while (isspace(*bp))
        !           596:                bp++;
        !           597:        goto again;
        !           598: }
        !           599: 
        !           600: char *
        !           601: trim(cp)
        !           602:        register char *cp;
        !           603: {
        !           604:        register char *dp;
        !           605: 
        !           606:        for (dp = cp; *dp; dp++)
        !           607:                if (*dp == '/')
        !           608:                        cp = dp + 1;
        !           609:        if (cp[0] != '.') {
        !           610:                if (cp + 3 <= dp && dp[-2] == '.' &&
        !           611:                    any(dp[-1], "cosa12345678npP"))
        !           612:                        dp[-2] = 0;
        !           613:                if (cp + 4 <= dp && dp[-3] == '.' &&
        !           614:                    any(dp[-2], "13") && isalpha(dp[-1]))
        !           615:                        dp[-3] = 0;
        !           616:        }
        !           617:        return (cp);
        !           618: }

unix.superglobalmegacorp.com

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