From f551135208adc1ac8990f5309ec54325cf897d7d Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Oct 2013 14:43:42 -0400 Subject: [PATCH 1/4] cmExtraEclipseCDT4Generator: Replace RunCommand with RunSingleCommand Avoid use of the old cmSystemTools::RunCommand by using RunSingleCommand instead. --- Source/cmExtraEclipseCDT4Generator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index bd3d6697f..a2dd903d0 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -1132,7 +1132,7 @@ cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path) #if defined(__CYGWIN__) std::string cmd = "cygpath -m " + path; std::string out; - if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false)) + if (!cmSystemTools::RunSingleCommand(cmd.c_str(), &out)) { return path; } From c076476d7de18802d99d3c715caee54f05d52781 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Oct 2013 15:37:09 -0400 Subject: [PATCH 2/4] cmake: Drop "cmake -E comspec" Win9x helper Since we dropped Win9x support there is no need for this helper. --- Help/manual/cmake.1.rst | 2 +- Source/cmcmd.cxx | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 64d0fb3f3..d026c6338 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -33,7 +33,7 @@ native tool on their platform. copy_directory, copy_if_different, echo, echo_append, environment, make_directory, md5sum, remove, remove_directory, rename, tar, time, touch, touch_nocreate. In addition, some platform specific commands - are available. On Windows: comspec, delete_regv, write_regv. On + are available. On Windows: delete_regv, write_regv. On UNIX: create_symlink. * ``-i``: Run in wizard mode. diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 48d7d7b59..9814aeaee 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -29,10 +29,6 @@ #include "cmVisualStudioWCEPlatformParser.h" #endif -#if defined(_WIN32) && !defined(__CYGWIN__) -# include "cmWin32ProcessExecution.h" -#endif - #include #include // required for atoi @@ -79,7 +75,6 @@ void CMakeCommandUsage(const char* program) << " touch_nocreate file - touch a file but do not create it.\n" #if defined(_WIN32) && !defined(__CYGWIN__) << "Available on Windows only:\n" - << " comspec - on windows 9x use this for RunCommand\n" << " delete_regv key - delete registry value\n" << " env_vs8_wince sdkname - displays a batch file which sets the " "environment for the provided Windows CE SDK installed in VS2005\n" @@ -743,13 +738,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) // Remove file else if (args[1] == "comspec" && args.size() > 2) { - unsigned int cc; - std::string command = args[2]; - for ( cc = 3; cc < args.size(); cc ++ ) - { - command += " " + args[cc]; - } - return cmWin32ProcessExecution::Windows9xHack(command.c_str()); + std::cerr << "Win9x helper \"cmake -E comspec\" no longer supported\n"; + return 1; } else if (args[1] == "env_vs8_wince" && args.size() == 3) { From 52b80b2643acdd2f31582fe20773cc4c3740b9ad Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Oct 2013 15:47:17 -0400 Subject: [PATCH 3/4] exec_program: Re-implement using KWSys Process Drop use of cmSystemTools::RunCommand. It used popen on UNIX (equivalent to /bin/sh -c "$command") and direct CreateProcess calls on Windows. Implement equivalent behavior using the KWSys Process library. Copy windows shortpath conversion logic from cmSystemTools::RunCommand. --- Source/cmExecProgramCommand.cxx | 196 +++++++++++++++++++++++++++++++- Source/cmExecProgramCommand.h | 4 + 2 files changed, 196 insertions(+), 4 deletions(-) diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 9fdb1e896..6c11345b7 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -12,6 +12,8 @@ #include "cmExecProgramCommand.h" #include "cmSystemTools.h" +#include + // cmExecProgramCommand bool cmExecProgramCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) @@ -103,13 +105,13 @@ bool cmExecProgramCommand if(args.size() - count == 2) { cmSystemTools::MakeDirectory(args[1].c_str()); - result = cmSystemTools::RunCommand(command.c_str(), output, retVal, - args[1].c_str(), verbose); + result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal, + args[1].c_str(), verbose); } else { - result = cmSystemTools::RunCommand(command.c_str(), output, - retVal, 0, verbose); + result = cmExecProgramCommand::RunCommand(command.c_str(), output, + retVal, 0, verbose); } if(!result) { @@ -143,3 +145,189 @@ bool cmExecProgramCommand return true; } +bool cmExecProgramCommand::RunCommand(const char* command, + std::string& output, + int &retVal, + const char* dir, + bool verbose) +{ + if(cmSystemTools::GetRunCommandOutput()) + { + verbose = false; + } + +#if defined(WIN32) && !defined(__CYGWIN__) + // if the command does not start with a quote, then + // try to find the program, and if the program can not be + // found use system to run the command as it must be a built in + // shell command like echo or dir + int count = 0; + std::string shortCmd; + if(command[0] == '\"') + { + // count the number of quotes + for(const char* s = command; *s != 0; ++s) + { + if(*s == '\"') + { + count++; + if(count > 2) + { + break; + } + } + } + // if there are more than two double quotes use + // GetShortPathName, the cmd.exe program in windows which + // is used by system fails to execute if there are more than + // one set of quotes in the arguments + if(count > 2) + { + cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)"); + if(quoted.find(command)) + { + std::string cmd = quoted.match(1); + std::string args = quoted.match(2); + if(! cmSystemTools::FileExists(cmd.c_str()) ) + { + shortCmd = cmd; + } + else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) + { + cmSystemTools::Error("GetShortPath failed for " , cmd.c_str()); + return false; + } + shortCmd += " "; + shortCmd += args; + + command = shortCmd.c_str(); + } + else + { + cmSystemTools::Error("Could not parse command line with quotes ", + command); + } + } + } +#endif + + // Allocate a process instance. + cmsysProcess* cp = cmsysProcess_New(); + if(!cp) + { + cmSystemTools::Error("Error allocating process instance."); + return false; + } + +#if defined(WIN32) && !defined(__CYGWIN__) + if(dir) + { + cmsysProcess_SetWorkingDirectory(cp, dir); + } + if(cmSystemTools::GetRunCommandHideConsole()) + { + cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); + } + cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1); + const char* cmd[] = {command, 0}; + cmsysProcess_SetCommand(cp, cmd); +#else + std::string commandInDir; + if(dir) + { + commandInDir = "cd \""; + commandInDir += dir; + commandInDir += "\" && "; + commandInDir += command; + } + else + { + commandInDir = command; + } +#ifndef __VMS + commandInDir += " 2>&1"; +#endif + command = commandInDir.c_str(); + if(verbose) + { + cmSystemTools::Stdout("running "); + cmSystemTools::Stdout(command); + cmSystemTools::Stdout("\n"); + } + fflush(stdout); + fflush(stderr); + const char* cmd[] = {"/bin/sh", "-c", command, 0}; + cmsysProcess_SetCommand(cp, cmd); +#endif + + cmsysProcess_Execute(cp); + + // Read the process output. + int length; + char* data; + int p; + while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p)) + { + if(p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) + { + if(verbose) + { + cmSystemTools::Stdout(data, length); + } + output.append(data, length); + } + } + + // All output has been read. Wait for the process to exit. + cmsysProcess_WaitForExit(cp, 0); + + // Check the result of running the process. + std::string msg; + switch(cmsysProcess_GetState(cp)) + { + case cmsysProcess_State_Exited: + retVal = cmsysProcess_GetExitValue(cp); + break; + case cmsysProcess_State_Exception: + retVal = -1; + msg += "\nProcess terminated due to: "; + msg += cmsysProcess_GetExceptionString(cp); + break; + case cmsysProcess_State_Error: + retVal = -1; + msg += "\nProcess failed because: "; + msg += cmsysProcess_GetErrorString(cp); + break; + case cmsysProcess_State_Expired: + retVal = -1; + msg += "\nProcess terminated due to timeout."; + break; + } + if(!msg.empty()) + { +#if defined(WIN32) && !defined(__CYGWIN__) + // Old Windows process execution printed this info. + msg += "\n\nfor command: "; + msg += command; + if(dir) + { + msg += "\nin dir: "; + msg += dir; + } + msg += "\n"; + if(verbose) + { + cmSystemTools::Stdout(msg.c_str()); + } + output += msg; +#else + // Old UNIX process execution only put message in output. + output += msg; +#endif + } + + // Delete the process instance. + cmsysProcess_Delete(cp); + + return true; +} diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index 4892dd858..6d28cdcc7 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -57,6 +57,10 @@ public: } cmTypeMacro(cmExecProgramCommand, cmCommand); +private: + static bool RunCommand(const char* command, std::string& output, + int &retVal, const char* directory = 0, + bool verbose = true); }; #endif From 765d783972dbacc336d11803cccf56cdc9aac6c5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Oct 2013 16:22:45 -0400 Subject: [PATCH 4/4] cmSystemTools: Drop old RunCommand method All calls to this method have been replaced by newer infrastructure. Remove it and the supporting cmWin32ProcessExecution class. --- Source/CMakeLists.txt | 12 - Source/CPack/cpack.cxx | 5 - Source/cmSystemTools.cxx | 358 ------------ Source/cmSystemTools.h | 27 - Source/cmWin32ProcessExecution.cxx | 884 ----------------------------- Source/cmWin32ProcessExecution.h | 169 ------ Source/cmake.cxx | 4 - Source/cmw9xcom.cxx | 45 -- Source/ctest.cxx | 4 - bootstrap | 3 +- 10 files changed, 1 insertion(+), 1510 deletions(-) delete mode 100644 Source/cmWin32ProcessExecution.cxx delete mode 100644 Source/cmWin32ProcessExecution.h delete mode 100644 Source/cmw9xcom.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 71fae5808..7efaa50d9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -363,8 +363,6 @@ if (WIN32) cmVisualStudioSlnParser.cxx cmVisualStudioWCEPlatformParser.h cmVisualStudioWCEPlatformParser.cxx - cmWin32ProcessExecution.cxx - cmWin32ProcessExecution.h ) endif() endif () @@ -540,16 +538,6 @@ endif() add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h) target_link_libraries(cmake CMakeLib) -# Build special executable for running programs on Windows 98. -# Included on any Windows (unconditional packaging required!). -if(WIN32) - if(NOT UNIX) - add_executable(cmw9xcom cmw9xcom.cxx) - target_link_libraries(cmw9xcom CMakeLib) - install(TARGETS cmw9xcom DESTINATION bin) - endif() -endif() - # Build CTest executable add_executable(ctest ctest.cxx) target_link_libraries(ctest CTestLib) diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 169ae9a4b..9f8cc14f5 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -403,11 +403,6 @@ int main (int argc, char *argv[]) } if ( parsed ) { -#ifdef _WIN32 - std::string comspec = "cmw9xcom.exe"; - cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str()); -#endif - const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: " << cpackGenerator->GetNameOfClass() << std::endl); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index cbd4632e3..8320ecf84 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -115,19 +115,6 @@ bool cmSystemTools::s_FatalErrorOccured = false; bool cmSystemTools::s_DisableMessages = false; bool cmSystemTools::s_ForceUnixPaths = false; -std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com"; -void cmSystemTools::SetWindows9xComspecSubstitute(const char* str) -{ - if ( str ) - { - cmSystemTools::s_Windows9xComspecSubstitute = str; - } -} -const char* cmSystemTools::GetWindows9xComspecSubstitute() -{ - return cmSystemTools::s_Windows9xComspecSubstitute.c_str(); -} - void (*cmSystemTools::s_ErrorCallback)(const char*, const char*, bool&, void*); void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*); @@ -787,351 +774,6 @@ bool cmSystemTools::RunSingleCommand( return cmSystemTools::RunSingleCommand(args, output,retVal, dir, outputflag, timeout); } -bool cmSystemTools::RunCommand(const char* command, - std::string& output, - const char* dir, - bool verbose, - int timeout) -{ - int dummy; - return cmSystemTools::RunCommand(command, output, dummy, - dir, verbose, timeout); -} - -#if defined(WIN32) && !defined(__CYGWIN__) -#include "cmWin32ProcessExecution.h" -// use this for shell commands like echo and dir -bool RunCommandViaWin32(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose, - int timeout) -{ -#if defined(__BORLANDC__) - return - cmWin32ProcessExecution:: - BorlandRunCommand(command, dir, output, - retVal, - verbose, timeout, - cmSystemTools::GetRunCommandHideConsole()); -#else // Visual studio - ::SetLastError(ERROR_SUCCESS); - if ( ! command ) - { - cmSystemTools::Error("No command specified"); - return false; - } - cmWin32ProcessExecution resProc; - if(cmSystemTools::GetRunCommandHideConsole()) - { - resProc.SetHideWindows(true); - } - - if ( cmSystemTools::GetWindows9xComspecSubstitute() ) - { - resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() ); - } - if ( !resProc.StartProcess(command, dir, verbose) ) - { - output = resProc.GetOutput(); - if(verbose) - { - cmSystemTools::Stdout(output.c_str()); - } - return false; - } - resProc.Wait(timeout); - output = resProc.GetOutput(); - retVal = resProc.GetExitValue(); - return true; -#endif -} - -// use this for shell commands like echo and dir -bool RunCommandViaSystem(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose) -{ - std::cout << "@@ " << command << std::endl; - - std::string commandInDir; - if(dir) - { - commandInDir = "cd "; - commandInDir += cmSystemTools::ConvertToOutputPath(dir); - commandInDir += " && "; - commandInDir += command; - } - else - { - commandInDir = command; - } - command = commandInDir.c_str(); - std::string commandToFile = command; - commandToFile += " > "; - std::string tempFile; - tempFile += _tempnam(0, "cmake"); - - commandToFile += tempFile; - retVal = system(commandToFile.c_str()); - std::ifstream fin(tempFile.c_str()); - if(!fin) - { - if(verbose) - { - std::string errormsg = "RunCommand produced no output: command: \""; - errormsg += command; - errormsg += "\""; - errormsg += "\nOutput file: "; - errormsg += tempFile; - cmSystemTools::Error(errormsg.c_str()); - } - fin.close(); - cmSystemTools::RemoveFile(tempFile.c_str()); - return false; - } - bool multiLine = false; - std::string line; - while(cmSystemTools::GetLineFromStream(fin, line)) - { - output += line; - if(multiLine) - { - output += "\n"; - } - multiLine = true; - } - fin.close(); - cmSystemTools::RemoveFile(tempFile.c_str()); - return true; -} - -#else // We have popen - -// BeOS seems to return from a successful pclose() before the process has -// legitimately exited, or at least before SIGCHLD is thrown...the signal may -// come quite some time after pclose returns! This causes havoc with later -// parts of CMake that expect to catch the signal from other child processes, -// so we explicitly wait to catch it here. This should be safe to do with -// popen() so long as we don't actually collect the zombie process ourselves. -#ifdef __BEOS__ -#include -#undef SIGBUS // this is the same as SIGSEGV on BeOS and causes issues below. -static volatile bool beos_seen_signal = false; -static void beos_popen_workaround(int sig) -{ - beos_seen_signal = true; -} -#endif - -bool RunCommandViaPopen(const char* command, - const char* dir, - std::string& output, - int& retVal, - bool verbose, - int /*timeout*/) -{ - // if only popen worked on windows..... - std::string commandInDir; - if(dir) - { - commandInDir = "cd \""; - commandInDir += dir; - commandInDir += "\" && "; - commandInDir += command; - } - else - { - commandInDir = command; - } -#ifndef __VMS - commandInDir += " 2>&1"; -#endif - command = commandInDir.c_str(); - const int BUFFER_SIZE = 4096; - char buffer[BUFFER_SIZE]; - if(verbose) - { - cmSystemTools::Stdout("running "); - cmSystemTools::Stdout(command); - cmSystemTools::Stdout("\n"); - } - fflush(stdout); - fflush(stderr); - -#ifdef __BEOS__ - beos_seen_signal = false; - signal(SIGCHLD, beos_popen_workaround); -#endif - - FILE* cpipe = popen(command, "r"); - if(!cpipe) - { -#ifdef __BEOS__ - signal(SIGCHLD, SIG_DFL); -#endif - return false; - } - if (!fgets(buffer, BUFFER_SIZE, cpipe)) - { - buffer[0] = 0; - } - while(!feof(cpipe)) - { - if(verbose) - { - cmSystemTools::Stdout(buffer); - } - output += buffer; - if(!fgets(buffer, BUFFER_SIZE, cpipe)) - { - buffer[0] = 0; - } - } - - retVal = pclose(cpipe); - -#ifdef __BEOS__ - for (int i = 0; (!beos_seen_signal) && (i < 3); i++) - { - ::sleep(1); // signals should interrupt this... - } - - if (!beos_seen_signal) - { - signal(SIGCHLD, SIG_DFL); // oh well, didn't happen. Go on anyhow. - } -#endif - - if (WIFEXITED(retVal)) - { - retVal = WEXITSTATUS(retVal); - return true; - } - if (WIFSIGNALED(retVal)) - { - retVal = WTERMSIG(retVal); - cmOStringStream error; - error << "\nProcess terminated due to "; - switch (retVal) - { -#ifdef SIGKILL - case SIGKILL: - error << "SIGKILL"; - break; -#endif -#ifdef SIGFPE - case SIGFPE: - error << "SIGFPE"; - break; -#endif -#ifndef __HAIKU__ -#ifdef SIGBUS - case SIGBUS: - error << "SIGBUS"; - break; -#endif -#endif -#ifdef SIGSEGV - case SIGSEGV: - error << "SIGSEGV"; - break; -#endif - default: - error << "signal " << retVal; - break; - } - output += error.str(); - } - return false; -} - -#endif // endif WIN32 not CYGWIN - - -// run a command unix uses popen (easy) -// windows uses system and ShortPath -bool cmSystemTools::RunCommand(const char* command, - std::string& output, - int &retVal, - const char* dir, - bool verbose, - int timeout) -{ - if(s_DisableRunCommandOutput) - { - verbose = false; - } - -#if defined(WIN32) && !defined(__CYGWIN__) - // if the command does not start with a quote, then - // try to find the program, and if the program can not be - // found use system to run the command as it must be a built in - // shell command like echo or dir - int count = 0; - if(command[0] == '\"') - { - // count the number of quotes - for(const char* s = command; *s != 0; ++s) - { - if(*s == '\"') - { - count++; - if(count > 2) - { - break; - } - } - } - // if there are more than two double quotes use - // GetShortPathName, the cmd.exe program in windows which - // is used by system fails to execute if there are more than - // one set of quotes in the arguments - if(count > 2) - { - cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)"); - if(quoted.find(command)) - { - std::string shortCmd; - std::string cmd = quoted.match(1); - std::string args = quoted.match(2); - if(! cmSystemTools::FileExists(cmd.c_str()) ) - { - shortCmd = cmd; - } - else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) - { - cmSystemTools::Error("GetShortPath failed for " , cmd.c_str()); - return false; - } - shortCmd += " "; - shortCmd += args; - - //return RunCommandViaSystem(shortCmd.c_str(), dir, - // output, retVal, verbose); - //return WindowsRunCommand(shortCmd.c_str(), dir, - //output, retVal, verbose); - return RunCommandViaWin32(shortCmd.c_str(), dir, - output, retVal, verbose, timeout); - } - else - { - cmSystemTools::Error("Could not parse command line with quotes ", - command); - } - } - } - // if there is only one set of quotes or no quotes then just run the command - //return RunCommandViaSystem(command, dir, output, retVal, verbose); - //return WindowsRunCommand(command, dir, output, retVal, verbose); - return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout); -#else - return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout); -#endif -} bool cmSystemTools::DoesFileExistWithExtensions( const char* name, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index cbc1140ff..07235daac 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -190,23 +190,6 @@ public: /** Compute the md5sum of a string. */ static std::string ComputeStringMD5(const char* input); - /** - * Run an executable command and put the stdout in output. - * A temporary file is created in the binaryDir for storing the - * output because windows does not have popen. - * - * If verbose is false, no user-viewable output from the program - * being run will be generated. - * - * If timeout is specified, the command will be terminated after - * timeout expires. - */ - static bool RunCommand(const char* command, std::string& output, - const char* directory = 0, - bool verbose = true, int timeout = 0); - static bool RunCommand(const char* command, std::string& output, - int &retVal, const char* directory = 0, - bool verbose = true, int timeout = 0); /** * Run a single executable command * @@ -312,14 +295,6 @@ public: */ static FileFormat GetFileFormat(const char* ext); - /** - * On Windows 9x we need a comspec (command.com) substitute to run - * programs correctly. This string has to be constant available - * through the running of program. This method does not create a copy. - */ - static void SetWindows9xComspecSubstitute(const char*); - static const char* GetWindows9xComspecSubstitute(); - /** Windows if this is true, the CreateProcess in RunCommand will * not show new consol windows when running programs. */ @@ -488,8 +463,6 @@ private: static void* s_ErrorCallbackClientData; static void* s_StdoutCallbackClientData; static void* s_InterruptCallbackClientData; - - static std::string s_Windows9xComspecSubstitute; }; #endif diff --git a/Source/cmWin32ProcessExecution.cxx b/Source/cmWin32ProcessExecution.cxx deleted file mode 100644 index 1bdeffbed..000000000 --- a/Source/cmWin32ProcessExecution.cxx +++ /dev/null @@ -1,884 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "cmWin32ProcessExecution.h" - -#include "cmSystemTools.h" - -#include -#include -#include -#include -#include - -#if defined(__BORLANDC__) -# define STRICMP stricmp -# define TO_INTPTR(x) ((long)(x)) -#endif // Borland -#if defined(_MSC_VER) // Visual studio -# if ( _MSC_VER >= 1300 ) -# include -# define TO_INTPTR(x) ((intptr_t)(x)) -# else // Visual Studio 6 -# define TO_INTPTR(x) ((long)(x)) -# endif // Visual studio .NET -# define STRICMP _stricmp -#endif // Visual Studio -#if defined(__MINGW32__) -# include -# define TO_INTPTR(x) ((intptr_t)(x)) -# define STRICMP _stricmp -#endif // MinGW - -#define POPEN_1 1 -#define POPEN_2 2 -#define POPEN_3 3 -#define POPEN_4 4 - -#define cmMAX(x,y) (((x)<(y))?(y):(x)) - -void DisplayErrorMessage() -{ - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - // Process any inserts in lpMsgBuf. - // ... - // Display the string. - MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); - // Free the buffer. - LocalFree( lpMsgBuf ); -} - -// Code from a Borland web site with the following explaination : -/* In this article, I will explain how to spawn a console application - * and redirect its standard input/output using anonymous pipes. An - * anonymous pipe is a pipe that goes only in one direction (read - * pipe, write pipe, etc.). Maybe you are asking, "why would I ever - * need to do this sort of thing?" One example would be a Windows - * telnet server, where you spawn a shell and listen on a port and - * send and receive data between the shell and the socket - * client. (Windows does not really have a built-in remote - * shell). First, we should talk about pipes. A pipe in Windows is - * simply a method of communication, often between process. The SDK - * defines a pipe as "a communication conduit with two ends; - a process - * with a handle to one end can communicate with a process having a - * handle to the other end." In our case, we are using "anonymous" - * pipes, one-way pipes that "transfer data between a parent process - * and a child process or between two child processes of the same - * parent process." It's easiest to imagine a pipe as its namesake. An - * actual pipe running between processes that can carry data. We are - * using anonymous pipes because the console app we are spawning is a - * child process. We use the CreatePipe function which will create an - * anonymous pipe and return a read handle and a write handle. We will - * create two pipes, on for stdin and one for stdout. We will then - * monitor the read end of the stdout pipe to check for display on our - * child process. Every time there is something availabe for reading, - * we will display it in our app. Consequently, we check for input in - * our app and send it off to the write end of the stdin pipe. */ - -inline bool IsWinNT() -//check if we're running NT -{ - OSVERSIONINFO osv; - osv.dwOSVersionInfoSize = sizeof(osv); - GetVersionEx(&osv); - return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT); -} - -//--------------------------------------------------------------------------- -bool cmWin32ProcessExecution::BorlandRunCommand( - const char* command, const char* dir, - std::string& output, int& retVal, bool verbose, int /* timeout */, - bool hideWindows) -{ - //verbose = true; - //std::cerr << std::endl - // << "WindowsRunCommand(" << command << ")" << std::endl - // << std::flush; - const int BUFFER_SIZE = 4096; - char buf[BUFFER_SIZE]; - -//i/o buffer - STARTUPINFO si; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - -//security information for pipes - PROCESS_INFORMATION pi; - HANDLE newstdin,newstdout,read_stdout,write_stdin; - -//pipe handles - if (IsWinNT()) -//initialize security descriptor (Windows NT) - { - InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&sd, true, NULL, false); - sa.lpSecurityDescriptor = &sd; - - } - else sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = true; - -//allow inheritable handles - if (!CreatePipe(&newstdin,&write_stdin,&sa,0)) -//create stdin pipe - { - return false; - } - if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) -//create stdout pipe - { - CloseHandle(newstdin); - CloseHandle(write_stdin); - return false; - - } - GetStartupInfo(&si); - -//set startupinfo for the spawned process - /* The dwFlags member tells CreateProcess how to make the - * process. STARTF_USESTDHANDLES validates the hStd* - * members. STARTF_USESHOWWINDOW validates the wShowWindow - * member. */ - - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - si.hStdOutput = newstdout; - si.hStdError = newstdout; - si.wShowWindow = SW_SHOWDEFAULT; - if(hideWindows) - { - si.wShowWindow = SW_HIDE; - } - -//set the new handles for the child process si.hStdInput = newstdin; - char* commandAndArgs = strcpy(new char[strlen(command)+1], command); - if (!CreateProcess(NULL,commandAndArgs,NULL,NULL,TRUE, - 0, // CREATE_NEW_CONSOLE, - NULL,dir,&si,&pi)) - { - std::cerr << "CreateProcess failed " << commandAndArgs << std::endl; - CloseHandle(newstdin); - CloseHandle(newstdout); - CloseHandle(read_stdout); - CloseHandle(write_stdin); - delete [] commandAndArgs; - return false; - - } - delete [] commandAndArgs; - unsigned long exit=0; - -//process exit code unsigned - unsigned long bread; - -//bytes read unsigned - unsigned long avail; - -//bytes available - memset(buf, 0, sizeof(buf)); - for(;;) -//main program loop - { - Sleep(10); -//check to see if there is any data to read from stdout - //std::cout << "Peek for data..." << std::endl; - PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL); - if (bread != 0) - { - memset(buf, 0, sizeof(buf)); - if (avail > 1023) - { - while (bread >= 1023) - { - //std::cout << "Read data..." << std::endl; - ReadFile(read_stdout,buf,1023,&bread,NULL); - - //read the stdout pipe - memset(buf, 0, sizeof(buf)); - output += buf; - if (verbose) - { - cmSystemTools::Stdout(buf); - } - } - } - else - { - ReadFile(read_stdout,buf,1023,&bread,NULL); - output += buf; - if(verbose) - { - cmSystemTools::Stdout(buf); - } - - } - - } - - //std::cout << "Check for process..." << std::endl; - GetExitCodeProcess(pi.hProcess,&exit); - -//while the process is running - if (exit != STILL_ACTIVE) break; - - } - WaitForSingleObject(pi.hProcess, INFINITE); - GetExitCodeProcess(pi.hProcess,&exit); - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - CloseHandle(newstdin); - -//clean stuff up - CloseHandle(newstdout); - CloseHandle(read_stdout); - CloseHandle(write_stdin); - retVal = exit; - return true; - -} - -bool cmWin32ProcessExecution::StartProcess( - const char* cmd, const char* path, bool verbose) -{ - this->Initialize(); - this->Verbose = verbose; - return this->PrivateOpen(cmd, path, _O_RDONLY | _O_TEXT, POPEN_3); -} - -bool cmWin32ProcessExecution::Wait(int timeout) -{ - return this->PrivateClose(timeout); -} - -static BOOL RealPopenCreateProcess(const char *cmdstring, - const char *path, - const char *szConsoleSpawn, - HANDLE hStdin, - HANDLE hStdout, - HANDLE hStderr, - HANDLE *hProcess, - bool hideWindows, - std::string& output) -{ - PROCESS_INFORMATION piProcInfo; - STARTUPINFO siStartInfo; - char *s1=0,*s2=0; - const char *s3 = " /c "; - int i = GetEnvironmentVariable("COMSPEC",NULL,0); - if (i) - { - char *comshell; - - s1 = (char *)malloc(i); - int x = GetEnvironmentVariable("COMSPEC", s1, i); - if (!x) - { - free(s1); - return x; - } - - /* Explicitly check if we are using COMMAND.COM. If we are - * then use the w9xpopen hack. - */ - comshell = s1 + x; - while (comshell >= s1 && *comshell != '\\') - --comshell; - ++comshell; - - if (GetVersion() < 0x80000000 && - STRICMP(comshell, "command.com") != 0) - { - /* NT/2000 and not using command.com. */ - x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1; - s2 = (char *)malloc(x); - ZeroMemory(s2, x); - //sprintf(s2, "%s%s%s", s1, s3, cmdstring); - sprintf(s2, "%s", cmdstring); - } - else - { - /* - * Oh gag, we're on Win9x or using COMMAND.COM. Use - * the workaround listed in KB: Q150956 - */ - char modulepath[_MAX_PATH]; - struct stat statinfo; - GetModuleFileName(NULL, modulepath, sizeof(modulepath)); - for (i = x = 0; modulepath[i]; i++) - if (modulepath[i] == '\\') - x = i+1; - modulepath[x] = '\0'; - /* Create the full-name to w9xpopen, so we can test it exists */ - strncat(modulepath, - szConsoleSpawn, - (sizeof(modulepath)/sizeof(modulepath[0])) - -strlen(modulepath)); - if (stat(modulepath, &statinfo) != 0) - { - /* Eeek - file-not-found - possibly an embedding - situation - see if we can locate it in sys.prefix - */ - strncpy(modulepath, - ".", - sizeof(modulepath)/sizeof(modulepath[0])); - if (modulepath[strlen(modulepath)-1] != '\\') - strcat(modulepath, "\\"); - strncat(modulepath, - szConsoleSpawn, - (sizeof(modulepath)/sizeof(modulepath[0])) - -strlen(modulepath)); - /* No where else to look - raise an easily identifiable - error, rather than leaving Windows to report - "file not found" - as the user is probably blissfully - unaware this shim EXE is used, and it will confuse them. - (well, it confused me for a while ;-) - */ - if (stat(modulepath, &statinfo) != 0) - { - std::cout - << "Can not locate '" << modulepath - << "' which is needed " - "for popen to work with your shell " - "or platform." << std::endl; - free(s1); - free(s2); - return FALSE; - } - } - x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1 + - (int)strlen(modulepath) + - (int)strlen(szConsoleSpawn) + 1; - if(s2) - { - free(s2); - } - s2 = (char *)malloc(x); - ZeroMemory(s2, x); - sprintf( - s2, - "%s %s%s%s", - modulepath, - s1, - s3, - cmdstring); - sprintf( - s2, - "%s %s", - modulepath, - cmdstring); - } - } - - /* Could be an else here to try cmd.exe / command.com in the path - Now we'll just error out.. */ - else - { - std::cout << "Cannot locate a COMSPEC environment variable to " - << "use as the shell" << std::endl; - free(s2); - free(s1); - return FALSE; - } - - ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); - siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - siStartInfo.hStdInput = hStdin; - siStartInfo.hStdOutput = hStdout; - siStartInfo.hStdError = hStderr; - siStartInfo.wShowWindow = SW_SHOWDEFAULT; - if(hideWindows) - { - siStartInfo.wShowWindow = SW_HIDE; - } - - //std::cout << "Create process: " << s2 << std::endl; - if (CreateProcess(NULL, - s2, - NULL, - NULL, - TRUE, - 0, //CREATE_NEW_CONSOLE, - NULL, - path, - &siStartInfo, - &piProcInfo) ) - { - /* Close the handles now so anyone waiting is woken. */ - CloseHandle(piProcInfo.hThread); - /* Return process handle */ - *hProcess = piProcInfo.hProcess; - //std::cout << "Process created..." << std::endl; - free(s2); - free(s1); - return TRUE; - } - - output += "CreateProcessError: "; - { - /* Format the error message. */ - char message[1024]; - DWORD original = GetLastError(); - DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - message, 1023, 0); - if(length < 1) - { - /* FormatMessage failed. Use a default message. */ - _snprintf(message, 1023, - "Process execution failed with error 0x%X. " - "FormatMessage failed with error 0x%X", - original, GetLastError()); - } - output += message; - } - output += "\n"; - output += "for command: "; - output += s2; - if(path) - { - output += "\nin dir: "; - output += path; - } - output += "\n"; - free(s2); - free(s1); - return FALSE; -} - -/* The following code is based off of KB: Q190351 */ - -bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring, - const char* path, - int mode, - int n) -{ - HANDLE hProcess; - - SECURITY_ATTRIBUTES saAttr; - BOOL fSuccess; - int fd1, fd2, fd3; - this->hChildStdinRd = 0; - this->hChildStdinWr = 0; - this->hChildStdoutRd = 0; - this->hChildStdoutWr = 0; - this->hChildStderrRd = 0; - this->hChildStderrWr = 0; - this->hChildStdinWrDup = 0; - this->hChildStdoutRdDup = 0; - this->hChildStderrRdDup = 0; - - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - fd1 = 0; - fd2 = 0; - fd3 = 0; - - if (!CreatePipe(&this->hChildStdinRd, &this->hChildStdinWr, &saAttr, 0)) - { - this->Output += "CreatePipeError\n"; - return false; - } - - /* Create new output read handle and the input write handle. Set - * the inheritance properties to FALSE. Otherwise, the child inherits - * these handles; resulting in non-closeable handles to the pipes - * being created. */ - fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdinWr, - GetCurrentProcess(), &this->hChildStdinWrDup, 0, - FALSE, - DUPLICATE_SAME_ACCESS); - if (!fSuccess) - { - this->Output += "DuplicateHandleError\n"; - return false; - } - - - /* Close the inheritable version of ChildStdin - that we're using. */ - CloseHandle(hChildStdinWr); - - if (!CreatePipe(&this->hChildStdoutRd, &this->hChildStdoutWr, &saAttr, 0)) - { - this->Output += "CreatePipeError\n"; - return false; - } - - fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdoutRd, - GetCurrentProcess(), &this->hChildStdoutRdDup, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!fSuccess) - { - this->Output += "DuplicateHandleError\n"; - return false; - } - - /* Close the inheritable version of ChildStdout - that we're using. */ - CloseHandle(hChildStdoutRd); - - if (n != POPEN_4) - { - if (!CreatePipe(&this->hChildStderrRd, &this->hChildStderrWr, &saAttr, 0)) - { - this->Output += "CreatePipeError\n"; - return false; - } - fSuccess = DuplicateHandle(GetCurrentProcess(), - this->hChildStderrRd, - GetCurrentProcess(), - &this->hChildStderrRdDup, 0, - FALSE, DUPLICATE_SAME_ACCESS); - if (!fSuccess) - { - this->Output += "DuplicateHandleError\n"; - return false; - } - /* Close the inheritable version of ChildStdErr that we're using. */ - CloseHandle(hChildStderrRd); - - } - - switch (n) - { - case POPEN_1: - switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) - { - case _O_WRONLY | _O_TEXT: - /* Case for writing to child Stdin in text mode. */ - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode); - /* We don't care about these pipes anymore, - so close them. */ - break; - - case _O_RDONLY | _O_TEXT: - /* Case for reading from child Stdout in text mode. */ - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode); - /* We don't care about these pipes anymore, - so close them. */ - break; - - case _O_RDONLY | _O_BINARY: - /* Case for readinig from child Stdout in - binary mode. */ - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode); - /* We don't care about these pipes anymore, - so close them. */ - break; - - case _O_WRONLY | _O_BINARY: - /* Case for writing to child Stdin in binary mode. */ - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode); - /* We don't care about these pipes anymore, - so close them. */ - break; - } - break; - - case POPEN_2: - case POPEN_4: - //if ( 1 ) - { - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode); - fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode); - break; - } - - case POPEN_3: - //if ( 1) - { - fd1 = _open_osfhandle(TO_INTPTR(this->hChildStdinWrDup), mode); - fd2 = _open_osfhandle(TO_INTPTR(this->hChildStdoutRdDup), mode); - fd3 = _open_osfhandle(TO_INTPTR(this->hChildStderrRdDup), mode); - break; - } - } - - if (n == POPEN_4) - { - if (!RealPopenCreateProcess(cmdstring, - path, - this->ConsoleSpawn.c_str(), - this->hChildStdinRd, - this->hChildStdoutWr, - this->hChildStdoutWr, - &hProcess, this->HideWindows, - this->Output)) - { - if(fd1 >= 0) - { - close(fd1); - } - if(fd2 >= 0) - { - close(fd2); - } - if(fd3 >= 0) - { - close(fd3); - } - return 0; - } - } - else - { - if (!RealPopenCreateProcess(cmdstring, - path, - this->ConsoleSpawn.c_str(), - this->hChildStdinRd, - this->hChildStdoutWr, - this->hChildStderrWr, - &hProcess, this->HideWindows, - this->Output)) - { - if(fd1 >= 0) - { - close(fd1); - } - if(fd2 >= 0) - { - close(fd2); - } - if(fd3 >= 0) - { - close(fd3); - } - return 0; - } - } - - /* Child is launched. Close the parents copy of those pipe - * handles that only the child should have open. You need to - * make sure that no handles to the write end of the output pipe - * are maintained in this process or else the pipe will not close - * when the child process exits and the ReadFile will hang. */ - this->ProcessHandle = hProcess; - if ( fd1 >= 0 ) - { - this->pStdIn = fd1; - } - if ( fd2 >= 0 ) - { - this->pStdOut = fd2; - } - if ( fd3 >= 0 ) - { - this->pStdErr = fd3; - } - - return true; -} - -bool cmWin32ProcessExecution::CloseHandles() -{ - if(this->pStdErr != -1 ) - { - // this will close this as well: this->hChildStderrRdDup - _close(this->pStdErr); - this->pStdErr = -1; - this->hChildStderrRdDup = 0; - } - if(this->pStdIn != -1 ) - { - // this will close this as well: this->hChildStdinWrDup - _close(this->pStdIn); - this->pStdIn = -1; - this->hChildStdinWrDup = 0; - } - if(this->pStdOut != -1 ) - { - // this will close this as well: this->hChildStdoutRdDup - _close(this->pStdOut); - this->pStdOut = -1; - this->hChildStdoutRdDup = 0; - } - - bool ret = true; - if (this->hChildStdinRd && !CloseHandle(this->hChildStdinRd)) - { - ret = false; - } - this->hChildStdinRd = 0; - // now close these two - if (this->hChildStdoutWr && !CloseHandle(this->hChildStdoutWr)) - { - ret = false; - } - this->hChildStdoutWr = 0; - if (this->hChildStderrWr && !CloseHandle(this->hChildStderrWr)) - { - ret = false; - } - this->hChildStderrWr = 0; - return ret; -} -cmWin32ProcessExecution::~cmWin32ProcessExecution() -{ - this->CloseHandles(); -} - -bool cmWin32ProcessExecution::PrivateClose(int /* timeout */) -{ - HANDLE hProcess = this->ProcessHandle; - - int result = -1; - DWORD exit_code; - - std::string output = ""; - bool done = false; - while(!done) - { - Sleep(10); - bool have_some = false; - struct _stat fsout; - struct _stat fserr; - int rout = _fstat(this->pStdOut, &fsout); - int rerr = _fstat(this->pStdErr, &fserr); - if ( rout && rerr ) - { - break; - } - if (fserr.st_size > 0) - { - char buffer[1024]; - int len = read(this->pStdErr, buffer, 1023); - buffer[len] = 0; - if ( this->Verbose ) - { - cmSystemTools::Stdout(buffer); - } - output += buffer; - have_some = true; - } - if (fsout.st_size > 0) - { - char buffer[1024]; - int len = read(this->pStdOut, buffer, 1023); - buffer[len] = 0; - if ( this->Verbose ) - { - cmSystemTools::Stdout(buffer); - } - output += buffer; - have_some = true; - } - unsigned long exitCode; - if ( ! have_some ) - { - GetExitCodeProcess(hProcess,&exitCode); - if (exitCode != STILL_ACTIVE) - { - break; - } - } - } - - - if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED && - GetExitCodeProcess(hProcess, &exit_code)) - { - result = exit_code; - } - else - { - /* Indicate failure - this will cause the file object - * to raise an I/O error and translate the last Win32 - * error code from errno. We do have a problem with - * last errors that overlap the normal errno table, - * but that's a consistent problem with the file object. - */ - if (result != EOF) - { - /* If the error wasn't from the fclose(), then - * set errno for the file object error handling. - */ - errno = GetLastError(); - } - result = -1; - } - - /* Free up the native handle at this point */ - CloseHandle(hProcess); - this->ExitValue = result; - this->Output += output; - bool ret = this->CloseHandles(); - if ( result < 0 || !ret) - { - return false; - } - return true; -} - -int cmWin32ProcessExecution::Windows9xHack(const char* command) -{ - BOOL bRet; - STARTUPINFO si; - PROCESS_INFORMATION pi; - DWORD exit_code=0; - - if (!command) - { - cmSystemTools::Error("Windows9xHack: Command not specified"); - return 1; - } - - /* Make child process use this app's standard files. */ - ZeroMemory(&si, sizeof si); - si.cb = sizeof si; - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - - char * app = 0; - char* cmd = new char[ strlen(command) + 1 ]; - strcpy(cmd, command); - - bRet = CreateProcess( - app, cmd, - 0, 0, - TRUE, 0, - 0, 0, - &si, &pi - ); - delete [] cmd; - - if (bRet) - { - if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) - { - GetExitCodeProcess(pi.hProcess, &exit_code); - } - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return exit_code; - } - - return 1; -} diff --git a/Source/cmWin32ProcessExecution.h b/Source/cmWin32ProcessExecution.h deleted file mode 100644 index 2127ebd2e..000000000 --- a/Source/cmWin32ProcessExecution.h +++ /dev/null @@ -1,169 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef cmWin32ProcessExecution_h -#define cmWin32ProcessExecution_h - -#include "cmStandardIncludes.h" -#include "windows.h" - -class cmMakefile; - -/** \class cmWin32ProcessExecution - * \brief A process executor for windows - * - * cmWin32ProcessExecution is a class that provides a "clean" way of - * executing processes on Windows. It is modified code from Python 2.1 - * distribution. - * - * Portable 'popen' replacement for Win32. - * - * Written by Bill Tutt . Minor tweaks and 2.0 - * integration by Fredrik Lundh Return code - * handling by David Bolen . - * - * Modified for CMake. - * - * For more information, please check Microsoft Knowledge Base - * Articles Q190351 and Q150956. - */ -class cmWin32ProcessExecution -{ -public: - cmWin32ProcessExecution() - { - this->HideWindows = false; - this->SetConsoleSpawn("w9xpopen.exe"); - this->Initialize(); - } - ~cmWin32ProcessExecution(); - ///! If true windows will be created hidden. - void SetHideWindows(bool v) { this->HideWindows = v; } - - /** - * Initialize the process execution datastructure. Do not call while - * running the process. - */ - void Initialize() - { - this->ProcessHandle = 0; - this->ExitValue = -1; - // Comment this out. Maybe we will need it in the future. - // file IO access to the process might be cool. - //this->StdIn = 0; - //this->StdOut = 0; - //this->StdErr = 0; - this->pStdIn = -1; - this->pStdOut = -1; - this->pStdErr = -1; - } - - /** - * Start the process in the directory path. Make sure that the - * executable is either in the path or specify the full path. The - * argument verbose specifies whether or not to display output while - * it is being generated. - */ - bool StartProcess(const char*, const char* path, bool verbose); - - /** - * Wait for the process to finish. If timeout is specified, it will - * break the process after timeout expires. (Timeout code is not yet - * implemented. - */ - bool Wait(int timeout); - - /** - * Get the output of the process (mixed stdout and stderr) as - * std::string. - */ - const std::string GetOutput() const { return this->Output; } - - /** - * Get the return value of the process. If the process is still - * running, the return value is -1. - */ - int GetExitValue() const { return this->ExitValue; } - - /** - * On Windows 9x there is a bug in the process execution code which - * may result in blocking. That is why this workaround is - * used. Specify the console spawn, which should run the - * Windows9xHack code. - */ - void SetConsoleSpawn(const char* prog) { this->ConsoleSpawn = prog; } - static int Windows9xHack(const char* command); - - /** Code from a Borland web site with the following explaination : - * In this article, I will explain how to spawn a console - * application and redirect its standard input/output using - * anonymous pipes. An anonymous pipe is a pipe that goes only in - * one direction (read pipe, write pipe, etc.). Maybe you are - * asking, "why would I ever need to do this sort of thing?" One - * example would be a Windows telnet server, where you spawn a shell - * and listen on a port and send and receive data between the shell - * and the socket client. (Windows does not really have a built-in - * remote shell). First, we should talk about pipes. A pipe in - * Windows is simply a method of communication, often between - * process. The SDK defines a pipe as "a communication conduit with - * two ends; a process with a handle to one end can communicate with - * a process having a handle to the other end." In our case, we are - * using "anonymous" pipes, one-way pipes that "transfer data - * between a parent process and a child process or between two child - * processes of the same parent process." It's easiest to imagine a - * pipe as its namesake. An actual pipe running between processes - * that can carry data. We are using anonymous pipes because the - * console app we are spawning is a child process. We use the - * CreatePipe function which will create an anonymous pipe and - * return a read handle and a write handle. We will create two - * pipes, on for stdin and one for stdout. We will then monitor the - * read end of the stdout pipe to check for display on our child - * process. Every time there is something availabe for reading, we - * will display it in our app. Consequently, we check for input in - * our app and send it off to the write end of the stdin pipe. - */ - static bool BorlandRunCommand(const char* command, - const char* dir, - std::string& output, int& retVal, - bool verbose, - int timeout, bool hideWindows); - -private: - bool CloseHandles(); - bool PrivateOpen(const char*, const char*, int, int); - bool PrivateClose(int timeout); - - HANDLE ProcessHandle; - HANDLE hChildStdinRd; - HANDLE hChildStdinWr; - HANDLE hChildStdoutRd; - HANDLE hChildStdoutWr; - HANDLE hChildStderrRd; - HANDLE hChildStderrWr; - HANDLE hChildStdinWrDup; - HANDLE hChildStdoutRdDup; - HANDLE hChildStderrRdDup; - - - int pStdIn; - int pStdOut; - int pStdErr; - - int ExitValue; - - std::string Output; - std::string ConsoleSpawn; - bool Verbose; - bool HideWindows; -}; - - -#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index d11a40b60..9c79516c6 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1104,10 +1104,6 @@ int cmake::AddCMakePaths() ("CMAKE_ROOT", cMakeRoot.c_str(), "Path to CMake installation.", cmCacheManager::INTERNAL); -#ifdef _WIN32 - std::string comspec = "cmw9xcom.exe"; - cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str()); -#endif return 1; } diff --git a/Source/cmw9xcom.cxx b/Source/cmw9xcom.cxx deleted file mode 100644 index ab238d539..000000000 --- a/Source/cmw9xcom.cxx +++ /dev/null @@ -1,45 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "cmSystemTools.h" -#include "cmWin32ProcessExecution.h" - -// this is a test driver program for cmake. -int main (int argc, char *argv[]) -{ - cmSystemTools::EnableMSVCDebugHook(); - if ( argc <= 1 ) - { - std::cerr << "Usage: " << argv[0] << " executable" << std::endl; - return 1; - } - std::string arg = argv[1]; - if ( (arg.find_first_of(" ") != arg.npos) && - (arg.find_first_of("\"") == arg.npos) ) - { - arg = "\"" + arg + "\""; - } - std::string command = arg; - int cc; - for ( cc = 2; cc < argc; cc ++ ) - { - std::string nextArg = argv[cc]; - if ( (nextArg.find_first_of(" ") != nextArg.npos) && - (nextArg.find_first_of("\"") == nextArg.npos) ) - { - nextArg = "\"" + nextArg + "\""; - } - command += " "; - command += nextArg; - } - - return cmWin32ProcessExecution::Windows9xHack(command.c_str()); -} diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 16cdd1365..12e71b61d 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -171,10 +171,6 @@ int main (int argc, char *argv[]) } } -#ifdef _WIN32 - std::string comspec = "cmw9xcom.exe"; - cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str()); -#endif // copy the args to a vector std::vector args; for(int i =0; i < argc; ++i) diff --git a/bootstrap b/bootstrap index f2cfcaa53..b85590104 100755 --- a/bootstrap +++ b/bootstrap @@ -302,8 +302,7 @@ CMAKE_CXX_SOURCES="\ if ${cmake_system_mingw}; then CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\ cmGlobalMSYSMakefileGenerator \ - cmGlobalMinGWMakefileGenerator \ - cmWin32ProcessExecution" + cmGlobalMinGWMakefileGenerator" fi CMAKE_C_SOURCES="\