summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmSystemTools.cxx347
1 files changed, 98 insertions, 249 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index ecdfb48..2cb2de3 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -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(