1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/utilsexec.cpp 3// Purpose: Various utilities 4// Author: David Webster 5// Modified by: 6// Created: 10/17/99 7// RCS-ID: $Id: utilsexc.cpp 38920 2006-04-26 08:21:31Z ABX $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifndef WX_PRECOMP 16 #include "wx/utils.h" 17 #include "wx/app.h" 18 #include "wx/intl.h" 19 #include "wx/log.h" 20#endif 21 22#include "wx/process.h" 23 24#include "wx/os2/private.h" 25 26#define PURE_32 27#ifndef __EMX__ 28 #include <upm.h> 29 #ifndef __WATCOMC__ 30 #include <netcons.h> 31 #include <netbios.h> 32 #endif 33#endif 34 35#include <ctype.h> 36#ifdef __EMX__ 37#include <dirent.h> 38#endif 39 40#include <sys/stat.h> 41#include <io.h> 42 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <errno.h> 47#include <stdarg.h> 48 49 50// this message is sent when the process we're waiting for terminates 51#define wxWM_PROC_TERMINATED (WM_USER + 10000) 52 53#ifndef NO_ERROR 54# define NO_ERROR 0 55#endif 56 57// structure describing the process we're being waiting for 58struct wxExecuteData 59{ 60public: 61 ~wxExecuteData() 62 { 63// cout << "Closing thread: " << endl; 64 DosExit(EXIT_PROCESS, 0); 65 } 66 67 HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used] 68 RESULTCODES vResultCodes; 69 wxProcess* pHandler; 70 ULONG ulExitCode; // the exit code of the process 71 bool bState; // set to false when the process finishes 72}; 73 74static ULONG wxExecuteThread(wxExecuteData* pData) 75{ 76 ULONG ulRc; 77 PID vPidChild; 78 79// cout << "Executing thread: " << endl; 80 81 ulRc = ::DosWaitChild( DCWA_PROCESSTREE 82 ,DCWW_NOWAIT 83 ,&pData->vResultCodes 84 ,&vPidChild 85 ,pData->vResultCodes.codeTerminate // process PID to look at 86 ); 87 if (ulRc != NO_ERROR) 88 { 89 wxLogLastError(wxT("DosWaitChild")); 90 } 91 delete pData; 92 return 0; 93} 94 95// window procedure of a hidden window which is created just to receive 96// the notification message when a process exits 97MRESULT APIENTRY wxExecuteWindowCbk( HWND hWnd, 98 ULONG ulMessage, 99 MPARAM WXUNUSED(wParam), 100 MPARAM lParam) 101{ 102 if (ulMessage == wxWM_PROC_TERMINATED) 103 { 104 wxExecuteData* pData = (wxExecuteData *)lParam; 105 106 if (pData->pHandler) 107 { 108 pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate 109 ,(int)pData->vResultCodes.codeResult 110 ); 111 } 112 113 if (pData->bState) 114 { 115 // we're executing synchronously, tell the waiting thread 116 // that the process finished 117 pData->bState = 0; 118 } 119 else 120 { 121 // asynchronous execution - we should do the clean up 122 delete pData; 123 } 124 ::WinDestroyWindow(hWnd); // we don't need it any more 125 } 126 return 0; 127} 128 129long wxExecute( const wxString& rCommand, 130 int flags, 131 wxProcess* pHandler) 132{ 133 if (rCommand.empty()) 134 { 135// cout << "empty command in wxExecute." << endl; 136 return 0; 137 } 138 139 // create the process 140 UCHAR vLoadError[CCHMAXPATH] = {0}; 141 RESULTCODES vResultCodes = {0}; 142 ULONG ulExecFlag; 143 PSZ zArgs = NULL; 144 PSZ zEnvs = NULL; 145 APIRET rc; 146 TID vTID; 147 148 if (flags & wxEXEC_SYNC) 149 ulExecFlag = EXEC_SYNC; 150 else 151 ulExecFlag = EXEC_ASYNCRESULT; 152 153 rc = ::DosExecPgm( (PCHAR)vLoadError 154 ,sizeof(vLoadError) 155 ,ulExecFlag 156 ,zArgs 157 ,zEnvs 158 ,&vResultCodes 159 ,(PSZ)rCommand.c_str() 160 ); 161 if (rc != NO_ERROR) 162 { 163 wxLogSysError(_("Execution of command '%s' failed with error: %ul"), rCommand.c_str(), rc); 164 return 0; 165 } 166// cout << "Executing: " << rCommand.c_str() << endl; 167 // Alloc data 168 wxExecuteData* pData = new wxExecuteData; 169 170 pData->vResultCodes = vResultCodes; 171 pData->hWnd = NULLHANDLE; 172 pData->bState = (flags & wxEXEC_SYNC) != 0; 173 if (flags & wxEXEC_SYNC) 174 { 175 wxASSERT_MSG(!pHandler, wxT("wxProcess param ignored for sync execution")); 176 pData->pHandler = NULL; 177 } 178 else 179 { 180 // may be NULL or not 181 pData->pHandler = pHandler; 182 } 183 184 rc = ::DosCreateThread( &vTID 185 ,(PFNTHREAD)&wxExecuteThread 186 ,(ULONG)pData 187 ,CREATE_READY|STACK_SPARSE 188 ,8192 189 ); 190 if (rc != NO_ERROR) 191 { 192 wxLogLastError(wxT("CreateThread in wxExecute")); 193 delete pData; 194 195 // the process still started up successfully... 196 return vResultCodes.codeTerminate; 197 } 198 if (!(flags & wxEXEC_SYNC)) 199 { 200 // return the pid 201 // warning: don't exit your app unless you actively 202 // kill and cleanup you child processes 203 // Maybe detach the process here??? 204 // If cmd.exe need to pass DETACH to detach the process here 205 return vResultCodes.codeTerminate; 206 } 207 208 // waiting until command executed 209 ::DosWaitThread(&vTID, DCWW_WAIT); 210 211 ULONG ulExitCode = pData->vResultCodes.codeResult; 212 delete pData; 213 214 // return the exit code 215 return (long)ulExitCode; 216} 217 218long wxExecute( 219 char** ppArgv 220, int flags 221, wxProcess* pHandler 222) 223{ 224 wxString sCommand; 225 226 while (*ppArgv != NULL) 227 { 228 wxString sArg((wxChar*)(*ppArgv++)); 229 230 231 sCommand << sArg.c_str() << ' '; 232 } 233 sCommand.RemoveLast(); 234 return wxExecute( sCommand 235 ,flags 236 ,pHandler 237 ); 238} 239 240bool wxGetFullHostName( wxChar* zBuf, int nMaxSize) 241{ 242 return wxGetHostName( zBuf, nMaxSize ); 243} 244