source: trunk/src/msvcrt/process.c@ 9633

Last change on this file since 9633 was 9633, checked in by sandervl, 23 years ago

PF: Msvcrt Wine port with GCC

File size: 11.1 KB
Line 
1/*
2 * msvcrt.dll spawn/exec functions
3 *
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 * FIXME:
24 * -File handles need some special handling. Sometimes children get
25 * open file handles, sometimes not. The docs are confusing
26 * -No check for maximum path/argument/environment size is done
27 */
28#ifdef __WIN32OS2__
29#include <emxheader.h>
30#else
31#include "config.h"
32#endif
33
34#include <stdarg.h>
35
36#include "msvcrt.h"
37#include "msvcrt/errno.h"
38
39#include "msvcrt/process.h"
40#include "msvcrt/stdlib.h"
41#include "msvcrt/string.h"
42
43#include "wine/debug.h"
44
45WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
46
47/* FIXME: Check file extensions for app to run */
48static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
49static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
50static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
51static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
52
53/* INTERNAL: Spawn a child process */
54static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
55{
56 STARTUPINFOA si;
57 PROCESS_INFORMATION pi;
58
59 if (sizeof(HANDLE) != sizeof(int))
60 WARN("This call is unsuitable for your architecture\n");
61
62 if ((unsigned)flags > _P_DETACH)
63 {
64 *MSVCRT__errno() = MSVCRT_EINVAL;
65 return -1;
66 }
67
68 FIXME(":must dup/kill streams for child process\n");
69
70 memset(&si, 0, sizeof(si));
71 si.cb = sizeof(si);
72
73 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
74 flags == _P_DETACH ? DETACHED_PROCESS : 0,
75 env, NULL, &si, &pi))
76 {
77 MSVCRT__set_errno(GetLastError());
78 return -1;
79 }
80
81 switch(flags)
82 {
83 case _P_WAIT:
84 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
85 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
86 CloseHandle(pi.hProcess);
87 CloseHandle(pi.hThread);
88 return (int)pi.dwProcessId;
89 case _P_DETACH:
90 CloseHandle(pi.hProcess);
91 pi.hProcess = 0;
92 /* fall through */
93 case _P_NOWAIT:
94 case _P_NOWAITO:
95 CloseHandle(pi.hThread);
96 return (int)pi.hProcess;
97 case _P_OVERLAY:
98 MSVCRT__exit(0);
99 }
100 return -1; /* can't reach here */
101}
102
103/* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
104 * extra '\0' to terminate it
105 */
106static char* msvcrt_argvtos(const char* const* arg, char delim)
107{
108 const char* const* a;
109 long size;
110 char* p;
111 char* ret;
112
113 if (!arg && !delim)
114 {
115 /* Return NULL for an empty environment list */
116 return NULL;
117 }
118
119 /* get length */
120 a = arg;
121 size = 0;
122 while (*a)
123 {
124 size += strlen(*a) + 1;
125 a++;
126 }
127
128 ret = (char*)MSVCRT_malloc(size + 1);
129 if (!ret)
130 return NULL;
131
132 /* fill string */
133 a = arg;
134 p = ret;
135 while (*a)
136 {
137 int len = strlen(*a);
138 memcpy(p,*a,len);
139 p += len;
140 *p++ = delim;
141 a++;
142 }
143 if (delim && p > ret) p[-1] = 0;
144 else *p = 0;
145 return ret;
146}
147
148/* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
149 * extra '\0' to terminate it
150 */
151static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
152{
153 va_list alist2;
154 long size;
155 const char *arg;
156 char* p;
157 char *ret;
158
159#if HAVE_VA_COPY
160 va_copy(alist2,alist);
161#else
162# if HAVE___VA_COPY
163 __va_copy(alist2,alist);
164# else
165 alist2 = alist;
166# endif
167#endif
168
169 if (!arg0 && !delim)
170 {
171 /* Return NULL for an empty environment list */
172 return NULL;
173 }
174
175 /* get length */
176 arg = arg0;
177 size = 0;
178 do {
179 size += strlen(arg) + 1;
180 arg = va_arg(alist, char*);
181 } while (arg != NULL);
182
183 ret = (char*)MSVCRT_malloc(size + 1);
184 if (!ret)
185 return NULL;
186
187 /* fill string */
188 arg = arg0;
189 p = ret;
190 do {
191 int len = strlen(arg);
192 memcpy(p,arg,len);
193 p += len;
194 *p++ = delim;
195 arg = va_arg(alist2, char*);
196 } while (arg != NULL);
197 if (delim && p > ret) p[-1] = 0;
198 else *p = 0;
199 return ret;
200}
201
202/*********************************************************************
203 * _cwait (MSVCRT.@)
204 */
205int _cwait(int *status, int pid, int action)
206{
207 HANDLE hPid = (HANDLE)pid;
208 int doserrno;
209
210 action = action; /* Remove warning */
211
212 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
213 {
214 if (status)
215 {
216 DWORD stat;
217 GetExitCodeProcess(hPid, &stat);
218 *status = (int)stat;
219 }
220 return (int)pid;
221 }
222 doserrno = GetLastError();
223
224 if (doserrno == ERROR_INVALID_HANDLE)
225 {
226 *MSVCRT__errno() = MSVCRT_ECHILD;
227 *__doserrno() = doserrno;
228 }
229 else
230 MSVCRT__set_errno(doserrno);
231
232 return status ? *status = -1 : -1;
233}
234
235/*********************************************************************
236 * _execl (MSVCRT.@)
237 *
238 * Like on Windows, this function does not handle arguments with spaces
239 * or double-quotes.
240 */
241int _execl(const char* name, const char* arg0, ...)
242{
243 va_list ap;
244 char * args;
245 int ret;
246
247 va_start(ap, arg0);
248 args = msvcrt_valisttos(arg0, ap, ' ');
249 va_end(ap);
250
251 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
252 MSVCRT_free(args);
253
254 return ret;
255}
256
257/*********************************************************************
258 * _execlp (MSVCRT.@)
259 *
260 * Like on Windows, this function does not handle arguments with spaces
261 * or double-quotes.
262 */
263int _execlp(const char* name, const char* arg0, ...)
264{
265 va_list ap;
266 char * args;
267 int ret;
268 char fullname[MAX_PATH];
269
270 _searchenv(name, "PATH", fullname);
271
272 va_start(ap, arg0);
273 args = msvcrt_valisttos(arg0, ap, ' ');
274 va_end(ap);
275
276 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
277 MSVCRT_free(args);
278
279 return ret;
280}
281
282/*********************************************************************
283 * _execv (MSVCRT.@)
284 *
285 * Like on Windows, this function does not handle arguments with spaces
286 * or double-quotes.
287 */
288int _execv(const char* name, char* const* argv)
289{
290 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
291}
292
293/*********************************************************************
294 * _execve (MSVCRT.@)
295 *
296 * Like on Windows, this function does not handle arguments with spaces
297 * or double-quotes.
298 */
299int _execve(const char* name, char* const* argv, const char* const* envv)
300{
301 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
302}
303
304/*********************************************************************
305 * _execvpe (MSVCRT.@)
306 *
307 * Like on Windows, this function does not handle arguments with spaces
308 * or double-quotes.
309 */
310int _execvpe(const char* name, char* const* argv, const char* const* envv)
311{
312 char fullname[MAX_PATH];
313
314 _searchenv(name, "PATH", fullname);
315 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
316 (const char* const*) argv, envv);
317}
318
319/*********************************************************************
320 * _execvp (MSVCRT.@)
321 *
322 * Like on Windows, this function does not handle arguments with spaces
323 * or double-quotes.
324 */
325int _execvp(const char* name, char* const* argv)
326{
327 return _execvpe(name, argv, NULL);
328}
329
330/*********************************************************************
331 * _spawnl (MSVCRT.@)
332 *
333 * Like on Windows, this function does not handle arguments with spaces
334 * or double-quotes.
335 */
336int _spawnl(int flags, const char* name, const char* arg0, ...)
337{
338 va_list ap;
339 char * args;
340 int ret;
341
342 va_start(ap, arg0);
343 args = msvcrt_valisttos(arg0, ap, ' ');
344 va_end(ap);
345
346 ret = msvcrt_spawn(flags, name, args, NULL);
347 MSVCRT_free(args);
348
349 return ret;
350}
351
352/*********************************************************************
353 * _spawnlp (MSVCRT.@)
354 *
355 * Like on Windows, this function does not handle arguments with spaces
356 * or double-quotes.
357 */
358int _spawnlp(int flags, const char* name, const char* arg0, ...)
359{
360 va_list ap;
361 char * args;
362 int ret;
363 char fullname[MAX_PATH];
364
365 _searchenv(name, "PATH", fullname);
366
367 va_start(ap, arg0);
368 args = msvcrt_valisttos(arg0, ap, ' ');
369 va_end(ap);
370
371 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
372 MSVCRT_free(args);
373
374 return ret;
375}
376
377/*********************************************************************
378 * _spawnve (MSVCRT.@)
379 *
380 * Like on Windows, this function does not handle arguments with spaces
381 * or double-quotes.
382 */
383int _spawnve(int flags, const char* name, const char* const* argv,
384 const char* const* envv)
385{
386 char * args = msvcrt_argvtos(argv,' ');
387 char * envs = msvcrt_argvtos(envv,0);
388 const char *fullname = name;
389 int ret = -1;
390
391 FIXME(":not translating name %s to locate program\n",fullname);
392 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
393
394 if (args)
395 {
396 ret = msvcrt_spawn(flags, fullname, args, envs);
397 MSVCRT_free(args);
398 }
399 if (envs)
400 MSVCRT_free(envs);
401
402 return ret;
403}
404
405/*********************************************************************
406 * _spawnv (MSVCRT.@)
407 *
408 * Like on Windows, this function does not handle arguments with spaces
409 * or double-quotes.
410 */
411int _spawnv(int flags, const char* name, const char* const* argv)
412{
413 return _spawnve(flags, name, argv, NULL);
414}
415
416/*********************************************************************
417 * _spawnvpe (MSVCRT.@)
418 *
419 * Like on Windows, this function does not handle arguments with spaces
420 * or double-quotes.
421 */
422int _spawnvpe(int flags, const char* name, const char* const* argv,
423 const char* const* envv)
424{
425 char fullname[MAX_PATH];
426 _searchenv(name, "PATH", fullname);
427 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
428}
429
430/*********************************************************************
431 * _spawnvp (MSVCRT.@)
432 *
433 * Like on Windows, this function does not handle arguments with spaces
434 * or double-quotes.
435 */
436int _spawnvp(int flags, const char* name, const char* const* argv)
437{
438 return _spawnvpe(flags, name, argv, NULL);
439}
440
441/*********************************************************************
442 * system (MSVCRT.@)
443 */
444int MSVCRT_system(const char* cmd)
445{
446 char* cmdcopy;
447 int res;
448
449 /* Make a writable copy for CreateProcess */
450 cmdcopy=_strdup(cmd);
451 /* FIXME: should probably launch cmd interpreter in COMSPEC */
452 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
453 MSVCRT_free(cmdcopy);
454 return res;
455}
456
457/*********************************************************************
458 * _loaddll (MSVCRT.@)
459 */
460int _loaddll(const char* dllname)
461{
462 return (int)LoadLibraryA(dllname);
463}
464
465/*********************************************************************
466 * _unloaddll (MSVCRT.@)
467 */
468int _unloaddll(int dll)
469{
470 if (FreeLibrary((HMODULE)dll))
471 return 0;
472 else
473 {
474 int err = GetLastError();
475 MSVCRT__set_errno(err);
476 return err;
477 }
478}
Note: See TracBrowser for help on using the repository browser.