LLVM API Documentation
00001 //===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the Unix specific portion of the Program class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 //===----------------------------------------------------------------------===// 00015 //=== WARNING: Implementation here must contain only generic UNIX code that 00016 //=== is guaranteed to work on *all* UNIX variants. 00017 //===----------------------------------------------------------------------===// 00018 00019 #include <llvm/Config/config.h> 00020 #include "Unix.h" 00021 #include <iostream> 00022 #if HAVE_SYS_STAT_H 00023 #include <sys/stat.h> 00024 #endif 00025 #if HAVE_SYS_RESOURCE_H 00026 #include <sys/resource.h> 00027 #endif 00028 #if HAVE_SIGNAL_H 00029 #include <signal.h> 00030 #endif 00031 #if HAVE_FCNTL_H 00032 #include <fcntl.h> 00033 #endif 00034 00035 namespace llvm { 00036 using namespace sys; 00037 00038 // This function just uses the PATH environment variable to find the program. 00039 Path 00040 Program::FindProgramByName(const std::string& progName) { 00041 00042 // Check some degenerate cases 00043 if (progName.length() == 0) // no program 00044 return Path(); 00045 Path temp; 00046 if (!temp.set(progName)) // invalid name 00047 return Path(); 00048 // FIXME: have to check for absolute filename - we cannot assume anything 00049 // about "." being in $PATH 00050 if (temp.canExecute()) // already executable as is 00051 return temp; 00052 00053 // At this point, the file name is valid and its not executable 00054 00055 // Get the path. If its empty, we can't do anything to find it. 00056 const char *PathStr = getenv("PATH"); 00057 if (PathStr == 0) 00058 return Path(); 00059 00060 // Now we have a colon separated list of directories to search; try them. 00061 size_t PathLen = strlen(PathStr); 00062 while (PathLen) { 00063 // Find the first colon... 00064 const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); 00065 00066 // Check to see if this first directory contains the executable... 00067 Path FilePath; 00068 if (FilePath.set(std::string(PathStr,Colon))) { 00069 FilePath.appendComponent(progName); 00070 if (FilePath.canExecute()) 00071 return FilePath; // Found the executable! 00072 } 00073 00074 // Nope it wasn't in this directory, check the next path in the list! 00075 PathLen -= Colon-PathStr; 00076 PathStr = Colon; 00077 00078 // Advance past duplicate colons 00079 while (*PathStr == ':') { 00080 PathStr++; 00081 PathLen--; 00082 } 00083 } 00084 return Path(); 00085 } 00086 00087 static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { 00088 if (Path == 0) 00089 // Noop 00090 return false; 00091 std::string File; 00092 if (Path->isEmpty()) 00093 // Redirect empty paths to /dev/null 00094 File = "/dev/null"; 00095 else 00096 File = Path->toString(); 00097 00098 // Open the file 00099 int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); 00100 if (InFD == -1) { 00101 MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " 00102 + (FD == 0 ? "input" : "output") + "!\n"); 00103 return true; 00104 } 00105 00106 // Install it as the requested FD 00107 if (-1 == dup2(InFD, FD)) { 00108 MakeErrMsg(ErrMsg, "Cannot dup2"); 00109 return true; 00110 } 00111 close(InFD); // Close the original FD 00112 return false; 00113 } 00114 00115 static bool Timeout = false; 00116 static void TimeOutHandler(int Sig) { 00117 Timeout = true; 00118 } 00119 00120 static void SetMemoryLimits (unsigned size) 00121 { 00122 #if HAVE_SYS_RESOURCE_H 00123 struct rlimit r; 00124 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; 00125 00126 // Heap size 00127 getrlimit (RLIMIT_DATA, &r); 00128 r.rlim_cur = limit; 00129 setrlimit (RLIMIT_DATA, &r); 00130 #ifdef RLIMIT_RSS 00131 // Resident set size. 00132 getrlimit (RLIMIT_RSS, &r); 00133 r.rlim_cur = limit; 00134 setrlimit (RLIMIT_RSS, &r); 00135 #endif 00136 #ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. 00137 // Virtual memory. 00138 getrlimit (RLIMIT_AS, &r); 00139 r.rlim_cur = limit; 00140 setrlimit (RLIMIT_AS, &r); 00141 #endif 00142 #endif 00143 } 00144 00145 int 00146 Program::ExecuteAndWait(const Path& path, 00147 const char** args, 00148 const char** envp, 00149 const Path** redirects, 00150 unsigned secondsToWait, 00151 unsigned memoryLimit, 00152 std::string* ErrMsg) 00153 { 00154 if (!path.canExecute()) { 00155 if (ErrMsg) 00156 *ErrMsg = path.toString() + " is not executable"; 00157 return -1; 00158 } 00159 00160 #ifdef HAVE_SYS_WAIT_H 00161 // Create a child process. 00162 int child = fork(); 00163 switch (child) { 00164 // An error occured: Return to the caller. 00165 case -1: 00166 MakeErrMsg(ErrMsg, "Couldn't fork"); 00167 return -1; 00168 00169 // Child process: Execute the program. 00170 case 0: { 00171 // Redirect file descriptors... 00172 if (redirects) { 00173 // Redirect stdin 00174 if (RedirectIO(redirects[0], 0, ErrMsg)) { return -1; } 00175 // Redirect stdout 00176 if (RedirectIO(redirects[1], 1, ErrMsg)) { return -1; } 00177 if (redirects[1] && redirects[2] && 00178 *(redirects[1]) == *(redirects[2])) { 00179 // If stdout and stderr should go to the same place, redirect stderr 00180 // to the FD already open for stdout. 00181 if (-1 == dup2(1,2)) { 00182 MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); 00183 return -1; 00184 } 00185 } else { 00186 // Just redirect stderr 00187 if (RedirectIO(redirects[2], 2, ErrMsg)) { return -1; } 00188 } 00189 } 00190 00191 // Set memory limits 00192 if (memoryLimit!=0) { 00193 SetMemoryLimits(memoryLimit); 00194 } 00195 00196 // Execute! 00197 if (envp != 0) 00198 execve (path.c_str(), (char**)args, (char**)envp); 00199 else 00200 execv (path.c_str(), (char**)args); 00201 // If the execve() failed, we should exit and let the parent pick up 00202 // our non-zero exit status. 00203 exit (errno); 00204 } 00205 00206 // Parent process: Break out of the switch to do our processing. 00207 default: 00208 break; 00209 } 00210 00211 // Make sure stderr and stdout have been flushed 00212 std::cerr << std::flush; 00213 std::cout << std::flush; 00214 fsync(1); 00215 fsync(2); 00216 00217 struct sigaction Act, Old; 00218 00219 // Install a timeout handler. 00220 if (secondsToWait) { 00221 Timeout = false; 00222 Act.sa_sigaction = 0; 00223 Act.sa_handler = TimeOutHandler; 00224 sigemptyset(&Act.sa_mask); 00225 Act.sa_flags = 0; 00226 sigaction(SIGALRM, &Act, &Old); 00227 alarm(secondsToWait); 00228 } 00229 00230 // Parent process: Wait for the child process to terminate. 00231 int status; 00232 while (wait(&status) != child) 00233 if (secondsToWait && errno == EINTR) { 00234 // Kill the child. 00235 kill(child, SIGKILL); 00236 00237 // Turn off the alarm and restore the signal handler 00238 alarm(0); 00239 sigaction(SIGALRM, &Old, 0); 00240 00241 // Wait for child to die 00242 if (wait(&status) != child) 00243 MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); 00244 else 00245 MakeErrMsg(ErrMsg, "Child timed out", 0); 00246 00247 return -1; // Timeout detected 00248 } else if (errno != EINTR) { 00249 MakeErrMsg(ErrMsg, "Error waiting for child process"); 00250 return -1; 00251 } 00252 00253 // We exited normally without timeout, so turn off the timer. 00254 if (secondsToWait) { 00255 alarm(0); 00256 sigaction(SIGALRM, &Old, 0); 00257 } 00258 00259 // Return the proper exit status. 0=success, >0 is programs' exit status, 00260 // <0 means a signal was returned, -9999999 means the program dumped core. 00261 int result = 0; 00262 if (WIFEXITED(status)) 00263 result = WEXITSTATUS(status); 00264 else if (WIFSIGNALED(status)) 00265 result = 0 - WTERMSIG(status); 00266 #ifdef WCOREDUMP 00267 else if (WCOREDUMP(status)) 00268 result |= 0x01000000; 00269 #endif 00270 return result; 00271 #else 00272 return -99; 00273 #endif 00274 00275 } 00276 00277 bool Program::ChangeStdinToBinary(){ 00278 // Do nothing, as Unix doesn't differentiate between text and binary. 00279 return false; 00280 } 00281 00282 bool Program::ChangeStdoutToBinary(){ 00283 // Do nothing, as Unix doesn't differentiate between text and binary. 00284 return false; 00285 } 00286 00287 }