2 * msvcrt.dll spawn/exec functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
10 * -File handles need some special handling. Sometimes children get
11 * open file handles, sometimes not. The docs are confusing
12 * -No check for maximum path/argument/environment size is done
17 #include "msvcrt/process.h"
18 #include "msvcrt/stdlib.h"
19 #include "msvcrt/string.h"
21 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
25 /* FIXME: Check file extensions for app to run */
26 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
27 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
28 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
29 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
31 /* INTERNAL: Spawn a child process */
32 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
35 PROCESS_INFORMATION pi;
37 if (sizeof(HANDLE) != sizeof(int))
38 WARN("This call is unsuitable for your architecture\n");
40 if ((unsigned)flags > _P_DETACH)
42 SET_THREAD_VAR(errno,MSVCRT_EINVAL);
46 FIXME(":must dup/kill streams for child process\n");
48 memset(&si, 0, sizeof(si));
51 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
52 flags == _P_DETACH ? DETACHED_PROCESS : 0,
55 MSVCRT__set_errno(GetLastError());
62 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
63 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
64 CloseHandle(pi.hProcess);
65 CloseHandle(pi.hThread);
66 return (int)pi.dwProcessId;
68 CloseHandle(pi.hProcess);
73 CloseHandle(pi.hThread);
74 return (int)pi.hProcess;
78 return -1; /* can't reach here */
81 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
82 * extra '\0' to terminate it
84 static char* msvcrt_argvtos(const char* const* arg, char delim)
93 /* Return NULL for an empty environment list */
102 size += strlen(*a) + 1;
106 ret = (char*)MSVCRT_malloc(size + 1);
115 int len = strlen(*a);
116 memcpy(ret+size,*a,len);
125 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
126 * extra '\0' to terminate it
128 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
130 va_list alist2 = alist;
138 /* Return NULL for an empty environment list */
146 size += strlen(arg) + 1;
147 arg = va_arg(alist, char*);
148 } while (arg != NULL);
150 ret = (char*)MSVCRT_malloc(size + 1);
158 int len = strlen(arg);
162 arg = va_arg(alist2, char*);
163 } while (arg != NULL);
168 /*********************************************************************
171 int _cwait(int *status, int pid, int action)
173 HANDLE hPid = (HANDLE)pid;
176 action = action; /* Remove warning */
178 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
183 GetExitCodeProcess(hPid, &stat);
188 doserrno = GetLastError();
190 if (doserrno == ERROR_INVALID_HANDLE)
192 SET_THREAD_VAR(errno, MSVCRT_ECHILD);
193 SET_THREAD_VAR(doserrno,doserrno);
196 MSVCRT__set_errno(doserrno);
198 return status ? *status = -1 : -1;
201 /*********************************************************************
204 * Like on Windows, this function does not handle arguments with spaces
207 int _execl(const char* name, const char* arg0, ...)
214 args = msvcrt_valisttos(arg0, ap, ' ');
217 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
223 /*********************************************************************
226 * Like on Windows, this function does not handle arguments with spaces
229 int _execlp(const char* name, const char* arg0, ...)
234 char fullname[MAX_PATH];
236 _searchenv(name, "PATH", fullname);
239 args = msvcrt_valisttos(arg0, ap, ' ');
242 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
248 /*********************************************************************
251 * Like on Windows, this function does not handle arguments with spaces
254 int _execv(const char* name, char* const* argv)
256 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
259 /*********************************************************************
262 * Like on Windows, this function does not handle arguments with spaces
265 int _execve(const char* name, char* const* argv, const char* const* envv)
267 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
270 /*********************************************************************
271 * _execvpe (MSVCRT.@)
273 * Like on Windows, this function does not handle arguments with spaces
276 int _execvpe(const char* name, char* const* argv, const char* const* envv)
278 char fullname[MAX_PATH];
280 _searchenv(name, "PATH", fullname);
281 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
282 (const char* const*) argv, envv);
285 /*********************************************************************
288 * Like on Windows, this function does not handle arguments with spaces
291 int _execvp(const char* name, char* const* argv)
293 return _execvpe(name, argv, NULL);
296 /*********************************************************************
299 * Like on Windows, this function does not handle arguments with spaces
302 int _spawnl(int flags, const char* name, const char* arg0, ...)
309 args = msvcrt_valisttos(arg0, ap, ' ');
312 ret = msvcrt_spawn(flags, name, args, NULL);
318 /*********************************************************************
319 * _spawnlp (MSVCRT.@)
321 * Like on Windows, this function does not handle arguments with spaces
324 int _spawnlp(int flags, const char* name, const char* arg0, ...)
329 char fullname[MAX_PATH];
331 _searchenv(name, "PATH", fullname);
334 args = msvcrt_valisttos(arg0, ap, ' ');
337 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
343 /*********************************************************************
344 * _spawnve (MSVCRT.@)
346 * Like on Windows, this function does not handle arguments with spaces
349 int _spawnve(int flags, const char* name, const char* const* argv,
350 const char* const* envv)
352 char * args = msvcrt_argvtos(argv,' ');
353 char * envs = msvcrt_argvtos(envv,0);
354 const char *fullname = name;
357 FIXME(":not translating name %s to locate program\n",fullname);
358 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
362 ret = msvcrt_spawn(flags, fullname, args, envs);
371 /*********************************************************************
374 * Like on Windows, this function does not handle arguments with spaces
377 int _spawnv(int flags, const char* name, const char* const* argv)
379 return _spawnve(flags, name, argv, NULL);
382 /*********************************************************************
383 * _spawnvpe (MSVCRT.@)
385 * Like on Windows, this function does not handle arguments with spaces
388 int _spawnvpe(int flags, const char* name, const char* const* argv,
389 const char* const* envv)
391 char fullname[MAX_PATH];
392 _searchenv(name, "PATH", fullname);
393 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
396 /*********************************************************************
397 * _spawnvp (MSVCRT.@)
399 * Like on Windows, this function does not handle arguments with spaces
402 int _spawnvp(int flags, const char* name, const char* const* argv)
404 return _spawnvpe(flags, name, argv, NULL);
407 /*********************************************************************
410 int MSVCRT_system(const char* cmd)
415 /* Make a writable copy for CreateProcess */
416 cmdcopy=_strdup(cmd);
417 /* FIXME: should probably launch cmd interpreter in COMSPEC */
418 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
419 MSVCRT_free(cmdcopy);
423 /*********************************************************************
424 * _loaddll (MSVCRT.@)
426 int _loaddll(const char* dllname)
428 return LoadLibraryA(dllname);
431 /*********************************************************************
432 * _unloaddll (MSVCRT.@)
434 int _unloaddll(int dll)
436 if (FreeLibrary((HANDLE)dll))
440 int err = GetLastError();
441 MSVCRT__set_errno(err);