//===- 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 "Support/SystemUtils.h"
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <cstdlib>
#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"
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <cstdlib>
+#include <cerrno>
+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!
return Buf.st_mode & S_IXOTH;
}
-
/// 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.
+/// 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 FindExecutable(const std::string &ExeName,
- const std::string &ProgramPath) {
+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.
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);
}
/// 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();
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;
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
}
// a generic library function. The caller or executed program should report
// errors in the way it sees fit.
//
-int
-ExecWait (char ** argv, char **envp)
-{
+// 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;
int status;
//
- // Because UNIX is sometimes less than convenient, we need to use
- // FindExecutable() to find the full pathname to the file to execute.
+ // Create local versions of the parameters that can be passed into execve()
+ // without creating const problems.
//
- // This is becausse execvp() doesn't use PATH, and we want to look for
- // programs in the LLVM binary directory first anyway.
- //
- std::string Program = FindExecutable (argv[0], "");
- if (Program.empty())
- {
- return 1;
- }
+ 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 (Program.c_str(), argv, envp);
- return 1;
+ 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;
}
//
return 1;
}
-