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 /* INTERNAL: Spawn a child process */
45 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
48 PROCESS_INFORMATION pi;
50 if (sizeof(HANDLE) != sizeof(int))
51 WARN("This call is unsuitable for your architecture\n");
53 if ((unsigned)flags > _P_DETACH)
55 *MSVCRT__errno() = MSVCRT_EINVAL;
59 FIXME(":must dup/kill streams for child process\n");
61 memset(&si, 0, sizeof(si));
64 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
65 flags == _P_DETACH ? DETACHED_PROCESS : 0,
68 MSVCRT__set_errno(GetLastError());
75 WaitForSingleObject(pi.hProcess, INFINITE);
76 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
77 CloseHandle(pi.hProcess);
78 CloseHandle(pi.hThread);
79 return (int)pi.dwProcessId;
81 CloseHandle(pi.hProcess);
86 CloseHandle(pi.hThread);
87 return (int)pi.hProcess;
91 return -1; /* can't reach here */
94 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
95 * extra '\0' to terminate it
97 static char* msvcrt_argvtos(const char* const* arg, char delim)
106 /* Return NULL for an empty environment list */
115 size += strlen(*a) + 1;
119 ret = (char*)MSVCRT_malloc(size + 1);
128 int len = strlen(*a);
134 if (delim && p > ret) p[-1] = 0;
139 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
140 * extra '\0' to terminate it
142 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
151 va_copy(alist2,alist);
153 # ifdef HAVE___VA_COPY
154 __va_copy(alist2,alist);
162 /* Return NULL for an empty environment list */
170 size += strlen(arg) + 1;
171 arg = va_arg(alist, char*);
172 } while (arg != NULL);
174 ret = (char*)MSVCRT_malloc(size + 1);
182 int len = strlen(arg);
186 arg = va_arg(alist2, char*);
187 } while (arg != NULL);
188 if (delim && p > ret) p[-1] = 0;
193 /*********************************************************************
196 int _cwait(int *status, int pid, int action)
198 HANDLE hPid = (HANDLE)pid;
201 action = action; /* Remove warning */
203 if (!WaitForSingleObject(hPid, INFINITE))
208 GetExitCodeProcess(hPid, &stat);
213 doserrno = GetLastError();
215 if (doserrno == ERROR_INVALID_HANDLE)
217 *MSVCRT__errno() = MSVCRT_ECHILD;
218 *MSVCRT___doserrno() = doserrno;
221 MSVCRT__set_errno(doserrno);
223 return status ? *status = -1 : -1;
226 /*********************************************************************
229 * Like on Windows, this function does not handle arguments with spaces
232 int _execl(const char* name, const char* arg0, ...)
239 args = msvcrt_valisttos(arg0, ap, ' ');
242 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
248 /*********************************************************************
251 int _execle(const char* name, const char* arg0, ...)
257 /*********************************************************************
260 * Like on Windows, this function does not handle arguments with spaces
263 int _execlp(const char* name, const char* arg0, ...)
268 char fullname[MAX_PATH];
270 _searchenv(name, "PATH", fullname);
273 args = msvcrt_valisttos(arg0, ap, ' ');
276 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
282 /*********************************************************************
283 * _execlpe (MSVCRT.@)
285 int _execlpe(const char* name, const char* arg0, ...)
291 /*********************************************************************
294 * Like on Windows, this function does not handle arguments with spaces
297 int _execv(const char* name, char* const* argv)
299 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
302 /*********************************************************************
305 * Like on Windows, this function does not handle arguments with spaces
308 int _execve(const char* name, char* const* argv, const char* const* envv)
310 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
313 /*********************************************************************
314 * _execvpe (MSVCRT.@)
316 * Like on Windows, this function does not handle arguments with spaces
319 int _execvpe(const char* name, char* const* argv, const char* const* envv)
321 char fullname[MAX_PATH];
323 _searchenv(name, "PATH", fullname);
324 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
325 (const char* const*) argv, envv);
328 /*********************************************************************
331 * Like on Windows, this function does not handle arguments with spaces
334 int _execvp(const char* name, char* const* argv)
336 return _execvpe(name, argv, NULL);
339 /*********************************************************************
342 * Like on Windows, this function does not handle arguments with spaces
345 int _spawnl(int flags, const char* name, const char* arg0, ...)
352 args = msvcrt_valisttos(arg0, ap, ' ');
355 ret = msvcrt_spawn(flags, name, args, NULL);
361 /*********************************************************************
362 * _spawnle (MSVCRT.@)
364 int _spawnle(int flags, const char* name, const char* arg0, ...)
371 /*********************************************************************
372 * _spawnlp (MSVCRT.@)
374 * Like on Windows, this function does not handle arguments with spaces
377 int _spawnlp(int flags, const char* name, const char* arg0, ...)
382 char fullname[MAX_PATH];
384 _searchenv(name, "PATH", fullname);
387 args = msvcrt_valisttos(arg0, ap, ' ');
390 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
396 /*********************************************************************
397 * _spawnlpe (MSVCRT.@)
399 int _spawnlpe(int flags, const char* name, const char* arg0, ...)
405 /*********************************************************************
406 * _spawnve (MSVCRT.@)
408 * Like on Windows, this function does not handle arguments with spaces
411 int _spawnve(int flags, const char* name, const char* const* argv,
412 const char* const* envv)
414 char * args = msvcrt_argvtos(argv,' ');
415 char * envs = msvcrt_argvtos(envv,0);
416 const char *fullname = name;
419 FIXME(":not translating name %s to locate program\n",fullname);
420 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
424 ret = msvcrt_spawn(flags, fullname, args, envs);
433 /*********************************************************************
436 * Like on Windows, this function does not handle arguments with spaces
439 int _spawnv(int flags, const char* name, const char* const* argv)
441 return _spawnve(flags, name, argv, NULL);
444 /*********************************************************************
445 * _spawnvpe (MSVCRT.@)
447 * Like on Windows, this function does not handle arguments with spaces
450 int _spawnvpe(int flags, const char* name, const char* const* argv,
451 const char* const* envv)
453 char fullname[MAX_PATH];
454 _searchenv(name, "PATH", fullname);
455 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
458 /*********************************************************************
459 * _spawnvp (MSVCRT.@)
461 * Like on Windows, this function does not handle arguments with spaces
464 int _spawnvp(int flags, const char* name, const char* const* argv)
466 return _spawnvpe(flags, name, argv, NULL);
469 /*********************************************************************
472 MSVCRT_FILE* MSVCRT__popen(const char* command, const char* mode)
474 FIXME("(command=%s, mode=%s): stub\n", debugstr_a(command), debugstr_a(mode));
478 /*********************************************************************
481 MSVCRT_FILE* MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
483 FIXME("(command=%s, mode=%s): stub\n", debugstr_w(command), debugstr_w(mode));
487 /*********************************************************************
490 int MSVCRT__pclose(MSVCRT_FILE* file)
492 FIXME("(file=%p): stub\n", file);
496 /*********************************************************************
499 int MSVCRT_system(const char* cmd)
504 /* Make a writable copy for CreateProcess */
505 cmdcopy=_strdup(cmd);
506 /* FIXME: should probably launch cmd interpreter in COMSPEC */
507 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
508 MSVCRT_free(cmdcopy);
512 /*********************************************************************
513 * _loaddll (MSVCRT.@)
515 int _loaddll(const char* dllname)
517 return (int)LoadLibraryA(dllname);
520 /*********************************************************************
521 * _unloaddll (MSVCRT.@)
523 int _unloaddll(int dll)
525 if (FreeLibrary((HMODULE)dll))
529 int err = GetLastError();
530 MSVCRT__set_errno(err);
535 /*********************************************************************
536 * _getdllprocaddr (MSVCRT.@)
538 void *_getdllprocaddr(int dll, const char *name, int ordinal)
542 if (ordinal != -1) return NULL;
543 return GetProcAddress( (HMODULE)dll, name );
545 if (HIWORD(ordinal)) return NULL;
546 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );