Get rid of the Pid_ member in the Program class.
[oota-llvm.git] / lib / System / Unix / Program.inc
1 //===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Unix specific portion of the Program class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 //=== WARNING: Implementation here must contain only generic UNIX code that
16 //===          is guaranteed to work on *all* UNIX variants.
17 //===----------------------------------------------------------------------===//
18
19 #include <llvm/Config/config.h>
20 #include "Unix.h"
21 #if HAVE_SYS_STAT_H
22 #include <sys/stat.h>
23 #endif
24 #if HAVE_SYS_RESOURCE_H
25 #include <sys/resource.h>
26 #endif
27 #if HAVE_SIGNAL_H
28 #include <signal.h>
29 #endif
30 #if HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
33
34 namespace llvm {
35 using namespace sys;
36
37 Program::Program() : Data_(0) {}
38
39 Program::~Program() {}
40
41 unsigned Program::GetPid() {
42   return reinterpret_cast<unsigned>(Data_);
43 }
44
45 // This function just uses the PATH environment variable to find the program.
46 Path
47 Program::FindProgramByName(const std::string& progName) {
48
49   // Check some degenerate cases
50   if (progName.length() == 0) // no program
51     return Path();
52   Path temp;
53   if (!temp.set(progName)) // invalid name
54     return Path();
55   // Use the given path verbatim if it contains any slashes; this matches
56   // the behavior of sh(1) and friends.
57   if (progName.find('/') != std::string::npos)
58     return temp;
59
60   // At this point, the file name does not contain slashes. Search for it
61   // through the directories specified in the PATH environment variable.
62
63   // Get the path. If its empty, we can't do anything to find it.
64   const char *PathStr = getenv("PATH");
65   if (PathStr == 0)
66     return Path();
67
68   // Now we have a colon separated list of directories to search; try them.
69   size_t PathLen = strlen(PathStr);
70   while (PathLen) {
71     // Find the first colon...
72     const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
73
74     // Check to see if this first directory contains the executable...
75     Path FilePath;
76     if (FilePath.set(std::string(PathStr,Colon))) {
77       FilePath.appendComponent(progName);
78       if (FilePath.canExecute())
79         return FilePath;                    // Found the executable!
80     }
81
82     // Nope it wasn't in this directory, check the next path in the list!
83     PathLen -= Colon-PathStr;
84     PathStr = Colon;
85
86     // Advance past duplicate colons
87     while (*PathStr == ':') {
88       PathStr++;
89       PathLen--;
90     }
91   }
92   return Path();
93 }
94
95 static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) {
96   if (Path == 0)
97     // Noop
98     return false;
99   std::string File;
100   if (Path->isEmpty())
101     // Redirect empty paths to /dev/null
102     File = "/dev/null";
103   else
104     File = Path->str();
105
106   // Open the file
107   int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
108   if (InFD == -1) {
109     MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
110               + (FD == 0 ? "input" : "output"));
111     return true;
112   }
113
114   // Install it as the requested FD
115   if (-1 == dup2(InFD, FD)) {
116     MakeErrMsg(ErrMsg, "Cannot dup2");
117     return true;
118   }
119   close(InFD);      // Close the original FD
120   return false;
121 }
122
123 static void SetMemoryLimits (unsigned size)
124 {
125 #if HAVE_SYS_RESOURCE_H
126   struct rlimit r;
127   __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
128
129   // Heap size
130   getrlimit (RLIMIT_DATA, &r);
131   r.rlim_cur = limit;
132   setrlimit (RLIMIT_DATA, &r);
133 #ifdef RLIMIT_RSS
134   // Resident set size.
135   getrlimit (RLIMIT_RSS, &r);
136   r.rlim_cur = limit;
137   setrlimit (RLIMIT_RSS, &r);
138 #endif
139 #ifdef RLIMIT_AS  // e.g. NetBSD doesn't have it.
140   // Virtual memory.
141   getrlimit (RLIMIT_AS, &r);
142   r.rlim_cur = limit;
143   setrlimit (RLIMIT_AS, &r);
144 #endif
145 #endif
146 }
147
148 bool
149 Program::Execute(const Path& path,
150                  const char** args,
151                  const char** envp,
152                  const Path** redirects,
153                  unsigned memoryLimit,
154                  std::string* ErrMsg)
155 {
156   if (!path.canExecute()) {
157     if (ErrMsg)
158       *ErrMsg = path.str() + " is not executable";
159     return false;
160   }
161
162   // Create a child process.
163   int child = fork();
164   switch (child) {
165     // An error occured:  Return to the caller.
166     case -1:
167       MakeErrMsg(ErrMsg, "Couldn't fork");
168       return false;
169
170     // Child process: Execute the program.
171     case 0: {
172       // Redirect file descriptors...
173       if (redirects) {
174         // Redirect stdin
175         if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; }
176         // Redirect stdout
177         if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; }
178         if (redirects[1] && redirects[2] &&
179             *(redirects[1]) == *(redirects[2])) {
180           // If stdout and stderr should go to the same place, redirect stderr
181           // to the FD already open for stdout.
182           if (-1 == dup2(1,2)) {
183             MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
184             return false;
185           }
186         } else {
187           // Just redirect stderr
188           if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; }
189         }
190       }
191
192       // Set memory limits
193       if (memoryLimit!=0) {
194         SetMemoryLimits(memoryLimit);
195       }
196
197       // Execute!
198       if (envp != 0)
199         execve(path.c_str(), (char**)args, (char**)envp);
200       else
201         execv(path.c_str(), (char**)args);
202       // If the execve() failed, we should exit. Follow Unix protocol and
203       // return 127 if the executable was not found, and 126 otherwise.
204       // Use _exit rather than exit so that atexit functions and static
205       // object destructors cloned from the parent process aren't
206       // redundantly run, and so that any data buffered in stdio buffers
207       // cloned from the parent aren't redundantly written out.
208       _exit(errno == ENOENT ? 127 : 126);
209     }
210
211     // Parent process: Break out of the switch to do our processing.
212     default:
213       break;
214   }
215
216   Data_ = reinterpret_cast<void*>(child);
217
218   return true;
219 }
220
221 int
222 Program::Wait(unsigned secondsToWait,
223               std::string* ErrMsg)
224 {
225 #ifdef HAVE_SYS_WAIT_H
226   struct sigaction Act, Old;
227
228   if (Data_ == 0) {
229     MakeErrMsg(ErrMsg, "Process not started!");
230     return -1;
231   }
232
233   // Install a timeout handler.
234   if (secondsToWait) {
235     memset(&Act, 0, sizeof(Act));
236     Act.sa_handler = SIG_IGN;
237     sigemptyset(&Act.sa_mask);
238     sigaction(SIGALRM, &Act, &Old);
239     alarm(secondsToWait);
240   }
241
242   // Parent process: Wait for the child process to terminate.
243   int status;
244   pid_t child = reinterpret_cast<pid_t>(Data_);
245   while (wait(&status) != child)
246     if (secondsToWait && errno == EINTR) {
247       // Kill the child.
248       kill(child, SIGKILL);
249
250       // Turn off the alarm and restore the signal handler
251       alarm(0);
252       sigaction(SIGALRM, &Old, 0);
253
254       // Wait for child to die
255       if (wait(&status) != child)
256         MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
257       else
258         MakeErrMsg(ErrMsg, "Child timed out", 0);
259
260       return -1;   // Timeout detected
261     } else if (errno != EINTR) {
262       MakeErrMsg(ErrMsg, "Error waiting for child process");
263       return -1;
264     }
265
266   // We exited normally without timeout, so turn off the timer.
267   if (secondsToWait) {
268     alarm(0);
269     sigaction(SIGALRM, &Old, 0);
270   }
271
272   // Return the proper exit status. 0=success, >0 is programs' exit status,
273   // <0 means a signal was returned, -9999999 means the program dumped core.
274   int result = 0;
275   if (WIFEXITED(status))
276     result = WEXITSTATUS(status);
277   else if (WIFSIGNALED(status))
278     result = 0 - WTERMSIG(status);
279 #ifdef WCOREDUMP
280   else if (WCOREDUMP(status))
281     result |= 0x01000000;
282 #endif
283   return result;
284 #else
285   return -99;
286 #endif
287
288 }
289
290 bool
291 Program::Kill(std::string* ErrMsg) {
292   if (Data_ == 0) {
293     MakeErrMsg(ErrMsg, "Process not started!");
294     return true;
295   }
296
297   pid_t pid = reinterpret_cast<pid_t>(Data_);
298   return (kill(pid, SIGKILL) == 0);
299 }
300
301 bool Program::ChangeStdinToBinary(){
302   // Do nothing, as Unix doesn't differentiate between text and binary.
303   return false;
304 }
305
306 bool Program::ChangeStdoutToBinary(){
307   // Do nothing, as Unix doesn't differentiate between text and binary.
308   return false;
309 }
310
311 }