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"
20 DEFAULT_DEBUG_CHANNEL(msvcrt);
22 /* FIXME: Check file extensions for app to run */
23 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
24 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
25 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
26 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
28 /* INTERNAL: Spawn a child process */
29 static int msvcrt_spawn(int flags, const char* exe, char* args, char* env)
32 PROCESS_INFORMATION pi;
34 if (sizeof(HANDLE) != sizeof(int))
35 WARN("This call is unsuitable for your architecture\n");
37 if ((unsigned)flags > _P_DETACH)
39 SET_THREAD_VAR(errno,MSVCRT_EINVAL);
43 FIXME(":must dup/kill streams for child process\n");
45 memset(&si, 0, sizeof(si));
48 if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
49 flags == _P_DETACH ? DETACHED_PROCESS : 0,
52 MSVCRT__set_errno(GetLastError());
59 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
60 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
61 CloseHandle(pi.hProcess);
62 CloseHandle(pi.hThread);
63 return (int)pi.dwProcessId;
65 CloseHandle(pi.hProcess);
70 CloseHandle(pi.hThread);
71 return (int)pi.hProcess;
75 return -1; /* can't reach here */
78 /* INTERNAL: Convert argv list to a single 'delim'-separated string */
79 static char* msvcrt_argvtos(const char* const* arg, char delim)
81 const char* const* search = arg;
91 size += strlen(*search) + 1;
95 if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
103 int strsize = strlen(*search);
104 memcpy(ret+size,*search,strsize);
105 ret[size+strsize] = delim;
112 /* INTERNAL: Convert va_list to a single 'delim'-separated string */
113 static char* msvcrt_valisttos(const char* arg0, va_list ap, char delim)
125 size = strlen(arg0) + 1;
126 while((arg = va_arg(search, char *)) != NULL)
128 size += strlen(arg) + 1;
131 if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
137 strsize = strlen(arg0);
138 memcpy(ret+size,arg0,strsize);
139 ret[size+strsize] = delim;
141 while((arg = va_arg(search, char *)) != NULL)
143 strsize = strlen(search);
144 memcpy(ret+size,search,strsize);
145 ret[size+strsize] = delim;
151 /*********************************************************************
154 int _cwait(int *status, int pid, int action)
156 HANDLE hPid = (HANDLE)pid;
159 action = action; /* Remove warning */
161 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
166 GetExitCodeProcess(hPid, &stat);
171 doserrno = GetLastError();
173 if (doserrno == ERROR_INVALID_HANDLE)
175 SET_THREAD_VAR(errno, MSVCRT_ECHILD);
176 SET_THREAD_VAR(doserrno,doserrno);
179 MSVCRT__set_errno(doserrno);
181 return status ? *status = -1 : -1;
184 /*********************************************************************
187 int _execl(const char* name, const char* arg0, ...)
194 args = msvcrt_valisttos(arg0, ap, ' ');
197 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
203 /*********************************************************************
206 int _execlp(const char* name, const char* arg0, ...)
211 char fullname[MAX_PATH];
213 _searchenv(name, "PATH", fullname);
216 args = msvcrt_valisttos(arg0, ap, ' ');
219 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
225 /*********************************************************************
228 int _execv(const char* name, char* const* argv)
230 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
233 /*********************************************************************
236 int _execve(const char* name, char* const* argv, const char* const* envv)
238 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
241 /*********************************************************************
242 * _execvpe (MSVCRT.@)
244 int _execvpe(const char* name, char* const* argv, const char* const* envv)
246 char fullname[MAX_PATH];
248 _searchenv(name, "PATH", fullname);
249 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
250 (const char* const*) argv, envv);
253 /*********************************************************************
256 int _execvp(const char* name, char* const* argv)
258 return _execvpe(name, argv, NULL);
261 /*********************************************************************
264 int _spawnl(int flags, const char* name, const char* arg0, ...)
271 args = msvcrt_valisttos(arg0, ap, ' ');
274 ret = msvcrt_spawn(flags, name, args, NULL);
280 /*********************************************************************
281 * _spawnlp (MSVCRT.@)
283 int _spawnlp(int flags, const char* name, const char* arg0, ...)
288 char fullname[MAX_PATH];
290 _searchenv(name, "PATH", fullname);
293 args = msvcrt_valisttos(arg0, ap, ' ');
296 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
302 /*********************************************************************
303 * _spawnve (MSVCRT.@)
305 int _spawnve(int flags, const char* name, const char* const* argv,
306 const char* const* envv)
308 char * args = msvcrt_argvtos(argv,' ');
309 char * envs = msvcrt_argvtos(envv,0);
310 const char *fullname = name;
313 FIXME(":not translating name %s to locate program\n",fullname);
314 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
318 ret = msvcrt_spawn(flags, fullname, args, envs);
327 /*********************************************************************
330 int _spawnv(int flags, const char* name, const char* const* argv)
332 return _spawnve(flags, name, argv, NULL);
335 /*********************************************************************
336 * _spawnvpe (MSVCRT.@)
338 int _spawnvpe(int flags, const char* name, const char* const* argv,
339 const char* const* envv)
341 char fullname[MAX_PATH];
342 _searchenv(name, "PATH", fullname);
343 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
346 /*********************************************************************
347 * _spawnvp (MSVCRT.@)
349 int _spawnvp(int flags, const char* name, const char* const* argv)
351 return _spawnvpe(flags, name, argv, NULL);
354 /*********************************************************************
357 int MSVCRT_system(const char* cmd)
359 /* FIXME: should probably launch cmd interpreter in COMSPEC */
360 return msvcrt_spawn(_P_WAIT, cmd, NULL, NULL);
363 /*********************************************************************
364 * _loaddll (MSVCRT.@)
366 int _loaddll(const char* dllname)
368 return LoadLibraryA(dllname);
371 /*********************************************************************
372 * _unloaddll (MSVCRT.@)
374 int _unloaddll(int dll)
376 if (FreeLibrary((HANDLE)dll))
380 int err = GetLastError();
381 MSVCRT__set_errno(err);