root/usr/src/ucbcmd/whereis/whereis.c
/*
 * Copyright 1990 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#include <sys/param.h>
#include <dirent.h>
#include <stdio.h>
#include <ctype.h>

static char *bindirs[] = {
        "/etc",
        "/sbin",
        "/usr/bin",
        "/usr/ccs/bin",
        "/usr/ccs/lib",
        "/usr/lang",
        "/usr/lbin",
        "/usr/lib",
        "/usr/sbin",
        "/usr/ucb",
        "/usr/ucblib",
        "/usr/ucbinclude",
        "/usr/games",
        "/usr/local",
        "/usr/local/bin",
        "/usr/new",
        "/usr/old",
        "/usr/hosts",
        "/usr/include",
        "/usr/etc",
        0
};
static char *mandirs[] = {
        "/usr/man/man1",
        "/usr/man/man1b",
        "/usr/man/man1c",
        "/usr/man/man1f",
        "/usr/man/man1m",
        "/usr/man/man1s",
        "/usr/man/man2",
        "/usr/man/man3",
        "/usr/man/man3b",
        "/usr/man/man3c",
        "/usr/man/man3e",
        "/usr/man/man3g",
        "/usr/man/man3j",
        "/usr/man/man3k",
        "/usr/man/man3l",
        "/usr/man/man3m",
        "/usr/man/man3n",
        "/usr/man/man3s",
        "/usr/man/man3w",
        "/usr/man/man3x",
        "/usr/man/man3x11",
        "/usr/man/man3xt",
        "/usr/man/man4",
        "/usr/man/man4b",
        "/usr/man/man5",
        "/usr/man/man6",
        "/usr/man/man7",
        "/usr/man/man7b",
        "/usr/man/man8",
        "/usr/man/man9e",
        "/usr/man/man9f",
        "/usr/man/man9s",
        "/usr/man/manl",
        "/usr/man/mann",
        "/usr/man/mano",
        0
};
static char *srcdirs[]  = {
        "/usr/src/cmd",
        "/usr/src/head",
        "/usr/src/lib",
        "/usr/src/lib/libc",
        "/usr/src/lib/libc/port",
        "/usr/src/lib/libc/port/gen",
        "/usr/src/lib/libc/port/print",
        "/usr/src/lib/libc/port/stdio",
        "/usr/src/lib/libc/port/sys",
        "/usr/src/lib/libc/sparc",
        "/usr/src/lib/libc/sparc/gen",
        "/usr/src/lib/libc/sparc/sys",
        "/usr/src/ucbcmd",
        "/usr/src/ucblib",
        "/usr/src/ucbinclude",
        "/usr/src/uts",
        "/usr/src/uts/common",
        "/usr/src/uts/sun",
        "/usr/src/uts/sun4",
        "/usr/src/uts/sun4c",
        "/usr/src/uts/sparc",
        "/usr/src/local",
        "/usr/src/new",
        "/usr/src/old",
        0
};

char    sflag = 1;
char    bflag = 1;
char    mflag = 1;
char    **Sflag;
int     Scnt;
char    **Bflag;
int     Bcnt;
char    **Mflag;
int     Mcnt;
char    uflag;

void getlist(int *, char ***, char ***, int *);
void zerof(void);
void lookup(char *);
void looksrc(char *);
void lookbin(char *);
void lookman(char *);
void findv(char **, int, char *);
void find(char **, char *);
void findin(char *, char *);

/*
 * whereis name
 * look for source, documentation and binaries
 */
