static int execvp_win32(const char *prog, char **argv) { int ret = spawnvp(P_NOWAIT, prog, (const char *const*)argv); if (-1 == ret) return ret; cwait(&ret, ret, WAIT_CHILD); exit(ret); }
void main() { int process_id; int status; process_id = spawnl( P_NOWAIT, "child.exe", "child", "parm", NULL ); cwait( &status, process_id, WAIT_CHILD ); }
/* wait waits for a process started by fork_exec. * In general, this is called after the complete IO to the called process but * it isn't guaranteed. Never call if you don't expect a sudden death of the * subprocess. * Returns the exit status of the subprocess under normal circumstances. If * the subprocess has died by a signal, the return value is -signalnumber. */ static int Os2_wait(int process) { int rc, retval, status; #ifdef __WATCOMC__ /* * Watcom is strange. EINTR isn't an indicator for a retry of the call. */ status = -1; rc = cwait(&status, process, WAIT_CHILD); if (rc == -1) { if ((status != -1) && (errno == EINTR)) retval = -status; /* Exception reason in lower byte */ else retval = -errno; /* I don't have a better idea */ } else { if (status & 0xFF) retval = -status; /* Exception reason in lower byte */ else retval = status >> 8; } #else do { rc = waitpid(process, &status, 0); } while ((rc == -1) && (errno == EINTR)); if (WIFEXITED(status)) { retval = (int) WEXITSTATUS(status); if ( retval < 0 ) retval = -retval; } else if (WIFSIGNALED(status)) { retval = -WTERMSIG(status); if ( retval > 0 ) retval = -retval; else if ( retval == 0 ) retval = -1; } else { retval = -WSTOPSIG(status); if ( retval > 0 ) retval = -retval; else if ( retval == 0 ) retval = -1; } #endif return(retval); }
/* npflush is called for filter ops effected with temp files */ void npflush(void) { char buf[NFILEN + 128]; int rc, term_status; /* * caller has filled and closed the write pipe data stream. time to * exec a process. */ if ((stdout_fd = open(stdout_name, O_RDONLY|O_BINARY)) == BAD_FD) { /* oh my, put complaint in user's face. */ sprintf(buf, "[unable to open temp file \"%s\": %s]", stdout_name, strerror(errno)); lastditch_msg(buf); } else { /* handles[1-2] were initialized by tmp_npopen_open() */ handles[0] = (HANDLE) _get_osfhandle(stdout_fd); rc = (exec_shell(shcmd, handles, TRUE /* do hide child window */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (! rc) { /* Shell process failed, put complaint in user's face. */ sprintf(buf, SHELL_ERR_MSG, get_shell()); lastditch_msg(buf); } else { /* now wait for app to exit */ (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in npflush\n")); close_proc_handle(); } /* * When closing descriptors shared between parent and child, order * is quite important when $shell == command.com . In this * situation, the descriptors can't be closed until the exec'd * process exits. */ close_fd(stdout_fd); } }
int Process::join(int pid) { int status, result; if(pid == -1) return pid; result = (int)cwait(&status, pid, WAIT_CHILD); if(status & 0x0) return -1; return result; }
static void native_npclose(FILE *fp) { int term_status; (void) fflush(fp); (void) fclose(fp); if (proc_handle != BAD_PROC_HANDLE) { (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in native_npclose\n")); close_proc_handle(); } common_cleanup(); }
static void tmp_npclose(FILE *fp) { char buf[NFILEN + 128]; int rc, term_status; (void) fflush(fp); (void) fclose(fp); if (stdout_fd != BAD_FD) { /* * write pipe, but not a filter. Editor has written data to temp * file, time now to exec "cmd" and hook its stdin to the file. * * It should be noted that exec'ing a process in the npclose() * phase of a write pipe is not exactly keeping in spirit with * the control flow in file.c :-) . However, the strategy used * here ensures that the launched process reads a temp file that * is completey flushed to disk. The only direct drawback with * this approach is that when the exec'd process exits, the user * does not receive a "[press return to continue]" prompt from * file.c . But, cough, we can work around that problem :-) . */ if ((stdout_fd = open(stdout_name, O_RDONLY|O_BINARY)) == BAD_FD) { /* oh my, put complaint in user's face. */ sprintf(buf, "[unable to open temp file \"%s\": %s]", stdout_name, strerror(errno)); lastditch_msg(buf); } else { handles[0] = (HANDLE) _get_osfhandle(stdout_fd); handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE); rc = (exec_shell(shcmd, handles, FALSE /* don't hide child window */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (! rc) { /* Shell process failed, put complaint in user's face. */ sprintf(buf, SHELL_ERR_MSG, get_shell()); lastditch_msg(buf); } else { /* now wait for app to exit */ (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in tmp_npclose\n")); close_proc_handle(); } /* * When closing descriptors shared between parent and child, * order is quite important when $shell == command.com . In * this situation, the descriptors can't be closed until the * exec'd process exits. */ close_fd(stdout_fd); } pressreturn(); /* cough */ sgarbf = TRUE; } tmp_cleanup(); }
static int tmp_inout_popen(FILE **fr, FILE **fw, char *cmd) { char buf[NFILEN + 128]; DWORD dummy, len; int rc, term_status, tmpin_fd; TRACE(("tmp_inout_popen cmd=%s\n", cmd)); proc_handle = BAD_PROC_HANDLE; handles[0] = handles[1] = handles[2] = INVALID_HANDLE_VALUE; tmpin_fd = stdin_fd = stdout_fd = BAD_FD; tmpin_name = stdin_name = stdout_name = NULL; set_console_title(cmd); do { if (fr) { *fr = NULL; if ((stdin_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((stdin_fd = open(stdin_name, O_RDWR|O_CREAT|O_TRUNC|O_TEXT, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } handles[2] = handles[1] = (HANDLE) _get_osfhandle(stdin_fd); if (! fw) { /* * This is a read pipe (only). Connect child's stdin to * an empty file. Under no circumstances should the * child's stdin be connected to a device (else lots of * screwy things will occur). In particular, connecting * the child's stdin to the parent's stdin will cause * aborts and hangs on the various Win32 hosts. You've * been warned. */ if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((tmpin_fd = open(tmpin_name, O_RDONLY|O_CREAT|O_TRUNC, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } handles[0] = (HANDLE) _get_osfhandle(tmpin_fd); } else { /* * Set up descriptor for filter operation. Note the * sublteties here: exec'd shell is passed a descriptor * to the temp file that's opened "w". The editor * receives a descriptor to the file that's opened "r". */ if ((*fr = fopen(stdin_name, "r")) == NULL) break; } } if (fw) { *fw = NULL; /* create a temp file to receive data from the editor */ if ((stdout_name = _tempnam(getenv("TEMP"), "vile")) == NULL) break; if ((stdout_fd = open(stdout_name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, _S_IWRITE|_S_IREAD)) == BAD_FD) { break; } if ((*fw = fdopen(stdout_fd, "w")) == 0) break; /* * we're all set up, but can't exec "cmd" until the editor * writes data to the temp file connected to stdout. */ shcmd = cmd; /* remember this */ return (TRUE); } /* This must be a read (only) pipe. Appropriate to exec "cmd". */ rc = (exec_shell(cmd, handles, TRUE /* hide child wdw */ ) == BAD_PROC_HANDLE) ? FALSE : TRUE; if (! rc) { /* * Shell process failed, put complaint in user's buffer, which * is currently proxied by a temp file that the editor will * suck in shortly. */ len = (DWORD) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf); (void) WriteFile(handles[1], buf, len, &dummy, NULL); FlushFileBuffers(handles[1]); } else { /* wait for exec'd process to exit */ (void) cwait(&term_status, (CWAIT_PARAM_TYPE) proc_handle, 0); TRACE(("...CreateProcess finished waiting in tmp_inout_popen\n")); close_proc_handle(); } /* * When closing descriptors shared between parent and child, order * is quite important when $shell == command.com . In this * situation, the descriptors can't be closed until the exec'd * process exits (I kid you not). */ close_fd(stdin_fd); (void) close(tmpin_fd); /* let the editor consume the output of the read pipe */ if ((*fr = fopen(stdin_name, "r")) == NULL) { /* * impossible to put error in user's buffer since that file * descriptor is closed. */ sprintf(buf, "[error opening temp file \"%s\": %s]", stdin_name, strerror(errno)); lastditch_msg(buf); break; } return (rc); } while (FALSE); /* If we get here -- some operation has failed. Clean up. */ tmp_cleanup(); return (FALSE); }
int hb_fsProcessValue( HB_FHANDLE hProcess, HB_BOOL fWait ) { int iRetStatus = -1; HB_TRACE( HB_TR_DEBUG, ( "hb_fsProcessValue(%p, %d)", ( void * ) ( HB_PTRDIFF ) hProcess, fWait ) ); #if defined( HB_OS_WIN ) { HB_BOOL fError = HB_TRUE; DWORD dwResult; HANDLE hProc = ( HANDLE ) hb_fsGetOsHandle( hProcess ); if( hProc ) { hb_vmUnlock(); dwResult = WaitForSingleObject( hProc, fWait ? INFINITE : 0 ); if( dwResult == WAIT_OBJECT_0 ) { fError = ! GetExitCodeProcess( hProc, &dwResult ); iRetStatus = ! fError ? ( int ) dwResult : -2; } hb_fsSetIOError( ! fError, 0 ); if( ! fError ) CloseHandle( hProc ); hb_vmLock(); } else hb_fsSetError( ( HB_ERRCODE ) FS_ERROR ); } #elif defined( HB_OS_UNIX ) || ( defined( HB_OS_OS2 ) && defined( __GNUC__ ) ) { int iStatus; pid_t pid = ( pid_t ) hProcess; if( pid > 0 ) { hb_vmUnlock(); iRetStatus = waitpid( pid, &iStatus, fWait ? 0 : WNOHANG ); hb_fsSetIOError( iRetStatus >= 0, 0 ); #ifdef ERESTARTSYS if( iRetStatus < 0 && hb_fsOsError() != ( HB_ERRCODE ) ERESTARTSYS ) #else if( iRetStatus < 0 ) #endif iRetStatus = -2; else if( iRetStatus == 0 ) iRetStatus = -1; else iRetStatus = WIFEXITED( iStatus ) ? WEXITSTATUS( iStatus ) : 0; hb_vmLock(); } else hb_fsSetError( ( HB_ERRCODE ) FS_ERROR ); } #elif defined( HB_OS_OS2 ) { PID pid = ( PID ) hProcess; if( pid > 0 ) { RESULTCODES resultCodes = { 0, 0 }; APIRET ret; ret = DosWaitChild( DCWA_PROCESS, fWait ? DCWW_WAIT : DCWW_NOWAIT, &resultCodes, &pid, pid ); hb_fsSetIOError( ret == NO_ERROR, 0 ); if( ret == NO_ERROR ) iRetStatus = resultCodes.codeResult; else iRetStatus = -2; } else hb_fsSetError( ( HB_ERRCODE ) FS_ERROR ); } #elif defined( HB_OS_OS2 ) || defined( HB_OS_WIN ) { int iPid = ( int ) hProcess; HB_SYMBOL_UNUSED( fWait ); if( iPid > 0 ) { hb_vmUnlock(); #if defined( __BORLANDC__ ) iPid = cwait( &iRetStatus, iPid, 0 ); #else iPid = _cwait( &iRetStatus, iPid, 0 ); #endif hb_fsSetIOError( iPid > 0, 0 ); if( iPid != ( int ) hProcess ) iRetStatus = -1; hb_vmLock(); } else hb_fsSetError( ( HB_ERRCODE ) FS_ERROR ); } #else { int iTODO; /* TODO: for given platform */ HB_SYMBOL_UNUSED( hProcess ); HB_SYMBOL_UNUSED( fWait ); hb_fsSetError( ( HB_ERRCODE ) FS_ERROR ); } #endif return iRetStatus; }
_WCRTLINK int wait( int *status ) { return( cwait( status, 0, 0 ) ); }