home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / rc / part06 / which.c < prev   
Encoding:
C/C++ Source or Header  |  1992-05-30  |  2.7 KB  |  115 lines

  1. /* which.c: check to see if a file is executable.
  2.  
  3.    This function was originally written with Maarten Litmaath's which.c as
  4.    a template, but was changed in order to accomodate the possibility of
  5.    rc's running setuid or the possibility of executing files not in the
  6.    primary group. Much of this file has been re-vamped by Paul Haahr.
  7.    I re-re-vamped the functions that Paul supplied to correct minor bugs
  8.    and to strip out unneeded functionality.
  9. */
  10.  
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <sys/param.h>
  14. #include <errno.h>
  15. #include "rc.h"
  16.  
  17. #define X_USR 0100
  18. #define X_GRP 0010
  19. #define X_OTH 0001
  20. #define X_ALL (X_USR|X_GRP|X_OTH)
  21.  
  22. extern int stat(const char *, struct stat *);
  23.  
  24. static bool initialized = FALSE;
  25. static int uid, gid;
  26.  
  27. #ifdef NGROUPS
  28. static int ngroups, gidset[NGROUPS];
  29.  
  30. /* determine whether gid lies in gidset */
  31.  
  32. static int ingidset(int g) {
  33.     int i;
  34.     for (i = 0; i < ngroups; i++)
  35.         if (g == gidset[i])
  36.             return 1;
  37.     return 0;
  38. }
  39. #endif
  40.  
  41. /*
  42.    A home-grown access/stat. Does the right thing for group-executable files.
  43.    Returns a bool instead of this -1 nonsense.
  44. */
  45.  
  46. static bool rc_access(char *path, bool verbose) {
  47.     struct stat st;
  48.     int mask;
  49.     if (stat(path, &st) != 0) {
  50.         if (verbose) /* verbose flag only set for absolute pathname */
  51.             uerror(path);
  52.         return FALSE;
  53.     }
  54.     if (uid == 0)
  55.         mask = X_ALL;
  56.     else if (uid == st.st_uid)
  57.         mask = X_USR;
  58. #ifdef NGROUPS
  59.     else if (gid == st.st_gid || ingidset(st.st_gid))
  60. #else
  61.     else if (gid == st.st_gid)
  62. #endif
  63.         mask = X_GRP;
  64.     else
  65.         mask = X_OTH;
  66.     if (((st.st_mode & S_IFMT) == S_IFREG) && (st.st_mode & mask))
  67.         return TRUE;
  68.     errno = EACCES;
  69.     if (verbose)
  70.         uerror(path);
  71.     return FALSE;
  72. }
  73.  
  74. /* return a full pathname by searching $path, and by checking the status of the file */
  75.  
  76. extern char *which(char *name, bool verbose) {
  77.     static char *test = NULL;
  78.     static SIZE_T testlen = 0;
  79.     List *path;
  80.     int len;
  81.     if (name == NULL)    /* no filename? can happen with "> foo" as a command */
  82.         return NULL;
  83.     if (!initialized) {
  84.         initialized = TRUE;
  85.         uid = geteuid();
  86.         gid = getegid();
  87. #ifdef NGROUPS
  88.         ngroups = getgroups(NGROUPS, gidset);
  89. #endif
  90.     }
  91.     if (isabsolute(name)) /* absolute pathname? */
  92.         return rc_access(name, verbose) ? name : NULL;
  93.     len = strlen(name);
  94.     for (path = varlookup("path"); path != NULL; path = path->n) {
  95.         SIZE_T need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */
  96.         if (testlen < need) {
  97.             efree(test);
  98.             test = ealloc(testlen = need);
  99.         }
  100.         if (*path->w == '\0') {
  101.             strcpy(test, name);
  102.         } else {
  103.             strcpy(test, path->w);
  104.             if (!streq(test, "/")) /* "//" is special to POSIX */
  105.                 strcat(test, "/");
  106.             strcat(test, name);
  107.         }
  108.         if (rc_access(test, FALSE))
  109.             return test;
  110.     }
  111.     if (verbose)
  112.         fprint(2, "%s not found\n", name);
  113.     return NULL;
  114. }
  115.