|
|
@@ -22,6 +22,7 @@
|
|
|
|
|
|
#include <cmsys/RegularExpression.hxx>
|
|
|
#include <cmsys/Directory.hxx>
|
|
|
+#include <cmsys/Process.h>
|
|
|
|
|
|
// support for realpath call
|
|
|
#ifndef _WIN32
|
|
|
@@ -301,283 +302,131 @@ bool cmSystemTools::RunCommand(const char* command,
|
|
|
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)
|
|
|
+bool cmSystemTools::RunCommand(const char* command,
|
|
|
+ std::string& output,
|
|
|
+ int &retVal,
|
|
|
+ const char* dir,
|
|
|
+ bool verbose,
|
|
|
+ int)
|
|
|
{
|
|
|
-#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())
|
|
|
+ if(s_DisableRunCommandOutput)
|
|
|
{
|
|
|
- resProc.SetHideWindows(true);
|
|
|
+ verbose = false;
|
|
|
}
|
|
|
|
|
|
- if ( cmSystemTools::GetWindows9xComspecSubstitute() )
|
|
|
- {
|
|
|
- resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
|
|
|
- }
|
|
|
- if ( !resProc.StartProcess(command, dir, verbose) )
|
|
|
- {
|
|
|
- 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)
|
|
|
+ std::vector<std::string> args;
|
|
|
+ std::string arg;
|
|
|
+
|
|
|
+ // Split the command into an argv array.
|
|
|
+ for(const char* c = command; *c;)
|
|
|
{
|
|
|
- if(verbose)
|
|
|
+ // Skip over whitespace.
|
|
|
+ while(*c == ' ' || *c == '\t')
|
|
|
{
|
|
|
- std::string errormsg = "RunCommand produced no output: command: \"";
|
|
|
- errormsg += command;
|
|
|
- errormsg += "\"";
|
|
|
- errormsg += "\nOutput file: ";
|
|
|
- errormsg += tempFile;
|
|
|
- cmSystemTools::Error(errormsg.c_str());
|
|
|
+ ++c;
|
|
|
}
|
|
|
- fin.close();
|
|
|
- cmSystemTools::RemoveFile(tempFile.c_str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- bool multiLine = false;
|
|
|
- std::string line;
|
|
|
- while(cmSystemTools::GetLineFromStream(fin, line))
|
|
|
- {
|
|
|
- output += line;
|
|
|
- if(multiLine)
|
|
|
+ arg = "";
|
|
|
+ if(*c == '"')
|
|
|
+ {
|
|
|
+ // Parse a quoted argument.
|
|
|
+ ++c;
|
|
|
+ while(*c && *c != '"')
|
|
|
+ {
|
|
|
+ if(*c == '\\')
|
|
|
+ {
|
|
|
+ ++c;
|
|
|
+ if(*c)
|
|
|
+ {
|
|
|
+ arg.append(1, *c);
|
|
|
+ ++c;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ arg.append(1, *c);
|
|
|
+ ++c;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(*c)
|
|
|
+ {
|
|
|
+ ++c;
|
|
|
+ }
|
|
|
+ args.push_back(arg);
|
|
|
+ }
|
|
|
+ else if(*c)
|
|
|
{
|
|
|
- output += "\n";
|
|
|
+ // Parse an unquoted argument.
|
|
|
+ while(*c && *c != ' ' && *c != '\t')
|
|
|
+ {
|
|
|
+ arg.append(1, *c);
|
|
|
+ ++c;
|
|
|
+ }
|
|
|
+ args.push_back(arg);
|
|
|
}
|
|
|
- multiLine = true;
|
|
|
- }
|
|
|
- fin.close();
|
|
|
- cmSystemTools::RemoveFile(tempFile.c_str());
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-#else // We have popen
|
|
|
-
|
|
|
-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
|
|
|
+
|
|
|
+ std::vector<const char*> argv;
|
|
|
+ for(std::vector<std::string>::const_iterator a = args.begin();
|
|
|
+ a != args.end(); ++a)
|
|
|
{
|
|
|
- commandInDir = command;
|
|
|
+ argv.push_back(a->c_str());
|
|
|
}
|
|
|
- commandInDir += " 2>&1";
|
|
|
- command = commandInDir.c_str();
|
|
|
- const int BUFFER_SIZE = 4096;
|
|
|
- char buffer[BUFFER_SIZE];
|
|
|
- if(verbose)
|
|
|
+ argv.push_back(0);
|
|
|
+
|
|
|
+ if(argv.size() < 2)
|
|
|
{
|
|
|
- std::cout << "running " << command << std::endl;
|
|
|
+ return false;
|
|
|
}
|
|
|
- fflush(stdout);
|
|
|
- fflush(stderr);
|
|
|
- FILE* cpipe = popen(command, "r");
|
|
|
- if(!cpipe)
|
|
|
+
|
|
|
+ // Change to specified working directory.
|
|
|
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
|
|
|
+ if(dir)
|
|
|
{
|
|
|
- return false;
|
|
|
+ if(cmSystemTools::ChangeDirectory(dir) < 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
- fgets(buffer, BUFFER_SIZE, cpipe);
|
|
|
- while(!feof(cpipe))
|
|
|
+
|
|
|
+ output = "";
|
|
|
+ cmsysProcess* cp = cmsysProcess_New();
|
|
|
+ cmsysProcess_SetCommand(cp, &*argv.begin());
|
|
|
+ cmsysProcess_Execute(cp);
|
|
|
+
|
|
|
+ char* data;
|
|
|
+ int length;
|
|
|
+ while(cmsysProcess_WaitForData(cp, (cmsysProcess_Pipe_STDOUT |
|
|
|
+ cmsysProcess_Pipe_STDERR),
|
|
|
+ &data, &length, 0))
|
|
|
{
|
|
|
+ output.append(data, length);
|
|
|
if(verbose)
|
|
|
{
|
|
|
- std::cout << buffer << std::flush;
|
|
|
+ std::cout.write(data, length);
|
|
|
}
|
|
|
- output += buffer;
|
|
|
- fgets(buffer, BUFFER_SIZE, cpipe);
|
|
|
}
|
|
|
-
|
|
|
- retVal = pclose(cpipe);
|
|
|
- if (WIFEXITED(retVal))
|
|
|
+
|
|
|
+ cmsysProcess_WaitForExit(cp, 0);
|
|
|
+
|
|
|
+ bool result = true;
|
|
|
+ if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
|
|
|
{
|
|
|
- retVal = WEXITSTATUS(retVal);
|
|
|
- return true;
|
|
|
+ retVal = cmsysProcess_GetExitValue(cp);
|
|
|
}
|
|
|
- if (WIFSIGNALED(retVal))
|
|
|
+ else
|
|
|
{
|
|
|
- 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
|
|
|
-#ifdef SIGBUS
|
|
|
- case SIGBUS:
|
|
|
- error << "SIGBUS";
|
|
|
- break;
|
|
|
-#endif
|
|
|
-#ifdef SIGSEGV
|
|
|
- case SIGSEGV:
|
|
|
- error << "SIGSEGV";
|
|
|
- break;
|
|
|
-#endif
|
|
|
- default:
|
|
|
- error << "signal " << retVal;
|
|
|
- break;
|
|
|
- }
|
|
|
- output += error.str();
|
|
|
+ result = false;
|
|
|
}
|
|
|
- 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)
|
|
|
+
|
|
|
+ cmsysProcess_Delete(cp);
|
|
|
+
|
|
|
+ // Restore old working directory.
|
|
|
+ if(dir)
|
|
|
{
|
|
|
- verbose = false;
|
|
|
+ cmSystemTools::ChangeDirectory(cwd.c_str());
|
|
|
}
|
|
|
|
|
|
-#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
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
bool cmSystemTools::DoesFileExistWithExtensions(
|