]> git.saurik.com Git - wxWidgets.git/blob - src/os2/utilsexc.cpp
70e7e5a1edf69d70e39e7cdd0ed2d85d030502b0
[wxWidgets.git] / src / os2 / utilsexc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/utilsexec.cpp
3 // Purpose: Various utilities
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/17/99
7 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15 #include "wx/utils.h"
16 #include "wx/app.h"
17 #include "wx/intl.h"
18 #include "wx/log.h"
19 #endif
20
21 #include "wx/process.h"
22
23 #include "wx/os2/private.h"
24
25 #define PURE_32
26 #ifndef __EMX__
27 #include <upm.h>
28 #ifndef __WATCOMC__
29 #include <netcons.h>
30 #include <netbios.h>
31 #endif
32 #endif
33
34 #include <ctype.h>
35 #ifdef __EMX__
36 #include <dirent.h>
37 #endif
38
39 #include <sys/stat.h>
40 #include <io.h>
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <stdarg.h>
47
48
49 // this message is sent when the process we're waiting for terminates
50 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
51
52 #ifndef NO_ERROR
53 # define NO_ERROR 0
54 #endif
55
56 // structure describing the process we're being waiting for
57 struct wxExecuteData
58 {
59 public:
60 ~wxExecuteData()
61 {
62 // cout << "Closing thread: " << endl;
63 DosExit(EXIT_PROCESS, 0);
64 }
65
66 HWND hWnd; // window to send wxWM_PROC_TERMINATED to [not used]
67 RESULTCODES vResultCodes;
68 wxProcess* pHandler;
69 ULONG ulExitCode; // the exit code of the process
70 bool bState; // set to false when the process finishes
71 };
72
73 static ULONG wxExecuteThread(wxExecuteData* pData)
74 {
75 ULONG ulRc;
76 PID vPidChild;
77
78 // cout << "Executing thread: " << endl;
79
80 ulRc = ::DosWaitChild( DCWA_PROCESSTREE
81 ,DCWW_NOWAIT
82 ,&pData->vResultCodes
83 ,&vPidChild
84 ,pData->vResultCodes.codeTerminate // process PID to look at
85 );
86 if (ulRc != NO_ERROR)
87 {
88 wxLogLastError(wxT("DosWaitChild"));
89 }
90 delete pData;
91 return 0;
92 }
93
94 // window procedure of a hidden window which is created just to receive
95 // the notification message when a process exits
96 MRESULT APIENTRY wxExecuteWindowCbk( HWND hWnd,
97 ULONG ulMessage,
98 MPARAM WXUNUSED(wParam),
99 MPARAM lParam)
100 {
101 if (ulMessage == wxWM_PROC_TERMINATED)
102 {
103 wxExecuteData* pData = (wxExecuteData *)lParam;
104
105 if (pData->pHandler)
106 {
107 pData->pHandler->OnTerminate( (int)pData->vResultCodes.codeTerminate
108 ,(int)pData->vResultCodes.codeResult
109 );
110 }
111
112 if (pData->bState)
113 {
114 // we're executing synchronously, tell the waiting thread
115 // that the process finished
116 pData->bState = 0;
117 }
118 else
119 {
120 // asynchronous execution - we should do the clean up
121 delete pData;
122 }
123 ::WinDestroyWindow(hWnd); // we don't need it any more
124 }
125 return 0;
126 }
127
128 long wxExecute( const wxString& rCommand,
129 int flags,
130 wxProcess* pHandler,
131 const wxExecuteEnv *env)
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 ,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
218 long wxExecute(
219 char** ppArgv
220 , int flags
221 , wxProcess* pHandler
222 , const wxExecuteEnv *env
223 )
224 {
225 wxString sCommand;
226
227 while (*ppArgv != NULL)
228 {
229 wxString sArg((wxChar*)(*ppArgv++));
230
231
232 sCommand << sArg.c_str() << ' ';
233 }
234 sCommand.RemoveLast();
235 return wxExecute( sCommand
236 ,flags
237 ,pHandler
238 , env
239 );
240 }
241
242 bool wxGetFullHostName( wxChar* zBuf, int nMaxSize)
243 {
244 return wxGetHostName( zBuf, nMaxSize );
245 }