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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1987 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that the above copyright notice and this paragraph are
        !             7:  * duplicated in all such forms and that any documentation,
        !             8:  * advertising materials, and other materials related to such
        !             9:  * distribution and use acknowledge that the software was developed
        !            10:  * by the University of California, Berkeley.  The name of the
        !            11:  * University may not be used to endorse or promote products derived
        !            12:  * from this software without specific prior written permission.
        !            13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: char copyright[] =
        !            20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
        !            21:  All rights reserved.\n";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #ifndef lint
        !            25: static char sccsid[] = "@(#)man.c      5.17 (Berkeley) 6/29/88";
        !            26: #endif /* not lint */
        !            27: 
        !            28: #include <sys/param.h>
        !            29: #include <sys/file.h>
        !            30: #include <stdio.h>
        !            31: #include <ctype.h>
        !            32: 
        !            33: #define        DEF_PAGER       "/usr/ucb/more -s"
        !            34: #define        DEF_PATH        "/usr/man:/usr/new/man:/usr/local/man"
        !            35: #define        LOCAL_PATH      "/usr/local/man"
        !            36: #define        NEW_PATH        "/usr/new/man"
        !            37: 
        !            38: #define        NO      0
        !            39: #define        YES     1
        !            40: 
        !            41: static char    *command,               /* command buffer */
        !            42:                *defpath,               /* default search path */
        !            43:                *locpath,               /* local search path */
        !            44:                *machine,               /* machine type */
        !            45:                *manpath,               /* current search path */
        !            46:                *newpath,               /* new search path */
        !            47:                *pager,                 /* requested pager */
        !            48:                how;                    /* how to display */
        !            49: 
        !            50: #define        ALL     0x1                     /* show all man pages */
        !            51: #define        CAT     0x2                     /* copy file to stdout */
        !            52: #define        WHERE   0x4                     /* just tell me where */
        !            53: 
        !            54: main(argc, argv)
        !            55:        int argc;
        !            56:        register char **argv;
        !            57: {
        !            58:        extern char *optarg;
        !            59:        extern int optind;
        !            60:        int ch;
        !            61:        char *getenv(), *malloc();
        !            62: 
        !            63:        while ((ch = getopt(argc, argv, "-M:P:afkw")) != EOF)
        !            64:                switch((char)ch) {
        !            65:                case '-':
        !            66:                        how |= CAT;
        !            67:                        break;
        !            68:                case 'M':
        !            69:                case 'P':               /* backward compatibility */
        !            70:                        defpath = optarg;
        !            71:                        break;
        !            72:                case 'a':
        !            73:                        how |= ALL;
        !            74:                        break;
        !            75:                /*
        !            76:                 * "man -f" and "man -k" are backward contemptible,
        !            77:                 * undocumented ways of calling whatis(1) and apropos(1).
        !            78:                 */
        !            79:                case 'f':
        !            80:                        jump(argv, "-f", "whatis");
        !            81:                        /*NOTREACHED*/
        !            82:                case 'k':
        !            83:                        jump(argv, "-k", "apropos");
        !            84:                        /*NOTREACHED*/
        !            85:                /*
        !            86:                 * Deliberately undocumented; really only useful when
        !            87:                 * you're moving man pages around.  Not worth adding.
        !            88:                 */
        !            89:                case 'w':
        !            90:                        how |= WHERE | ALL;
        !            91:                        break;
        !            92:                case '?':
        !            93:                default:
        !            94:                        usage();
        !            95:                }
        !            96:        argv += optind;
        !            97: 
        !            98:        if (!*argv)
        !            99:                usage();
        !           100: 
        !           101:        if (!(how & CAT))
        !           102:                if (!isatty(1))
        !           103:                        how |= CAT;
        !           104:                else if (pager = getenv("PAGER")) {
        !           105:                        register char *p;
        !           106: 
        !           107:                        /*
        !           108:                         * if the user uses "more", we make it "more -s"
        !           109:                         * watch out for PAGER = "mypager /usr/ucb/more"
        !           110:                         */
        !           111:                        for (p = pager; *p && !isspace(*p); ++p);
        !           112:                        for (; p > pager && *p != '/'; --p);
        !           113:                        if (p != pager)
        !           114:                                ++p;
        !           115:                        /* make sure it's "more", not "morex" */
        !           116:                        if (!strncmp(p, "more", 4) && (!p[4] || isspace(p[4]))){
        !           117:                                char *opager = pager;
        !           118:                                /*
        !           119:                                 * allocate space to add the "-s"
        !           120:                                 */
        !           121:                                if (!(pager = malloc((u_int)(strlen(opager) 
        !           122:                                    + sizeof("-s") + 1)))) {
        !           123:                                        fputs("man: out of space.\n", stderr);
        !           124:                                        exit(1);
        !           125:                                }
        !           126:                                (void)sprintf(pager, "%s %s", opager, "-s");
        !           127:                        }
        !           128:                }
        !           129:                else
        !           130:                        pager = DEF_PAGER;
        !           131:        if (!(machine = getenv("MACHINE")))
        !           132:                machine = MACHINE;
        !           133:        if (!defpath && !(defpath = getenv("MANPATH")))
        !           134:                defpath = DEF_PATH;
        !           135:        locpath = LOCAL_PATH;
        !           136:        newpath = NEW_PATH;
        !           137:        man(argv);
        !           138:        /* use system(3) in case someone's pager is "pager arg1 arg2" */
        !           139:        if (command)
        !           140:                (void)system(command);
        !           141:        exit(0);
        !           142: }
        !           143: 
        !           144: typedef struct {
        !           145:        char    *name, *msg;
        !           146: } DIR;
        !           147: static DIR     list1[] = {             /* section one list */
        !           148:        "cat1", "1st",          "cat8", "8th",          "cat6", "6th",
        !           149:        "cat.old", "old",       NULL, NULL,
        !           150: },             list2[] = {             /* rest of the list */
        !           151:        "cat2", "2nd",          "cat3", "3rd",          "cat4", "4th",
        !           152:        "cat5", "5th",          "cat7", "7th",          "cat3f", "3rd (F)",
        !           153:        NULL, NULL,
        !           154: },             list3[2];               /* single section */
        !           155: 
        !           156: static
        !           157: man(argv)
        !           158:        char **argv;
        !           159: {
        !           160:        register char *p;
        !           161:        DIR *section, *getsect();
        !           162:        int res;
        !           163: 
        !           164:        for (; *argv; ++argv) {
        !           165:                manpath = defpath;
        !           166:                section = NULL;
        !           167:                switch(**argv) {
        !           168:                case 'l':                               /* local */
        !           169:                        /* support the "{l,local,n,new}###"  syntax */
        !           170:                        for (p = *argv; isalpha(*p); ++p);
        !           171:                        if (!strncmp(*argv, "l", p - *argv) ||
        !           172:                            !strncmp(*argv, "local", p - *argv)) {
        !           173:                                ++argv;
        !           174:                                manpath = locpath;
        !           175:                                section = getsect(p);
        !           176:                        }
        !           177:                        break;
        !           178:                case 'n':                               /* new */
        !           179:                        for (p = *argv; isalpha(*p); ++p);
        !           180:                        if (!strncmp(*argv, "n", p - *argv) ||
        !           181:                            !strncmp(*argv, "new", p - *argv)) {
        !           182:                                ++argv;
        !           183:                                manpath = newpath;
        !           184:                                section = getsect(p);
        !           185:                        }
        !           186:                        break;
        !           187:                /*
        !           188:                 * old isn't really a separate section of the manual,
        !           189:                 * and its entries are all in a single directory.
        !           190:                 */
        !           191:                case 'o':                               /* old */
        !           192:                        for (p = *argv; isalpha(*p); ++p);
        !           193:                        if (!strncmp(*argv, "o", p - *argv) ||
        !           194:                            !strncmp(*argv, "old", p - *argv)) {
        !           195:                                ++argv;
        !           196:                                list3[0] = list1[3];
        !           197:                                section = list3;
        !           198:                        }
        !           199:                        break;
        !           200:                case '1': case '2': case '3': case '4':
        !           201:                case '5': case '6': case '7': case '8':
        !           202:                        if (section = getsect(*argv))
        !           203:                                ++argv;
        !           204:                }
        !           205: 
        !           206:                if (*argv) {
        !           207:                        if (section)
        !           208:                                res = manual(section, *argv);
        !           209:                        else {
        !           210:                                res = manual(list1, *argv);
        !           211:                                if (!res || (how & ALL))
        !           212:                                        res += manual(list2, *argv);
        !           213:                        }
        !           214:                        if (res || how&WHERE)
        !           215:                                continue;
        !           216:                }
        !           217: 
        !           218:                fputs("man: ", stderr);
        !           219:                if (*argv)
        !           220:                        fprintf(stderr, "no entry for %s in the ", *argv);
        !           221:                else
        !           222:                        fputs("what do you want from the ", stderr);
        !           223:                if (section)
        !           224:                        fprintf(stderr, "%s section of the ", section->msg);
        !           225:                if (manpath == locpath)
        !           226:                        fputs("local ", stderr);
        !           227:                else if (manpath == newpath)
        !           228:                        fputs("new ", stderr);
        !           229:                if (*argv)
        !           230:                        fputs("manual.\n", stderr);
        !           231:                else
        !           232:                        fputs("manual?\n", stderr);
        !           233:                exit(1);
        !           234:        }
        !           235: }
        !           236: 
        !           237: /*
        !           238:  * manual --
        !           239:  *     given a directory list and a file name find a file that
        !           240:  *     matches; check ${directory}/${dir}/{file name} and
        !           241:  *     ${directory}/${dir}/${machine}/${file name}.
        !           242:  */
        !           243: static
        !           244: manual(section, name)
        !           245:        DIR *section;
        !           246:        char *name;
        !           247: {
        !           248:        register char *beg, *end;
        !           249:        register DIR *dp;
        !           250:        register int res;
        !           251:        char fname[MAXPATHLEN + 1], *index();
        !           252: 
        !           253:        for (beg = manpath, res = 0;; beg = end + 1) {
        !           254:                if (end = index(beg, ':'))
        !           255:                        *end = '\0';
        !           256:                for (dp = section; dp->name; ++dp) {
        !           257:                        (void)sprintf(fname, "%s/%s/%s.0", beg, dp->name, name);
        !           258:                        if (access(fname, R_OK)) {
        !           259:                                (void)sprintf(fname, "%s/%s/%s/%s.0", beg,
        !           260:                                    dp->name, machine, name);
        !           261:                                if (access(fname, R_OK))
        !           262:                                        continue;
        !           263:                        }
        !           264:                        if (how & WHERE)
        !           265:                                printf("man: found in %s.\n", fname);
        !           266:                        else if (how & CAT)
        !           267:                                cat(fname);
        !           268:                        else
        !           269:                                add(fname);
        !           270:                        if (!(how & ALL))
        !           271:                                return(1);
        !           272:                        res = 1;
        !           273:                }
        !           274:                if (!end)
        !           275:                        return(res);
        !           276:                *end = ':';
        !           277:        }
        !           278:        /*NOTREACHED*/
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * cat --
        !           283:  *     cat out the file
        !           284:  */
        !           285: static
        !           286: cat(fname)
        !           287:        char *fname;
        !           288: {
        !           289:        register int fd, n;
        !           290:        char buf[BUFSIZ];
        !           291: 
        !           292:        if (!(fd = open(fname, O_RDONLY, 0))) {
        !           293:                perror("man: open");
        !           294:                exit(1);
        !           295:        }
        !           296:        while ((n = read(fd, buf, sizeof(buf))) > 0)
        !           297:                if (write(1, buf, n) != n) {
        !           298:                        perror("man: write");
        !           299:                        exit(1);
        !           300:                }
        !           301:        if (n == -1) {
        !           302:                perror("man: read");
        !           303:                exit(1);
        !           304:        }
        !           305:        (void)close(fd);
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * add --
        !           310:  *     add a file name to the list for future paging
        !           311:  */
        !           312: static
        !           313: add(fname)
        !           314:        char *fname;
        !           315: {
        !           316:        static u_int buflen;
        !           317:        static int len;
        !           318:        static char *cp;
        !           319:        int flen;
        !           320:        char *malloc(), *realloc(), *strcpy();
        !           321: 
        !           322:        if (!command) {
        !           323:                if (!(command = malloc(buflen = 1024))) {
        !           324:                        fputs("man: out of space.\n", stderr);
        !           325:                        exit(1);
        !           326:                }
        !           327:                len = strlen(strcpy(command, pager));
        !           328:                cp = command + len;
        !           329:        }
        !           330:        flen = strlen(fname);
        !           331:        if (len + flen + 2 > buflen) {          /* +2 == space, EOS */
        !           332:                if (!(command = realloc(command, buflen += 1024))) {
        !           333:                        fputs("man: out of space.\n", stderr);
        !           334:                        exit(1);
        !           335:                }
        !           336:                cp = command + len;
        !           337:        }
        !           338:        *cp++ = ' ';
        !           339:        len += flen + 1;                        /* +1 = space */
        !           340:        (void)strcpy(cp, fname);
        !           341:        cp += flen;
        !           342: }
        !           343: 
        !           344: /*
        !           345:  * getsect --
        !           346:  *     return a point to the section structure for a particular suffix
        !           347:  */
        !           348: static DIR *
        !           349: getsect(s)
        !           350:        char *s;
        !           351: {
        !           352:        switch(*s++) {
        !           353:        case '1':
        !           354:                if (!*s)
        !           355:                        return(list1);
        !           356:                break;
        !           357:        case '2':
        !           358:                if (!*s) {
        !           359:                        list3[0] = list2[0];
        !           360:                        return(list3);
        !           361:                }
        !           362:                break;
        !           363:        /* sect. 3 requests are for either section 3, or section 3[fF]. */
        !           364:        case '3':
        !           365:                if (!*s) {
        !           366:                        list3[0] = list2[1];
        !           367:                        return(list3);
        !           368:                }
        !           369:                else if ((*s == 'f'  || *s == 'F') && !*++s) {
        !           370:                        list3[0] = list2[5];
        !           371:                        return(list3);
        !           372:                }
        !           373:                break;
        !           374:        case '4':
        !           375:                if (!*s) {
        !           376:                        list3[0] = list2[2];
        !           377:                        return(list3);
        !           378:                }
        !           379:                break;
        !           380:        case '5':
        !           381:                if (!*s) {
        !           382:                        list3[0] = list2[3];
        !           383:                        return(list3);
        !           384:                }
        !           385:                break;
        !           386:        case '6':
        !           387:                if (!*s) {
        !           388:                        list3[0] = list1[2];
        !           389:                        return(list3);
        !           390:                }
        !           391:                break;
        !           392:        case '7':
        !           393:                if (!*s) {
        !           394:                        list3[0] = list2[4];
        !           395:                        return(list3);
        !           396:                }
        !           397:                break;
        !           398:        case '8':
        !           399:                if (!*s) {
        !           400:                        list3[0] = list1[1];
        !           401:                        return(list3);
        !           402:                }
        !           403:        }
        !           404:        return((DIR *)NULL);
        !           405: }
        !           406: 
        !           407: /*
        !           408:  * jump --
        !           409:  *     strip out flag argument and jump
        !           410:  */
        !           411: static
        !           412: jump(argv, flag, name)
        !           413:        char **argv, *name;
        !           414:        register char *flag;
        !           415: {
        !           416:        register char **arg;
        !           417: 
        !           418:        argv[0] = name;
        !           419:        for (arg = argv + 1; *arg; ++arg)
        !           420:                if (!strcmp(*arg, flag))
        !           421:                        break;
        !           422:        for (; *arg; ++arg)
        !           423:                arg[0] = arg[1];
        !           424:        execvp(name, argv);
        !           425:        fprintf(stderr, "%s: Command not found.\n", name);
        !           426:        exit(1);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * usage --
        !           431:  *     print usage and die
        !           432:  */
        !           433: static
        !           434: usage()
        !           435: {
        !           436:        fputs("usage: man [-] [-a] [-M path] [section] title ...\n", stderr);
        !           437:        exit(1);
        !           438: }

unix.superglobalmegacorp.com

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