diff options
Diffstat (limited to '')
| -rw-r--r-- | mingw.bld | 44 | ||||
| -rw-r--r-- | src/experimental/cachestorefiles.h | 4 | ||||
| -rw-r--r-- | src/stable/process.cpp | 347 | ||||
| -rw-r--r-- | src/stable/process.h | 25 |
4 files changed, 330 insertions, 90 deletions
| @@ -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 | ||
| 19 | target files("src/*.h").replace("src/", "bu/") | 19 | for 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 | } | ||
| 33 | target 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 | } |
| 29 | target files("src/compat/*.h").replace("src/", "bu/") | 43 | target ["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 | ||
| 40 | target "libbu++win.a" | 55 | target "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 | ||
| 47 | target ["src/process.win_o", "src/lzma.win_o"] | 63 | target ["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 | } | ||
| 54 | target "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 | } | ||
| 61 | target "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 | ||
| 21 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | 28 | Bu::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 | |||
| 42 | Bu::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 | ||
| 34 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : | 51 | Bu::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 | ||
| 64 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : | 77 | Bu::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 | ||
| 78 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : | 87 | Bu::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 | ||
| 119 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | 124 | void 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 | ||
| 175 | void Bu::Process::close() | 277 | void 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 | ||
| 190 | void Bu::Process::closeStdIn() | 312 | void 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 | ||
| 196 | void Bu::Process::closeStdOut() | 323 | void 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 | ||
| 202 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) | 334 | Bu::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 | ||
| 232 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) | 383 | Bu::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 | ||
| 262 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) | 425 | Bu::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 | ||
| 267 | Bu::size Bu::Process::tell() | 441 | Bu::size Bu::Process::tell() |
| @@ -283,12 +457,16 @@ void Bu::Process::setPosEnd( Bu::size ) | |||
| 283 | 457 | ||
| 284 | bool Bu::Process::isEos() | 458 | bool 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 | ||
| 289 | bool Bu::Process::isOpen() | 467 | bool Bu::Process::isOpen() |
| 290 | { | 468 | { |
| 291 | return (iPid != 0); | 469 | return !isEos(); |
| 292 | } | 470 | } |
| 293 | 471 | ||
| 294 | void Bu::Process::flush() | 472 | void Bu::Process::flush() |
| @@ -327,21 +505,24 @@ bool Bu::Process::isBlocking() | |||
| 327 | 505 | ||
| 328 | void Bu::Process::setBlocking( bool bBlocking ) | 506 | void 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 | ||
| 347 | void Bu::Process::setSize( Bu::size ) | 528 | void Bu::Process::setSize( Bu::size ) |
| @@ -365,70 +546,107 @@ Bu::String Bu::Process::getLocation() const | |||
| 365 | 546 | ||
| 366 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) | 547 | void 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 | ||
| 388 | bool Bu::Process::isRunning() | 572 | bool 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 | ||
| 395 | void Bu::Process::ignoreStdErr() | 586 | void 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 | ||
| 404 | pid_t Bu::Process::getPid() | 598 | pid_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 | ||
| 409 | bool Bu::Process::childExited() | 607 | bool 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 | ||
| 414 | int Bu::Process::childExitStatus() | 616 | int 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 | ||
| 419 | bool Bu::Process::childSignaled() | 625 | bool 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 | ||
| 424 | int Bu::Process::childSignal() | 634 | int 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 | ||
| 429 | bool Bu::Process::childCoreDumped() | 643 | bool 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 | ||
| 434 | void Bu::Process::checkClose() | 652 | void 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; |
