cmProcess.cxx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include <cmProcess.h>
  14. #include <iostream>
  15. cmProcess::cmProcess()
  16. {
  17. this->Process = 0;
  18. this->Timeout = 0;
  19. }
  20. cmProcess::~cmProcess()
  21. {
  22. cmsysProcess_Delete(this->Process);
  23. }
  24. void cmProcess::SetCommand(const char* command)
  25. {
  26. this->Command = command;
  27. }
  28. void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
  29. {
  30. this->Arguments = args;
  31. }
  32. bool cmProcess::StartProcess()
  33. {
  34. if(this->Command.size() == 0)
  35. {
  36. return false;
  37. }
  38. this->ProcessArgs.clear();
  39. // put the command as arg0
  40. this->ProcessArgs.push_back(this->Command.c_str());
  41. // now put the command arguments in
  42. for(std::vector<std::string>::iterator i = this->Arguments.begin();
  43. i != this->Arguments.end(); ++i)
  44. {
  45. this->ProcessArgs.push_back(i->c_str());
  46. }
  47. this->ProcessArgs.push_back(0); // null terminate the list
  48. this->Process = cmsysProcess_New();
  49. cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
  50. if(this->WorkingDirectory.size())
  51. {
  52. cmsysProcess_SetWorkingDirectory(this->Process,
  53. this->WorkingDirectory.c_str());
  54. }
  55. cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
  56. cmsysProcess_SetTimeout(this->Process, this->Timeout);
  57. cmsysProcess_Execute(this->Process);
  58. return (cmsysProcess_GetState(this->Process)
  59. == cmsysProcess_State_Executing);
  60. }
  61. // return true if there is a new line of data
  62. // return false if there is no new data
  63. int cmProcess::CheckOutput(double timeout,
  64. std::string& stdOutLine,
  65. std::string& stdErrLine)
  66. {
  67. stdOutLine = "";
  68. stdErrLine = "";
  69. std::vector<char>::iterator outiter =
  70. this->StdOutBuffer.begin();
  71. std::vector<char>::iterator erriter =
  72. this->StdErrorBuffer.begin();
  73. while(1)
  74. {
  75. // Check for a newline in stdout.
  76. for(;outiter != this->StdOutBuffer.end(); ++outiter)
  77. {
  78. if((*outiter == '\r') && ((outiter+1) == this->StdOutBuffer.end()))
  79. {
  80. break;
  81. }
  82. else if(*outiter == '\n' || *outiter == '\0')
  83. {
  84. int length = outiter-this->StdOutBuffer.begin();
  85. if(length > 1 && *(outiter-1) == '\r')
  86. {
  87. --length;
  88. }
  89. if(length > 0)
  90. {
  91. stdOutLine.append(&this->StdOutBuffer[0], length);
  92. }
  93. this->StdOutBuffer.erase(this->StdOutBuffer.begin(), outiter+1);
  94. this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
  95. return this->LastOutputPipe;;
  96. }
  97. }
  98. // Check for a newline in stderr.
  99. for(;erriter != this->StdErrorBuffer.end(); ++erriter)
  100. {
  101. if((*erriter == '\r') && ((erriter+1) == this->StdErrorBuffer.end()))
  102. {
  103. break;
  104. }
  105. else if(*erriter == '\n' || *erriter == '\0')
  106. {
  107. int length = erriter-this->StdErrorBuffer.begin();
  108. if(length > 1 && *(erriter-1) == '\r')
  109. {
  110. --length;
  111. }
  112. if(length > 0)
  113. {
  114. stdErrLine.append(&this->StdErrorBuffer[0], length);
  115. }
  116. this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), erriter+1);
  117. this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
  118. return this->LastOutputPipe;
  119. }
  120. }
  121. // No newlines found. Wait for more data from the process.
  122. int length;
  123. char* data;
  124. int pipe = cmsysProcess_WaitForData(this->Process, &data,
  125. &length, &timeout);
  126. if(pipe == cmsysProcess_Pipe_Timeout)
  127. {
  128. // Timeout has been exceeded.
  129. this->LastOutputPipe = pipe;
  130. return pipe;
  131. }
  132. else if(pipe == cmsysProcess_Pipe_STDOUT)
  133. {
  134. // Append to the stdout buffer.
  135. std::vector<char>::size_type size = this->StdOutBuffer.size();
  136. this->StdOutBuffer.insert(this->StdOutBuffer.end(), data, data+length);
  137. outiter = this->StdOutBuffer.begin()+size;
  138. }
  139. else if(pipe == cmsysProcess_Pipe_STDERR)
  140. {
  141. // Append to the stderr buffer.
  142. std::vector<char>::size_type size = this->StdErrorBuffer.size();
  143. this->StdErrorBuffer.insert(this->StdErrorBuffer.end(),
  144. data, data+length);
  145. erriter = this->StdErrorBuffer.begin()+size;
  146. }
  147. else if(pipe == cmsysProcess_Pipe_None)
  148. {
  149. // Both stdout and stderr pipes have broken. Return leftover data.
  150. if(!this->StdOutBuffer.empty())
  151. {
  152. stdOutLine.append(&this->StdOutBuffer[0],
  153. outiter-this->StdOutBuffer.begin());
  154. this->StdOutBuffer.erase(this->StdOutBuffer.begin(),
  155. this->StdOutBuffer.end());
  156. this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
  157. return this->LastOutputPipe;
  158. }
  159. else if(!this->StdErrorBuffer.empty())
  160. {
  161. stdErrLine.append(&this->StdErrorBuffer[0],
  162. erriter-this->StdErrorBuffer.begin());
  163. this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(),
  164. this->StdErrorBuffer.end());
  165. this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
  166. return this->LastOutputPipe;
  167. }
  168. else
  169. {
  170. this->LastOutputPipe = cmsysProcess_Pipe_None;
  171. return this->LastOutputPipe;
  172. }
  173. }
  174. }
  175. }
  176. // return the process status
  177. int cmProcess::GetProcessStatus()
  178. {
  179. if(!this->Process)
  180. {
  181. return cmsysProcess_State_Exited;
  182. }
  183. return cmsysProcess_GetState(this->Process);
  184. }
  185. // return true if the process is running
  186. bool cmProcess::IsRunning()
  187. {
  188. int status = this->GetProcessStatus();
  189. if(status == cmsysProcess_State_Executing )
  190. {
  191. if(this->LastOutputPipe != 0)
  192. {
  193. return true;
  194. }
  195. }
  196. // if the process is done, then wait for it to exit
  197. cmsysProcess_WaitForExit(this->Process, 0);
  198. this->ExitValue = cmsysProcess_GetExitValue(this->Process);
  199. return false;
  200. }
  201. int cmProcess::ReportStatus()
  202. {
  203. int result = 1;
  204. switch(cmsysProcess_GetState(this->Process))
  205. {
  206. case cmsysProcess_State_Starting:
  207. {
  208. std::cerr << "cmProcess: Never started "
  209. << this->Command << " process.\n";
  210. } break;
  211. case cmsysProcess_State_Error:
  212. {
  213. std::cerr << "cmProcess: Error executing " << this->Command << " process: "
  214. << cmsysProcess_GetErrorString(this->Process)
  215. << "\n";
  216. } break;
  217. case cmsysProcess_State_Exception:
  218. {
  219. std::cerr << "cmProcess: " << this->Command
  220. << " process exited with an exception: ";
  221. switch(cmsysProcess_GetExitException(this->Process))
  222. {
  223. case cmsysProcess_Exception_None:
  224. {
  225. std::cerr << "None";
  226. } break;
  227. case cmsysProcess_Exception_Fault:
  228. {
  229. std::cerr << "Segmentation fault";
  230. } break;
  231. case cmsysProcess_Exception_Illegal:
  232. {
  233. std::cerr << "Illegal instruction";
  234. } break;
  235. case cmsysProcess_Exception_Interrupt:
  236. {
  237. std::cerr << "Interrupted by user";
  238. } break;
  239. case cmsysProcess_Exception_Numerical:
  240. {
  241. std::cerr << "Numerical exception";
  242. } break;
  243. case cmsysProcess_Exception_Other:
  244. {
  245. std::cerr << "Unknown";
  246. } break;
  247. }
  248. std::cerr << "\n";
  249. } break;
  250. case cmsysProcess_State_Executing:
  251. {
  252. std::cerr << "cmProcess: Never terminated " << this->Command << " process.\n";
  253. } break;
  254. case cmsysProcess_State_Exited:
  255. {
  256. result = cmsysProcess_GetExitValue(this->Process);
  257. std::cerr << "cmProcess: " << this->Command << " process exited with code "
  258. << result << "\n";
  259. } break;
  260. case cmsysProcess_State_Expired:
  261. {
  262. std::cerr << "cmProcess: killed " << this->Command << " process due to timeout.\n";
  263. } break;
  264. case cmsysProcess_State_Killed:
  265. {
  266. std::cerr << "cmProcess: killed " << this->Command << " process.\n";
  267. } break;
  268. }
  269. return result;
  270. }