From 893a0f9f0e8f816c7fb0eb4cfcc972e7e3c68731 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 2 Mar 2009 22:17:15 +0000 Subject: [PATCH] Fix main executable path name resolution on FreeBSD, patch by Ed Schouten! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65882 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/System/Unix/Path.inc | 61 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc index 3a651f957cd..4a6b5051998 100644 --- a/lib/System/Unix/Path.inc +++ b/lib/System/Unix/Path.inc @@ -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) { -- 2.34.1