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
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.
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.
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
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
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
37 /* INTERNAL: Spawn a child process */
38 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
41 PROCESS_INFORMATION pi;
43 if (sizeof(HANDLE) != sizeof(int))
44 WARN("This call is unsuitable for your architecture\n");
46 if ((unsigned)flags > MSVCRT__P_DETACH)
48 *MSVCRT__errno() = MSVCRT_EINVAL;
52 FIXME(":must dup/kill streams for child process\n");
54 memset(&si, 0, sizeof(si));
57 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
58 flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
61 msvcrt_set_errno(GetLastError());
68 WaitForSingleObject(pi.hProcess, INFINITE);
69 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
70 CloseHandle(pi.hProcess);
71 CloseHandle(pi.hThread);
72 return (int)pi.dwProcessId;
73 case MSVCRT__P_DETACH:
74 CloseHandle(pi.hProcess);
77 case MSVCRT__P_NOWAIT:
78 case MSVCRT__P_NOWAITO:
79 CloseHandle(pi.hThread);
80 return (int)pi.hProcess;
81 case MSVCRT__P_OVERLAY:
84 return -1; /* can't reach here */
87 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
88 * extra '\0' to terminate it
90 static char* msvcrt_argvtos(const char* const* arg, char delim)
99 /* Return NULL for an empty environment list */
108 size += strlen(*a) + 1;
112 ret = (char*)MSVCRT_malloc(size + 1);
121 int len = strlen(*a);
127 if (delim && p > ret) p[-1] = 0;
132 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
133 * extra '\0' to terminate it
135 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
144 va_copy(alist2,alist);
146 # ifdef HAVE___VA_COPY
147 __va_copy(alist2,alist);
155 /* Return NULL for an empty environment list */
163 size += strlen(arg) + 1;
164 arg = va_arg(alist, char*);
165 } while (arg != NULL);
167 ret = (char*)MSVCRT_malloc(size + 1);
175 int len = strlen(arg);
179 arg = va_arg(alist2, char*);
180 } while (arg != NULL);
181 if (delim && p > ret) p[-1] = 0;
186 /*********************************************************************
189 int _cwait(int *status, int pid, int action)
191 HANDLE hPid = (HANDLE)pid;
194 action = action; /* Remove warning */
196 if (!WaitForSingleObject(hPid, INFINITE))
201 GetExitCodeProcess(hPid, &stat);
206 doserrno = GetLastError();
208 if (doserrno == ERROR_INVALID_HANDLE)
210 *MSVCRT__errno() = MSVCRT_ECHILD;
211 *MSVCRT___doserrno() = doserrno;
214 msvcrt_set_errno(doserrno);
216 return status ? *status = -1 : -1;
219 /*********************************************************************
222 * Like on Windows, this function does not handle arguments with spaces
225 int _execl(const char* name, const char* arg0, ...)
232 args = msvcrt_valisttos(arg0, ap, ' ');
235 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL);
241 /*********************************************************************
244 int _execle(const char* name, const char* arg0, ...)
250 /*********************************************************************
253 * Like on Windows, this function does not handle arguments with spaces
256 int _execlp(const char* name, const char* arg0, ...)
261 char fullname[MAX_PATH];
263 _searchenv(name, "PATH", fullname);
266 args = msvcrt_valisttos(arg0, ap, ' ');
269 ret = msvcrt_spawn(MSVCRT__P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
275 /*********************************************************************
276 * _execlpe (MSVCRT.@)
278 int _execlpe(const char* name, const char* arg0, ...)
284 /*********************************************************************
287 * Like on Windows, this function does not handle arguments with spaces
290 int _execv(const char* name, char* const* argv)
292 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, NULL);
295 /*********************************************************************
298 * Like on Windows, this function does not handle arguments with spaces
301 int _execve(const char* name, char* const* argv, const char* const* envv)
303 return _spawnve(MSVCRT__P_OVERLAY, name, (const char* const*) argv, envv);
306 /*********************************************************************
307 * _execvpe (MSVCRT.@)
309 * Like on Windows, this function does not handle arguments with spaces
312 int _execvpe(const char* name, char* const* argv, const char* const* envv)
314 char fullname[MAX_PATH];
316 _searchenv(name, "PATH", fullname);
317 return _spawnve(MSVCRT__P_OVERLAY, fullname[0] ? fullname : name,
318 (const char* const*) argv, envv);
321 /*********************************************************************
324 * Like on Windows, this function does not handle arguments with spaces
327 int _execvp(const char* name, char* const* argv)
329 return _execvpe(name, argv, NULL);
332 /*********************************************************************
335 * Like on Windows, this function does not handle arguments with spaces
338 int _spawnl(int flags, const char* name, const char* arg0, ...)
345 args = msvcrt_valisttos(arg0, ap, ' ');
348 ret = msvcrt_spawn(flags, name, args, NULL);
354 /*********************************************************************
355 * _spawnle (MSVCRT.@)
357 int _spawnle(int flags, const char* name, const char* arg0, ...)
360 char *args, *envs = NULL;
361 const char * const *envp;
365 args = msvcrt_valisttos(arg0, ap, ' ');
369 while (va_arg( ap, char * ) != NULL) /*nothing*/;
370 envp = va_arg( ap, const char * const * );
371 if (envp) envs = msvcrt_argvtos(envp, 0);
374 ret = msvcrt_spawn(flags, name, args, envs);
377 if (envs) MSVCRT_free(envs);
382 /*********************************************************************
383 * _spawnlp (MSVCRT.@)
385 * Like on Windows, this function does not handle arguments with spaces
388 int _spawnlp(int flags, const char* name, const char* arg0, ...)
393 char fullname[MAX_PATH];
395 _searchenv(name, "PATH", fullname);
398 args = msvcrt_valisttos(arg0, ap, ' ');
401 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
407 /*********************************************************************
408 * _spawnlpe (MSVCRT.@)
410 int _spawnlpe(int flags, const char* name, const char* arg0, ...)
413 char *args, *envs = NULL;
414 const char * const *envp;
416 char fullname[MAX_PATH];
418 _searchenv(name, "PATH", fullname);
421 args = msvcrt_valisttos(arg0, ap, ' ');
425 while (va_arg( ap, char * ) != NULL) /*nothing*/;
426 envp = va_arg( ap, const char * const * );
427 if (envp) envs = msvcrt_argvtos(envp, 0);
430 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, envs);
433 if (envs) MSVCRT_free(envs);
437 /*********************************************************************
438 * _spawnve (MSVCRT.@)
440 * Like on Windows, this function does not handle arguments with spaces
443 int _spawnve(int flags, const char* name, const char* const* argv,
444 const char* const* envv)
446 char * args = msvcrt_argvtos(argv,' ');
447 char * envs = msvcrt_argvtos(envv,0);
448 const char *fullname = name;
451 FIXME(":not translating name %s to locate program\n",fullname);
452 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
456 ret = msvcrt_spawn(flags, fullname, args, envs);
465 /*********************************************************************
468 * Like on Windows, this function does not handle arguments with spaces
471 int _spawnv(int flags, const char* name, const char* const* argv)
473 return _spawnve(flags, name, argv, NULL);
476 /*********************************************************************
477 * _spawnvpe (MSVCRT.@)
479 * Like on Windows, this function does not handle arguments with spaces
482 int _spawnvpe(int flags, const char* name, const char* const* argv,
483 const char* const* envv)
485 char fullname[MAX_PATH];
486 _searchenv(name, "PATH", fullname);
487 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
490 /*********************************************************************
491 * _spawnvp (MSVCRT.@)
493 * Like on Windows, this function does not handle arguments with spaces
496 int _spawnvp(int flags, const char* name, const char* const* argv)
498 return _spawnvpe(flags, name, argv, NULL);
501 /*********************************************************************
504 MSVCRT_FILE* MSVCRT__popen(const char* command, const char* mode)
506 FIXME("(command=%s, mode=%s): stub\n", debugstr_a(command), debugstr_a(mode));
510 /*********************************************************************
513 MSVCRT_FILE* MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
515 FIXME("(command=%s, mode=%s): stub\n", debugstr_w(command), debugstr_w(mode));
519 /*********************************************************************
522 int MSVCRT__pclose(MSVCRT_FILE* file)
524 FIXME("(file=%p): stub\n", file);
528 /*********************************************************************
531 int MSVCRT_system(const char* cmd)
536 /* Make a writable copy for CreateProcess */
537 cmdcopy=_strdup(cmd);
538 /* FIXME: should probably launch cmd interpreter in COMSPEC */
539 res=msvcrt_spawn(MSVCRT__P_WAIT, NULL, cmdcopy, NULL);
540 MSVCRT_free(cmdcopy);
544 /*********************************************************************
545 * _loaddll (MSVCRT.@)
547 int _loaddll(const char* dllname)
549 return (int)LoadLibraryA(dllname);
552 /*********************************************************************
553 * _unloaddll (MSVCRT.@)
555 int _unloaddll(int dll)
557 if (FreeLibrary((HMODULE)dll))
561 int err = GetLastError();
562 msvcrt_set_errno(err);
567 /*********************************************************************
568 * _getdllprocaddr (MSVCRT.@)
570 void *_getdllprocaddr(int dll, const char *name, int ordinal)
574 if (ordinal != -1) return NULL;
575 return GetProcAddress( (HMODULE)dll, name );
577 if (HIWORD(ordinal)) return NULL;
578 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );