X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FSystemUtils.cpp;h=e1a0bd04d4555cdd7d1156b25623dbd7545d9caf;hb=2cdd21c2e4d855500dfb53f77aa74da53ccf9de6;hp=034c141f794f732db4e248620a12cabd38a28942;hpb=3301b695cb158e09ec540cc8318eacef9877b638;p=oota-llvm.git diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp index 034c141f794..e1a0bd04d45 100644 --- a/lib/Support/SystemUtils.cpp +++ b/lib/Support/SystemUtils.cpp @@ -1,60 +1,34 @@ //===- SystemUtils.h - Utilities to do low-level system stuff --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// // // This file contains functions used to do a variety of low-level, often // system-specific, tasks. // //===----------------------------------------------------------------------===// -#include "SystemUtils.h" +#include "Support/SystemUtils.h" #include #include #include #include -#include -#include -#include -#include -#include -#include -#include - -/// removeFile - Delete the specified file -/// -void removeFile(const std::string &Filename) { - unlink(Filename.c_str()); -} - -/// getUniqueFilename - Return a filename with the specified prefix. If the -/// file does not exist yet, return it, otherwise add a suffix to make it -/// unique. -/// -std::string getUniqueFilename(const std::string &FilenameBase) { - if (!std::ifstream(FilenameBase.c_str())) - return FilenameBase; // Couldn't open the file? Use it! - - // Create a pattern for mkstemp... - char *FNBuffer = (char*)alloca(FilenameBase.size()+8); - strcpy(FNBuffer, FilenameBase.c_str()); - strcpy(FNBuffer+FilenameBase.size(), "-XXXXXX"); - - // Agree on a temporary file name to use.... - int TempFD; - if ((TempFD = mkstemp(FNBuffer)) == -1) { - std::cerr << "bugpoint: ERROR: Cannot create temporary file in the current " - << " directory!\n"; - exit(1); - } - - // We don't need to hold the temp file descriptor... we will trust that noone - // will overwrite/delete the file while we are working on it... - close(TempFD); - return FNBuffer; -} +#include "Config/sys/types.h" +#include "Config/sys/stat.h" +#include "Config/fcntl.h" +#include "Config/sys/wait.h" +#include "Config/unistd.h" +#include "Config/errno.h" +using namespace llvm; /// isExecutableFile - This function returns true if the filename specified /// exists and is executable. /// -bool isExecutableFile(const std::string &ExeFileName) { +bool llvm::isExecutableFile(const std::string &ExeFileName) { struct stat Buf; if (stat(ExeFileName.c_str(), &Buf)) return false; // Must not be executable! @@ -70,18 +44,19 @@ bool isExecutableFile(const std::string &ExeFileName) { return Buf.st_mode & S_IXOTH; } - -// FindExecutable - Find a named executable, giving the argv[0] of bugpoint. -// This assumes the executable is in the same directory as bugpoint itself. -// If the executable cannot be found, return an empty string. -// -std::string FindExecutable(const std::string &ExeName, - const std::string &BugPointPath) { +/// FindExecutable - Find a named executable, giving the argv[0] of program +/// being executed. This allows us to find another LLVM tool if it is built +/// into the same directory, but that directory is neither the current +/// directory, nor in the PATH. If the executable cannot be found, return an +/// empty string. +/// +std::string llvm::FindExecutable(const std::string &ExeName, + const std::string &ProgramPath) { // First check the directory that bugpoint is in. We can do this if // BugPointPath contains at least one / character, indicating that it is a // relative path to bugpoint itself. // - std::string Result = BugPointPath; + std::string Result = ProgramPath; while (!Result.empty() && Result[Result.size()-1] != '/') Result.erase(Result.size()-1, 1); @@ -90,12 +65,12 @@ std::string FindExecutable(const std::string &ExeName, if (isExecutableFile(Result)) return Result; // Found it? } - // Okay, if the path to bugpoint didn't tell us anything, try using the PATH - // environment variable. + // Okay, if the path to the program didn't tell us anything, try using the + // PATH environment variable. const char *PathStr = getenv("PATH"); if (PathStr == 0) return ""; - // Now we have a colon seperated list of directories to search... try them... + // Now we have a colon separated list of directories to search... try them... unsigned PathLen = strlen(PathStr); while (PathLen) { // Find the first colon... @@ -126,7 +101,7 @@ static void RedirectFD(const std::string &File, int FD) { int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); if (InFD == -1) { std::cerr << "Error opening file '" << File << "' for " - << (FD == 0 ? "input" : "output") << "!\n"; + << (FD == 0 ? "input" : "output") << "!\n"; exit(1); } @@ -136,15 +111,15 @@ static void RedirectFD(const std::string &File, int FD) { /// RunProgramWithTimeout - This function executes the specified program, with /// the specified null-terminated argument array, with the stdin/out/err fd's -/// redirected, with a timeout specified on the commandline. This terminates +/// redirected, with a timeout specified on the command line. This terminates /// the calling program if there is an error executing the specified program. /// It returns the return value of the program, or -1 if a timeout is detected. /// -int RunProgramWithTimeout(const std::string &ProgramPath, const char **Args, - const std::string &StdInFile, - const std::string &StdOutFile, - const std::string &StdErrFile) { - +int llvm::RunProgramWithTimeout(const std::string &ProgramPath, + const char **Args, + const std::string &StdInFile, + const std::string &StdOutFile, + const std::string &StdErrFile) { // FIXME: install sigalarm handler here for timeout... int Child = fork(); @@ -158,9 +133,10 @@ int RunProgramWithTimeout(const std::string &ProgramPath, const char **Args, RedirectFD(StdErrFile, 2); execv(ProgramPath.c_str(), (char *const *)Args); - std::cerr << "Error executing program '" << ProgramPath; + std::cerr << "Error executing program: '" << ProgramPath; for (; *Args; ++Args) std::cerr << " " << *Args; + std::cerr << "'\n"; exit(1); default: break; @@ -174,12 +150,12 @@ int RunProgramWithTimeout(const std::string &ProgramPath, const char **Args, if (errno == EINTR) { static bool FirstTimeout = true; if (FirstTimeout) { - std::cout << + std::cout << "*** Program execution timed out! This mechanism is designed to handle\n" " programs stuck in infinite loops gracefully. The -timeout option\n" " can be used to change the timeout threshold or disable it completely\n" " (with -timeout=0). This message is only displayed once.\n"; - FirstTimeout = false; + FirstTimeout = false; } return -1; // Timeout detected } @@ -189,3 +165,109 @@ int RunProgramWithTimeout(const std::string &ProgramPath, const char **Args, } return Status; } + + +// +// Function: ExecWait () +// +// Description: +// This function executes a program with the specified arguments and +// environment. It then waits for the progarm to termiante and then returns +// to the caller. +// +// Inputs: +// argv - The arguments to the program as an array of C strings. The first +// argument should be the name of the program to execute, and the +// last argument should be a pointer to NULL. +// +// envp - The environment passes to the program as an array of C strings in +// the form of "name=value" pairs. The last element should be a +// pointer to NULL. +// +// Outputs: +// None. +// +// Return value: +// 0 - No errors. +// 1 - The program could not be executed. +// 1 - The program returned a non-zero exit status. +// 1 - The program terminated abnormally. +// +// Notes: +// The program will inherit the stdin, stdout, and stderr file descriptors +// as well as other various configuration settings (umask). +// +// This function should not print anything to stdout/stderr on its own. It is +// a generic library function. The caller or executed program should report +// errors in the way it sees fit. +// +// This function does not use $PATH to find programs. +// +int llvm::ExecWait(const char * const old_argv[], + const char * const old_envp[]) { + // Child process ID + register int child; + + // Status from child process when it exits + int status; + + // + // Create local versions of the parameters that can be passed into execve() + // without creating const problems. + // + char ** const argv = (char ** const) old_argv; + char ** const envp = (char ** const) old_envp; + + // + // Create a child process. + // + switch (child=fork()) + { + // + // An error occured: Return to the caller. + // + case -1: + return 1; + break; + + // + // Child process: Execute the program. + // + case 0: + execve (argv[0], argv, envp); + + // + // If the execve() failed, we should exit and let the parent pick up + // our non-zero exit status. + // + exit (1); + break; + + // + // Parent process: Break out of the switch to do our processing. + // + default: + break; + } + + // + // Parent process: Wait for the child process to termiante. + // + if ((wait (&status)) == -1) + { + return 1; + } + + // + // If the program exited normally with a zero exit status, return success! + // + if (WIFEXITED (status) && (WEXITSTATUS(status) == 0)) + { + return 0; + } + + // + // Otherwise, return failure. + // + return 1; +}