]>
Commit | Line | Data |
---|---|---|
0e320a79 DW |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: utilsexec.cpp | |
d90895ac DW |
3 | // Purpose: Various utilities |
4 | // Author: David Webster | |
0e320a79 | 5 | // Modified by: |
d90895ac | 6 | // Created: 10/17/99 |
0e320a79 | 7 | // RCS-ID: $Id$ |
d90895ac DW |
8 | // Copyright: (c) David Webster |
9 | // Licence: wxWindows license | |
0e320a79 DW |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
d90895ac DW |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
0e320a79 | 14 | |
d90895ac DW |
15 | #ifndef WX_PRECOMP |
16 | #include "wx/setup.h" | |
0e320a79 | 17 | #include "wx/utils.h" |
d90895ac DW |
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 | ||
d90895ac DW |
28 | #include <ctype.h> |
29 | #include <direct.h> | |
30 | ||
31 | #include <sys/stat.h> | |
32 | #include <io.h> | |
0e320a79 DW |
33 | |
34 | #include <stdio.h> | |
35 | #include <stdlib.h> | |
36 | #include <string.h> | |
d90895ac DW |
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 | ||
dde11e60 DW |
43 | #ifndef NO_ERROR |
44 | # define NO_ERROR 0 | |
45 | #endif | |
46 | ||
d90895ac DW |
47 | // structure describing the process we're being waiting for |
48 | struct wxExecuteData | |
49 | { | |
50 | public: | |
51 | ~wxExecuteData() | |
52 | { | |
dde11e60 | 53 | DosExit(EXIT_PROCESS, 0); |
d90895ac DW |
54 | } |
55 | ||
dde11e60 DW |
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 | |
d90895ac DW |
61 | }; |
62 | ||
dde11e60 DW |
63 | static ULONG wxExecuteThread( |
64 | wxExecuteData* pData | |
65 | ) | |
d90895ac | 66 | { |
dde11e60 DW |
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) | |
d90895ac | 77 | { |
dde11e60 | 78 | wxLogLastError("DosWaitChild"); |
d90895ac | 79 | } |
dde11e60 | 80 | delete pData; |
d90895ac | 81 | |
d90895ac | 82 | |
dde11e60 | 83 | // ::WinSendMsg(pData->hWnd, (ULONG)wxWM_PROC_TERMINATED, 0, (MPARAM)pData); |
d90895ac DW |
84 | return 0; |
85 | } | |
86 | ||
dde11e60 DW |
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 | ) | |
d90895ac | 95 | { |
dde11e60 | 96 | if (ulMessage == wxWM_PROC_TERMINATED) |
d90895ac | 97 | { |
dde11e60 | 98 | wxExecuteData* pData = (wxExecuteData *)lParam; |
d90895ac | 99 | |
dde11e60 | 100 | if (pData->pHandler) |
d90895ac | 101 | { |
dde11e60 DW |
102 | pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate |
103 | ,(int)pData->vResultCodes.codeResult | |
104 | ); | |
d90895ac DW |
105 | } |
106 | ||
dde11e60 | 107 | if (pData->bState) |
d90895ac DW |
108 | { |
109 | // we're executing synchronously, tell the waiting thread | |
110 | // that the process finished | |
dde11e60 | 111 | pData->bState = 0; |
d90895ac DW |
112 | } |
113 | else | |
114 | { | |
115 | // asynchronous execution - we should do the clean up | |
dde11e60 | 116 | delete pData; |
d90895ac | 117 | } |
dde11e60 | 118 | ::WinDestroyWindow(hWnd); // we don't need it any more |
d90895ac | 119 | } |
d90895ac DW |
120 | return 0; |
121 | } | |
122 | ||
123 | extern wxChar wxPanelClassName[]; | |
0e320a79 | 124 | |
dde11e60 DW |
125 | long wxExecute( |
126 | const wxString& rCommand | |
127 | , bool bSync | |
128 | , wxProcess* pHandler | |
129 | ) | |
0e320a79 | 130 | { |
dde11e60 | 131 | wxCHECK_MSG(!!rCommand, 0, wxT("empty command in wxExecute")); |
d90895ac DW |
132 | |
133 | // create the process | |
dde11e60 DW |
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 | )) | |
d90895ac | 157 | { |
dde11e60 | 158 | wxLogSysError(_("Execution of command '%s' failed"), rCommand.c_str()); |
d90895ac DW |
159 | return 0; |
160 | } | |
161 | ||
dde11e60 DW |
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 | ); | |
d90895ac | 178 | wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); |
dde11e60 | 179 | pOldProc = ::WinSubclassWindow(hwnd, (PFNWP)&wxExecuteWindowCbk); |
d90895ac | 180 | |
dde11e60 | 181 | */ |
d90895ac | 182 | // Alloc data |
dde11e60 | 183 | wxExecuteData* pData = new wxExecuteData; |
d90895ac | 184 | |
dde11e60 DW |
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; | |
d90895ac DW |
192 | } |
193 | else | |
194 | { | |
195 | // may be NULL or not | |
dde11e60 | 196 | pData->pHandler = pHandler; |
d90895ac DW |
197 | } |
198 | ||
dde11e60 DW |
199 | rc = ::DosCreateThread( &vTID |
200 | ,(PFNTHREAD)&wxExecuteThread | |
201 | ,(ULONG)pData | |
202 | ,CREATE_READY|STACK_SPARSE | |
203 | ,8192 | |
204 | ); | |
205 | if (rc != NO_ERROR) | |
d90895ac DW |
206 | { |
207 | wxLogLastError("CreateThread in wxExecute"); | |
208 | ||
dde11e60 DW |
209 | // ::WinDestroyWindow(hwnd); |
210 | delete pData; | |
d90895ac DW |
211 | |
212 | // the process still started up successfully... | |
dde11e60 | 213 | return vResultCodes.codeTerminate; |
d90895ac | 214 | } |
dde11e60 | 215 | if (!bSync) |
d90895ac DW |
216 | { |
217 | // clean up will be done when the process terminates | |
218 | ||
219 | // return the pid | |
dde11e60 | 220 | return vResultCodes.codeTerminate; |
d90895ac | 221 | } |
dde11e60 | 222 | ::DosWaitThread(&vTID, DCWW_WAIT); |
d90895ac | 223 | |
dde11e60 DW |
224 | ULONG ulExitCode = pData->vResultCodes.codeResult; |
225 | delete pData; | |
d90895ac DW |
226 | |
227 | // return the exit code | |
dde11e60 | 228 | return (long)ulExitCode; |
0e320a79 | 229 | } |
d90895ac | 230 | |
dde11e60 DW |
231 | long wxExecute( |
232 | char** ppArgv | |
233 | , bool bSync | |
234 | , wxProcess* pHandler | |
235 | ) | |
d90895ac | 236 | { |
dde11e60 | 237 | wxString sCommand; |
d90895ac | 238 | |
dde11e60 | 239 | while (*ppArgv != NULL) |
d90895ac | 240 | { |
dde11e60 | 241 | sCommand << *ppArgv++ << ' '; |
d90895ac | 242 | } |
dde11e60 DW |
243 | sCommand.RemoveLast(); |
244 | return wxExecute( sCommand | |
245 | ,bSync | |
246 | ,pHandler | |
247 | ); | |
d90895ac DW |
248 | } |
249 | ||
dde11e60 DW |
250 | bool wxGetFullHostName( |
251 | wxChar* zBuf | |
252 | , int nMaxSize | |
253 | ) | |
d90895ac | 254 | { |
dde11e60 DW |
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; | |
d90895ac DW |
276 | return TRUE; |
277 | } | |
278 |