int
main(int argc, char *argv[])
{

        argc--, argv++;
        if (argc == 0) {
usage:
                fprintf(stderr, "whereis [ -sbmu ] [ -SBM dir ... -f ] "
                    "name...\n");
                exit(1);
        }
        do
                if (argv[0][0] == '-') {
                        char *cp = argv[0] + 1;
                        while (*cp) {

                                switch (*cp++) {

                        case 'f':
                                break;

                        case 'S':
                                getlist(&argc, &argv, &Sflag, &Scnt);
                                break;

                        case 'B':
                                getlist(&argc, &argv, &Bflag, &Bcnt);
                                break;

                        case 'M':
                                getlist(&argc, &argv, &Mflag, &Mcnt);
                                break;

                        case 's':
                                zerof();
                                sflag++;
                                continue;

                        case 'u':
                                uflag++;
                                continue;

                        case 'b':
                                zerof();
                                bflag++;
                                continue;

                        case 'm':
                                zerof();
                                mflag++;
                                continue;

                        default:
                                goto usage;
                                }
                        }
                        argv++;
                } else
                        lookup(*argv++);
        while (--argc > 0);
        return (0);
}

void
getlist(int *argcp, char ***argvp, char ***flagp, int *cntp)
{

        (*argvp)++;
        *flagp = *argvp;
        *cntp = 0;
        for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
                (*cntp)++, (*argvp)++;
        (*argcp)++;
        (*argvp)--;
}

void
zerof(void)
{

        if (sflag && bflag && mflag)
                sflag = bflag = mflag = 0;
}
int     count;
int     print;

void
lookup(char *cp)
{
        char *dp;

        for (dp = cp; *dp; dp++)
                continue;
        for (; dp > cp; dp--) {
                if (*dp == '.') {
                        *dp = 0;
                        break;
                }
        }
        for (dp = cp; *dp; dp++)
                if (*dp == '/')
                        cp = dp + 1;
        if (uflag) {
                print = 0;
                count = 0;
        } else
                print = 1;
again:
        if (print)
                printf("%s:", cp);
        if (sflag) {
                looksrc(cp);
                if (uflag && print == 0 && count != 1) {
                        print = 1;
                        goto again;
                }
        }
        count = 0;
        if (bflag) {
                lookbin(cp);
                if (uflag && print == 0 && count != 1) {
                        print = 1;
                        goto again;
                }
        }
        count = 0;
        if (mflag) {
                lookman(cp);
                if (uflag && print == 0 && count != 1) {
                        print = 1;
                        goto again;
                }
        }
        if (print)
                printf("\n");
}

void
looksrc(char *cp)
{
        if (Sflag == 0) {
                find(srcdirs, cp);
        } else
                findv(Sflag, Scnt, cp);
}

void
lookbin(char *cp)
{
        if (Bflag == 0)
                find(bindirs, cp);
        else
                findv(Bflag, Bcnt, cp);
}

void
lookman(char *cp)
{
        if (Mflag == 0) {
                find(mandirs, cp);
        } else
                findv(Mflag, Mcnt, cp);
}

void
findv(char **dirv, int dirc, char *cp)
{

        while (dirc > 0)
                findin(*dirv++, cp), dirc--;
}

void
find(char **dirs, char *cp)
{

        while (*dirs)
                findin(*dirs++, cp);
}

void
findin(char *dir, char *cp)
{
        DIR *dirp;
        struct dirent *dp;

        dirp = opendir(dir);
        if (dirp == NULL)
                return;
        while ((dp = readdir(dirp)) != NULL) {
                if (itsit(cp, dp->d_name)) {
                        count++;
                        if (print)
                                printf(" %s/%s", dir, dp->d_name);
                }
        }
        closedir(dirp);
}

int
itsit(char *cp, char *dp)
{
        int i = strlen(dp);

        if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
                return (1);
        while (*cp && *dp && *cp == *dp)
                cp++, dp++, i--;
        if (*cp == 0 && *dp == 0)
                return (1);
        while (isdigit(*dp))
                dp++;
        if (*cp == 0 && *dp++ == '.') {
                --i;
                while (i > 0 && *dp)
                        if (--i, *dp++ == '.')
                                return (*dp++ == 'C' && *dp++ == 0);
                return (1);
        }
        return (0);
}