summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mingw.bld44
-rw-r--r--src/experimental/cachestorefiles.h4
-rw-r--r--src/stable/process.cpp347
-rw-r--r--src/stable/process.h25
4 files changed, 330 insertions, 90 deletions
diff --git a/mingw.bld b/mingw.bld
index 5deff19..69be44e 100644
--- a/mingw.bld
+++ b/mingw.bld
@@ -16,53 +16,55 @@ action "default"
16 build: [targets("header-links"), "libbu++win.a"]; 16 build: [targets("header-links"), "libbu++win.a"];
17} 17}
18 18
19target files("src/*.h").replace("src/", "bu/") 19for base in ["stable", "unstable", "experimental"] do
20{
21 target files("src/${base}/*.h").replace("src/${base}/", "bu/")
22 {
23 tag "header-links";
24 display "symlink";
25 input OUTPUT.replace("bu/","src/${base}/");
26 profile "build"
27 {
28 DIR = OUTPUT.dirName();
29 execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}");
30 }
31 }
32}
33target files("src/compat/*.h").replace("src/", "bu/")
20{ 34{
21 tag "header-links"; 35 tag "header-links";
22 display "symlink"; 36 display "symlink";
23 input OUTPUT.replace("bu/","src/"); 37 input OUTPUT.replace("bu/","src/");
24 profile "build" 38 profile "build"
25 { 39 {
26 execute("mkdir -p $(dirname ${OUTPUT}); ln -s ../${INPUT} ${OUTPUT}"); 40 execute("mkdir -p $(dirname ${OUTPUT}); ln -s ../../${INPUT} ${OUTPUT}");
27 } 41 }
28} 42}
29target files("src/compat/*.h").replace("src/", "bu/") 43target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"]
30{ 44{
31 tag "header-links"; 45 tag "header-links";
32 display "symlink"; 46 display "symlink";
33 input OUTPUT.replace("bu/","src/"); 47 input OUTPUT.replace("bu/","src/");
34 profile "build" 48 profile "build"
35 { 49 {
36 execute("mkdir -p $(dirname ${OUTPUT}); ln -s ../../${INPUT} ${OUTPUT}"); 50 DIR = OUTPUT.dirName();
51 execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}");
37 } 52 }
38} 53}
39 54
40target "libbu++win.a" 55target "libbu++win.a"
41{ 56{
42 input files("src/*.cpp", "src/compat/*.cpp"); 57 input files("src/stable/*.cpp", "src/unstable/*.cpp",
58 "src/experimental/*.cpp", "src/compat/*.cpp");
43 rule "lib"; 59 rule "lib";
44 CXXFLAGS += "-I. -Isupport/windows"; 60 CXXFLAGS += "-I. -Isupport/windows";
45} 61}
46 62
47target ["src/process.win_o", "src/lzma.win_o"] 63target ["src/stable/lzma.win_o", "src/experimental/cachestorefiles.win_o", "src/experimental/regex.win_o"]
48{
49 profile "build"
50 {
51 execute("rm -f src/process.win_o && touch src/process.win_o && echo NOT BUILDING PROCESS RIGHT NOW!!!");
52 }
53}
54target "src/regex.win_o"
55{
56 profile "build"
57 {
58 execute("rm -f src/regex.win_o && touch src/regex.win_o && echo NOT BUILDING REGEX RIGHT NOW!!!");
59 }
60}
61target "src/cachestorefiles.win_o"
62{ 64{
63 profile "build" 65 profile "build"
64 { 66 {
65 execute("rm -f src/cachestorefiles.win_o && touch src/cachestorefiles.win_o && echo NOT BUILDING REGEX RIGHT NOW!!!"); 67 execute("rm -f ${OUTPUT} && touch ${OUTPUT} && echo NOT BUILDING PROCESS RIGHT NOW!!!");
66 } 68 }
67} 69}
68 70
diff --git a/src/experimental/cachestorefiles.h b/src/experimental/cachestorefiles.h
index 10b2c1b..5f94f4c 100644
--- a/src/experimental/cachestorefiles.h
+++ b/src/experimental/cachestorefiles.h
@@ -58,7 +58,11 @@ namespace Bu
58 { 58 {
59 if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) ) 59 if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) )
60 { 60 {
61#ifdef WIN32
62 mkdir( sPrefix.getStr() );
63#else
61 mkdir( sPrefix.getStr(), 0755 ); 64 mkdir( sPrefix.getStr(), 0755 );
65#endif
62 } 66 }
63 } 67 }
64 68
diff --git a/src/stable/process.cpp b/src/stable/process.cpp
index a98936e..92e7086 100644
--- a/src/stable/process.cpp
+++ b/src/stable/process.cpp
@@ -6,23 +6,40 @@
6 */ 6 */
7 7
8#include "bu/process.h" 8#include "bu/process.h"
9#include <sys/types.h>
10#include <sys/wait.h>
11#include <unistd.h> 9#include <unistd.h>
12#include <stdarg.h> 10#include <stdarg.h>
13#include <signal.h> 11
12#ifndef WIN32
13#include <sys/wait.h>
14#include <sys/types.h>
14#include <fcntl.h> 15#include <fcntl.h>
16#include <signal.h>
17#include <sys/select.h>
15#include <errno.h> 18#include <errno.h>
19#else
20#include <windows.h>
21#include <tchar.h>
22#include <wchar.h>
23#endif
16 24
17#include <sys/select.h>
18 25
19#include "bu/config.h" 26#include "bu/config.h"
20 27
21Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : 28Bu::Process::ProcData::ProcData() :
29#ifdef WIN32
30 hStdIn( NULL ),
31 hStdOut( NULL ),
32 hStdErr( NULL )
33#else
22 iStdIn( -1 ), 34 iStdIn( -1 ),
23 iStdOut( -1 ), 35 iStdOut( -1 ),
24 iStdErr( -1 ), 36 iStdErr( -1 )
25 iPid( 0 ), 37#endif
38{
39}
40
41
42Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) :
26 iProcStatus( 0 ), 43 iProcStatus( 0 ),
27 bBlocking( true ), 44 bBlocking( true ),
28 bStdOutEos( true ), 45 bStdOutEos( true ),
@@ -32,10 +49,6 @@ Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) :
32} 49}
33 50
34Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : 51Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) :
35 iStdIn( -1 ),
36 iStdOut( -1 ),
37 iStdErr( -1 ),
38 iPid( 0 ),
39 iProcStatus( 0 ), 52 iProcStatus( 0 ),
40 bBlocking( true ), 53 bBlocking( true ),
41 bStdOutEos( true ), 54 bStdOutEos( true ),
@@ -62,10 +75,6 @@ Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) :
62} 75}
63 76
64Bu::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[] ) :
65 iStdIn( -1 ),
66 iStdOut( -1 ),
67 iStdErr( -1 ),
68 iPid( 0 ),
69 iProcStatus( 0 ), 78 iProcStatus( 0 ),
70 bBlocking( true ), 79 bBlocking( true ),
71 bStdOutEos( true ), 80 bStdOutEos( true ),
@@ -76,10 +85,6 @@ Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char
76} 85}
77 86
78Bu::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, ...) :
79 iStdIn( -1 ),
80 iStdOut( -1 ),
81 iStdErr( -1 ),
82 iPid( 0 ),
83 iProcStatus( 0 ), 88 iProcStatus( 0 ),
84 bBlocking( true ), 89 bBlocking( true ),
85 bStdOutEos( true ), 90 bStdOutEos( true ),
@@ -118,6 +123,102 @@ void Bu::Process::wait()
118 123
119void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) 124void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] )
120{ 125{
126#ifdef WIN32
127 bStdErrEos = true;
128 SECURITY_ATTRIBUTES saAttr;
129 HANDLE hChildStd_IN_Rd;
130 HANDLE hChildStd_IN_Wr;
131 HANDLE hChildStd_OUT_Rd;
132 HANDLE hChildStd_OUT_Wr;
133
134 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
135 saAttr.bInheritHandle = TRUE;
136 saAttr.lpSecurityDescriptor = NULL;
137
138 // Create a pipe for the child process's STDOUT.
139 if ( ! CreatePipe(
140 &hChildStd_OUT_Rd,
141 &hChildStd_OUT_Wr,
142 &saAttr, 0) )
143 throw "StdoutRd CreatePipe";
144
145 // Ensure the read handle to the pipe for STDOUT is not inherited.
146 if ( ! SetHandleInformation(
147 hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
148 throw "Stdout SetHandleInformation";
149
150 // Create a pipe for the child process's STDIN.
151 if (! CreatePipe(
152 &hChildStd_IN_Rd,
153 &hChildStd_IN_Wr,
154 &saAttr, 0))
155 throw "Stdin CreatePipe";
156
157 // Ensure the write handle to the pipe for STDIN is not inherited.
158 if ( ! SetHandleInformation(
159 hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
160 throw "Stdin SetHandleInformation";
161
162 //TCHAR szCmdline[] = TEXT( sName );
163 //PROCESS_INFORMATION pd.piProcInfo;
164 STARTUPINFO siStartInfo;
165 BOOL bSuccess = FALSE;
166
167 // Set up members of the PROCESS_INFORMATION structure.
168 ZeroMemory( &pd.piProcInfo, sizeof(PROCESS_INFORMATION) );
169
170 // Set up members of the STARTUPINFO structure.
171 // This structure specifies the STDIN and STDOUT handles for redirection.
172 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
173 siStartInfo.cb = sizeof(STARTUPINFO);
174 siStartInfo.hStdError = hChildStd_OUT_Wr;
175 siStartInfo.hStdOutput = hChildStd_OUT_Wr;
176 siStartInfo.hStdInput = hChildStd_IN_Rd;
177 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
178
179 Bu::String sCmd;
180 for( char *const *arg = argv; *arg; arg++ )
181 {
182 if( arg != argv )
183 sCmd += " ";
184 sCmd += *arg;
185 }
186
187 // Create the child process.
188 bSuccess = CreateProcessA(
189 sName, //sName, //module name
190 sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line
191 NULL, // process security attributes
192 NULL, // primary thread security attributes
193 TRUE, // handles are inherited
194 CREATE_NO_WINDOW, // creation flags
195 NULL, // use parent's environment
196 NULL, // use parent's current directory
197 &siStartInfo, // STARTUPINFO pointer
198 &pd.piProcInfo ); // receives PROCESS_INFORMATION
199
200 // If an error occurs, exit the application.
201 if ( ! bSuccess )
202 {
203 throw Bu::ExceptionBase("Error spawning child process.");
204 return;
205 }
206 else
207 {
208 // Close handles to the child process and its primary thread.
209 // Some applications might keep these handles to monitor the status
210 // of the child process, for example.
211
212 //CloseHandle(pData->pd.piProcInfo.hProcess);
213 CloseHandle(pd.piProcInfo.hThread);
214
215 // Close the ends we can't use
216 CloseHandle( hChildStd_OUT_Wr );
217 CloseHandle( hChildStd_IN_Rd );
218 pd.hStdIn = hChildStd_IN_Wr;
219 pd.hStdOut = hChildStd_OUT_Rd;
220 }
221#else
121 int iaStdIn[2]; 222 int iaStdIn[2];
122 int iaStdOut[2]; 223 int iaStdOut[2];
123 int iaStdErr[2]; 224 int iaStdErr[2];
@@ -125,22 +226,22 @@ void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] )
125 if( eFlags & StdOut ) 226 if( eFlags & StdOut )
126 { 227 {
127 pipe( iaStdOut ); 228 pipe( iaStdOut );
128 iStdOut = iaStdOut[0]; 229 pd.iStdOut = iaStdOut[0];
129 bStdOutEos = false; 230 bStdOutEos = false;
130 } 231 }
131 if( eFlags & StdErr ) 232 if( eFlags & StdErr )
132 { 233 {
133 pipe( iaStdErr ); 234 pipe( iaStdErr );
134 iStdErr = iaStdErr[0]; 235 pd.iStdErr = iaStdErr[0];
135 bStdErrEos = false; 236 bStdErrEos = false;
136 } 237 }
137 238
138 iStdIn = iaStdIn[1]; 239 pd.iStdIn = iaStdIn[1];
139 240
140// fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); 241// fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK );
141 242
142 iPid = fork(); 243 pd.iPid = fork();
143 if( iPid == 0 ) 244 if( pd.iPid == 0 )
144 { 245 {
145 ::close( iaStdIn[1] ); 246 ::close( iaStdIn[1] );
146 dup2( iaStdIn[0], 0 ); 247 dup2( iaStdIn[0], 0 );
@@ -170,48 +271,97 @@ void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] )
170 ::close( iaStdOut[1] ); 271 ::close( iaStdOut[1] );
171 if( eFlags & StdErr ) 272 if( eFlags & StdErr )
172 ::close( iaStdErr[1] ); 273 ::close( iaStdErr[1] );
274#endif
173} 275}
174 276
175void Bu::Process::close() 277void Bu::Process::close()
176{ 278{
177 if( iPid ) 279#ifdef WIN32
280 if( pd.hStdIn )
281 {
282 CloseHandle( pd.hStdIn );
283 CloseHandle( pd.hStdOut );
284
285 pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL;
286
287 if( !TerminateProcess(pd.piProcInfo.hProcess, 1) )
288 {
289 throw Bu::ExceptionBase("Error closing process.");
290 }
291
292 GetExitCodeProcess( pd.piProcInfo.hProcess, (PDWORD)&iProcStatus );
293
294 CloseHandle( pd.piProcInfo.hProcess );
295 pd.piProcInfo.hProcess = NULL;
296 }
297#else
298 if( pd.iPid )
178 { 299 {
179 if( iStdIn > -1 ) 300 if( pd.iStdIn > -1 )
180 ::close( iStdIn ); 301 ::close( pd.iStdIn );
181 if( iStdOut > -1 ) 302 if( pd.iStdOut > -1 )
182 ::close( iStdOut ); 303 ::close( pd.iStdOut );
183 if( iStdErr > -1 ) 304 if( pd.iStdErr > -1 )
184 ::close( iStdErr ); 305 ::close( pd.iStdErr );
185 waitpid( iPid, &iProcStatus, 0 ); 306 waitpid( pd.iPid, &iProcStatus, 0 );
186 iPid = 0; 307 pd.iPid = 0;
187 } 308 }
309#endif
188} 310}
189 311
190void Bu::Process::closeStdIn() 312void Bu::Process::closeStdIn()
191{ 313{
192 ::close( iStdIn ); 314#ifdef WIN32
193 iStdIn = -1; 315 CloseHandle( pd.hStdIn );
316 pd.hStdIn = NULL;
317#else
318 ::close( pd.iStdIn );
319 pd.iStdIn = -1;
320#endif
194} 321}
195 322
196void Bu::Process::closeStdOut() 323void Bu::Process::closeStdOut()
197{ 324{
198 ::close( iStdOut ); 325#ifdef WIN32
199 iStdOut = -1; 326 CloseHandle( pd.hStdOut );
327 pd.hStdOut = NULL;
328#else
329 ::close( pd.iStdOut );
330 pd.iStdOut = -1;
331#endif
200} 332}
201 333
202Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) 334Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes )
203{ 335{
336#ifdef WIN32
337 DWORD dwRead;
338 DWORD lExitCode;
339 BOOL bSuccess = FALSE;
340 DWORD dwLen = (DWORD) nBytes;
341 bSuccess = ReadFile(
342 pd.hStdOut, (char *) pBuf,
343 dwLen, &dwRead, NULL);
344// if( dwRead < dwLen )
345 {
346 bSuccess = GetExitCodeProcess( pd.piProcInfo.hProcess, &lExitCode );
347 if( lExitCode != STILL_ACTIVE )
348 {
349 bStdOutEos = true;
350 }
351 }
352 return (int32_t) dwRead;
353#else
204 if( bStdOutEos ) 354 if( bStdOutEos )
205 return 0; 355 return 0;
206 fd_set rfds; 356 fd_set rfds;
207 FD_ZERO( &rfds ); 357 FD_ZERO( &rfds );
208 FD_SET( iStdOut, &rfds ); 358 FD_SET( pd.iStdOut, &rfds );
209 struct timeval tv = {0, 0}; 359 struct timeval tv = {0, 0};
210 if( ::bu_select( iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) 360 if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 )
211 throw Bu::ExceptionBase( strerror( errno ) ); 361 throw Bu::ExceptionBase( strerror( errno ) );
212 if( FD_ISSET( iStdOut, &rfds ) || bBlocking ) 362 if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking )
213 { 363 {
214 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( iStdOut, pBuf, nBytes ) ); 364 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) );
215 if( nRead == 0 ) 365 if( nRead == 0 )
216 { 366 {
217 bStdOutEos = true; 367 bStdOutEos = true;
@@ -227,21 +377,33 @@ Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes )
227 return nRead; 377 return nRead;
228 } 378 }
229 return 0; 379 return 0;
380#endif
230} 381}
231 382
232Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) 383Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes )
233{ 384{
385#ifdef WIN32
386 if( !pd.hStdErr )
387 return 0;
388 DWORD dwRead;
389 BOOL bSuccess = FALSE;
390 DWORD dwLen = (DWORD) nBytes;
391 bSuccess = ReadFile(
392 pd.hStdErr, (char *) pBuf,
393 dwLen, &dwRead, NULL);
394 return (int32_t) dwRead;
395#else
234 if( bStdErrEos ) 396 if( bStdErrEos )
235 return 0; 397 return 0;
236 fd_set rfds; 398 fd_set rfds;
237 FD_ZERO( &rfds ); 399 FD_ZERO( &rfds );
238 FD_SET( iStdErr, &rfds ); 400 FD_SET( pd.iStdErr, &rfds );
239 struct timeval tv = {0, 0}; 401 struct timeval tv = {0, 0};
240 if( ::bu_select( iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) 402 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 )
241 throw Bu::ExceptionBase( strerror( errno ) ); 403 throw Bu::ExceptionBase( strerror( errno ) );
242 if( FD_ISSET( iStdErr, &rfds ) || bBlocking ) 404 if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking )
243 { 405 {
244 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( iStdErr, pBuf, nBytes ) ); 406 Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) );
245 if( nRead == 0 ) 407 if( nRead == 0 )
246 { 408 {
247 bStdErrEos = true; 409 bStdErrEos = true;
@@ -257,11 +419,23 @@ Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes )
257 return nRead; 419 return nRead;
258 } 420 }
259 return 0; 421 return 0;
422#endif
260} 423}
261 424
262Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) 425Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes )
263{ 426{
264 return TEMP_FAILURE_RETRY( ::write( iStdIn, pBuf, nBytes ) ); 427#ifdef WIN32
428 DWORD dwWritten;
429 BOOL bSuccess = FALSE;
430 DWORD dwLen = (DWORD) nBytes;
431 bSuccess = WriteFile(
432 pd.hStdIn, (const char *) pBuf,
433 dwLen, &dwWritten, NULL );
434 FlushFileBuffers( pd.hStdIn );
435 return (int32_t) dwWritten;
436#else
437 return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) );
438#endif
265} 439}
266 440
267Bu::size Bu::Process::tell() 441Bu::size Bu::Process::tell()
@@ -283,12 +457,16 @@ void Bu::Process::setPosEnd( Bu::size )
283 457
284bool Bu::Process::isEos() 458bool Bu::Process::isEos()
285{ 459{
286 return (iPid == 0); 460#ifdef WIN32
461 return (pd.piProcInfo.hProcess == NULL);
462#else
463 return (pd.iPid == 0);
464#endif
287} 465}
288 466
289bool Bu::Process::isOpen() 467bool Bu::Process::isOpen()
290{ 468{
291 return (iPid != 0); 469 return !isEos();
292} 470}
293 471
294void Bu::Process::flush() 472void Bu::Process::flush()
@@ -327,21 +505,24 @@ bool Bu::Process::isBlocking()
327 505
328void Bu::Process::setBlocking( bool bBlocking ) 506void Bu::Process::setBlocking( bool bBlocking )
329{ 507{
508#ifdef WIN32
509#else
330 if( bBlocking ) 510 if( bBlocking )
331 { 511 {
332 if( !bStdOutEos ) 512 if( !bStdOutEos )
333 fcntl( iStdOut, F_SETFL, fcntl(iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); 513 fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) );
334 if( !bStdErrEos ) 514 if( !bStdErrEos )
335 fcntl( iStdErr, F_SETFL, fcntl(iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); 515 fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) );
336 } 516 }
337 else 517 else
338 { 518 {
339 if( !bStdOutEos ) 519 if( !bStdOutEos )
340 fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); 520 fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK );
341 if( !bStdErrEos ) 521 if( !bStdErrEos )
342 fcntl( iStdErr, F_SETFL, fcntl( iStdErr, F_GETFL, 0 )|O_NONBLOCK ); 522 fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK );
343 } 523 }
344 this->bBlocking = bBlocking; 524 this->bBlocking = bBlocking;
525#endif
345} 526}
346 527
347void Bu::Process::setSize( Bu::size ) 528void Bu::Process::setSize( Bu::size )
@@ -365,70 +546,107 @@ Bu::String Bu::Process::getLocation() const
365 546
366void Bu::Process::select( bool &bStdOut, bool &bStdErr ) 547void Bu::Process::select( bool &bStdOut, bool &bStdErr )
367{ 548{
549#ifdef WIN32
550#else
368 fd_set rfds; 551 fd_set rfds;
369 FD_ZERO( &rfds ); 552 FD_ZERO( &rfds );
370 if( !bStdOutEos ) 553 if( !bStdOutEos )
371 FD_SET( iStdOut, &rfds ); 554 FD_SET( pd.iStdOut, &rfds );
372 if( !bStdErrEos ) 555 if( !bStdErrEos )
373 FD_SET( iStdErr, &rfds ); 556 FD_SET( pd.iStdErr, &rfds );
374 if( ::bu_select( iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) 557 if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 )
375 throw Bu::ExceptionBase( strerror( errno ) ); 558 throw Bu::ExceptionBase( strerror( errno ) );
376 559
377 if( FD_ISSET( iStdOut, &rfds ) ) 560 if( FD_ISSET( pd.iStdOut, &rfds ) )
378 bStdOut = true; 561 bStdOut = true;
379 else 562 else
380 bStdOut = false; 563 bStdOut = false;
381 564
382 if( FD_ISSET( iStdErr, &rfds ) ) 565 if( FD_ISSET( pd.iStdErr, &rfds ) )
383 bStdErr = true; 566 bStdErr = true;
384 else 567 else
385 bStdErr = false; 568 bStdErr = false;
569#endif
386} 570}
387 571
388bool Bu::Process::isRunning() 572bool Bu::Process::isRunning()
389{ 573{
390 if( waitpid( iPid, NULL, WNOHANG ) == iPid ) 574#ifdef WIN32
575 DWORD lExitCode;
576 GetExitCodeProcess( pd.piProcInfo.hProcess, &lExitCode );
577 if( lExitCode != STILL_ACTIVE )
391 checkClose(); 578 checkClose();
392 return iPid != 0; 579#else
580 if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid )
581 checkClose();
582#endif
583 return isOpen();
393} 584}
394 585
395void Bu::Process::ignoreStdErr() 586void Bu::Process::ignoreStdErr()
396{ 587{
397 if( iStdErr == -1 ) 588#ifdef WIN32
589#else
590 if( pd.iStdErr == -1 )
398 return; 591 return;
399 ::close( iStdErr ); 592 ::close( pd.iStdErr );
400 iStdErr = -1; 593 pd.iStdErr = -1;
401 bStdErrEos = true; 594 bStdErrEos = true;
595#endif
402} 596}
403 597
404pid_t Bu::Process::getPid() 598pid_t Bu::Process::getPid()
405{ 599{
406 return iPid; 600#ifdef WIN32
601 return 0;
602#else
603 return pd.iPid;
604#endif
407} 605}
408 606
409bool Bu::Process::childExited() 607bool Bu::Process::childExited()
410{ 608{
609#ifdef WIN32
610 return pd.piProcInfo.hProcess != NULL;
611#else
411 return WIFEXITED( iProcStatus ); 612 return WIFEXITED( iProcStatus );
613#endif
412} 614}
413 615
414int Bu::Process::childExitStatus() 616int Bu::Process::childExitStatus()
415{ 617{
618#ifdef WIN32
619 return iProcStatus;
620#else
416 return WEXITSTATUS( iProcStatus ); 621 return WEXITSTATUS( iProcStatus );
622#endif
417} 623}
418 624
419bool Bu::Process::childSignaled() 625bool Bu::Process::childSignaled()
420{ 626{
627#ifdef WIN32
628 return false;
629#else
421 return WIFSIGNALED( iProcStatus ); 630 return WIFSIGNALED( iProcStatus );
631#endif
422} 632}
423 633
424int Bu::Process::childSignal() 634int Bu::Process::childSignal()
425{ 635{
636#ifdef WIN32
637 return 0;
638#else
426 return WTERMSIG( iProcStatus ); 639 return WTERMSIG( iProcStatus );
640#endif
427} 641}
428 642
429bool Bu::Process::childCoreDumped() 643bool Bu::Process::childCoreDumped()
430{ 644{
645#ifdef WIN32
646 return false;
647#else
431 return WCOREDUMP( iProcStatus ); 648 return WCOREDUMP( iProcStatus );
649#endif
432} 650}
433 651
434void Bu::Process::checkClose() 652void Bu::Process::checkClose()
@@ -438,4 +656,3 @@ void Bu::Process::checkClose()
438 close(); 656 close();
439 } 657 }
440} 658}
441
diff --git a/src/stable/process.h b/src/stable/process.h
index d6282e0..f010633 100644
--- a/src/stable/process.h
+++ b/src/stable/process.h
@@ -8,6 +8,10 @@
8#ifndef BU_PROCESS_H 8#ifndef BU_PROCESS_H
9#define BU_PROCESS_H 9#define BU_PROCESS_H
10 10
11#ifdef WIN32
12#include <windows.h>
13#endif
14
11#include <stdint.h> 15#include <stdint.h>
12#include <sys/types.h> 16#include <sys/types.h>
13 17
@@ -135,10 +139,23 @@ namespace Bu
135 bool childCoreDumped(); 139 bool childCoreDumped();
136 140
137 private: 141 private:
138 int iStdIn; 142 class ProcData
139 int iStdOut; 143 {
140 int iStdErr; 144 public:
141 pid_t iPid; 145 ProcData();
146#ifdef WIN32
147 void *hStdIn;
148 void *hStdOut;
149 void *hStdErr;
150 PROCESS_INFORMATION piProcInfo;
151#else
152 int iStdIn;
153 int iStdOut;
154 int iStdErr;
155 pid_t iPid;
156#endif
157 };
158 ProcData pd;
142 int iProcStatus; 159 int iProcStatus;
143 bool bBlocking; 160 bool bBlocking;
144 bool bStdOutEos; 161 bool bStdOutEos;