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