Execution control stuff
[wxWidgets.git] / src / os2 / utilsexc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: utilsexec.cpp
3 // Purpose: Various utilities
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/17/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/setup.h"
17 #include "wx/utils.h"
18 #include "wx/app.h"
19 #include "wx/intl.h"
20 #endif
21
22 #include "wx/log.h"
23
24 #include "wx/process.h"
25
26 #include "wx/os2/private.h"
27
28 #include <ctype.h>
29 #include <direct.h>
30
31 #include <sys/stat.h>
32 #include <io.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <stdarg.h>
39
40 // this message is sent when the process we're waiting for terminates
41 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
42
43 #ifndef NO_ERROR
44 # define NO_ERROR 0
45 #endif
46
47 // structure describing the process we're being waiting for
48 struct wxExecuteData
49 {
50 public:
51 ~wxExecuteData()
52 {
53 DosExit(EXIT_PROCESS, 0);
54 }
55
56 HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used]
57 RESULTCODES vResultCodes;
58 wxProcess* pHandler;
59 ULONG ulExitCode; // the exit code of the process
60 bool bState; // set to FALSE when the process finishes
61 };
62
63 static ULONG wxExecuteThread(
64 wxExecuteData* pData
65 )
66 {
67 ULONG ulRc;
68 PID vPidChild;
69
70 ulRc = ::DosWaitChild( DCWA_PROCESSTREE
71 ,DCWW_WAIT
72 ,&pData->vResultCodes
73 ,&vPidChild
74 ,pData->vResultCodes.codeTerminate // process PID to look at
75 );
76 if (ulRc != NO_ERROR)
77 {
78 wxLogLastError("DosWaitChild");
79 }
80 delete pData;
81
82
83 // ::WinSendMsg(pData->hWnd, (ULONG)wxWM_PROC_TERMINATED, 0, (MPARAM)pData);
84 return 0;
85 }
86
87 // Unlike windows where everything needs a window, console apps in OS/2
88 // need no windows so this is not ever used
89 MRESULT APIENTRY wxExecuteWindowCbk(
90 HWND hWnd
91 , ULONG ulMessage
92 , MPARAM wParam
93 , MPARAM lParam
94 )
95 {
96 if (ulMessage == wxWM_PROC_TERMINATED)
97 {
98 wxExecuteData* pData = (wxExecuteData *)lParam;
99
100 if (pData->pHandler)
101 {
102 pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate
103 ,(int)pData->vResultCodes.codeResult
104 );
105 }
106
107 if (pData->bState)
108 {
109 // we're executing synchronously, tell the waiting thread
110 // that the process finished
111 pData->bState = 0;
112 }
113 else
114 {
115 // asynchronous execution - we should do the clean up
116 delete pData;
117 }
118 ::WinDestroyWindow(hWnd); // we don't need it any more
119 }
120 return 0;
121 }
122
123 extern wxChar wxPanelClassName[];
124
125 long wxExecute(
126 const wxString& rCommand
127 , bool bSync
128 , wxProcess* pHandler
129 )
130 {
131 wxCHECK_MSG(!!rCommand, 0, wxT("empty command in wxExecute"));
132
133 // create the process
134 UCHAR vLoadError[CCHMAXPATH] = {0};
135 RESULTCODES vResultCodes = {0};
136 ULONG ulExecFlag;
137 PSZ zArgs = NULL;
138 PSZ zEnvs = NULL;
139 ULONG ulWindowId;
140 APIRET rc;
141 PFNWP pOldProc;
142 TID vTID;
143
144 if (bSync)
145 ulExecFlag = EXEC_SYNC;
146 else
147 ulExecFlag = EXEC_ASYNCRESULT;
148
149 if (::DosExecPgm( (PCHAR)vLoadError
150 ,sizeof(vLoadError)
151 ,ulExecFlag
152 ,zArgs
153 ,zEnvs
154 ,&vResultCodes
155 ,rCommand
156 ))
157 {
158 wxLogSysError(_("Execution of command '%s' failed"), rCommand.c_str());
159 return 0;
160 }
161
162 // PM does not need non visible object windows to run console child processes
163 /*
164 HWND hwnd = ::WinCreateWindow( HWND_DESKTOP
165 ,wxPanelClassName
166 ,NULL
167 ,0
168 ,0
169 ,0
170 ,0
171 ,0
172 ,NULLHANDLE
173 ,NULLHANDLE
174 ,ulWindowId
175 ,NULL
176 ,NULL
177 );
178 wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
179 pOldProc = ::WinSubclassWindow(hwnd, (PFNWP)&wxExecuteWindowCbk);
180
181 */
182 // Alloc data
183 wxExecuteData* pData = new wxExecuteData;
184
185 pData->vResultCodes = vResultCodes;
186 pData->hWnd = NULLHANDLE;
187 pData->bState = bSync;
188 if (bSync)
189 {
190 wxASSERT_MSG(!pHandler, wxT("wxProcess param ignored for sync execution"));
191 pData->pHandler = NULL;
192 }
193 else
194 {
195 // may be NULL or not
196 pData->pHandler = pHandler;
197 }
198
199 rc = ::DosCreateThread( &vTID
200 ,(PFNTHREAD)&wxExecuteThread
201 ,(ULONG)pData
202 ,CREATE_READY|STACK_SPARSE
203 ,8192
204 );
205 if (rc != NO_ERROR)
206 {
207 wxLogLastError("CreateThread in wxExecute");
208
209 // ::WinDestroyWindow(hwnd);
210 delete pData;
211
212 // the process still started up successfully...
213 return vResultCodes.codeTerminate;
214 }
215 if (!bSync)
216 {
217 // clean up will be done when the process terminates
218
219 // return the pid
220 return vResultCodes.codeTerminate;
221 }
222 ::DosWaitThread(&vTID, DCWW_WAIT);
223
224 ULONG ulExitCode = pData->vResultCodes.codeResult;
225 delete pData;
226
227 // return the exit code
228 return (long)ulExitCode;
229 }
230
231 long wxExecute(
232 char** ppArgv
233 , bool bSync
234 , wxProcess* pHandler
235 )
236 {
237 wxString sCommand;
238
239 while (*ppArgv != NULL)
240 {
241 sCommand << *ppArgv++ << ' ';
242 }
243 sCommand.RemoveLast();
244 return wxExecute( sCommand
245 ,bSync
246 ,pHandler
247 );
248 }
249
250 bool wxGetFullHostName(
251 wxChar* zBuf
252 , int nMaxSize
253 )
254 {
255 #if wxUSE_NET_API
256 char zServer[256];
257 char zComputer[256];
258 unsigned short nLevel = 0;
259 unsigned char* zBuffer;
260 unsigned short nBuffer;
261 unsigned short* pnTotalAvail;
262
263 NetBios32GetInfo( (const unsigned char*)zServer
264 ,(const unsigned char*)zComputer
265 ,nLevel
266 ,zBuffer
267 ,nBuffer
268 ,pnTotalAvail
269 );
270 strncpy(zBuf, zComputer, nMaxSize);
271 zBuf[nMaxSize] = _T('\0');
272 #else
273 strcpy(zBuf, "noname");
274 #endif
275 return *zBuf ? TRUE : FALSE;
276 return TRUE;
277 }
278