| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*=========================================================================
- Program: CMake - Cross-Platform Makefile Generator
- Module: $RCSfile$
- Language: C++
- Date: $Date$
- Version: $Revision$
- Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
- See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
- =========================================================================*/
- #include <cmProcess.h>
- #include <cmSystemTools.h>
- cmProcess::cmProcess()
- {
- this->Process = 0;
- this->Timeout = 0;
- }
- cmProcess::~cmProcess()
- {
- cmsysProcess_Delete(this->Process);
- }
- void cmProcess::SetCommand(const char* command)
- {
- this->Command = command;
- }
- void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
- {
- this->Arguments = args;
- }
- bool cmProcess::StartProcess()
- {
- if(this->Command.size() == 0)
- {
- return false;
- }
- this->StartTime = cmSystemTools::GetTime();
- this->ProcessArgs.clear();
- // put the command as arg0
- this->ProcessArgs.push_back(this->Command.c_str());
- // now put the command arguments in
- for(std::vector<std::string>::iterator i = this->Arguments.begin();
- i != this->Arguments.end(); ++i)
- {
- this->ProcessArgs.push_back(i->c_str());
- }
- this->ProcessArgs.push_back(0); // null terminate the list
- this->Process = cmsysProcess_New();
- cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
- if(this->WorkingDirectory.size())
- {
- cmsysProcess_SetWorkingDirectory(this->Process,
- this->WorkingDirectory.c_str());
- }
- cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
- cmsysProcess_SetTimeout(this->Process, this->Timeout);
- cmsysProcess_Execute(this->Process);
- return (cmsysProcess_GetState(this->Process)
- == cmsysProcess_State_Executing);
- }
-
- // return true if there is a new line of data
- // return false if there is no new data
- int cmProcess::CheckOutput(double timeout,
- std::string& stdOutLine,
- std::string& stdErrLine)
- {
- stdOutLine = "";
- stdErrLine = "";
- std::vector<char>::iterator outiter =
- this->StdOutBuffer.begin();
- std::vector<char>::iterator erriter =
- this->StdErrorBuffer.begin();
- while(1)
- {
- // Check for a newline in stdout.
- for(;outiter != this->StdOutBuffer.end(); ++outiter)
- {
- if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end()))
- {
- break;
- }
- else if(*outiter == '\n' || *outiter == '\0')
- {
- int length = outiter-this->StdOutBuffer.begin();
- if(length > 1 && *(outiter-1) == '\r')
- {
- --length;
- }
- if(length > 0)
- {
- stdOutLine.append(&this->StdOutBuffer[0], length);
- }
- this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1);
- this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
- return this->LastOutputPipe;;
- }
- }
- // Check for a newline in stderr.
- for(;erriter != this->StdErrorBuffer.end(); ++erriter)
- {
- if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end()))
- {
- break;
- }
- else if(*erriter == '\n' || *erriter == '\0')
- {
- int length = erriter-this->StdErrorBuffer.begin();
- if(length > 1 && *(erriter-1) == '\r')
- {
- --length;
- }
- if(length > 0)
- {
- stdErrLine.append(&this->StdErrorBuffer[0], length);
- }
- this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1);
- this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
- return this->LastOutputPipe;
- }
- }
- // No newlines found. Wait for more data from the process.
- int length;
- char* data;
- int pipe = cmsysProcess_WaitForData(this->Process, &data,
- &length, &timeout);
- if(pipe == cmsysProcess_Pipe_Timeout)
- {
- // Timeout has been exceeded.
- this->LastOutputPipe = pipe;
- return pipe;
- }
- else if(pipe == cmsysProcess_Pipe_STDOUT)
- {
- // Append to the stdout buffer.
- std::vector<char>::size_type size = this->StdOutBuffer.size();
- this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length);
- outiter = this->StdOutBuffer.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_STDERR)
- {
- // Append to the stderr buffer.
- std::vector<char>::size_type size = this->StdErrorBuffer.size();
- this->StdErrorBuffer.insert(this->StdErrorBuffer.end(),
- data, data+length);
- erriter = this->StdErrorBuffer.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_None)
- {
- // Both stdout and stderr pipes have broken. Return leftover data.
- if(!this->StdOutBuffer.empty())
- {
- stdOutLine.append(&this->StdOutBuffer[0],
- outiter-this->StdOutBuffer.begin());
- this->StdOutBuffer.erase(this->StdOutBuffer.begin(),
- this->StdOutBuffer.end());
- this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
- return this->LastOutputPipe;
- }
- else if(!this->StdErrorBuffer.empty())
- {
- stdErrLine.append(&this->StdErrorBuffer[0],
- erriter-this->StdErrorBuffer.begin());
- this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(),
- this->StdErrorBuffer.end());
- this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
- return this->LastOutputPipe;
- }
- else
- {
- this->LastOutputPipe = cmsysProcess_Pipe_None;
- return this->LastOutputPipe;
- }
- }
- }
- }
- // return the process status
- int cmProcess::GetProcessStatus()
- {
- if(!this->Process)
- {
- return cmsysProcess_State_Exited;
- }
- return cmsysProcess_GetState(this->Process);
- }
- // return true if the process is running
- bool cmProcess::IsRunning()
- {
- int status = this->GetProcessStatus();
- if(status == cmsysProcess_State_Executing )
- {
- if(this->LastOutputPipe != 0)
- {
- return true;
- }
- }
- // if the process is done, then wait for it to exit
- cmsysProcess_WaitForExit(this->Process, 0);
- this->ExitValue = cmsysProcess_GetExitValue(this->Process);
- this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
- std::cerr << "Time to run: " << this->TotalTime << "\n";
- return false;
- }
- int cmProcess::ReportStatus()
- {
- int result = 1;
- switch(cmsysProcess_GetState(this->Process))
- {
- case cmsysProcess_State_Starting:
- {
- std::cerr << "cmProcess: Never started "
- << this->Command << " process.\n";
- } break;
- case cmsysProcess_State_Error:
- {
- std::cerr << "cmProcess: Error executing " << this->Command
- << " process: "
- << cmsysProcess_GetErrorString(this->Process)
- << "\n";
- } break;
- case cmsysProcess_State_Exception:
- {
- std::cerr << "cmProcess: " << this->Command
- << " process exited with an exception: ";
- switch(cmsysProcess_GetExitException(this->Process))
- {
- case cmsysProcess_Exception_None:
- {
- std::cerr << "None";
- } break;
- case cmsysProcess_Exception_Fault:
- {
- std::cerr << "Segmentation fault";
- } break;
- case cmsysProcess_Exception_Illegal:
- {
- std::cerr << "Illegal instruction";
- } break;
- case cmsysProcess_Exception_Interrupt:
- {
- std::cerr << "Interrupted by user";
- } break;
- case cmsysProcess_Exception_Numerical:
- {
- std::cerr << "Numerical exception";
- } break;
- case cmsysProcess_Exception_Other:
- {
- std::cerr << "Unknown";
- } break;
- }
- std::cerr << "\n";
- } break;
- case cmsysProcess_State_Executing:
- {
- std::cerr << "cmProcess: Never terminated " <<
- this->Command << " process.\n";
- } break;
- case cmsysProcess_State_Exited:
- {
- result = cmsysProcess_GetExitValue(this->Process);
- std::cerr << "cmProcess: " << this->Command
- << " process exited with code "
- << result << "\n";
- } break;
- case cmsysProcess_State_Expired:
- {
- std::cerr << "cmProcess: killed " << this->Command
- << " process due to timeout.\n";
- } break;
- case cmsysProcess_State_Killed:
- {
- std::cerr << "cmProcess: killed " << this->Command << " process.\n";
- } break;
- }
- return result;
- }
|