diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2005-01-09 23:29:00 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2005-01-09 23:29:00 +0000 |
commit | bccc8abc79338d1cfdd5ea20f7288452ddf75b84 (patch) | |
tree | c7009daa6a24f65cb6addfee22bc6bc8f40b0d4b /lib/System/Unix/Program.cpp | |
parent | 5cdcc58d51c792d329202bab97c34aefbc043b15 (diff) |
Rename Unix/*.cpp and Win32/*.cpp to have a *.inc suffix so that the silly
gdb debugger doesn't get confused on which file it is reading (the one in
lib/System or the one in lib/System/{Win32,Unix})
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19426 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/System/Unix/Program.cpp')
-rw-r--r-- | lib/System/Unix/Program.cpp | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/lib/System/Unix/Program.cpp b/lib/System/Unix/Program.cpp deleted file mode 100644 index 1bd3eae0f9..0000000000 --- a/lib/System/Unix/Program.cpp +++ /dev/null @@ -1,225 +0,0 @@ -//===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Reid Spencer and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Unix specific portion of the Program class. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic UNIX code that -//=== is guaranteed to work on *all* UNIX variants. -//===----------------------------------------------------------------------===// - -#include <llvm/Config/config.h> -#include "Unix.h" -#include <iostream> -#if HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#if HAVE_SIGNAL_H -#include <signal.h> -#endif -#if HAVE_FCNTL_H -#include <fcntl.h> -#endif - -extern char** environ; - -namespace llvm { -using namespace sys; - -// This function just uses the PATH environment variable to find the program. -Path -Program::FindProgramByName(const std::string& progName) { - - // Check some degenerate cases - if (progName.length() == 0) // no program - return Path(); - Path temp; - if (!temp.setFile(progName)) // invalid name - return Path(); - if (temp.executable()) // already executable as is - return temp; - - // At this point, the file name is valid and its not executable - - // Get the path. If its empty, we can't do anything to find it. - const char *PathStr = getenv("PATH"); - if (PathStr == 0) - return Path(); - - // Now we have a colon separated list of directories to search; try them. - unsigned PathLen = strlen(PathStr); - while (PathLen) { - // Find the first colon... - const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); - - // Check to see if this first directory contains the executable... - Path FilePath; - if (FilePath.setDirectory(std::string(PathStr,Colon))) { - FilePath.appendFile(progName); - if (FilePath.executable()) - return FilePath; // Found the executable! - } - - // Nope it wasn't in this directory, check the next path in the list! - PathLen -= Colon-PathStr; - PathStr = Colon; - - // Advance past duplicate colons - while (*PathStr == ':') { - PathStr++; - PathLen--; - } - } - return Path(); -} - -static void RedirectFD(const std::string &File, int FD) { - if (File.empty()) return; // Noop - - // Open the file - int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); - if (InFD == -1) { - ThrowErrno("Cannot open file '" + File + "' for " - + (FD == 0 ? "input" : "output") + "!\n"); - } - - dup2(InFD, FD); // Install it as the requested FD - close(InFD); // Close the original FD -} - -static bool Timeout = false; -static void TimeOutHandler(int Sig) { - Timeout = true; -} - -int -Program::ExecuteAndWait(const Path& path, - const char** args, - const char** envp, - const Path** redirects, - unsigned secondsToWait -) { - if (!path.executable()) - throw path.toString() + " is not executable"; - -#ifdef HAVE_SYS_WAIT_H - // Create a child process. - int child = fork(); - switch (child) { - // An error occured: Return to the caller. - case -1: - ThrowErrno(std::string("Couldn't execute program '") + path.toString() + - "'"); - break; - - // Child process: Execute the program. - case 0: { - // Redirect file descriptors... - if (redirects) { - if (redirects[0]) - if (redirects[0]->isEmpty()) - RedirectFD("/dev/null",0); - else - RedirectFD(redirects[0]->toString(), 0); - if (redirects[1]) - if (redirects[1]->isEmpty()) - RedirectFD("/dev/null",1); - else - RedirectFD(redirects[1]->toString(), 1); - if (redirects[1] && redirects[2] && - *(redirects[1]) != *(redirects[2])) { - if (redirects[2]->isEmpty()) - RedirectFD("/dev/null",2); - else - RedirectFD(redirects[2]->toString(), 2); - } else { - dup2(1, 2); - } - } - - // Set up the environment - char** env = environ; - if (envp != 0) - env = (char**) envp; - - // Execute! - execve (path.c_str(), (char** const)args, env); - // If the execve() failed, we should exit and let the parent pick up - // our non-zero exit status. - exit (errno); - } - - // Parent process: Break out of the switch to do our processing. - default: - break; - } - - // Make sure stderr and stdout have been flushed - std::cerr << std::flush; - std::cout << std::flush; - fsync(1); - fsync(2); - - struct sigaction Act, Old; - - // Install a timeout handler. - if (secondsToWait) { - Timeout = false; - Act.sa_sigaction = 0; - Act.sa_handler = TimeOutHandler; - sigemptyset(&Act.sa_mask); - Act.sa_flags = 0; - sigaction(SIGALRM, &Act, &Old); - alarm(secondsToWait); - } - - // Parent process: Wait for the child process to terminate. - int status; - while (wait(&status) != child) - if (secondsToWait && errno == EINTR) { - // Kill the child. - kill(child, SIGKILL); - - // Turn off the alarm and restore the signal handler - alarm(0); - sigaction(SIGALRM, &Old, 0); - - // Wait for child to die - if (wait(&status) != child) - ThrowErrno("Child timedout but wouldn't die"); - - return -1; // Timeout detected - } else { - ThrowErrno("Error waiting for child process"); - } - - // We exited normally without timeout, so turn off the timer. - if (secondsToWait) { - alarm(0); - sigaction(SIGALRM, &Old, 0); - } - - // If the program exited normally with a zero exit status, return success! - if (WIFEXITED (status)) - return WEXITSTATUS(status); - else if (WIFSIGNALED(status)) - throw std::string("Program '") + path.toString() + - "' received terminating signal."; - -#else - throw std::string( - "Program::ExecuteAndWait not implemented on this platform!\n"); -#endif - return 0; -} - -} -// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab |