1 //===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides the Win32 specific implementation of the Program class.
12 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/Support/FileSystem.h"
22 //===----------------------------------------------------------------------===//
23 //=== WARNING: Implementation here must contain only Win32 specific code
24 //=== and must not be UNIX code
25 //===----------------------------------------------------------------------===//
30 ProcessInfo::ProcessInfo() : Pid(0), ProcessHandle(0), ReturnCode(0) {}
32 // This function just uses the PATH environment variable to find the program.
33 std::string sys::FindProgramByName(const std::string &progName) {
34 // Check some degenerate cases
35 if (progName.length() == 0) // no program
37 std::string temp = progName;
38 // Return paths with slashes verbatim.
39 if (progName.find('\\') != std::string::npos ||
40 progName.find('/') != std::string::npos)
43 // At this point, the file name is valid and does not contain slashes.
44 // Let Windows search for it.
46 buffer.resize(MAX_PATH);
48 DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH,
51 // See if it wasn't found.
55 // See if we got the entire path.
59 // Buffer was too small; grow and retry.
62 DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, &buffer[0], &dummy);
64 // It is unlikely the search failed, but it's always possible some file
65 // was added or removed since the last search, so be paranoid...
75 static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) {
78 DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
79 GetCurrentProcess(), &h,
80 0, TRUE, DUPLICATE_SAME_ACCESS);
90 SECURITY_ATTRIBUTES sa;
91 sa.nLength = sizeof(sa);
92 sa.lpSecurityDescriptor = 0;
93 sa.bInheritHandle = TRUE;
95 h = CreateFile(fname.c_str(), fd ? GENERIC_WRITE : GENERIC_READ,
96 FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
97 FILE_ATTRIBUTE_NORMAL, NULL);
98 if (h == INVALID_HANDLE_VALUE) {
99 MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " +
100 (fd ? "input: " : "output: "));
106 /// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
108 static bool ArgNeedsQuotes(const char *Str) {
109 return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0;
112 /// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur
113 /// in the C string Start.
114 static unsigned int CountPrecedingBackslashes(const char *Start,
116 unsigned int Count = 0;
118 while (Cur >= Start && *Cur == '\\') {
125 /// EscapePrecedingEscapes - Append a backslash to Dst for every backslash
126 /// preceding Cur in the Start string. Assumes Dst has enough space.
127 static char *EscapePrecedingEscapes(char *Dst, const char *Start,
129 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur);
130 while (PrecedingEscapes > 0) {
137 /// ArgLenWithQuotes - Check whether argument needs to be quoted when calling
138 /// CreateProcess and returns length of quoted arg with escaped quotes
139 static unsigned int ArgLenWithQuotes(const char *Str) {
140 const char *Start = Str;
141 bool Quoted = ArgNeedsQuotes(Str);
142 unsigned int len = Quoted ? 2 : 0;
144 while (*Str != '\0') {
146 // We need to add a backslash, but ensure that it isn't escaped.
147 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
148 len += PrecedingEscapes + 1;
150 // Note that we *don't* need to escape runs of backslashes that don't
151 // precede a double quote! See MSDN:
152 // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
159 // Make sure the closing quote doesn't get escaped by a trailing backslash.
160 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
161 len += PrecedingEscapes + 1;
169 static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
170 const char **envp, const StringRef **redirects,
171 unsigned memoryLimit, std::string *ErrMsg) {
172 if (!sys::fs::can_execute(Program)) {
174 *ErrMsg = "program not executable";
178 // Windows wants a command line, not an array of args, to pass to the new
179 // process. We have to concatenate them all, while quoting the args that
180 // have embedded spaces (or are empty).
182 // First, determine the length of the command line.
184 for (unsigned i = 0; args[i]; i++) {
185 len += ArgLenWithQuotes(args[i]) + 1;
188 // Now build the command line.
189 OwningArrayPtr<char> command(new char[len+1]);
190 char *p = command.get();
192 for (unsigned i = 0; args[i]; i++) {
193 const char *arg = args[i];
194 const char *start = arg;
196 bool needsQuoting = ArgNeedsQuotes(arg);
200 while (*arg != '\0') {
202 // Escape all preceding escapes (if any), and then escape the quote.
203 p = EscapePrecedingEscapes(p, start, arg);
211 // Make sure our quote doesn't get escaped by a trailing backslash.
212 p = EscapePrecedingEscapes(p, start, arg);
220 // The pointer to the environment block for the new process.
221 OwningArrayPtr<char> envblock;
224 // An environment block consists of a null-terminated block of
225 // null-terminated strings. Convert the array of environment variables to
226 // an environment block by concatenating them.
228 // First, determine the length of the environment block.
230 for (unsigned i = 0; envp[i]; i++)
231 len += strlen(envp[i]) + 1;
233 // Now build the environment block.
234 envblock.reset(new char[len+1]);
237 for (unsigned i = 0; envp[i]; i++) {
238 const char *ev = envp[i];
239 size_t len = strlen(ev) + 1;
247 // Create a child process.
249 memset(&si, 0, sizeof(si));
251 si.hStdInput = INVALID_HANDLE_VALUE;
252 si.hStdOutput = INVALID_HANDLE_VALUE;
253 si.hStdError = INVALID_HANDLE_VALUE;
256 si.dwFlags = STARTF_USESTDHANDLES;
258 si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
259 if (si.hStdInput == INVALID_HANDLE_VALUE) {
260 MakeErrMsg(ErrMsg, "can't redirect stdin");
263 si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
264 if (si.hStdOutput == INVALID_HANDLE_VALUE) {
265 CloseHandle(si.hStdInput);
266 MakeErrMsg(ErrMsg, "can't redirect stdout");
269 if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
270 // If stdout and stderr should go to the same place, redirect stderr
271 // to the handle already open for stdout.
272 DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
273 GetCurrentProcess(), &si.hStdError,
274 0, TRUE, DUPLICATE_SAME_ACCESS);
276 // Just redirect stderr
277 si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
278 if (si.hStdError == INVALID_HANDLE_VALUE) {
279 CloseHandle(si.hStdInput);
280 CloseHandle(si.hStdOutput);
281 MakeErrMsg(ErrMsg, "can't redirect stderr");
287 PROCESS_INFORMATION pi;
288 memset(&pi, 0, sizeof(pi));
292 std::string ProgramStr = Program;
293 BOOL rc = CreateProcess(ProgramStr.c_str(), command.get(), NULL, NULL, TRUE,
294 0, envblock.get(), NULL, &si, &pi);
295 DWORD err = GetLastError();
297 // Regardless of whether the process got created or not, we are done with
298 // the handles we created for it to inherit.
299 CloseHandle(si.hStdInput);
300 CloseHandle(si.hStdOutput);
301 CloseHandle(si.hStdError);
303 // Now return an error if the process didn't get created.
306 MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
311 PI.Pid = pi.dwProcessId;
312 PI.ProcessHandle = pi.hProcess;
314 // Make sure these get closed no matter what.
315 ScopedCommonHandle hThread(pi.hThread);
317 // Assign the process to a job if a memory limit is defined.
318 ScopedJobHandle hJob;
319 if (memoryLimit != 0) {
320 hJob = CreateJobObject(0, 0);
321 bool success = false;
323 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
324 memset(&jeli, 0, sizeof(jeli));
325 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
326 jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
327 if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
328 &jeli, sizeof(jeli))) {
329 if (AssignProcessToJobObject(hJob, pi.hProcess))
334 SetLastError(GetLastError());
335 MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
336 TerminateProcess(pi.hProcess, 1);
337 WaitForSingleObject(pi.hProcess, INFINITE);
346 ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
347 bool WaitUntilChildTerminates, std::string *ErrMsg) {
348 assert(PI.Pid && "invalid pid to wait on, process not started?");
349 assert(PI.ProcessHandle &&
350 "invalid process handle to wait on, process not started?");
351 DWORD milliSecondsToWait = 0;
352 if (WaitUntilChildTerminates)
353 milliSecondsToWait = INFINITE;
354 else if (SecondsToWait > 0)
355 milliSecondsToWait = SecondsToWait * 1000;
357 ProcessInfo WaitResult = PI;
358 DWORD WaitStatus = WaitForSingleObject(PI.ProcessHandle, milliSecondsToWait);
359 if (WaitStatus == WAIT_TIMEOUT) {
361 if (!TerminateProcess(PI.ProcessHandle, 1)) {
363 MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
365 // -2 indicates a crash or timeout as opposed to failure to execute.
366 WaitResult.ReturnCode = -2;
367 CloseHandle(PI.ProcessHandle);
370 WaitForSingleObject(PI.ProcessHandle, INFINITE);
371 CloseHandle(PI.ProcessHandle);
373 // Non-blocking wait.
374 return ProcessInfo();
378 // Get its exit status.
380 BOOL rc = GetExitCodeProcess(PI.ProcessHandle, &status);
381 DWORD err = GetLastError();
382 CloseHandle(PI.ProcessHandle);
387 MakeErrMsg(ErrMsg, "Failed getting status for program.");
389 // -2 indicates a crash or timeout as opposed to failure to execute.
390 WaitResult.ReturnCode = -2;
397 // Pass 10(Warning) and 11(Error) to the callee as negative value.
398 if ((status & 0xBFFF0000U) == 0x80000000U)
399 WaitResult.ReturnCode = static_cast<int>(status);
400 else if (status & 0xFF)
401 WaitResult.ReturnCode = status & 0x7FFFFFFF;
403 WaitResult.ReturnCode = 1;
408 error_code sys::ChangeStdinToBinary(){
409 int result = _setmode( _fileno(stdin), _O_BINARY );
411 return error_code(errno, generic_category());
412 return make_error_code(errc::success);
415 error_code sys::ChangeStdoutToBinary(){
416 int result = _setmode( _fileno(stdout), _O_BINARY );
418 return error_code(errno, generic_category());
419 return make_error_code(errc::success);
422 error_code sys::ChangeStderrToBinary(){
423 int result = _setmode( _fileno(stderr), _O_BINARY );
425 return error_code(errno, generic_category());
426 return make_error_code(errc::success);
429 bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {
430 // The documented max length of the command line passed to CreateProcess.
431 static const size_t MaxCommandStringLength = 32768;
432 size_t ArgLength = 0;
433 for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();
435 // Account for the trailing space for every arg but the last one and the
436 // trailing NULL of the last argument.
437 ArgLength += ArgLenWithQuotes(*I) + 1;
438 if (ArgLength > MaxCommandStringLength) {