From 93377b377fdc891dfe1dc5ca4c22d66e53b81cea Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Mon, 2 Jan 2017 11:36:00 +0000 Subject: [PATCH] Use execve instead of execvp & setting environ global variable If the app name doesn't have a directory separator search PATH directories to find path of application to launch. Resolve the app name fully then change the working directory --- renderdoc/os/posix/posix_process.cpp | 53 ++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/renderdoc/os/posix/posix_process.cpp b/renderdoc/os/posix/posix_process.cpp index dca4d9cd2..3bf7acf78 100644 --- a/renderdoc/os/posix/posix_process.cpp +++ b/renderdoc/os/posix/posix_process.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,39 @@ char **GetCurrentEnvironment(); int GetIdentPort(pid_t childPid); +static const string GetAbsoluteAppPathFromName(const string &appName) +{ + // If the application name contains a slash character convert it to an absolute path and return it + if(appName.find("/") != string::npos) + { + char realpathBuffer[PATH_MAX]; + string appDir = dirname(appName); + string appBasename = basename(appName); + realpath(appDir.c_str(), realpathBuffer); + string appPath(realpathBuffer); + appPath += "/" + appBasename; + return appPath; + } + + // Search the PATH directory list for the application (like shell which) to get the absolute path + // Return "" if no exectuable found in the PATH list + char *pathEnvVar = getenv("PATH"); + if(!pathEnvVar) + return string(); + + const char *pathSeparator = ":"; + const char *path = strtok(pathEnvVar, pathSeparator); + while(path) + { + string testPath(path); + testPath += "/" + appName; + if(!access(testPath.c_str(), X_OK)) + return testPath; + path = strtok(NULL, pathSeparator); + } + return string(); +} + static vector &GetEnvModifications() { static vector envCallbacks; @@ -315,13 +349,18 @@ static pid_t RunProcess(const char *app, const char *workingDir, const char *cmd pid_t childPid = fork(); if(childPid == 0) { - chdir(workDir.c_str()); - - // in child process, so we can change environment - environ = envp; - execvp(appName.c_str(), argv); - - RDCERR("Failed to execute %s: %s", appName.c_str(), strerror(errno)); + const string appPath(GetAbsoluteAppPathFromName(appName)); + if(!appPath.empty()) + { + chdir(workDir.c_str()); + execve(appPath.c_str(), argv, envp); + RDCERR("Failed to execute '%s' %s", appName.c_str(), strerror(errno)); + RDCERR("Full Path: '%s'", appPath.c_str()); + } + else + { + RDCERR("Failed to execute '%s' Executable not found", appName.c_str()); + } exit(0); }