1 //===- SystemUtils.cpp - Utilities for low-level system tasks -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains functions used to do a variety of low-level, often
11 // system-specific, tasks.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Support/SystemUtils.h"
16 #include "llvm/System/Program.h"
17 #include "llvm/Config/fcntl.h"
18 #include "llvm/Config/sys/wait.h"
28 /// isStandardOutAConsole - Return true if we can tell that the standard output
29 /// stream goes to a terminal window or console.
30 bool llvm::isStandardOutAConsole() {
34 // If we don't have isatty, just return false.
39 /// FindExecutable - Find a named executable, giving the argv[0] of program
40 /// being executed. This allows us to find another LLVM tool if it is built
41 /// into the same directory, but that directory is neither the current
42 /// directory, nor in the PATH. If the executable cannot be found, return an
45 #undef FindExecutable // needed on windows :(
46 sys::Path llvm::FindExecutable(const std::string &ExeName,
47 const std::string &ProgramPath) {
48 // First check the directory that the calling program is in. We can do this
49 // if ProgramPath contains at least one / character, indicating that it is a
50 // relative path to bugpoint itself.
52 sys::Path Result ( ProgramPath );
55 if (!Result.isEmpty()) {
56 Result.appendFile(ExeName);
57 if (Result.executable()) return Result;
60 return sys::Program::FindProgramByName(ExeName);
63 static void RedirectFD(const std::string &File, int FD) {
64 if (File.empty()) return; // Noop
67 int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
69 std::cerr << "Error opening file '" << File << "' for "
70 << (FD == 0 ? "input" : "output") << "!\n";
74 dup2(InFD, FD); // Install it as the requested FD
75 close(InFD); // Close the original FD
78 static bool Timeout = false;
79 static void TimeOutHandler(int Sig) {
83 /// RunProgramWithTimeout - This function executes the specified program, with
84 /// the specified null-terminated argument array, with the stdin/out/err fd's
85 /// redirected, with a timeout specified by the last argument. This terminates
86 /// the calling program if there is an error executing the specified program.
87 /// It returns the return value of the program, or -1 if a timeout is detected.
89 int llvm::RunProgramWithTimeout(const std::string &ProgramPath,
91 const std::string &StdInFile,
92 const std::string &StdOutFile,
93 const std::string &StdErrFile,
94 unsigned NumSeconds) {
95 #ifdef HAVE_SYS_WAIT_H
99 std::cerr << "ERROR forking!\n";
102 RedirectFD(StdInFile, 0); // Redirect file descriptors...
103 RedirectFD(StdOutFile, 1);
104 if (StdOutFile != StdErrFile)
105 RedirectFD(StdErrFile, 2);
109 execv(ProgramPath.c_str(), (char *const *)Args);
110 std::cerr << "Error executing program: '" << ProgramPath;
111 for (; *Args; ++Args)
112 std::cerr << " " << *Args;
119 // Make sure all output has been written while waiting
120 std::cout << std::flush;
122 // Install a timeout handler.
124 struct sigaction Act, Old;
125 Act.sa_sigaction = 0;
126 Act.sa_handler = TimeOutHandler;
127 sigemptyset(&Act.sa_mask);
129 sigaction(SIGALRM, &Act, &Old);
131 // Set the timeout if one is set.
136 while (wait(&Status) != Child)
137 if (errno == EINTR) {
140 kill(Child, SIGKILL);
142 if (wait(&Status) != Child)
143 std::cerr << "Something funny happened waiting for the child!\n";
146 sigaction(SIGALRM, &Old, 0);
147 return -1; // Timeout detected
149 std::cerr << "Error waiting for child process!\n";
155 sigaction(SIGALRM, &Old, 0);
159 std::cerr << "RunProgramWithTimeout not implemented on this platform!\n";