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 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
25 /* FIXME: Check file extensions for app to run */
26 static const unsigned int EXE
= 'e' << 16 | 'x' << 8 | 'e';
27 static const unsigned int BAT
= 'b' << 16 | 'a' << 8 | 't';
28 static const unsigned int CMD
= 'c' << 16 | 'm' << 8 | 'd';
29 static const unsigned int COM
= 'c' << 16 | 'o' << 8 | 'm';
31 /* INTERNAL: Spawn a child process */
32 static int msvcrt_spawn(int flags
, const char* exe
, char* cmdline
, char* env
)
35 PROCESS_INFORMATION pi
;
37 if (sizeof(HANDLE
) != sizeof(int))
38 WARN("This call is unsuitable for your architecture\n");
40 if ((unsigned)flags
> _P_DETACH
)
42 SET_THREAD_VAR(errno
,MSVCRT_EINVAL
);
46 FIXME(":must dup/kill streams for child process\n");
48 memset(&si
, 0, sizeof(si
));
51 if (!CreateProcessA(exe
, cmdline
, NULL
, NULL
, TRUE
,
52 flags
== _P_DETACH
? DETACHED_PROCESS
: 0,
55 MSVCRT__set_errno(GetLastError());
62 WaitForSingleObject(pi
.hProcess
,-1); /* wait forvever */
63 GetExitCodeProcess(pi
.hProcess
,&pi
.dwProcessId
);
64 CloseHandle(pi
.hProcess
);
65 CloseHandle(pi
.hThread
);
66 return (int)pi
.dwProcessId
;
68 CloseHandle(pi
.hProcess
);
73 CloseHandle(pi
.hThread
);
74 return (int)pi
.hProcess
;
78 return -1; /* can't reach here */
81 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
82 * extra '\0' to terminate it
84 static char* msvcrt_argvtos(const char* const* arg
, char delim
)
93 /* Return NULL for an empty environment list */
102 size
+= strlen(*a
) + 1;
106 ret
= (char*)MSVCRT_malloc(size
+ 1);
115 int len
= strlen(*a
);
116 memcpy(ret
+size
,*a
,len
);
125 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
126 * extra '\0' to terminate it
128 static char* msvcrt_valisttos(const char* arg0
, va_list alist
, char delim
)
130 va_list alist2
= alist
;
138 /* Return NULL for an empty environment list */
146 size
+= strlen(arg
) + 1;
147 arg
= va_arg(alist
, char*);
148 } while (arg
!= NULL
);
150 ret
= (char*)MSVCRT_malloc(size
+ 1);
158 int len
= strlen(arg
);
162 arg
= va_arg(alist2
, char*);
163 } while (arg
!= NULL
);
168 /*********************************************************************
171 int _cwait(int *status
, int pid
, int action
)
173 HANDLE hPid
= (HANDLE
)pid
;
176 action
= action
; /* Remove warning */
178 if (!WaitForSingleObject(hPid
, -1)) /* wait forever */
183 GetExitCodeProcess(hPid
, &stat
);
188 doserrno
= GetLastError();
190 if (doserrno
== ERROR_INVALID_HANDLE
)
192 SET_THREAD_VAR(errno
, MSVCRT_ECHILD
);
193 SET_THREAD_VAR(doserrno
,doserrno
);
196 MSVCRT__set_errno(doserrno
);
198 return status
? *status
= -1 : -1;
201 /*********************************************************************
204 * Like on Windows, this function does not handle arguments with spaces
207 int _execl(const char* name
, const char* arg0
, ...)
214 args
= msvcrt_valisttos(arg0
, ap
, ' ');
217 ret
= msvcrt_spawn(_P_OVERLAY
, name
, args
, NULL
);
223 /*********************************************************************
226 * Like on Windows, this function does not handle arguments with spaces
229 int _execlp(const char* name
, const char* arg0
, ...)
234 char fullname
[MAX_PATH
];
236 _searchenv(name
, "PATH", fullname
);
239 args
= msvcrt_valisttos(arg0
, ap
, ' ');
242 ret
= msvcrt_spawn(_P_OVERLAY
, fullname
[0] ? fullname
: name
, args
, NULL
);
248 /*********************************************************************
251 * Like on Windows, this function does not handle arguments with spaces
254 int _execv(const char* name
, char* const* argv
)
256 return _spawnve(_P_OVERLAY
, name
, (const char* const*) argv
, NULL
);
259 /*********************************************************************
262 * Like on Windows, this function does not handle arguments with spaces
265 int _execve(const char* name
, char* const* argv
, const char* const* envv
)
267 return _spawnve(_P_OVERLAY
, name
, (const char* const*) argv
, envv
);
270 /*********************************************************************
271 * _execvpe (MSVCRT.@)
273 * Like on Windows, this function does not handle arguments with spaces
276 int _execvpe(const char* name
, char* const* argv
, const char* const* envv
)
278 char fullname
[MAX_PATH
];
280 _searchenv(name
, "PATH", fullname
);
281 return _spawnve(_P_OVERLAY
, fullname
[0] ? fullname
: name
,
282 (const char* const*) argv
, envv
);
285 /*********************************************************************
288 * Like on Windows, this function does not handle arguments with spaces
291 int _execvp(const char* name
, char* const* argv
)
293 return _execvpe(name
, argv
, NULL
);
296 /*********************************************************************
299 * Like on Windows, this function does not handle arguments with spaces
302 int _spawnl(int flags
, const char* name
, const char* arg0
, ...)
309 args
= msvcrt_valisttos(arg0
, ap
, ' ');
312 ret
= msvcrt_spawn(flags
, name
, args
, NULL
);
318 /*********************************************************************
319 * _spawnlp (MSVCRT.@)
321 * Like on Windows, this function does not handle arguments with spaces
324 int _spawnlp(int flags
, const char* name
, const char* arg0
, ...)
329 char fullname
[MAX_PATH
];
331 _searchenv(name
, "PATH", fullname
);
334 args
= msvcrt_valisttos(arg0
, ap
, ' ');
337 ret
= msvcrt_spawn(flags
, fullname
[0] ? fullname
: name
, args
, NULL
);
343 /*********************************************************************
344 * _spawnve (MSVCRT.@)
346 * Like on Windows, this function does not handle arguments with spaces
349 int _spawnve(int flags
, const char* name
, const char* const* argv
,
350 const char* const* envv
)
352 char * args
= msvcrt_argvtos(argv
,' ');
353 char * envs
= msvcrt_argvtos(envv
,0);
354 const char *fullname
= name
;
357 FIXME(":not translating name %s to locate program\n",fullname
);
358 TRACE(":call (%s), params (%s), env (%s)\n",name
,args
,envs
?"Custom":"Null");
362 ret
= msvcrt_spawn(flags
, fullname
, args
, envs
);
371 /*********************************************************************
374 * Like on Windows, this function does not handle arguments with spaces
377 int _spawnv(int flags
, const char* name
, const char* const* argv
)
379 return _spawnve(flags
, name
, argv
, NULL
);
382 /*********************************************************************
383 * _spawnvpe (MSVCRT.@)
385 * Like on Windows, this function does not handle arguments with spaces
388 int _spawnvpe(int flags
, const char* name
, const char* const* argv
,
389 const char* const* envv
)
391 char fullname
[MAX_PATH
];
392 _searchenv(name
, "PATH", fullname
);
393 return _spawnve(flags
, fullname
[0] ? fullname
: name
, argv
, envv
);
396 /*********************************************************************
397 * _spawnvp (MSVCRT.@)
399 * Like on Windows, this function does not handle arguments with spaces
402 int _spawnvp(int flags
, const char* name
, const char* const* argv
)
404 return _spawnvpe(flags
, name
, argv
, NULL
);
407 /*********************************************************************
410 int MSVCRT_system(const char* cmd
)
415 /* Make a writable copy for CreateProcess */
416 cmdcopy
=_strdup(cmd
);
417 /* FIXME: should probably launch cmd interpreter in COMSPEC */
418 res
=msvcrt_spawn(_P_WAIT
, NULL
, cmdcopy
, NULL
);
419 MSVCRT_free(cmdcopy
);
423 /*********************************************************************
424 * _loaddll (MSVCRT.@)
426 int _loaddll(const char* dllname
)
428 return LoadLibraryA(dllname
);
431 /*********************************************************************
432 * _unloaddll (MSVCRT.@)
434 int _unloaddll(int dll
)
436 if (FreeLibrary((HANDLE
)dll
))
440 int err
= GetLastError();
441 MSVCRT__set_errno(err
);