summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r--Source/cmSystemTools.cxx338
1 files changed, 252 insertions, 86 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index d6ec70f..ecdfb48 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -22,7 +22,6 @@
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Directory.hxx>
-#include <cmsys/Process.h>
// support for realpath call
#ifndef _WIN32
@@ -302,116 +301,283 @@ bool cmSystemTools::RunCommand(const char* command,
dir, verbose, timeout);
}
-bool cmSystemTools::RunCommand(const char* command,
- std::string& output,
- int &retVal,
- const char* dir,
- bool verbose,
- int)
+#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(s_DisableRunCommandOutput)
+#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())
{
- verbose = false;
+ resProc.SetHideWindows(true);
}
- std::vector<std::string> args;
- std::string arg;
-
- // Split the command into an argv array.
- for(const char* c = command; *c;)
+ if ( cmSystemTools::GetWindows9xComspecSubstitute() )
{
- // Skip over whitespace.
- while(*c == ' ' || *c == '\t')
- {
- ++c;
- }
- arg = "";
- if(*c == '"')
+ 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)
+ {
+ if(verbose)
{
- // 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);
+ std::string errormsg = "RunCommand produced no output: command: \"";
+ errormsg += command;
+ errormsg += "\"";
+ errormsg += "\nOutput file: ";
+ errormsg += tempFile;
+ cmSystemTools::Error(errormsg.c_str());
}
- else if(*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)
{
- // Parse an unquoted argument.
- while(*c && *c != ' ' && *c != '\t')
- {
- arg.append(1, *c);
- ++c;
- }
- args.push_back(arg);
+ output += "\n";
}
+ multiLine = true;
}
-
- std::vector<const char*> argv;
- for(std::vector<std::string>::const_iterator a = args.begin();
- a != args.end(); ++a)
+ 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)
{
- argv.push_back(a->c_str());
+ commandInDir = "cd \"";
+ commandInDir += dir;
+ commandInDir += "\" && ";
+ commandInDir += command;
}
- argv.push_back(0);
-
- if(argv.size() < 2)
+ else
+ {
+ commandInDir = command;
+ }
+ commandInDir += " 2>&1";
+ command = commandInDir.c_str();
+ const int BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ if(verbose)
+ {
+ std::cout << "running " << command << std::endl;
+ }
+ fflush(stdout);
+ fflush(stderr);
+ FILE* cpipe = popen(command, "r");
+ if(!cpipe)
{
return false;
}
-
- output = "";
- cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
- cmsysProcess_SetWorkingDirectory(cp, dir);
- cmsysProcess_Execute(cp);
-
- char* data;
- int length;
- while(cmsysProcess_WaitForData(cp, (cmsysProcess_Pipe_STDOUT |
- cmsysProcess_Pipe_STDERR),
- &data, &length, 0))
+ fgets(buffer, BUFFER_SIZE, cpipe);
+ while(!feof(cpipe))
{
- output.append(data, length);
if(verbose)
{
- std::cout.write(data, length);
+ std::cout << buffer << std::flush;
}
+ output += buffer;
+ fgets(buffer, BUFFER_SIZE, cpipe);
}
-
- cmsysProcess_WaitForExit(cp, 0);
-
- bool result = true;
- if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
+
+ retVal = pclose(cpipe);
+ if (WIFEXITED(retVal))
{
- retVal = cmsysProcess_GetExitValue(cp);
+ retVal = WEXITSTATUS(retVal);
+ return true;
}
- else
+ if (WIFSIGNALED(retVal))
{
- result = false;
+ 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();
+ }
+ 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;
}
- cmsysProcess_Delete(cp);
-
- return result;
+#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(