Fix main executable path name resolution on FreeBSD, patch by
authorChris Lattner <sabre@nondot.org>
Mon, 2 Mar 2009 22:17:15 +0000 (22:17 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 2 Mar 2009 22:17:15 +0000 (22:17 +0000)
Ed Schouten!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65882 91177308-0d34-0410-b5e6-96231b3b80d8

lib/System/Unix/Path.inc

index 3a651f957cd0aa5f37ae3ac8f33e848a1cc6e4b4..4a6b50519980f70b46ea7f3f7eb26a8f031a46ec 100644 (file)
@@ -266,10 +266,69 @@ Path::GetCurrentDirectory() {
   return Path(pathname);
 }
 
+#ifdef __FreeBSD__
+static int
+test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
+    const char *dir, const char *bin)
+{
+       struct stat sb;
+
+       snprintf(buf, PATH_MAX, "%s//%s", dir, bin);
+       if (realpath(buf, ret) == NULL)
+               return (1);
+       if (stat(buf, &sb) != 0)
+               return (1);
+       
+       return (0);
+}
+
+static char *
+getprogpath(char ret[PATH_MAX], const char *bin)
+{
+       char *pv, *s, *t, buf[PATH_MAX];
+
+       /* First approach: absolute path. */
+       if (bin[0] == '/') {
+               if (test_dir(buf, ret, "/", bin) == 0)
+                       return (ret);
+               return (NULL);
+       }
+
+       /* Second approach: relative path. */
+       if (strchr(bin, '/') != NULL) {
+               if (getcwd(buf, PATH_MAX) == NULL)
+                       return (NULL);
+               if (test_dir(buf, ret, buf, bin) == 0)
+                       return (ret);
+               return (NULL);
+       }
+
+       /* Third approach: $PATH */
+       if ((pv = getenv("PATH")) == NULL)
+               return (NULL);
+       s = pv = strdup(pv);
+       if (pv == NULL)
+               return (NULL);
+       while ((t = strsep(&s, ":")) != NULL) {
+               if (test_dir(buf, ret, t, bin) == 0) {
+                       free(pv);
+                       return (ret);
+               }
+       }
+       free(pv);
+       return (NULL);
+}
+#endif
+
 /// GetMainExecutable - Return the path to the main executable, given the
 /// value of argv[0] from program startup.
 Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
-#if defined(__linux__) || defined(__CYGWIN__)
+#if defined(__FreeBSD__)
+  char exe_path[PATH_MAX];
+
+  if (getprogpath(exe_path, argv0) != NULL)
+    return Path(std::string(exe_path));
+#elif defined(__linux__) || defined(__CYGWIN__)
   char exe_path[MAXPATHLEN];
   ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
   if (len > 0 && len < MAXPATHLEN - 1) {