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 DEFAULT_DEBUG_CHANNEL(msvcrt);
23 /* FIXME: Check file extensions for app to run */
24 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
25 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
26 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
27 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
29 /* INTERNAL: Spawn a child process */
30 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
33 PROCESS_INFORMATION pi;
35 if (sizeof(HANDLE) != sizeof(int))
36 WARN("This call is unsuitable for your architecture\n");
38 if ((unsigned)flags > _P_DETACH)
40 SET_THREAD_VAR(errno,MSVCRT_EINVAL);
44 FIXME(":must dup/kill streams for child process\n");
46 memset(&si, 0, sizeof(si));
49 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
50 flags == _P_DETACH ? DETACHED_PROCESS : 0,
53 MSVCRT__set_errno(GetLastError());
60 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
61 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
62 CloseHandle(pi.hProcess);
63 CloseHandle(pi.hThread);
64 return (int)pi.dwProcessId;
66 CloseHandle(pi.hProcess);
71 CloseHandle(pi.hThread);
72 return (int)pi.hProcess;
76 return -1; /* can't reach here */
79 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
80 * extra '\0' to terminate it
82 static char* msvcrt_argvtos(const char* const* arg, char delim)
91 /* Return NULL for an empty environment list */
100 size += strlen(*a) + 1;
104 ret = (char*)MSVCRT_malloc(size + 1);
113 int len = strlen(*a);
114 memcpy(ret+size,*a,len);
123 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
124 * extra '\0' to terminate it
126 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
128 va_list alist2 = alist;
136 /* Return NULL for an empty environment list */
144 size += strlen(arg) + 1;
145 arg = va_arg(alist, char*);
146 } while (arg != NULL);
148 ret = (char*)MSVCRT_malloc(size + 1);
156 int len = strlen(arg);
160 arg = va_arg(alist2, char*);
161 } while (arg != NULL);
166 /*********************************************************************
169 int _cwait(int *status, int pid, int action)
171 HANDLE hPid = (HANDLE)pid;
174 action = action; /* Remove warning */
176 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
181 GetExitCodeProcess(hPid, &stat);
186 doserrno = GetLastError();
188 if (doserrno == ERROR_INVALID_HANDLE)
190 SET_THREAD_VAR(errno, MSVCRT_ECHILD);
191 SET_THREAD_VAR(doserrno,doserrno);
194 MSVCRT__set_errno(doserrno);
196 return status ? *status = -1 : -1;
199 /*********************************************************************
202 * Like on Windows, this function does not handle arguments with spaces
205 int _execl(const char* name, const char* arg0, ...)
212 args = msvcrt_valisttos(arg0, ap, ' ');
215 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
221 /*********************************************************************
224 * Like on Windows, this function does not handle arguments with spaces
227 int _execlp(const char* name, const char* arg0, ...)
232 char fullname[MAX_PATH];
234 _searchenv(name, "PATH", fullname);
237 args = msvcrt_valisttos(arg0, ap, ' ');
240 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
246 /*********************************************************************
249 * Like on Windows, this function does not handle arguments with spaces
252 int _execv(const char* name, char* const* argv)
254 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
257 /*********************************************************************
260 * Like on Windows, this function does not handle arguments with spaces
263 int _execve(const char* name, char* const* argv, const char* const* envv)
265 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
268 /*********************************************************************
269 * _execvpe (MSVCRT.@)
271 * Like on Windows, this function does not handle arguments with spaces
274 int _execvpe(const char* name, char* const* argv, const char* const* envv)
276 char fullname[MAX_PATH];
278 _searchenv(name, "PATH", fullname);
279 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
280 (const char* const*) argv, envv);
283 /*********************************************************************
286 * Like on Windows, this function does not handle arguments with spaces
289 int _execvp(const char* name, char* const* argv)
291 return _execvpe(name, argv, NULL);
294 /*********************************************************************
297 * Like on Windows, this function does not handle arguments with spaces
300 int _spawnl(int flags, const char* name, const char* arg0, ...)
307 args = msvcrt_valisttos(arg0, ap, ' ');
310 ret = msvcrt_spawn(flags, name, args, NULL);
316 /*********************************************************************
317 * _spawnlp (MSVCRT.@)
319 * Like on Windows, this function does not handle arguments with spaces
322 int _spawnlp(int flags, const char* name, const char* arg0, ...)
327 char fullname[MAX_PATH];
329 _searchenv(name, "PATH", fullname);
332 args = msvcrt_valisttos(arg0, ap, ' ');
335 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
341 /*********************************************************************
342 * _spawnve (MSVCRT.@)
344 * Like on Windows, this function does not handle arguments with spaces
347 int _spawnve(int flags, const char* name, const char* const* argv,
348 const char* const* envv)
350 char * args = msvcrt_argvtos(argv,' ');
351 char * envs = msvcrt_argvtos(envv,0);
352 const char *fullname = name;
355 FIXME(":not translating name %s to locate program\n",fullname);
356 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
360 ret = msvcrt_spawn(flags, fullname, args, envs);
369 /*********************************************************************
372 * Like on Windows, this function does not handle arguments with spaces
375 int _spawnv(int flags, const char* name, const char* const* argv)
377 return _spawnve(flags, name, argv, NULL);
380 /*********************************************************************
381 * _spawnvpe (MSVCRT.@)
383 * Like on Windows, this function does not handle arguments with spaces
386 int _spawnvpe(int flags, const char* name, const char* const* argv,
387 const char* const* envv)
389 char fullname[MAX_PATH];
390 _searchenv(name, "PATH", fullname);
391 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
394 /*********************************************************************
395 * _spawnvp (MSVCRT.@)
397 * Like on Windows, this function does not handle arguments with spaces
400 int _spawnvp(int flags, const char* name, const char* const* argv)
402 return _spawnvpe(flags, name, argv, NULL);
405 /*********************************************************************
408 int MSVCRT_system(const char* cmd)
413 /* Make a writable copy for CreateProcess */
414 cmdcopy=_strdup(cmd);
415 /* FIXME: should probably launch cmd interpreter in COMSPEC */
416 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
417 MSVCRT_free(cmdcopy);
421 /*********************************************************************
422 * _loaddll (MSVCRT.@)
424 int _loaddll(const char* dllname)
426 return LoadLibraryA(dllname);
429 /*********************************************************************
430 * _unloaddll (MSVCRT.@)
432 int _unloaddll(int dll)
434 if (FreeLibrary((HANDLE)dll))
438 int err = GetLastError();
439 MSVCRT__set_errno(err);