Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CTest / cmProcess.cxx
blobf57acec95f0b262b57e9ee3ee12abb5133ba1c93
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmProcess.cxx,v $
5 Language: C++
6 Date: $Date: 2009-01-14 18:48:03 $
7 Version: $Revision: 1.6 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include <cmProcess.h>
19 #include <cmSystemTools.h>
21 cmProcess::cmProcess()
23 this->Process = 0;
24 this->Timeout = 0;
27 cmProcess::~cmProcess()
29 cmsysProcess_Delete(this->Process);
31 void cmProcess::SetCommand(const char* command)
33 this->Command = command;
36 void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
38 this->Arguments = args;
41 bool cmProcess::StartProcess()
43 if(this->Command.size() == 0)
45 return false;
47 this->StartTime = cmSystemTools::GetTime();
48 this->ProcessArgs.clear();
49 // put the command as arg0
50 this->ProcessArgs.push_back(this->Command.c_str());
51 // now put the command arguments in
52 for(std::vector<std::string>::iterator i = this->Arguments.begin();
53 i != this->Arguments.end(); ++i)
55 this->ProcessArgs.push_back(i->c_str());
57 this->ProcessArgs.push_back(0); // null terminate the list
58 this->Process = cmsysProcess_New();
59 cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
60 if(this->WorkingDirectory.size())
62 cmsysProcess_SetWorkingDirectory(this->Process,
63 this->WorkingDirectory.c_str());
65 cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
66 cmsysProcess_SetTimeout(this->Process, this->Timeout);
67 cmsysProcess_Execute(this->Process);
68 return (cmsysProcess_GetState(this->Process)
69 == cmsysProcess_State_Executing);
72 // return true if there is a new line of data
73 // return false if there is no new data
74 int cmProcess::CheckOutput(double timeout,
75 std::string& stdOutLine,
76 std::string& stdErrLine)
78 stdOutLine = "";
79 stdErrLine = "";
80 std::vector<char>::iterator outiter =
81 this->StdOutBuffer.begin();
82 std::vector<char>::iterator erriter =
83 this->StdErrorBuffer.begin();
84 while(1)
86 // Check for a newline in stdout.
87 for(;outiter != this->StdOutBuffer.end(); ++outiter)
89 if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end()))
91 break;
93 else if(*outiter == '\n' || *outiter == '\0')
95 int length = outiter-this->StdOutBuffer.begin();
96 if(length > 1 && *(outiter-1) == '\r')
98 --length;
100 if(length > 0)
102 stdOutLine.append(&this->StdOutBuffer[0], length);
104 this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1);
105 this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
106 return this->LastOutputPipe;;
110 // Check for a newline in stderr.
111 for(;erriter != this->StdErrorBuffer.end(); ++erriter)
113 if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end()))
115 break;
117 else if(*erriter == '\n' || *erriter == '\0')
119 int length = erriter-this->StdErrorBuffer.begin();
120 if(length > 1 && *(erriter-1) == '\r')
122 --length;
124 if(length > 0)
126 stdErrLine.append(&this->StdErrorBuffer[0], length);
128 this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1);
129 this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
130 return this->LastOutputPipe;
134 // No newlines found. Wait for more data from the process.
135 int length;
136 char* data;
137 int pipe = cmsysProcess_WaitForData(this->Process, &data,
138 &length, &timeout);
139 if(pipe == cmsysProcess_Pipe_Timeout)
141 // Timeout has been exceeded.
142 this->LastOutputPipe = pipe;
143 return pipe;
145 else if(pipe == cmsysProcess_Pipe_STDOUT)
147 // Append to the stdout buffer.
148 std::vector<char>::size_type size = this->StdOutBuffer.size();
149 this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length);
150 outiter = this->StdOutBuffer.begin()+size;
152 else if(pipe == cmsysProcess_Pipe_STDERR)
154 // Append to the stderr buffer.
155 std::vector<char>::size_type size = this->StdErrorBuffer.size();
156 this->StdErrorBuffer.insert(this->StdErrorBuffer.end(),
157 data, data+length);
158 erriter = this->StdErrorBuffer.begin()+size;
160 else if(pipe == cmsysProcess_Pipe_None)
162 // Both stdout and stderr pipes have broken. Return leftover data.
163 if(!this->StdOutBuffer.empty())
165 stdOutLine.append(&this->StdOutBuffer[0],
166 outiter-this->StdOutBuffer.begin());
167 this->StdOutBuffer.erase(this->StdOutBuffer.begin(),
168 this->StdOutBuffer.end());
169 this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
170 return this->LastOutputPipe;
172 else if(!this->StdErrorBuffer.empty())
174 stdErrLine.append(&this->StdErrorBuffer[0],
175 erriter-this->StdErrorBuffer.begin());
176 this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(),
177 this->StdErrorBuffer.end());
178 this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
179 return this->LastOutputPipe;
181 else
183 this->LastOutputPipe = cmsysProcess_Pipe_None;
184 return this->LastOutputPipe;
191 // return the process status
192 int cmProcess::GetProcessStatus()
194 if(!this->Process)
196 return cmsysProcess_State_Exited;
198 return cmsysProcess_GetState(this->Process);
201 // return true if the process is running
202 bool cmProcess::IsRunning()
204 int status = this->GetProcessStatus();
205 if(status == cmsysProcess_State_Executing )
207 if(this->LastOutputPipe != 0)
209 return true;
212 // if the process is done, then wait for it to exit
213 cmsysProcess_WaitForExit(this->Process, 0);
214 this->ExitValue = cmsysProcess_GetExitValue(this->Process);
215 this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
216 // std::cerr << "Time to run: " << this->TotalTime << "\n";
217 return false;
221 int cmProcess::ReportStatus()
223 int result = 1;
224 switch(cmsysProcess_GetState(this->Process))
226 case cmsysProcess_State_Starting:
228 std::cerr << "cmProcess: Never started "
229 << this->Command << " process.\n";
230 } break;
231 case cmsysProcess_State_Error:
233 std::cerr << "cmProcess: Error executing " << this->Command
234 << " process: "
235 << cmsysProcess_GetErrorString(this->Process)
236 << "\n";
237 } break;
238 case cmsysProcess_State_Exception:
240 std::cerr << "cmProcess: " << this->Command
241 << " process exited with an exception: ";
242 switch(cmsysProcess_GetExitException(this->Process))
244 case cmsysProcess_Exception_None:
246 std::cerr << "None";
247 } break;
248 case cmsysProcess_Exception_Fault:
250 std::cerr << "Segmentation fault";
251 } break;
252 case cmsysProcess_Exception_Illegal:
254 std::cerr << "Illegal instruction";
255 } break;
256 case cmsysProcess_Exception_Interrupt:
258 std::cerr << "Interrupted by user";
259 } break;
260 case cmsysProcess_Exception_Numerical:
262 std::cerr << "Numerical exception";
263 } break;
264 case cmsysProcess_Exception_Other:
266 std::cerr << "Unknown";
267 } break;
269 std::cerr << "\n";
270 } break;
271 case cmsysProcess_State_Executing:
273 std::cerr << "cmProcess: Never terminated " <<
274 this->Command << " process.\n";
275 } break;
276 case cmsysProcess_State_Exited:
278 result = cmsysProcess_GetExitValue(this->Process);
279 std::cerr << "cmProcess: " << this->Command
280 << " process exited with code "
281 << result << "\n";
282 } break;
283 case cmsysProcess_State_Expired:
285 std::cerr << "cmProcess: killed " << this->Command
286 << " process due to timeout.\n";
287 } break;
288 case cmsysProcess_State_Killed:
290 std::cerr << "cmProcess: killed " << this->Command << " process.\n";
291 } break;
293 return result;