1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmWin32ProcessExecution.h"
14 #include "cmSystemTools.h"
22 #if defined(__BORLANDC__)
23 # define STRICMP stricmp
24 # define TO_INTPTR(x) ((long)(x))
26 #if defined(_MSC_VER) // Visual studio
27 # if ( _MSC_VER >= 1300 )
29 # define TO_INTPTR(x) ((intptr_t)(x))
30 # else // Visual Studio 6
31 # define TO_INTPTR(x) ((long)(x))
32 # endif // Visual studio .NET
33 # define STRICMP _stricmp
34 #endif // Visual Studio
35 #if defined(__MINGW32__)
37 # define TO_INTPTR(x) ((intptr_t)(x))
38 # define STRICMP _stricmp
46 #define cmMAX(x,y) (((x)<(y))?(y):(x))
48 void DisplayErrorMessage()
52 FORMAT_MESSAGE_ALLOCATE_BUFFER |
53 FORMAT_MESSAGE_FROM_SYSTEM |
54 FORMAT_MESSAGE_IGNORE_INSERTS,
57 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
62 // Process any inserts in lpMsgBuf.
64 // Display the string.
65 MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
67 LocalFree( lpMsgBuf );
70 // Code from a Borland web site with the following explaination :
71 /* In this article, I will explain how to spawn a console application
72 * and redirect its standard input/output using anonymous pipes. An
73 * anonymous pipe is a pipe that goes only in one direction (read
74 * pipe, write pipe, etc.). Maybe you are asking, "why would I ever
75 * need to do this sort of thing?" One example would be a Windows
76 * telnet server, where you spawn a shell and listen on a port and
77 * send and receive data between the shell and the socket
78 * client. (Windows does not really have a built-in remote
79 * shell). First, we should talk about pipes. A pipe in Windows is
80 * simply a method of communication, often between process. The SDK
81 * defines a pipe as "a communication conduit with two ends;
83 * with a handle to one end can communicate with a process having a
84 * handle to the other end." In our case, we are using "anonymous"
85 * pipes, one-way pipes that "transfer data between a parent process
86 * and a child process or between two child processes of the same
87 * parent process." It's easiest to imagine a pipe as its namesake. An
88 * actual pipe running between processes that can carry data. We are
89 * using anonymous pipes because the console app we are spawning is a
90 * child process. We use the CreatePipe function which will create an
91 * anonymous pipe and return a read handle and a write handle. We will
92 * create two pipes, on for stdin and one for stdout. We will then
93 * monitor the read end of the stdout pipe to check for display on our
94 * child process. Every time there is something availabe for reading,
95 * we will display it in our app. Consequently, we check for input in
96 * our app and send it off to the write end of the stdin pipe. */
99 //check if we're running NT
102 osv.dwOSVersionInfoSize = sizeof(osv);
104 return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
107 //---------------------------------------------------------------------------
108 bool cmWin32ProcessExecution::BorlandRunCommand(
109 const char* command, const char* dir,
110 std::string& output, int& retVal, bool verbose, int /* timeout */,
114 //std::cerr << std::endl
115 // << "WindowsRunCommand(" << command << ")" << std::endl
117 const int BUFFER_SIZE = 4096;
118 char buf[BUFFER_SIZE];
122 SECURITY_ATTRIBUTES sa;
123 SECURITY_DESCRIPTOR sd;
125 //security information for pipes
126 PROCESS_INFORMATION pi;
127 HANDLE newstdin,newstdout,read_stdout,write_stdin;
131 //initialize security descriptor (Windows NT)
133 InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
134 SetSecurityDescriptorDacl(&sd, true, NULL, false);
135 sa.lpSecurityDescriptor = &sd;
138 else sa.lpSecurityDescriptor = NULL;
139 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
140 sa.bInheritHandle = true;
142 //allow inheritable handles
143 if (!CreatePipe(&newstdin,&write_stdin,&sa,0))
148 if (!CreatePipe(&read_stdout,&newstdout,&sa,0))
151 CloseHandle(newstdin);
152 CloseHandle(write_stdin);
158 //set startupinfo for the spawned process
159 /* The dwFlags member tells CreateProcess how to make the
160 * process. STARTF_USESTDHANDLES validates the hStd*
161 * members. STARTF_USESHOWWINDOW validates the wShowWindow
164 si.cb = sizeof(STARTUPINFO);
165 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
166 si.hStdOutput = newstdout;
167 si.hStdError = newstdout;
168 si.wShowWindow = SW_SHOWDEFAULT;
171 si.wShowWindow = SW_HIDE;
174 //set the new handles for the child process si.hStdInput = newstdin;
175 char* commandAndArgs = strcpy(new char[strlen(command)+1], command);
176 if (!CreateProcess(NULL,commandAndArgs,NULL,NULL,TRUE,
177 0, // CREATE_NEW_CONSOLE,
180 std::cerr << "CreateProcess failed " << commandAndArgs << std::endl;
181 CloseHandle(newstdin);
182 CloseHandle(newstdout);
183 CloseHandle(read_stdout);
184 CloseHandle(write_stdin);
185 delete [] commandAndArgs;
189 delete [] commandAndArgs;
190 unsigned long exit=0;
192 //process exit code unsigned
195 //bytes read unsigned
199 memset(buf, 0, sizeof(buf));
204 //check to see if there is any data to read from stdout
205 //std::cout << "Peek for data..." << std::endl;
206 PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
209 memset(buf, 0, sizeof(buf));
212 while (bread >= 1023)
214 //std::cout << "Read data..." << std::endl;
215 ReadFile(read_stdout,buf,1023,&bread,NULL);
217 //read the stdout pipe
218 memset(buf, 0, sizeof(buf));
222 cmSystemTools::Stdout(buf);
228 ReadFile(read_stdout,buf,1023,&bread,NULL);
232 cmSystemTools::Stdout(buf);
239 //std::cout << "Check for process..." << std::endl;
240 GetExitCodeProcess(pi.hProcess,&exit);
242 //while the process is running
243 if (exit != STILL_ACTIVE) break;
246 WaitForSingleObject(pi.hProcess, INFINITE);
247 GetExitCodeProcess(pi.hProcess,&exit);
248 CloseHandle(pi.hThread);
249 CloseHandle(pi.hProcess);
250 CloseHandle(newstdin);
253 CloseHandle(newstdout);
254 CloseHandle(read_stdout);
255 CloseHandle(write_stdin);
261 bool cmWin32ProcessExecution::StartProcess(
262 const char* cmd, const char* path, bool verbose)
265 this->Verbose = verbose;
266 return this->PrivateOpen(cmd, path, _O_RDONLY | _O_TEXT, POPEN_3);
269 bool cmWin32ProcessExecution::Wait(int timeout)
271 return this->PrivateClose(timeout);
275 * Internal dictionary mapping popen* file pointers to process handles,
276 * for use when retrieving the process exit code. See _PyPclose() below
277 * for more information on this dictionary's use.
279 static void *_PyPopenProcs = NULL;
281 static BOOL RealPopenCreateProcess(const char *cmdstring,
283 const char *szConsoleSpawn,
291 PROCESS_INFORMATION piProcInfo;
292 STARTUPINFO siStartInfo;
294 const char *s3 = " /c ";
295 int i = GetEnvironmentVariable("COMSPEC",NULL,0);
300 s1 = (char *)malloc(i);
301 int x = GetEnvironmentVariable("COMSPEC", s1, i);
308 /* Explicitly check if we are using COMMAND.COM. If we are
309 * then use the w9xpopen hack.
312 while (comshell >= s1 && *comshell != '\\')
316 if (GetVersion() < 0x80000000 &&
317 STRICMP(comshell, "command.com") != 0)
319 /* NT/2000 and not using command.com. */
320 x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1;
321 s2 = (char *)malloc(x);
323 //sprintf(s2, "%s%s%s", s1, s3, cmdstring);
324 sprintf(s2, "%s", cmdstring);
329 * Oh gag, we're on Win9x or using COMMAND.COM. Use
330 * the workaround listed in KB: Q150956
332 char modulepath[_MAX_PATH];
333 struct stat statinfo;
334 GetModuleFileName(NULL, modulepath, sizeof(modulepath));
335 for (i = x = 0; modulepath[i]; i++)
336 if (modulepath[i] == '\\')
338 modulepath[x] = '\0';
339 /* Create the full-name to w9xpopen, so we can test it exists */
342 (sizeof(modulepath)/sizeof(modulepath[0]))
343 -strlen(modulepath));
344 if (stat(modulepath, &statinfo) != 0)
346 /* Eeek - file-not-found - possibly an embedding
347 situation - see if we can locate it in sys.prefix
351 sizeof(modulepath)/sizeof(modulepath[0]));
352 if (modulepath[strlen(modulepath)-1] != '\\')
353 strcat(modulepath, "\\");
356 (sizeof(modulepath)/sizeof(modulepath[0]))
357 -strlen(modulepath));
358 /* No where else to look - raise an easily identifiable
359 error, rather than leaving Windows to report
360 "file not found" - as the user is probably blissfully
361 unaware this shim EXE is used, and it will confuse them.
362 (well, it confused me for a while ;-)
364 if (stat(modulepath, &statinfo) != 0)
367 << "Can not locate '" << modulepath
368 << "' which is needed "
369 "for popen to work with your shell "
370 "or platform." << std::endl;
376 x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1 +
377 (int)strlen(modulepath) +
378 (int)strlen(szConsoleSpawn) + 1;
383 s2 = (char *)malloc(x);
400 /* Could be an else here to try cmd.exe / command.com in the path
401 Now we'll just error out.. */
404 std::cout << "Cannot locate a COMSPEC environment variable to "
405 << "use as the shell" << std::endl;
411 ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
412 siStartInfo.cb = sizeof(STARTUPINFO);
413 siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
414 siStartInfo.hStdInput = hStdin;
415 siStartInfo.hStdOutput = hStdout;
416 siStartInfo.hStdError = hStderr;
417 siStartInfo.wShowWindow = SW_SHOWDEFAULT;
420 siStartInfo.wShowWindow = SW_HIDE;
423 //std::cout << "Create process: " << s2 << std::endl;
424 if (CreateProcess(NULL,
429 0, //CREATE_NEW_CONSOLE,
435 /* Close the handles now so anyone waiting is woken. */
436 CloseHandle(piProcInfo.hThread);
437 /* Return process handle */
438 *hProcess = piProcInfo.hProcess;
439 //std::cout << "Process created..." << std::endl;
445 output += "CreateProcessError: ";
447 /* Format the error message. */
449 DWORD original = GetLastError();
450 DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
451 FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
452 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
456 /* FormatMessage failed. Use a default message. */
457 _snprintf(message, 1023,
458 "Process execution failed with error 0x%X. "
459 "FormatMessage failed with error 0x%X",
460 original, GetLastError());
465 output += "for command: ";
469 output += "\nin dir: ";
478 /* The following code is based off of KB: Q190351 */
480 bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
487 SECURITY_ATTRIBUTES saAttr;
490 this->hChildStdinRd = 0;
491 this->hChildStdinWr = 0;
492 this->hChildStdoutRd = 0;
493 this->hChildStdoutWr = 0;
494 this->hChildStderrRd = 0;
495 this->hChildStderrWr = 0;
496 this->hChildStdinWrDup = 0;
497 this->hChildStdoutRdDup = 0;
498 this->hChildStderrRdDup = 0;
500 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
501 saAttr.bInheritHandle = TRUE;
502 saAttr.lpSecurityDescriptor = NULL;
508 if (!CreatePipe(&this->hChildStdinRd, &this->hChildStdinWr, &saAttr, 0))
510 this->Output += "CreatePipeError\n";
514 /* Create new output read handle and the input write handle. Set
515 * the inheritance properties to FALSE. Otherwise, the child inherits
516 * the these handles; resulting in non-closeable handles to the pipes
518 fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdinWr,
519 GetCurrentProcess(), &this->hChildStdinWrDup, 0,
521 DUPLICATE_SAME_ACCESS);
524 this->Output += "DuplicateHandleError\n";
529 /* Close the inheritable version of ChildStdin
531 CloseHandle(hChildStdinWr);
533 if (!CreatePipe(&this->hChildStdoutRd, &this->hChildStdoutWr, &saAttr, 0))
535 this->Output += "CreatePipeError\n";
539 fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdoutRd,
540 GetCurrentProcess(), &this->hChildStdoutRdDup, 0,
541 FALSE, DUPLICATE_SAME_ACCESS);
544 this->Output += "DuplicateHandleError\n";
548 /* Close the inheritable version of ChildStdout
550 CloseHandle(hChildStdoutRd);
554 if (!CreatePipe(&this->hChildStderrRd, &this->hChildStderrWr, &saAttr, 0))
556 this->Output += "CreatePipeError\n";
559 fSuccess = DuplicateHandle(GetCurrentProcess(),
560 this->hChildStderrRd,
562 &this->hChildStderrRdDup, 0,
563 FALSE, DUPLICATE_SAME_ACCESS);
566 this->Output += "DuplicateHandleError\n";
569 /* Close the inheritable version of ChildStdErr that we're using. */
570 CloseHandle(hChildStderrRd);
577 switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY))
579 case _O_WRONLY | _O_TEXT:
580 /* Case for writing to child Stdin in text mode. */
581 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
582 /* We don't care about these pipes anymore,
586 case _O_RDONLY | _O_TEXT:
587 /* Case for reading from child Stdout in text mode. */
588 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
589 /* We don't care about these pipes anymore,
593 case _O_RDONLY | _O_BINARY:
594 /* Case for readinig from child Stdout in
596 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
597 /* We don't care about these pipes anymore,
601 case _O_WRONLY | _O_BINARY:
602 /* Case for writing to child Stdin in binary mode. */
603 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
604 /* We don't care about these pipes anymore,
614 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
615 fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
622 fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode);
623 fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode);
624 fd3 = _open_osfhandle(TO_INTPTR(this->hChildStderrRdDup), mode);
631 if (!RealPopenCreateProcess(cmdstring,
633 this->ConsoleSpawn.c_str(),
635 this->hChildStdoutWr,
636 this->hChildStdoutWr,
637 &hProcess, this->HideWindows,
657 if (!RealPopenCreateProcess(cmdstring,
659 this->ConsoleSpawn.c_str(),
661 this->hChildStdoutWr,
662 this->hChildStderrWr,
663 &hProcess, this->HideWindows,
683 * Insert the files we've created into the process dictionary
684 * all referencing the list with the process handle and the
685 * initial number of files (see description below in _PyPclose).
686 * Since if _PyPclose later tried to wait on a process when all
687 * handles weren't closed, it could create a deadlock with the
688 * child, we spend some energy here to try to ensure that we
689 * either insert all file handles into the dictionary or none
690 * at all. It's a little clumsy with the various popen modes
691 * and variable number of files involved.
694 /* Child is launched. Close the parents copy of those pipe
695 * handles that only the child should have open. You need to
696 * make sure that no handles to the write end of the output pipe
697 * are maintained in this process or else the pipe will not close
698 * when the child process exits and the ReadFile will hang. */
699 this->ProcessHandle = hProcess;
716 bool cmWin32ProcessExecution::CloseHandles()
718 if(this->pStdErr != -1 )
720 // this will close this as well: this->hChildStderrRdDup
721 _close(this->pStdErr);
723 this->hChildStderrRdDup = 0;
725 if(this->pStdIn != -1 )
727 // this will close this as well: this->hChildStdinWrDup
728 _close(this->pStdIn);
730 this->hChildStdinWrDup = 0;
732 if(this->pStdOut != -1 )
734 // this will close this as well: this->hChildStdoutRdDup
735 _close(this->pStdOut);
737 this->hChildStdoutRdDup = 0;
741 if (this->hChildStdinRd && !CloseHandle(this->hChildStdinRd))
745 this->hChildStdinRd = 0;
746 // now close these two
747 if (this->hChildStdoutWr && !CloseHandle(this->hChildStdoutWr))
751 this->hChildStdoutWr = 0;
752 if (this->hChildStderrWr && !CloseHandle(this->hChildStderrWr))
756 this->hChildStderrWr = 0;
759 cmWin32ProcessExecution::~cmWin32ProcessExecution()
761 this->CloseHandles();
765 * Wrapper for fclose() to use for popen* files, so we can retrieve the
766 * exit code for the child process and return as a result of the close.
768 * This function uses the _PyPopenProcs dictionary in order to map the
769 * input file pointer to information about the process that was
770 * originally created by the popen* call that created the file pointer.
771 * The dictionary uses the file pointer as a key (with one entry
772 * inserted for each file returned by the original popen* call) and a
773 * single list object as the value for all files from a single call.
774 * The list object contains the Win32 process handle at [0], and a file
775 * count at [1], which is initialized to the total number of file
776 * handles using that list.
778 * This function closes whichever handle it is passed, and decrements
779 * the file count in the dictionary for the process handle pointed to
780 * by this file. On the last close (when the file count reaches zero),
781 * this function will wait for the child process and then return its
782 * exit code as the result of the close() operation. This permits the
783 * files to be closed in any order - it is always the close() of the
784 * final handle that will return the exit code.
787 /* RED_FLAG 31-Aug-2000 Tim
788 * This is always called (today!) between a pair of
789 * Py_BEGIN_ALLOW_THREADS/ Py_END_ALLOW_THREADS
790 * macros. So the thread running this has no valid thread state, as
791 * far as Python is concerned. However, this calls some Python API
792 * functions that cannot be called safely without a valid thread
793 * state, in particular PyDict_GetItem.
794 * As a temporary hack (although it may last for years ...), we
795 * *rely* on not having a valid thread state in this function, in
796 * order to create our own "from scratch".
797 * This will deadlock if _PyPclose is ever called by a thread
798 * holding the global lock.
801 bool cmWin32ProcessExecution::PrivateClose(int /* timeout */)
803 HANDLE hProcess = this->ProcessHandle;
808 std::string output = "";
813 bool have_some = false;
816 int rout = _fstat(this->pStdOut, &fsout);
817 int rerr = _fstat(this->pStdErr, &fserr);
822 if (fserr.st_size > 0)
825 int len = read(this->pStdErr, buffer, 1023);
829 cmSystemTools::Stdout(buffer);
834 if (fsout.st_size > 0)
837 int len = read(this->pStdOut, buffer, 1023);
841 cmSystemTools::Stdout(buffer);
846 unsigned long exitCode;
849 GetExitCodeProcess(hProcess,&exitCode);
850 if (exitCode != STILL_ACTIVE)
858 if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
859 GetExitCodeProcess(hProcess, &exit_code))
865 /* Indicate failure - this will cause the file object
866 * to raise an I/O error and translate the last Win32
867 * error code from errno. We do have a problem with
868 * last errors that overlap the normal errno table,
869 * but that's a consistent problem with the file object.
873 /* If the error wasn't from the fclose(), then
874 * set errno for the file object error handling.
876 errno = GetLastError();
881 /* Free up the native handle at this point */
882 CloseHandle(hProcess);
883 this->ExitValue = result;
884 this->Output += output;
885 bool ret = this->CloseHandles();
886 if ( result < 0 || !ret)
893 int cmWin32ProcessExecution::Windows9xHack(const char* command)
897 PROCESS_INFORMATION pi;
902 cmSystemTools::Error("Windows9xHack: Command not specified");
906 /* Make child process use this app's standard files. */
907 ZeroMemory(&si, sizeof si);
909 si.dwFlags = STARTF_USESTDHANDLES;
910 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
911 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
912 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
916 char* cmd = new char[ strlen(command) + 1 ];
917 strcpy(cmd, command);
919 bRet = CreateProcess(
930 if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED)
932 GetExitCodeProcess(pi.hProcess, &exit_code);
934 CloseHandle(pi.hProcess);
935 CloseHandle(pi.hThread);