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

Last change on this file since 10005 was 10005, checked in by sandervl, 22 years ago

PF: MSVCRT update

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