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 "msvcrt/errno.h"
35 #include "msvcrt/stdio.h"
36 #include "msvcrt/process.h"
37 #include "msvcrt/stdlib.h"
38 #include "msvcrt/string.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
44 /* FIXME: Check file extensions for app to run */
45 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
46 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
47 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
48 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
50 /* INTERNAL: Spawn a child process */
51 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
54 PROCESS_INFORMATION pi;
56 if (sizeof(HANDLE) != sizeof(int))
57 WARN("This call is unsuitable for your architecture\n");
59 if ((unsigned)flags > _P_DETACH)
61 *MSVCRT__errno() = MSVCRT_EINVAL;
65 FIXME(":must dup/kill streams for child process\n");
67 memset(&si, 0, sizeof(si));
70 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
71 flags == _P_DETACH ? DETACHED_PROCESS : 0,
74 MSVCRT__set_errno(GetLastError());
81 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
82 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
83 CloseHandle(pi.hProcess);
84 CloseHandle(pi.hThread);
85 return (int)pi.dwProcessId;
87 CloseHandle(pi.hProcess);
92 CloseHandle(pi.hThread);
93 return (int)pi.hProcess;
97 return -1; /* can't reach here */
100 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
101 * extra '\0' to terminate it
103 static char* msvcrt_argvtos(const char* const* arg, char delim)
105 const char* const* a;
112 /* Return NULL for an empty environment list */
121 size += strlen(*a) + 1;
125 ret = (char*)MSVCRT_malloc(size + 1);
134 int len = strlen(*a);
140 if (delim && p > ret) p[-1] = 0;
145 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
146 * extra '\0' to terminate it
148 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
157 va_copy(alist2,alist);
160 __va_copy(alist2,alist);
168 /* Return NULL for an empty environment list */
176 size += strlen(arg) + 1;
177 arg = va_arg(alist, char*);
178 } while (arg != NULL);
180 ret = (char*)MSVCRT_malloc(size + 1);
188 int len = strlen(arg);
192 arg = va_arg(alist2, char*);
193 } while (arg != NULL);
194 if (delim && p > ret) p[-1] = 0;
199 /*********************************************************************
202 int _cwait(int *status, int pid, int action)
204 HANDLE hPid = (HANDLE)pid;
207 action = action; /* Remove warning */
209 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
214 GetExitCodeProcess(hPid, &stat);
219 doserrno = GetLastError();
221 if (doserrno == ERROR_INVALID_HANDLE)
223 *MSVCRT__errno() = MSVCRT_ECHILD;
224 *__doserrno() = doserrno;
227 MSVCRT__set_errno(doserrno);
229 return status ? *status = -1 : -1;
232 /*********************************************************************
235 * Like on Windows, this function does not handle arguments with spaces
238 int _execl(const char* name, const char* arg0, ...)
245 args = msvcrt_valisttos(arg0, ap, ' ');
248 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
254 /*********************************************************************
257 * Like on Windows, this function does not handle arguments with spaces
260 int _execlp(const char* name, const char* arg0, ...)
265 char fullname[MAX_PATH];
267 _searchenv(name, "PATH", fullname);
270 args = msvcrt_valisttos(arg0, ap, ' ');
273 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
279 /*********************************************************************
282 * Like on Windows, this function does not handle arguments with spaces
285 int _execv(const char* name, char* const* argv)
287 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
290 /*********************************************************************
293 * Like on Windows, this function does not handle arguments with spaces
296 int _execve(const char* name, char* const* argv, const char* const* envv)
298 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
301 /*********************************************************************
302 * _execvpe (MSVCRT.@)
304 * Like on Windows, this function does not handle arguments with spaces
307 int _execvpe(const char* name, char* const* argv, const char* const* envv)
309 char fullname[MAX_PATH];
311 _searchenv(name, "PATH", fullname);
312 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
313 (const char* const*) argv, envv);
316 /*********************************************************************
319 * Like on Windows, this function does not handle arguments with spaces
322 int _execvp(const char* name, char* const* argv)
324 return _execvpe(name, argv, NULL);
327 /*********************************************************************
330 * Like on Windows, this function does not handle arguments with spaces
333 int _spawnl(int flags, const char* name, const char* arg0, ...)
340 args = msvcrt_valisttos(arg0, ap, ' ');
343 ret = msvcrt_spawn(flags, name, args, NULL);
349 /*********************************************************************
350 * _spawnlp (MSVCRT.@)
352 * Like on Windows, this function does not handle arguments with spaces
355 int _spawnlp(int flags, const char* name, const char* arg0, ...)
360 char fullname[MAX_PATH];
362 _searchenv(name, "PATH", fullname);
365 args = msvcrt_valisttos(arg0, ap, ' ');
368 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
374 /*********************************************************************
375 * _spawnve (MSVCRT.@)
377 * Like on Windows, this function does not handle arguments with spaces
380 int _spawnve(int flags, const char* name, const char* const* argv,
381 const char* const* envv)
383 char * args = msvcrt_argvtos(argv,' ');
384 char * envs = msvcrt_argvtos(envv,0);
385 const char *fullname = name;
388 FIXME(":not translating name %s to locate program\n",fullname);
389 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
393 ret = msvcrt_spawn(flags, fullname, args, envs);
402 /*********************************************************************
405 * Like on Windows, this function does not handle arguments with spaces
408 int _spawnv(int flags, const char* name, const char* const* argv)
410 return _spawnve(flags, name, argv, NULL);
413 /*********************************************************************
414 * _spawnvpe (MSVCRT.@)
416 * Like on Windows, this function does not handle arguments with spaces
419 int _spawnvpe(int flags, const char* name, const char* const* argv,
420 const char* const* envv)
422 char fullname[MAX_PATH];
423 _searchenv(name, "PATH", fullname);
424 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
427 /*********************************************************************
428 * _spawnvp (MSVCRT.@)
430 * Like on Windows, this function does not handle arguments with spaces
433 int _spawnvp(int flags, const char* name, const char* const* argv)
435 return _spawnvpe(flags, name, argv, NULL);
438 /*********************************************************************
441 MSVCRT_FILE* _popen(const char* command, const char* mode)
443 FIXME("(command=%s, mode=%s): stub\n", debugstr_a(command), debugstr_a(mode));
447 /*********************************************************************
450 MSVCRT_FILE* _wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
452 FIXME("(command=%s, mode=%s): stub\n", debugstr_w(command), debugstr_w(mode));
456 /*********************************************************************
459 int _pclose(MSVCRT_FILE* file)
461 FIXME("(file=%p): stub\n", file);
465 /*********************************************************************
468 int MSVCRT_system(const char* cmd)
473 /* Make a writable copy for CreateProcess */
474 cmdcopy=_strdup(cmd);
475 /* FIXME: should probably launch cmd interpreter in COMSPEC */
476 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
477 MSVCRT_free(cmdcopy);
481 /*********************************************************************
482 * _loaddll (MSVCRT.@)
484 int _loaddll(const char* dllname)
486 return (int)LoadLibraryA(dllname);
489 /*********************************************************************
490 * _unloaddll (MSVCRT.@)
492 int _unloaddll(int dll)
494 if (FreeLibrary((HMODULE)dll))
498 int err = GetLastError();
499 MSVCRT__set_errno(err);
504 /*********************************************************************
505 * _getdllprocaddr (MSVCRT.@)
507 void *_getdllprocaddr(int dll, const char *name, int ordinal)
511 if (ordinal != -1) return NULL;
512 return GetProcAddress( (HMODULE)dll, name );
514 if (HIWORD(ordinal)) return NULL;
515 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );