find_executable.c
上传用户:shenzhenrh
上传日期:2013-05-12
资源大小:2904k
文件大小:4k
源码类别:

信息检索与抽取

开发平台:

Unix_Linux

  1. #include <misc.h>
  2. #include <sys/param.h>
  3. #include <sys/fcntl.h>
  4. #define FALSE 0
  5. #define TRUE 1
  6. #ifndef MAXPATHLEN
  7. #define MAXPATHLEN 1024 /* Hurd */
  8. #endif
  9. static int
  10. maybe_executable (const char *filename, int fd)
  11.   struct stat statexe;
  12.   struct stat statfile;
  13.   if (access (filename, R_OK|X_OK) < 0)
  14.     return FALSE;
  15.   /* This loses with a script wrapper to Java things */
  16. #if 0
  17.   /* Should check that inodes match up, but only know how 
  18.      do that on Linux. */
  19.   if (fd != -1)
  20.     {
  21.       if (fstat (fd, &statexe) == -1)
  22.         return TRUE;
  23.       if (stat (filename, &statfile) == -1)
  24.         return FALSE;
  25.       if (statfile.st_dev
  26.           && statfile.st_dev == statexe.st_dev
  27.           && statfile.st_ino == statexe.st_ino)
  28.         return TRUE; 
  29.       return FALSE;
  30.     }
  31. #endif
  32.   return TRUE;
  33. }
  34. const char *
  35. find_executable (const char *program_name)
  36.   char *executable_name;
  37.   int executable_fd = -1;
  38. #ifdef __linux__
  39.   /* The executable is accessible as /proc/<pid>/exe. We try this
  40.      first because it is safer: no race condition w.r.t. the file
  41.      system. It may fail, however, if the user has not compiled /proc
  42.      support into his kernel. */
  43.   {
  44.     char buf[6+10+5];
  45.     sprintf (buf, "/proc/%d/exe", getpid ());
  46.     executable_fd = open (buf, O_RDONLY, 0644);
  47.   }
  48. #endif
  49.   /* Now we guess the executable's full path. We assume the executable
  50.      has been called via execlp() or execvp() with properly set up
  51.      argv[0].  The login(1) convention to add a '-' prefix to argv[0]
  52.      is not supported. */
  53.   {
  54.     int has_slash = FALSE;
  55.     {
  56.       const char * p;
  57.       for (p = program_name; *p; p++)
  58.         {
  59.           if (*p == '/')
  60.             {
  61.               has_slash = TRUE;
  62.               break;
  63.             }
  64.         }
  65.     }
  66.     if (!has_slash)
  67.       { 
  68.         /* exec searches paths without slashes in the directory list given
  69.            by $PATH. */
  70.         const char *path = getenv ("PATH");
  71.         if (!(path == NULL))
  72.           { 
  73.             const char *p;
  74.             const char *p_next;
  75.             for (p = path; *p; p = p_next)
  76.               { 
  77.                 const char * q;
  78.                 unsigned int p_len;
  79.                 for (q = p; *q; q++)
  80.                   {
  81.                     if (*q == ':')
  82.                       break;
  83.                   }
  84.                 p_len = q - p;
  85.                 p_next = (*q == '' ? q : q + 1);
  86.                 /* We have a path item at p, of length p_len.
  87.                    Now concatenate the path item and program_name. */
  88.                 {
  89.                   char *concat_name = (char *) xmalloc (p_len + strlen (program_name) + 2);
  90.                   if (p_len == 0)
  91.                     strcpy (concat_name, program_name);
  92.                   else
  93.                     {
  94.                       memcpy (concat_name, p, p_len);
  95.                       sprintf (concat_name + p_len, "/%s", program_name);
  96.                     }
  97.                   if (maybe_executable (concat_name, executable_fd))
  98.                     /* Assume we have found the executable */
  99.                     {
  100.                       program_name = concat_name;
  101.                       goto resolve;
  102.                     }
  103.                   XFREE (concat_name);
  104.                 }
  105.               }
  106.           }
  107.         /* Not found in the PATH, assume the current directory. */
  108.       }
  109.     /* exec treats paths containing slashes as relative to the current
  110.        directory. */
  111.     if (maybe_executable (program_name, executable_fd))
  112.       resolve:
  113.     /* resolve program_name */
  114.     {
  115.       char buf[MAXPATHLEN];
  116.       char *dupbuf;
  117.       memset (buf, 0, MAXPATHLEN);
  118.       /* Cygwin ends up converting /Swarm-2.1/bin to /bin, which 
  119.          screws up the search for SWARMHOME */
  120. #ifndef __CYGWIN__
  121.       if (realpath ((char *) program_name, buf) == NULL)
  122.         goto notfound;
  123. #else
  124.       strcpy (buf, program_name);
  125. #endif
  126.       
  127.       dupbuf = xmalloc (strlen (buf) + 1);
  128.       strcpy (dupbuf, buf);
  129.       return (const char *) dupbuf;
  130.     }
  131.     errno = ENOENT;
  132.   notfound:
  133.     return NULL;
  134.   }
  135. }