Portability fixes.
[wine.git] / dlls / msvcrt / process.c
blob0ed72a52ac9c4ba9c5effcbf07b85b211777fbc5
1 /*
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
23 * FIXME:
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
28 #include "config.h"
30 #include <stdarg.h>
32 #include "msvcrt.h"
33 #include "msvcrt/errno.h"
35 #include "msvcrt/process.h"
36 #include "msvcrt/stdlib.h"
37 #include "msvcrt/string.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
43 /* FIXME: Check file extensions for app to run */
44 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
45 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
46 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
47 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
49 /* INTERNAL: Spawn a child process */
50 static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
52 STARTUPINFOA si;
53 PROCESS_INFORMATION pi;
55 if (sizeof(HANDLE) != sizeof(int))
56 WARN("This call is unsuitable for your architecture\n");
58 if ((unsigned)flags > _P_DETACH)
60 *MSVCRT__errno() = MSVCRT_EINVAL;
61 return -1;
64 FIXME(":must dup/kill streams for child process\n");
66 memset(&si, 0, sizeof(si));
67 si.cb = sizeof(si);
69 if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
70 flags == _P_DETACH ? DETACHED_PROCESS : 0,
71 env, NULL, &si, &pi))
73 MSVCRT__set_errno(GetLastError());
74 return -1;
77 switch(flags)
79 case _P_WAIT:
80 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
81 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
82 CloseHandle(pi.hProcess);
83 CloseHandle(pi.hThread);
84 return (int)pi.dwProcessId;
85 case _P_DETACH:
86 CloseHandle(pi.hProcess);
87 pi.hProcess = 0;
88 /* fall through */
89 case _P_NOWAIT:
90 case _P_NOWAITO:
91 CloseHandle(pi.hThread);
92 return (int)pi.hProcess;
93 case _P_OVERLAY:
94 MSVCRT__exit(0);
96 return -1; /* can't reach here */
99 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
100 * extra '\0' to terminate it
102 static char* msvcrt_argvtos(const char* const* arg, char delim)
104 const char* const* a;
105 long size;
106 char* p;
107 char* ret;
109 if (!arg && !delim)
111 /* Return NULL for an empty environment list */
112 return NULL;
115 /* get length */
116 a = arg;
117 size = 0;
118 while (*a)
120 size += strlen(*a) + 1;
121 a++;
124 ret = (char*)MSVCRT_malloc(size + 1);
125 if (!ret)
126 return NULL;
128 /* fill string */
129 a = arg;
130 p = ret;
131 while (*a)
133 int len = strlen(*a);
134 memcpy(p,*a,len);
135 p += len;
136 *p++ = delim;
137 a++;
139 if (delim && p > ret) p[-1] = 0;
140 else *p = 0;
141 return ret;
144 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
145 * extra '\0' to terminate it
147 static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
149 va_list alist2;
150 long size;
151 const char *arg;
152 char* p;
153 char *ret;
155 #if HAVE_VA_COPY
156 va_copy(alist2,alist);
157 #else
158 # if HAVE___VA_COPY
159 __va_copy(alist2,alist);
160 # else
161 alist2 = alist;
162 # endif
163 #endif
165 if (!arg0 && !delim)
167 /* Return NULL for an empty environment list */
168 return NULL;
171 /* get length */
172 arg = arg0;
173 size = 0;
174 do {
175 size += strlen(arg) + 1;
176 arg = va_arg(alist, char*);
177 } while (arg != NULL);
179 ret = (char*)MSVCRT_malloc(size + 1);
180 if (!ret)
181 return NULL;
183 /* fill string */
184 arg = arg0;
185 p = ret;
186 do {
187 int len = strlen(arg);
188 memcpy(p,arg,len);
189 p += len;
190 *p++ = delim;
191 arg = va_arg(alist2, char*);
192 } while (arg != NULL);
193 if (delim && p > ret) p[-1] = 0;
194 else *p = 0;
195 return ret;
198 /*********************************************************************
199 * _cwait (MSVCRT.@)
201 int _cwait(int *status, int pid, int action)
203 HANDLE hPid = (HANDLE)pid;
204 int doserrno;
206 action = action; /* Remove warning */
208 if (!WaitForSingleObject(hPid, -1)) /* wait forever */
210 if (status)
212 DWORD stat;
213 GetExitCodeProcess(hPid, &stat);
214 *status = (int)stat;
216 return (int)pid;
218 doserrno = GetLastError();
220 if (doserrno == ERROR_INVALID_HANDLE)
222 *MSVCRT__errno() = MSVCRT_ECHILD;
223 *__doserrno() = doserrno;
225 else
226 MSVCRT__set_errno(doserrno);
228 return status ? *status = -1 : -1;
231 /*********************************************************************
232 * _execl (MSVCRT.@)
234 * Like on Windows, this function does not handle arguments with spaces
235 * or double-quotes.
237 int _execl(const char* name, const char* arg0, ...)
239 va_list ap;
240 char * args;
241 int ret;
243 va_start(ap, arg0);
244 args = msvcrt_valisttos(arg0, ap, ' ');
245 va_end(ap);
247 ret = msvcrt_spawn(_P_OVERLAY, name, args, NULL);
248 MSVCRT_free(args);
250 return ret;
253 /*********************************************************************
254 * _execlp (MSVCRT.@)
256 * Like on Windows, this function does not handle arguments with spaces
257 * or double-quotes.
259 int _execlp(const char* name, const char* arg0, ...)
261 va_list ap;
262 char * args;
263 int ret;
264 char fullname[MAX_PATH];
266 _searchenv(name, "PATH", fullname);
268 va_start(ap, arg0);
269 args = msvcrt_valisttos(arg0, ap, ' ');
270 va_end(ap);
272 ret = msvcrt_spawn(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL);
273 MSVCRT_free(args);
275 return ret;
278 /*********************************************************************
279 * _execv (MSVCRT.@)
281 * Like on Windows, this function does not handle arguments with spaces
282 * or double-quotes.
284 int _execv(const char* name, char* const* argv)
286 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, NULL);
289 /*********************************************************************
290 * _execve (MSVCRT.@)
292 * Like on Windows, this function does not handle arguments with spaces
293 * or double-quotes.
295 int _execve(const char* name, char* const* argv, const char* const* envv)
297 return _spawnve(_P_OVERLAY, name, (const char* const*) argv, envv);
300 /*********************************************************************
301 * _execvpe (MSVCRT.@)
303 * Like on Windows, this function does not handle arguments with spaces
304 * or double-quotes.
306 int _execvpe(const char* name, char* const* argv, const char* const* envv)
308 char fullname[MAX_PATH];
310 _searchenv(name, "PATH", fullname);
311 return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name,
312 (const char* const*) argv, envv);
315 /*********************************************************************
316 * _execvp (MSVCRT.@)
318 * Like on Windows, this function does not handle arguments with spaces
319 * or double-quotes.
321 int _execvp(const char* name, char* const* argv)
323 return _execvpe(name, argv, NULL);
326 /*********************************************************************
327 * _spawnl (MSVCRT.@)
329 * Like on Windows, this function does not handle arguments with spaces
330 * or double-quotes.
332 int _spawnl(int flags, const char* name, const char* arg0, ...)
334 va_list ap;
335 char * args;
336 int ret;
338 va_start(ap, arg0);
339 args = msvcrt_valisttos(arg0, ap, ' ');
340 va_end(ap);
342 ret = msvcrt_spawn(flags, name, args, NULL);
343 MSVCRT_free(args);
345 return ret;
348 /*********************************************************************
349 * _spawnlp (MSVCRT.@)
351 * Like on Windows, this function does not handle arguments with spaces
352 * or double-quotes.
354 int _spawnlp(int flags, const char* name, const char* arg0, ...)
356 va_list ap;
357 char * args;
358 int ret;
359 char fullname[MAX_PATH];
361 _searchenv(name, "PATH", fullname);
363 va_start(ap, arg0);
364 args = msvcrt_valisttos(arg0, ap, ' ');
365 va_end(ap);
367 ret = msvcrt_spawn(flags, fullname[0] ? fullname : name, args, NULL);
368 MSVCRT_free(args);
370 return ret;
373 /*********************************************************************
374 * _spawnve (MSVCRT.@)
376 * Like on Windows, this function does not handle arguments with spaces
377 * or double-quotes.
379 int _spawnve(int flags, const char* name, const char* const* argv,
380 const char* const* envv)
382 char * args = msvcrt_argvtos(argv,' ');
383 char * envs = msvcrt_argvtos(envv,0);
384 const char *fullname = name;
385 int ret = -1;
387 FIXME(":not translating name %s to locate program\n",fullname);
388 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
390 if (args)
392 ret = msvcrt_spawn(flags, fullname, args, envs);
393 MSVCRT_free(args);
395 if (envs)
396 MSVCRT_free(envs);
398 return ret;
401 /*********************************************************************
402 * _spawnv (MSVCRT.@)
404 * Like on Windows, this function does not handle arguments with spaces
405 * or double-quotes.
407 int _spawnv(int flags, const char* name, const char* const* argv)
409 return _spawnve(flags, name, argv, NULL);
412 /*********************************************************************
413 * _spawnvpe (MSVCRT.@)
415 * Like on Windows, this function does not handle arguments with spaces
416 * or double-quotes.
418 int _spawnvpe(int flags, const char* name, const char* const* argv,
419 const char* const* envv)
421 char fullname[MAX_PATH];
422 _searchenv(name, "PATH", fullname);
423 return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
426 /*********************************************************************
427 * _spawnvp (MSVCRT.@)
429 * Like on Windows, this function does not handle arguments with spaces
430 * or double-quotes.
432 int _spawnvp(int flags, const char* name, const char* const* argv)
434 return _spawnvpe(flags, name, argv, NULL);
437 /*********************************************************************
438 * system (MSVCRT.@)
440 int MSVCRT_system(const char* cmd)
442 char* cmdcopy;
443 int res;
445 /* Make a writable copy for CreateProcess */
446 cmdcopy=_strdup(cmd);
447 /* FIXME: should probably launch cmd interpreter in COMSPEC */
448 res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
449 MSVCRT_free(cmdcopy);
450 return res;
453 /*********************************************************************
454 * _loaddll (MSVCRT.@)
456 int _loaddll(const char* dllname)
458 return (int)LoadLibraryA(dllname);
461 /*********************************************************************
462 * _unloaddll (MSVCRT.@)
464 int _unloaddll(int dll)
466 if (FreeLibrary((HMODULE)dll))
467 return 0;
468 else
470 int err = GetLastError();
471 MSVCRT__set_errno(err);
472 return err;
476 /*********************************************************************
477 * _getdllprocaddr (MSVCRT.@)
479 void *_getdllprocaddr(int dll, const char *name, int ordinal)
481 if (name)
483 if (ordinal != -1) return NULL;
484 return GetProcAddress( (HMODULE)dll, name );
486 if (HIWORD(ordinal)) return NULL;
487 return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );