cmSystemTools: Drop old RunCommand method
All calls to this method have been replaced by newer infrastructure. Remove it and the supporting cmWin32ProcessExecution class.
This commit is contained in:
parent
52b80b2643
commit
765d783972
|
@ -363,8 +363,6 @@ if (WIN32)
|
||||||
cmVisualStudioSlnParser.cxx
|
cmVisualStudioSlnParser.cxx
|
||||||
cmVisualStudioWCEPlatformParser.h
|
cmVisualStudioWCEPlatformParser.h
|
||||||
cmVisualStudioWCEPlatformParser.cxx
|
cmVisualStudioWCEPlatformParser.cxx
|
||||||
cmWin32ProcessExecution.cxx
|
|
||||||
cmWin32ProcessExecution.h
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -540,16 +538,6 @@ endif()
|
||||||
add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h)
|
add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h)
|
||||||
target_link_libraries(cmake CMakeLib)
|
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
|
# Build CTest executable
|
||||||
add_executable(ctest ctest.cxx)
|
add_executable(ctest ctest.cxx)
|
||||||
target_link_libraries(ctest CTestLib)
|
target_link_libraries(ctest CTestLib)
|
||||||
|
|
|
@ -403,11 +403,6 @@ int main (int argc, char *argv[])
|
||||||
}
|
}
|
||||||
if ( parsed )
|
if ( parsed )
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
std::string comspec = "cmw9xcom.exe";
|
|
||||||
cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
|
const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
|
||||||
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: "
|
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: "
|
||||||
<< cpackGenerator->GetNameOfClass() << std::endl);
|
<< cpackGenerator->GetNameOfClass() << std::endl);
|
||||||
|
|
|
@ -115,19 +115,6 @@ bool cmSystemTools::s_FatalErrorOccured = false;
|
||||||
bool cmSystemTools::s_DisableMessages = false;
|
bool cmSystemTools::s_DisableMessages = false;
|
||||||
bool cmSystemTools::s_ForceUnixPaths = 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*,
|
void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
|
||||||
bool&, void*);
|
bool&, void*);
|
||||||
void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
|
void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
|
||||||
|
@ -787,351 +774,6 @@ bool cmSystemTools::RunSingleCommand(
|
||||||
return cmSystemTools::RunSingleCommand(args, output,retVal,
|
return cmSystemTools::RunSingleCommand(args, output,retVal,
|
||||||
dir, outputflag, timeout);
|
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 <signal.h>
|
|
||||||
#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(
|
bool cmSystemTools::DoesFileExistWithExtensions(
|
||||||
const char* name,
|
const char* name,
|
||||||
|
|
|
@ -190,23 +190,6 @@ public:
|
||||||
/** Compute the md5sum of a string. */
|
/** Compute the md5sum of a string. */
|
||||||
static std::string ComputeStringMD5(const char* input);
|
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
|
* Run a single executable command
|
||||||
*
|
*
|
||||||
|
@ -312,14 +295,6 @@ public:
|
||||||
*/
|
*/
|
||||||
static FileFormat GetFileFormat(const char* ext);
|
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
|
/** Windows if this is true, the CreateProcess in RunCommand will
|
||||||
* not show new consol windows when running programs.
|
* not show new consol windows when running programs.
|
||||||
*/
|
*/
|
||||||
|
@ -488,8 +463,6 @@ private:
|
||||||
static void* s_ErrorCallbackClientData;
|
static void* s_ErrorCallbackClientData;
|
||||||
static void* s_StdoutCallbackClientData;
|
static void* s_StdoutCallbackClientData;
|
||||||
static void* s_InterruptCallbackClientData;
|
static void* s_InterruptCallbackClientData;
|
||||||
|
|
||||||
static std::string s_Windows9xComspecSubstitute;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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 <malloc.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#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 <stddef.h>
|
|
||||||
# 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 <stdint.h>
|
|
||||||
# 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;
|
|
||||||
}
|
|
|
@ -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 <billtut@microsoft.com>. Minor tweaks and 2.0
|
|
||||||
* integration by Fredrik Lundh <fredrik@pythonware.com> Return code
|
|
||||||
* handling by David Bolen <db3l@fitlinxx.com>.
|
|
||||||
*
|
|
||||||
* 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
|
|
|
@ -1104,10 +1104,6 @@ int cmake::AddCMakePaths()
|
||||||
("CMAKE_ROOT", cMakeRoot.c_str(),
|
("CMAKE_ROOT", cMakeRoot.c_str(),
|
||||||
"Path to CMake installation.", cmCacheManager::INTERNAL);
|
"Path to CMake installation.", cmCacheManager::INTERNAL);
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
std::string comspec = "cmw9xcom.exe";
|
|
||||||
cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
|
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
|
@ -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
|
// copy the args to a vector
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
for(int i =0; i < argc; ++i)
|
for(int i =0; i < argc; ++i)
|
||||||
|
|
|
@ -302,8 +302,7 @@ CMAKE_CXX_SOURCES="\
|
||||||
if ${cmake_system_mingw}; then
|
if ${cmake_system_mingw}; then
|
||||||
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\
|
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\
|
||||||
cmGlobalMSYSMakefileGenerator \
|
cmGlobalMSYSMakefileGenerator \
|
||||||
cmGlobalMinGWMakefileGenerator \
|
cmGlobalMinGWMakefileGenerator"
|
||||||
cmWin32ProcessExecution"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CMAKE_C_SOURCES="\
|
CMAKE_C_SOURCES="\
|
||||||
|
|
Loading…
Reference in New Issue