home *** CD-ROM | disk | FTP | other *** search
- /* which.c: check to see if a file is executable.
-
- This function is isolated from the rest because of #include trouble with
- ANSI compilers.
-
- This function was originally written with Maarten Litmaath's which.c as
- a template, but was changed in order to accomodate the possibility of
- rc's running setuid or the possibility of executing files not in the
- primary group. Much of this file has been re-vamped by Paul Haahr.
- I re-re-vamped the functions that Paul supplied to correct minor bugs
- and to strip out unneeded functionality.
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include "builtins.h"
-
- #define M_USR 0700
- #define M_GRP 0070
- #define M_OTH 0007
- #define X_ALL 0111
-
- #ifndef NULL
- #define NULL 0
- #endif
-
- typedef struct List {
- char *w;
- char *m;
- struct List *n;
- } List;
-
- extern int stat(const char *, struct stat *);
- extern int geteuid(void);
- extern int getegid(void);
- extern int getgroups(int, int *);
- extern char *strcpy(char *, char *);
- extern char *strcat(char *, char *);
- extern int strlen(char *);
-
- extern List *varlookup(char *);
- extern void *ealloc(int);
- extern void efree(void *);
- extern int isabsolute(char *);
-
- static int initialized = 0;
- static int uid, gid;
-
- #ifdef NGROUPS
- static int ngroups, gidset[NGROUPS];
-
- /* determine whether gid lies in gidset */
-
- static int ingidset(int gid) {
- int i;
- for (i = 0; i < ngroups; i++)
- if (gid == gidset[i])
- return 1;
- return 0;
- }
- #endif
-
- /*
- A home-grown access/stat. Does the right thing for group-executable files.
- Returns a boolean result instead of this -1 nonsense.
- */
-
- static int rc_access(char *path) {
- struct stat st;
- int mask;
-
- if (stat(path, &st) != 0)
- return 0;
-
- mask = X_ALL;
-
- if (uid != 0) {
- if (uid == st.st_uid)
- mask &= M_USR;
- #ifdef NGROUPS
- else if (gid == st.st_gid || ingidset(st.st_gid))
- #else
- else if (gid == st.st_gid)
- #endif
- mask &= M_GRP;
- else
- mask &= M_OTH;
- }
-
- return (st.st_mode & S_IFMT) == S_IFREG && (st.st_mode & mask) == mask;
- }
-
- /* return a full pathname by searching $path, and by checking the status of the file */
-
- char *which(char *name) {
- static char *test = NULL;
- static int testlen = 0;
- List *path;
- int len;
-
- if (name == NULL) /* no filename? can happen with "> foo" as a command */
- return NULL;
-
- if (!initialized) {
- initialized = 1;
- uid = geteuid();
- gid = getegid();
- #ifdef NGROUPS
- ngroups = getgroups(NGROUPS, gidset);
- #endif
- }
-
- if (isabsolute(name)) /* absolute pathname? */
- return rc_access(name) ? name : NULL;
-
- len = strlen(name);
- for (path = varlookup("path"); path != NULL; path = path->n) {
- int need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */
- if (testlen < need) {
- efree(test);
- test = ealloc(testlen = need);
- }
- if (*path->w == '\0') {
- strcpy(test, name);
- } else {
- strcpy(test, path->w);
- strcat(test, "/");
- strcat(test, name);
- }
- if (rc_access(test))
- return test;
- }
- return NULL;
- }
-