aboutsummaryrefslogtreecommitdiff
path: root/src/stable/process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/process.cpp')
-rw-r--r--src/stable/process.cpp820
1 files changed, 410 insertions, 410 deletions
diff --git a/src/stable/process.cpp b/src/stable/process.cpp
index a1adb23..a88ee7c 100644
--- a/src/stable/process.cpp
+++ b/src/stable/process.cpp
@@ -27,422 +27,422 @@
27 27
28Bu::Process::ProcData::ProcData() : 28Bu::Process::ProcData::ProcData() :
29#ifdef WIN32 29#ifdef WIN32
30 hStdIn( NULL ), 30 hStdIn( NULL ),
31 hStdOut( NULL ), 31 hStdOut( NULL ),
32 hStdErr( NULL ) 32 hStdErr( NULL )
33#else 33#else
34 iStdIn( -1 ), 34 iStdIn( -1 ),
35 iStdOut( -1 ), 35 iStdOut( -1 ),
36 iStdErr( -1 ) 36 iStdErr( -1 )
37#endif 37#endif
38{ 38{
39} 39}
40 40
41 41
42Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : 42Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) :
43 iProcStatus( 0 ), 43 iProcStatus( 0 ),
44 bBlocking( true ), 44 bBlocking( true ),
45 bStdOutEos( true ), 45 bStdOutEos( true ),
46 bStdErrEos( true ) 46 bStdErrEos( true )
47{ 47{
48 gexec( eFlags, sName, argv ); 48 gexec( eFlags, sName, argv );
49} 49}
50 50
51Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : 51Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) :
52 iProcStatus( 0 ), 52 iProcStatus( 0 ),
53 bBlocking( true ), 53 bBlocking( true ),
54 bStdOutEos( true ), 54 bStdOutEos( true ),
55 bStdErrEos( true ) 55 bStdErrEos( true )
56{ 56{
57 int iCnt = 0; 57 int iCnt = 0;
58 va_list ap; 58 va_list ap;
59 va_start( ap, argv ); 59 va_start( ap, argv );
60 for(; va_arg( ap, const char *); iCnt++ ) { } 60 for(; va_arg( ap, const char *); iCnt++ ) { }
61 va_end( ap ); 61 va_end( ap );
62 62
63 char const **list = new char const *[iCnt+2]; 63 char const **list = new char const *[iCnt+2];
64 va_start( ap, argv ); 64 va_start( ap, argv );
65 list[0] = argv; 65 list[0] = argv;
66 for( int j = 1; j <= iCnt; j++ ) 66 for( int j = 1; j <= iCnt; j++ )
67 { 67 {
68 list[j] = va_arg( ap, const char *); 68 list[j] = va_arg( ap, const char *);
69 } 69 }
70 list[iCnt+1] = NULL; 70 list[iCnt+1] = NULL;
71 va_end( ap ); 71 va_end( ap );
72 72
73 gexec( eFlags, sName, (char *const *)list ); 73 gexec( eFlags, sName, (char *const *)list );
74 delete[] list; 74 delete[] list;
75} 75}
76 76
77Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : 77Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) :
78 iProcStatus( 0 ), 78 iProcStatus( 0 ),
79 bBlocking( true ), 79 bBlocking( true ),
80 bStdOutEos( true ), 80 bStdOutEos( true ),
81 bStdErrEos( true ), 81 bStdErrEos( true ),
82 opt( opt ) 82 opt( opt )
83{ 83{
84 gexec( eFlags, sName, argv ); 84 gexec( eFlags, sName, argv );
85} 85}
86 86
87Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : 87Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) :
88 iProcStatus( 0 ), 88 iProcStatus( 0 ),
89 bBlocking( true ), 89 bBlocking( true ),
90 bStdOutEos( true ), 90 bStdOutEos( true ),
91 bStdErrEos( true ), 91 bStdErrEos( true ),
92 opt( opt ) 92 opt( opt )
93{ 93{
94 int iCnt = 0; 94 int iCnt = 0;
95 va_list ap; 95 va_list ap;
96 va_start( ap, argv ); 96 va_start( ap, argv );
97 for(; va_arg( ap, const char *); iCnt++ ) { } 97 for(; va_arg( ap, const char *); iCnt++ ) { }
98 va_end( ap ); 98 va_end( ap );
99 99
100 char const **list = new char const *[iCnt+2]; 100 char const **list = new char const *[iCnt+2];
101 va_start( ap, argv ); 101 va_start( ap, argv );
102 list[0] = argv; 102 list[0] = argv;
103 for( int j = 1; j <= iCnt; j++ ) 103 for( int j = 1; j <= iCnt; j++ )
104 { 104 {
105 list[j] = va_arg( ap, const char *); 105 list[j] = va_arg( ap, const char *);
106 } 106 }
107 list[iCnt+1] = NULL; 107 list[iCnt+1] = NULL;
108 va_end( ap ); 108 va_end( ap );
109 109
110 gexec( eFlags, sName, (char *const *)list ); 110 gexec( eFlags, sName, (char *const *)list );
111 delete[] list; 111 delete[] list;
112} 112}
113 113
114Bu::Process::~Process() 114Bu::Process::~Process()
115{ 115{
116 close(); 116 close();
117} 117}
118 118
119void Bu::Process::wait() 119void Bu::Process::wait()
120{ 120{
121 close(); 121 close();
122} 122}
123 123
124void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) 124void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] )
125{ 125{
126#ifdef WIN32 126#ifdef WIN32
127 bStdErrEos = true; 127 bStdErrEos = true;
128 SECURITY_ATTRIBUTES saAttr; 128 SECURITY_ATTRIBUTES saAttr;
129 HANDLE hChildStd_IN_Rd; 129 HANDLE hChildStd_IN_Rd;
130 HANDLE hChildStd_IN_Wr; 130 HANDLE hChildStd_IN_Wr;
131 HANDLE hChildStd_OUT_Rd; 131 HANDLE hChildStd_OUT_Rd;
132 HANDLE hChildStd_OUT_Wr; 132 HANDLE hChildStd_OUT_Wr;
133 PROCESS_INFORMATION piProcInfo; 133 PROCESS_INFORMATION piProcInfo;
134 134
135 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 135 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
136 saAttr.bInheritHandle = TRUE; 136 saAttr.bInheritHandle = TRUE;
137 saAttr.lpSecurityDescriptor = NULL; 137 saAttr.lpSecurityDescriptor = NULL;
138 138
139 // Create a pipe for the child process's STDOUT. 139 // Create a pipe for the child process's STDOUT.
140 if ( ! CreatePipe( 140 if ( ! CreatePipe(
141 &hChildStd_OUT_Rd, 141 &hChildStd_OUT_Rd,
142 &hChildStd_OUT_Wr, 142 &hChildStd_OUT_Wr,
143 &saAttr, 0) ) 143 &saAttr, 0) )
144 throw "StdoutRd CreatePipe"; 144 throw "StdoutRd CreatePipe";
145 145
146 // Ensure the read handle to the pipe for STDOUT is not inherited. 146 // Ensure the read handle to the pipe for STDOUT is not inherited.
147 if ( ! SetHandleInformation( 147 if ( ! SetHandleInformation(
148 hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) 148 hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
149 throw "Stdout SetHandleInformation"; 149 throw "Stdout SetHandleInformation";
150 150
151 // Create a pipe for the child process's STDIN. 151 // Create a pipe for the child process's STDIN.
152 if (! CreatePipe( 152 if (! CreatePipe(
153 &hChildStd_IN_Rd, 153 &hChildStd_IN_Rd,
154 &hChildStd_IN_Wr, 154 &hChildStd_IN_Wr,
155 &saAttr, 0)) 155 &saAttr, 0))
156 throw "Stdin CreatePipe"; 156 throw "Stdin CreatePipe";
157 157
158 // Ensure the write handle to the pipe for STDIN is not inherited. 158 // Ensure the write handle to the pipe for STDIN is not inherited.
159 if ( ! SetHandleInformation( 159 if ( ! SetHandleInformation(
160 hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) 160 hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
161 throw "Stdin SetHandleInformation"; 161 throw "Stdin SetHandleInformation";
162 162
163 //TCHAR szCmdline[] = TEXT( sName ); 163 //TCHAR szCmdline[] = TEXT( sName );
164 //PROCESS_INFORMATION pd.piProcInfo; 164 //PROCESS_INFORMATION pd.piProcInfo;
165 STARTUPINFO siStartInfo; 165 STARTUPINFO siStartInfo;
166 BOOL bSuccess = FALSE; 166 BOOL bSuccess = FALSE;
167 167
168 // Set up members of the PROCESS_INFORMATION structure. 168 // Set up members of the PROCESS_INFORMATION structure.
169 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); 169 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
170 170
171 // Set up members of the STARTUPINFO structure. 171 // Set up members of the STARTUPINFO structure.
172 // This structure specifies the STDIN and STDOUT handles for redirection. 172 // This structure specifies the STDIN and STDOUT handles for redirection.
173 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); 173 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
174 siStartInfo.cb = sizeof(STARTUPINFO); 174 siStartInfo.cb = sizeof(STARTUPINFO);
175 siStartInfo.hStdError = hChildStd_OUT_Wr; 175 siStartInfo.hStdError = hChildStd_OUT_Wr;
176 siStartInfo.hStdOutput = hChildStd_OUT_Wr; 176 siStartInfo.hStdOutput = hChildStd_OUT_Wr;
177 siStartInfo.hStdInput = hChildStd_IN_Rd; 177 siStartInfo.hStdInput = hChildStd_IN_Rd;
178 siStartInfo.dwFlags |= STARTF_USESTDHANDLES; 178 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
179 179
180 Bu::String sCmd; 180 Bu::String sCmd;
181 for( char *const *arg = argv; *arg; arg++ ) 181 for( char *const *arg = argv; *arg; arg++ )
182 { 182 {
183 if( arg != argv ) 183 if( arg != argv )
184 sCmd += " "; 184 sCmd += " ";
185 sCmd += *arg; 185 sCmd += *arg;
186 } 186 }
187 187
188 // Create the child process. 188 // Create the child process.
189 bSuccess = CreateProcessA( 189 bSuccess = CreateProcessA(
190 sName, //sName, //module name 190 sName, //sName, //module name
191 sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line 191 sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line
192 NULL, // process security attributes 192 NULL, // process security attributes
193 NULL, // primary thread security attributes 193 NULL, // primary thread security attributes
194 TRUE, // handles are inherited 194 TRUE, // handles are inherited
195 CREATE_NO_WINDOW, // creation flags 195 CREATE_NO_WINDOW, // creation flags
196 NULL, // use parent's environment 196 NULL, // use parent's environment
197 NULL, // use parent's current directory 197 NULL, // use parent's current directory
198 &siStartInfo, // STARTUPINFO pointer 198 &siStartInfo, // STARTUPINFO pointer
199 &piProcInfo ); // receives PROCESS_INFORMATION 199 &piProcInfo ); // receives PROCESS_INFORMATION
200 200
201 // If an error occurs, exit the application. 201 // If an error occurs, exit the application.
202 if ( ! bSuccess ) 202 if ( ! bSuccess )
203 { 203 {
204 throw Bu::ExceptionBase("Error spawning child process."); 204 throw Bu::ExceptionBase("Error spawning child process.");
205 return; 205 return;
206 } 206 }
207 else 207 else
208 { 208 {
209 // Close handles to the child process and its primary thread. 209 // Close handles to the child process and its primary thread.
210 // Some applications might keep these handles to monitor the status 210 // Some applications might keep these handles to monitor the status
211 // of the child process, for example. 211 // of the child process, for example.
212 212
213 //CloseHandle(pData->pd.piProcInfo.hProcess); 213 //CloseHandle(pData->pd.piProcInfo.hProcess);
214 CloseHandle(piProcInfo.hThread); 214 CloseHandle(piProcInfo.hThread);
215 pd.hProcess = piProcInfo.hProcess; 215 pd.hProcess = piProcInfo.hProcess;
216 216
217 // Close the ends we can't use 217 // Close the ends we can't use
218 CloseHandle( hChildStd_OUT_Wr ); 218 CloseHandle( hChildStd_OUT_Wr );
219 CloseHandle( hChildStd_IN_Rd ); 219 CloseHandle( hChildStd_IN_Rd );
220 pd.hStdIn = hChildStd_IN_Wr; 220 pd.hStdIn = hChildStd_IN_Wr;
221 pd.hStdOut = hChildStd_OUT_Rd; 221 pd.hStdOut = hChildStd_OUT_Rd;
222 } 222 }
223#else 223#else
224 int iaStdIn[2]; 224 int iaStdIn[2];
225 int iaStdOut[2]; 225 int iaStdOut[2];
226 int iaStdErr[2]; 226 int iaStdErr[2];
227 pipe( iaStdIn ); 227 pipe( iaStdIn );
228 if( eFlags & StdOut ) 228 if( eFlags & StdOut )
229 { 229 {
230 pipe( iaStdOut ); 230 pipe( iaStdOut );
231 pd.iStdOut = iaStdOut[0]; 231 pd.iStdOut = iaStdOut[0];
232 bStdOutEos = false; 232 bStdOutEos = false;
233 } 233 }
234 if( eFlags & StdErr ) 234 if( eFlags & StdErr )
235 { 235 {
236 pipe( iaStdErr ); 236 pipe( iaStdErr );
237 pd.iStdErr = iaStdErr[0]; 237 pd.iStdErr = iaStdErr[0];
238 bStdErrEos = false; 238 bStdErrEos = false;
239 } 239 }
240 240
241 pd.iStdIn = iaStdIn[1]; 241 pd.iStdIn = iaStdIn[1];
242 242
243// fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); 243// fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK );
244 244
245 pd.iPid = fork(); 245 pd.iPid = fork();
246 if( pd.iPid == 0 ) 246 if( pd.iPid == 0 )
247 { 247 {
248 ::close( iaStdIn[1] ); 248 ::close( iaStdIn[1] );
249 dup2( iaStdIn[0], 0 ); 249 dup2( iaStdIn[0], 0 );
250 if( eFlags & StdOut ) 250 if( eFlags & StdOut )
251 { 251 {
252 ::close( iaStdOut[0] ); 252 ::close( iaStdOut[0] );
253 dup2( iaStdOut[1], 1 ); 253 dup2( iaStdOut[1], 1 );
254 } 254 }
255 if( eFlags & StdErr ) 255 if( eFlags & StdErr )
256 { 256 {
257 ::close( iaStdErr[0] ); 257 ::close( iaStdErr[0] );
258 dup2( iaStdErr[1], 2 ); 258 dup2( iaStdErr[1], 2 );
259 } 259 }
260 if( (opt.eFlags&Options::SetGid) ) 260 if( (opt.eFlags&Options::SetGid) )
261 { 261 {
262 setgid( opt.iGid ); 262 setgid( opt.iGid );
263 } 263 }
264 if( (opt.eFlags&Options::SetUid) ) 264 if( (opt.eFlags&Options::SetUid) )
265 { 265 {
266 setuid( opt.iUid ); 266 setuid( opt.iUid );
267 } 267 }
268 execvp( sName, argv ); 268 execvp( sName, argv );
269 throw Bu::ExceptionBase("Hey, execvp failed!"); 269 throw Bu::ExceptionBase("Hey, execvp failed!");
270 } 270 }
271 ::close( iaStdIn[0] ); 271 ::close( iaStdIn[0] );
272 if( eFlags & StdOut ) 272 if( eFlags & StdOut )
273 ::close( iaStdOut[1] ); 273 ::close( iaStdOut[1] );
274 if( eFlags & StdErr ) 274 if( eFlags & StdErr )
275 ::close( iaStdErr[1] ); 275 ::close( iaStdErr[1] );
276#endif 276#endif
277} 277}
278 278
279void Bu::Process::close() 279void Bu::Process::close()
280{ 280{
281#ifdef WIN32 281#ifdef WIN32
282 if( pd.hStdIn ) 282 if( pd.hStdIn )
283 { 283 {
284 CloseHandle( pd.hStdIn ); 284 CloseHandle( pd.hStdIn );
285 CloseHandle( pd.hStdOut ); 285 CloseHandle( pd.hStdOut );
286 286
287 pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; 287 pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL;
288 288
289 if( !TerminateProcess(pd.hProcess, 1) ) 289 if( !TerminateProcess(pd.hProcess, 1) )
290 { 290 {
291 throw Bu::ExceptionBase("Error closing process."); 291 throw Bu::ExceptionBase("Error closing process.");
292 } 292 }
293 293
294 GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus ); 294 GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus );
295 295
296 CloseHandle( pd.hProcess ); 296 CloseHandle( pd.hProcess );
297 pd.hProcess = NULL; 297 pd.hProcess = NULL;
298 } 298 }
299#else 299#else
300 if( pd.iPid ) 300 if( pd.iPid )
301 { 301 {
302 if( pd.iStdIn > -1 ) 302 if( pd.iStdIn > -1 )
303 ::close( pd.iStdIn ); 303 ::close( pd.iStdIn );
304 if( pd.iStdOut > -1 ) 304 if( pd.iStdOut > -1 )
305 ::close( pd.iStdOut ); 305 ::close( pd.iStdOut );
306 if( pd.iStdErr > -1 ) 306 if( pd.iStdErr > -1 )
307 ::close( pd.iStdErr ); 307 ::close( pd.iStdErr );
308 waitpid( pd.iPid, &iProcStatus, 0 ); 308 waitpid( pd.iPid, &iProcStatus, 0 );
309 pd.iPid = 0; 309 pd.iPid = 0;
310 } 310 }
311#endif 311#endif
312} 312}
313 313
314void Bu::Process::closeStdIn() 314void Bu::Process::closeStdIn()
315{ 315{
316#ifdef WIN32 316#ifdef WIN32
317 CloseHandle( pd.hStdIn ); 317 CloseHandle( pd.hStdIn );
318 pd.hStdIn = NULL; 318 pd.hStdIn = NULL;
319#else 319#else
320 ::close( pd.iStdIn ); 320 ::close( pd.iStdIn );
321 pd.iStdIn = -1; 321 pd.iStdIn = -1;
322#endif 322#endif
323} 323}
324 324
325void Bu::Process::closeStdOut() 325void Bu::Process::closeStdOut()
326{ 326{
327#ifdef WIN32 327#ifdef WIN32
328 CloseHandle( pd.hStdOut ); 328 CloseHandle( pd.hStdOut );
329 pd.hStdOut = NULL; 329 pd.hStdOut = NULL;
330#else 330#else
331 ::close( pd.iStdOut ); 331 ::close( pd.iStdOut );
332 pd.iStdOut = -1; 332 pd.iStdOut = -1;
333#endif 333#endif
334} 334}
335 335
336Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) 336Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes )
337{ 337{
338#ifdef WIN32 338#ifdef WIN32
339 DWORD dwRead; 339 DWORD dwRead;
340 DWORD lExitCode; 340 DWORD lExitCode;
341 BOOL bSuccess = FALSE; 341 BOOL bSuccess = FALSE;
342 DWORD dwLen = (DWORD) nBytes; 342 DWORD dwLen = (DWORD) nBytes;
343 bSuccess = ReadFile( 343 bSuccess = ReadFile(
344 pd.hStdOut, (char *) pBuf, 344 pd.hStdOut, (char *) pBuf,
345 dwLen, &dwRead, NULL); 345 dwLen, &dwRead, NULL);
346// if( dwRead < dwLen ) 346// if( dwRead < dwLen )
347 { 347 {
348 bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode ); 348 bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode );
349 if( lExitCode != STILL_ACTIVE ) 349 if( lExitCode != STILL_ACTIVE )
350 { 350 {
351 bStdOutEos = true; 351 bStdOutEos = true;
352 } 352 }
353 } 353 }
354 return (int32_t) dwRead; 354 return (int32_t) dwRead;
355#else 355#else
356 if( bStdOutEos ) 356 if( bStdOutEos )
357 return 0; 357 return 0;
358 fd_set rfds; 358 fd_set rfds;
359 FD_ZERO( &rfds ); 359 FD_ZERO( &rfds );
360 FD_SET( pd.iStdOut, &rfds ); 360 FD_SET( pd.iStdOut, &rfds );
361 struct timeval tv = {0, 0}; 361 struct timeval tv = {0, 0};
362 if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) 362 if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 )
363 throw Bu::ExceptionBase( strerror( errno ) ); 363 throw Bu::ExceptionBase( strerror( errno ) );
364 if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) 364 if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking )
365 { 365 {
366 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); 366 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) );
367 if( nRead == 0 ) 367 if( nRead == 0 )
368 { 368 {
369 bStdOutEos = true; 369 bStdOutEos = true;
370 checkClose(); 370 checkClose();
371 return 0; 371 return 0;
372 } 372 }
373 if( nRead < 0 ) 373 if( nRead < 0 )
374 { 374 {
375 if( errno == EAGAIN ) 375 if( errno == EAGAIN )
376 return 0; 376 return 0;
377 throw Bu::ExceptionBase( strerror( errno ) ); 377 throw Bu::ExceptionBase( strerror( errno ) );
378 } 378 }
379 return nRead; 379 return nRead;
380 } 380 }
381 return 0; 381 return 0;
382#endif 382#endif
383} 383}
384 384
385Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) 385Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes )
386{ 386{
387#ifdef WIN32 387#ifdef WIN32
388 if( !pd.hStdErr ) 388 if( !pd.hStdErr )
389 return 0; 389 return 0;
390 DWORD dwRead; 390 DWORD dwRead;
391 BOOL bSuccess = FALSE; 391 BOOL bSuccess = FALSE;
392 DWORD dwLen = (DWORD) nBytes; 392 DWORD dwLen = (DWORD) nBytes;
393 bSuccess = ReadFile( 393 bSuccess = ReadFile(
394 pd.hStdErr, (char *) pBuf, 394 pd.hStdErr, (char *) pBuf,
395 dwLen, &dwRead, NULL); 395 dwLen, &dwRead, NULL);
396 return (int32_t) dwRead; 396 return (int32_t) dwRead;
397#else 397#else
398 if( bStdErrEos ) 398 if( bStdErrEos )
399 return 0; 399 return 0;
400 fd_set rfds; 400 fd_set rfds;
401 FD_ZERO( &rfds ); 401 FD_ZERO( &rfds );
402 FD_SET( pd.iStdErr, &rfds ); 402 FD_SET( pd.iStdErr, &rfds );
403 struct timeval tv = {0, 0}; 403 struct timeval tv = {0, 0};
404 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) 404 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 )
405 throw Bu::ExceptionBase( strerror( errno ) ); 405 throw Bu::ExceptionBase( strerror( errno ) );
406 if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) 406 if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking )
407 { 407 {
408 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); 408 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) );
409 if( nRead == 0 ) 409 if( nRead == 0 )
410 { 410 {
411 bStdErrEos = true; 411 bStdErrEos = true;
412 checkClose(); 412 checkClose();
413 return 0; 413 return 0;
414 } 414 }
415 if( nRead < 0 ) 415 if( nRead < 0 )
416 { 416 {
417 if( errno == EAGAIN ) 417 if( errno == EAGAIN )
418 return 0; 418 return 0;
419 throw Bu::ExceptionBase( strerror( errno ) ); 419 throw Bu::ExceptionBase( strerror( errno ) );
420 } 420 }
421 return nRead; 421 return nRead;
422 } 422 }
423 return 0; 423 return 0;
424#endif 424#endif
425} 425}
426 426
427Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) 427Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes )
428{ 428{
429#ifdef WIN32 429#ifdef WIN32
430 DWORD dwWritten; 430 DWORD dwWritten;
431 BOOL bSuccess = FALSE; 431 BOOL bSuccess = FALSE;
432 DWORD dwLen = (DWORD) nBytes; 432 DWORD dwLen = (DWORD) nBytes;
433 bSuccess = WriteFile( 433 bSuccess = WriteFile(
434 pd.hStdIn, (const char *) pBuf, 434 pd.hStdIn, (const char *) pBuf,
435 dwLen, &dwWritten, NULL ); 435 dwLen, &dwWritten, NULL );
436 FlushFileBuffers( pd.hStdIn ); 436 FlushFileBuffers( pd.hStdIn );
437 return (int32_t) dwWritten; 437 return (int32_t) dwWritten;
438#else 438#else
439 return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); 439 return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) );
440#endif 440#endif
441} 441}
442 442
443Bu::size Bu::Process::tell() 443Bu::size Bu::Process::tell()
444{ 444{
445 return 0; 445 return 0;
446} 446}
447 447
448void Bu::Process::seek( Bu::size ) 448void Bu::Process::seek( Bu::size )
@@ -460,15 +460,15 @@ void Bu::Process::setPosEnd( Bu::size )
460bool Bu::Process::isEos() 460bool Bu::Process::isEos()
461{ 461{
462#ifdef WIN32 462#ifdef WIN32
463 return (pd.hProcess == NULL); 463 return (pd.hProcess == NULL);
464#else 464#else
465 return (pd.iPid == 0); 465 return (pd.iPid == 0);
466#endif 466#endif
467} 467}
468 468
469bool Bu::Process::isOpen() 469bool Bu::Process::isOpen()
470{ 470{
471 return !isEos(); 471 return !isEos();
472} 472}
473 473
474void Bu::Process::flush() 474void Bu::Process::flush()
@@ -477,53 +477,53 @@ void Bu::Process::flush()
477 477
478bool Bu::Process::canRead() 478bool Bu::Process::canRead()
479{ 479{
480 return true; 480 return true;
481} 481}
482 482
483bool Bu::Process::canWrite() 483bool Bu::Process::canWrite()
484{ 484{
485 return true; 485 return true;
486} 486}
487 487
488bool Bu::Process::isReadable() 488bool Bu::Process::isReadable()
489{ 489{
490 return true; 490 return true;
491} 491}
492 492
493bool Bu::Process::isWritable() 493bool Bu::Process::isWritable()
494{ 494{
495 return true; 495 return true;
496} 496}
497 497
498bool Bu::Process::isSeekable() 498bool Bu::Process::isSeekable()
499{ 499{
500 return false; 500 return false;
501} 501}
502 502
503bool Bu::Process::isBlocking() 503bool Bu::Process::isBlocking()
504{ 504{
505 return true; 505 return true;
506} 506}
507 507
508void Bu::Process::setBlocking( bool bBlocking ) 508void Bu::Process::setBlocking( bool bBlocking )
509{ 509{
510#ifdef WIN32 510#ifdef WIN32
511#else 511#else
512 if( bBlocking ) 512 if( bBlocking )
513 { 513 {
514 if( !bStdOutEos ) 514 if( !bStdOutEos )
515 fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); 515 fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) );
516 if( !bStdErrEos ) 516 if( !bStdErrEos )
517 fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); 517 fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) );
518 } 518 }
519 else 519 else
520 { 520 {
521 if( !bStdOutEos ) 521 if( !bStdOutEos )
522 fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); 522 fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK );
523 if( !bStdErrEos ) 523 if( !bStdErrEos )
524 fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); 524 fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK );
525 } 525 }
526 this->bBlocking = bBlocking; 526 this->bBlocking = bBlocking;
527#endif 527#endif
528} 528}
529 529
@@ -533,128 +533,128 @@ void Bu::Process::setSize( Bu::size )
533 533
534Bu::size Bu::Process::getBlockSize() const 534Bu::size Bu::Process::getBlockSize() const
535{ 535{
536 return 0; 536 return 0;
537} 537}
538 538
539Bu::size Bu::Process::getSize() const 539Bu::size Bu::Process::getSize() const
540{ 540{
541 return 0; 541 return 0;
542} 542}
543 543
544Bu::String Bu::Process::getLocation() const 544Bu::String Bu::Process::getLocation() const
545{ 545{
546 return ""; 546 return "";
547} 547}
548 548
549void Bu::Process::select( bool &bStdOut, bool &bStdErr ) 549void Bu::Process::select( bool &bStdOut, bool &bStdErr )
550{ 550{
551#ifdef WIN32 551#ifdef WIN32
552#else 552#else
553 fd_set rfds; 553 fd_set rfds;
554 FD_ZERO( &rfds ); 554 FD_ZERO( &rfds );
555 if( !bStdOutEos ) 555 if( !bStdOutEos )
556 FD_SET( pd.iStdOut, &rfds ); 556 FD_SET( pd.iStdOut, &rfds );
557 if( !bStdErrEos ) 557 if( !bStdErrEos )
558 FD_SET( pd.iStdErr, &rfds ); 558 FD_SET( pd.iStdErr, &rfds );
559 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) 559 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 )
560 throw Bu::ExceptionBase( strerror( errno ) ); 560 throw Bu::ExceptionBase( strerror( errno ) );
561 561
562 if( FD_ISSET( pd.iStdOut, &rfds ) ) 562 if( FD_ISSET( pd.iStdOut, &rfds ) )
563 bStdOut = true; 563 bStdOut = true;
564 else 564 else
565 bStdOut = false; 565 bStdOut = false;
566 566
567 if( FD_ISSET( pd.iStdErr, &rfds ) ) 567 if( FD_ISSET( pd.iStdErr, &rfds ) )
568 bStdErr = true; 568 bStdErr = true;
569 else 569 else
570 bStdErr = false; 570 bStdErr = false;
571#endif 571#endif
572} 572}
573 573
574bool Bu::Process::isRunning() 574bool Bu::Process::isRunning()
575{ 575{
576#ifdef WIN32 576#ifdef WIN32
577 DWORD lExitCode; 577 DWORD lExitCode;
578 GetExitCodeProcess( pd.hProcess, &lExitCode ); 578 GetExitCodeProcess( pd.hProcess, &lExitCode );
579 if( lExitCode != STILL_ACTIVE ) 579 if( lExitCode != STILL_ACTIVE )
580 checkClose(); 580 checkClose();
581#else 581#else
582 if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) 582 if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid )
583 checkClose(); 583 checkClose();
584#endif 584#endif
585 return isOpen(); 585 return isOpen();
586} 586}
587 587
588void Bu::Process::ignoreStdErr() 588void Bu::Process::ignoreStdErr()
589{ 589{
590#ifdef WIN32 590#ifdef WIN32
591#else 591#else
592 if( pd.iStdErr == -1 ) 592 if( pd.iStdErr == -1 )
593 return; 593 return;
594 ::close( pd.iStdErr ); 594 ::close( pd.iStdErr );
595 pd.iStdErr = -1; 595 pd.iStdErr = -1;
596 bStdErrEos = true; 596 bStdErrEos = true;
597#endif 597#endif
598} 598}
599 599
600pid_t Bu::Process::getPid() 600pid_t Bu::Process::getPid()
601{ 601{
602#ifdef WIN32 602#ifdef WIN32
603 return 0; 603 return 0;
604#else 604#else
605 return pd.iPid; 605 return pd.iPid;
606#endif 606#endif
607} 607}
608 608
609bool Bu::Process::childExited() 609bool Bu::Process::childExited()
610{ 610{
611#ifdef WIN32 611#ifdef WIN32
612 return pd.hProcess != NULL; 612 return pd.hProcess != NULL;
613#else 613#else
614 return WIFEXITED( iProcStatus ); 614 return WIFEXITED( iProcStatus );
615#endif 615#endif
616} 616}
617 617
618int Bu::Process::childExitStatus() 618int Bu::Process::childExitStatus()
619{ 619{
620#ifdef WIN32 620#ifdef WIN32
621 return iProcStatus; 621 return iProcStatus;
622#else 622#else
623 return WEXITSTATUS( iProcStatus ); 623 return WEXITSTATUS( iProcStatus );
624#endif 624#endif
625} 625}
626 626
627bool Bu::Process::childSignaled() 627bool Bu::Process::childSignaled()
628{ 628{
629#ifdef WIN32 629#ifdef WIN32
630 return false; 630 return false;
631#else 631#else
632 return WIFSIGNALED( iProcStatus ); 632 return WIFSIGNALED( iProcStatus );
633#endif 633#endif
634} 634}
635 635
636int Bu::Process::childSignal() 636int Bu::Process::childSignal()
637{ 637{
638#ifdef WIN32 638#ifdef WIN32
639 return 0; 639 return 0;
640#else 640#else
641 return WTERMSIG( iProcStatus ); 641 return WTERMSIG( iProcStatus );
642#endif 642#endif
643} 643}
644 644
645bool Bu::Process::childCoreDumped() 645bool Bu::Process::childCoreDumped()
646{ 646{
647#ifdef WIN32 647#ifdef WIN32
648 return false; 648 return false;
649#else 649#else
650 return WCOREDUMP( iProcStatus ); 650 return WCOREDUMP( iProcStatus );
651#endif 651#endif
652} 652}
653 653
654void Bu::Process::checkClose() 654void Bu::Process::checkClose()
655{ 655{
656 if( bStdOutEos && bStdErrEos ) 656 if( bStdOutEos && bStdErrEos )
657 { 657 {
658 close(); 658 close();
659 } 659 }
660} 660}