Annotation of coherent/d/bin/which.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * locate a program file along the user's PATH.
                      3:  * try to mimic output of the BSD version.
                      4:  */
                      5: #include <stdio.h>
                      6: #include <sys/stat.h>
                      7: #include <access.h>
                      8: 
                      9: char   *getenv();
                     10: char   *index();
                     11: char   **parsepath();          /* parse PATH into argv-like structure */
                     12: void   fatal();                /* display error message and die */
                     13: void   usage();                /* display usage message and die */
                     14: char   *calloc();
                     15: char   *index();
                     16: 
                     17: #define        TRUE            (0 == 0)
                     18: #define        FALSE           (0 != 0)
                     19: #define        EXEC_BITS       (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6))
                     20: 
                     21: main(argc, argv)
                     22: int    argc;
                     23: char   *argv[];
                     24: {
                     25:        char    *pathp;                         /* pointer to PATH string */
                     26:        char    **pathpp;                       /* pointer to path entries */
                     27:        char    **pathlist;                     /* pointer to path list */
                     28:        static  char    pathbuf[BUFSIZ];        /* expanded file names */
                     29:        static  char    path[BUFSIZ];           /* saved copy for error msgs */
                     30: 
                     31:        if ((pathp = getenv("PATH")) == NULL)
                     32:                fatal("PATH not found in environment");
                     33:        strcpy(path, pathp);
                     34:        if (--argc < 1)
                     35:                usage();
                     36:        pathlist = parsepath(pathp);
                     37: 
                     38:        for (++argv; argc-- > 0; ++argv) {
                     39:                pathpp = pathlist;
                     40:                for ( ; *pathpp != NULL; ++pathpp) {
                     41:                        if (**pathpp != '\0') {
                     42:                                strcpy(pathbuf, *pathpp);
                     43:                                strcat(pathbuf, "/");
                     44:                                strcat(pathbuf, *argv);
                     45:                        } else
                     46:                                strcpy(pathbuf, *argv);
                     47:                        if (is_exec(pathbuf)) {
                     48:                                puts(pathbuf);
                     49:                                break;
                     50:                        }
                     51:                }
                     52:                if (*pathpp == NULL)
                     53:                        if (index(*argv, '/') != NULL)
                     54:                                printf("%s not found\n", *argv);
                     55:                        else
                     56:                                printf("no %s in %s\n", *argv, path);
                     57:        }
                     58:        exit(0);
                     59: }
                     60: 
                     61: /*
                     62:  * check to see if the given name is executable.
                     63:  * this isn't as trivial as it may seem since access() says
                     64:  * that root (UID 0) can execute anything, even if the
                     65:  * execute mode bits are not set.
                     66:  */
                     67: is_exec(name)
                     68: char   *name;
                     69: {
                     70:        static  struct  stat    statbuf;
                     71: 
                     72:        if (access(name, AEXEC) != 0)
                     73:                return FALSE;
                     74:        if (stat(name, &statbuf) == -1) {
                     75:                fprintf(stderr, "%s: Unable to stat\n", name);
                     76:                return FALSE;
                     77:        }
                     78:        if ((statbuf.st_mode & S_IFMT) != S_IFREG)
                     79:                return FALSE;
                     80:        return (getuid() != 0 || (statbuf.st_mode & EXEC_BITS));
                     81: }
                     82: 
                     83: /*
                     84:  * parse a path of the form dir1:dir2:dir3 into an array of pointers to
                     85:  * the individual directory entries. Note that this null terminates each
                     86:  * directory entry by replacing all ':' characters in "path" with NUL's. 
                     87:  * take special care of leading and trailing ':' which imply the current
                     88:  * directory.
                     89:  */
                     90: char   **
                     91: parsepath(path)
                     92: char   *path;
                     93: {
                     94:        register char   *cp;
                     95:        register int    i = 1;
                     96:        char    **patharray, **pp;
                     97: 
                     98:        for (cp = path; *cp != '\0'; )  /* calculate number of entries */
                     99:                if (*cp++ == ':')
                    100:                        ++i;
                    101:        if ((patharray = (char **)calloc(i + 1, sizeof (char *))) == NULL)
                    102:                fatal("Out of memory for PATH list");
                    103:        for (cp = path, pp = patharray; *cp != '\0' || pp == patharray; ) {
                    104:                *pp++ = cp;
                    105:                while (*cp != '\0') {
                    106:                        if (*cp == ':') {
                    107:                                *cp++ = '\0';
                    108:                                break;
                    109:                        }
                    110:                        ++cp;
                    111:                }
                    112:                if ((pp - patharray) < i)
                    113:                        *pp = cp;
                    114:        }
                    115:        return (patharray);
                    116: }
                    117: 
                    118: void
                    119: usage()
                    120: {
                    121:        fatal("usage: which name ....");
                    122: }
                    123: 
                    124: void
                    125: fatal(info)
                    126: char   *info;
                    127: {
                    128:        fprintf(stderr, "which: %r\n", &info);
                    129:        exit(1);
                    130: }

unix.superglobalmegacorp.com

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