aboutsummaryrefslogtreecommitdiff
path: root/lib/System/Unix/Program.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/System/Unix/Program.cpp')
-rw-r--r--lib/System/Unix/Program.cpp225
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