diff options
author | Stephen Hines <srhines@google.com> | 2013-08-07 15:07:10 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2013-08-07 15:07:10 -0700 |
commit | fab2daa4a1127ecb217abe2b07c1769122b6fee1 (patch) | |
tree | 268ebfd1963fd98ba412e76819afdf95a7d4267b /lib/Support/Unix/Program.inc | |
parent | 8197ac1c1a0a91baa70c4dea8cb488f254ef974c (diff) | |
parent | 10251753b6897adcd22cc981c0cc42f348c109de (diff) | |
download | external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.zip external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.gz external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.bz2 |
Merge commit '10251753b6897adcd22cc981c0cc42f348c109de' into merge-20130807
Conflicts:
lib/Archive/ArchiveReader.cpp
lib/Support/Unix/PathV2.inc
Change-Id: I29d8c1e321a4a380b6013f00bac6a8e4b593cc4e
Diffstat (limited to 'lib/Support/Unix/Program.inc')
-rw-r--r-- | lib/Support/Unix/Program.inc | 116 |
1 files changed, 61 insertions, 55 deletions
diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index aa03d48..a93a912 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -47,20 +47,14 @@ namespace llvm { using namespace sys; -Program::Program() : Data_(0) {} - -Program::~Program() {} - // This function just uses the PATH environment variable to find the program. -Path -Program::FindProgramByName(const std::string& progName) { +std::string +sys::FindProgramByName(const std::string& progName) { // Check some degenerate cases if (progName.length() == 0) // no program - return Path(); - Path temp; - if (!temp.set(progName)) // invalid name - return Path(); + return ""; + std::string temp = progName; // Use the given path verbatim if it contains any slashes; this matches // the behavior of sh(1) and friends. if (progName.find('/') != std::string::npos) @@ -72,7 +66,7 @@ Program::FindProgramByName(const std::string& progName) { // Get the path. If its empty, we can't do anything to find it. const char *PathStr = getenv("PATH"); if (PathStr == 0) - return Path(); + return ""; // Now we have a colon separated list of directories to search; try them. size_t PathLen = strlen(PathStr); @@ -81,12 +75,10 @@ Program::FindProgramByName(const std::string& progName) { const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); // Check to see if this first directory contains the executable... - Path FilePath; - if (FilePath.set(std::string(PathStr,Colon))) { - FilePath.appendComponent(progName); - if (FilePath.canExecute()) - return FilePath; // Found the executable! - } + SmallString<128> FilePath(PathStr,Colon); + sys::path::append(FilePath, progName); + if (sys::fs::can_execute(Twine(FilePath))) + return FilePath.str(); // Found the executable! // Nope it wasn't in this directory, check the next path in the list! PathLen -= Colon-PathStr; @@ -98,23 +90,23 @@ Program::FindProgramByName(const std::string& progName) { PathLen--; } } - return Path(); + return ""; } -static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { +static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { if (Path == 0) // Noop return false; - const char *File; - if (Path->isEmpty()) + std::string File; + if (Path->empty()) // Redirect empty paths to /dev/null File = "/dev/null"; else - File = Path->c_str(); + File = *Path; // Open the file - int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); if (InFD == -1) { - MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for " + MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " + (FD == 0 ? "input" : "output")); return true; } @@ -130,19 +122,20 @@ static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { } #ifdef HAVE_POSIX_SPAWN -static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, +static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg, posix_spawn_file_actions_t *FileActions) { if (Path == 0) // Noop return false; const char *File; - if (Path->isEmpty()) + if (Path->empty()) // Redirect empty paths to /dev/null File = "/dev/null"; else File = Path->c_str(); - if (int Err = posix_spawn_file_actions_addopen(FileActions, FD, - File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) + if (int Err = posix_spawn_file_actions_addopen( + FileActions, FD, File, + FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) return MakeErrMsg(ErrMsg, "Cannot dup2", Err); return false; } @@ -180,10 +173,11 @@ static void SetMemoryLimits (unsigned size) #endif } -bool -Program::Execute(const Path &path, const char **args, const char **envp, - const Path **redirects, unsigned memoryLimit, - std::string *ErrMsg) { +} + +static bool Execute(void **Data, StringRef Program, const char **args, + const char **envp, const StringRef **redirects, + unsigned memoryLimit, std::string *ErrMsg) { // If this OS has posix_spawn and there is no memory limit being implied, use // posix_spawn. It is more efficient than fork/exec. #ifdef HAVE_POSIX_SPAWN @@ -191,18 +185,32 @@ Program::Execute(const Path &path, const char **args, const char **envp, posix_spawn_file_actions_t FileActionsStore; posix_spawn_file_actions_t *FileActions = 0; + // If we call posix_spawn_file_actions_addopen we have to make sure the + // c strings we pass to it stay alive until the call to posix_spawn, + // so we copy any StringRefs into this variable. + std::string RedirectsStorage[3]; + if (redirects) { + std::string *RedirectsStr[3] = {0, 0, 0}; + for (int I = 0; I < 3; ++I) { + if (redirects[I]) { + RedirectsStorage[I] = *redirects[I]; + RedirectsStr[I] = &RedirectsStorage[I]; + } + } + FileActions = &FileActionsStore; posix_spawn_file_actions_init(FileActions); // Redirect stdin/stdout. - if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || - RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) + if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) || + RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions)) return false; if (redirects[1] == 0 || redirects[2] == 0 || *redirects[1] != *redirects[2]) { // Just redirect stderr - if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; + if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions)) + return false; } else { // If stdout and stderr should go to the same place, redirect stderr // to the FD already open for stdout. @@ -222,7 +230,7 @@ Program::Execute(const Path &path, const char **args, const char **envp, // Explicitly initialized to prevent what appears to be a valgrind false // positive. pid_t PID = 0; - int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, + int Err = posix_spawn(&PID, Program.str().c_str(), FileActions, /*attrp*/0, const_cast<char **>(args), const_cast<char **>(envp)); if (FileActions) @@ -231,7 +239,8 @@ Program::Execute(const Path &path, const char **args, const char **envp, if (Err) return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); - Data_ = reinterpret_cast<void*>(PID); + if (Data) + *Data = reinterpret_cast<void*>(PID); return true; } #endif @@ -272,12 +281,13 @@ Program::Execute(const Path &path, const char **args, const char **envp, } // Execute! + std::string PathStr = Program; if (envp != 0) - execve(path.c_str(), + execve(PathStr.c_str(), const_cast<char **>(args), const_cast<char **>(envp)); else - execv(path.c_str(), + execv(PathStr.c_str(), const_cast<char **>(args)); // If the execve() failed, we should exit. Follow Unix protocol and // return 127 if the executable was not found, and 126 otherwise. @@ -293,23 +303,17 @@ Program::Execute(const Path &path, const char **args, const char **envp, break; } - Data_ = reinterpret_cast<void*>(child); + if (Data) + *Data = reinterpret_cast<void*>(child); return true; } -int -Program::Wait(const sys::Path &path, - unsigned secondsToWait, - std::string* ErrMsg) -{ +static int Wait(void *&Data, StringRef Program, unsigned secondsToWait, + std::string *ErrMsg) { #ifdef HAVE_SYS_WAIT_H struct sigaction Act, Old; - - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return -1; - } + assert(Data && "invalid pid to wait on, process not started?"); // Install a timeout handler. The handler itself does nothing, but the simple // fact of having a handler at all causes the wait below to return with EINTR, @@ -324,7 +328,7 @@ Program::Wait(const sys::Path &path, // Parent process: Wait for the child process to terminate. int status; - uint64_t pid = reinterpret_cast<uint64_t>(Data_); + uint64_t pid = reinterpret_cast<uint64_t>(Data); pid_t child = static_cast<pid_t>(pid); while (waitpid(pid, &status, 0) != child) if (secondsToWait && errno == EINTR) { @@ -364,7 +368,7 @@ Program::Wait(const sys::Path &path, // itself apparently does not), check to see if the failure was due to some // reason other than the file not existing, and return 126 in this case. bool Exists; - if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) + if (result == 127 && !llvm::sys::fs::exists(Program, Exists) && Exists) result = 126; #endif if (result == 127) { @@ -397,17 +401,19 @@ Program::Wait(const sys::Path &path, #endif } -error_code Program::ChangeStdinToBinary(){ +namespace llvm { + +error_code sys::ChangeStdinToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } -error_code Program::ChangeStdoutToBinary(){ +error_code sys::ChangeStdoutToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } -error_code Program::ChangeStderrToBinary(){ +error_code sys::ChangeStderrToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); } |