source: trunk/src/crtdll/spawn.c@ 6645

Last change on this file since 6645 was 6645, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 4.9 KB
Line 
1/* $Id: spawn.c,v 1.3 2001-09-05 12:14:25 bird Exp $ */
2/*
3 * CRTDLL spawn functions
4 *
5 * Copyright 1996,1998 Marcus Meissner
6 * Copyright 1996 Jukka Iivonen
7 * Copyright 1997,2000 Uwe Bonnes
8 * Copyright 2000 Jon Griffiths
9 *
10 * These functions differ in whether they pass arguments as an array
11 * (v in the name) or as varags (l in the name), whether they
12 * seach the path (p in the name) and/or whether they take an
13 * environment (e in the name) or pass the parents environment.
14 * Args as Search Take
15 * Name varargs? path? environment?
16 * spawnl N N N
17 * spawnle N N Y
18 * spawnlp N Y N
19 * spawnlpe N Y Y
20 * spawnv Y N N
21 * spawnve Y N Y
22 * spawnvp Y Y N
23 * spawnvpe Y Y Y
24 *
25 * Implementation Notes:
26 * MT Safe - But only because of missing functionality.
27 *
28 * After translating input arguments into the required format for
29 * CreateProcess(), the internal function __CRTDLL__spawn() is
30 * called to perform the actual spawning.
31 *
32 * FIXME:
33 * -File handles need some special handling. Sometimes children get
34 * open file handles, sometimes not. The docs are confusing.
35 * -No check for maximum path/argument/environment size is done.
36 * -Wine has a "process.h" which is not the same as any crt version.
37 * Unresolved issues Uwe Bonnes 970904:
38 * -system-call calls another wine process, but without debugging arguments
39 * and uses the first wine executable in the path
40 */
41
42#include "crtdll.h"
43#include <errno.h>
44#include "process.h"
45#include <stdlib.h>
46#include <string.h>
47
48
49DEFAULT_DEBUG_CHANNEL(crtdll);
50
51/* Process creation flags */
52#define _P_WAIT 0
53#define _P_NOWAIT 1
54#define _P_OVERLAY 2
55#define _P_NOWAITO 3
56#define _P_DETACH 4
57
58
59extern void __CRTDLL__set_errno(ULONG err);
60extern LPVOID CDECL CRTDLL_calloc(DWORD size, DWORD count);
61extern VOID CDECL CRTDLL_free(void *ptr);
62extern VOID CDECL CRTDLL__exit(LONG ret);
63extern INT CRTDLL_doserrno;
64
65
66/* INTERNAL: Spawn a child process */
67static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env);
68static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
69{
70 STARTUPINFOA si;
71 PROCESS_INFORMATION pi;
72
73 if ((unsigned)flags > _P_DETACH)
74 {
75 CRTDLL_errno = EINVAL;
76 return -1;
77 }
78
79 FIXME(":must dup/kill streams for child process\n");
80
81 memset(&si, 0, sizeof(si));
82 si.cb = sizeof(si);
83
84 if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
85 flags == _P_DETACH ? DETACHED_PROCESS : 0,
86 env, NULL, &si, &pi))
87 {
88 __CRTDLL__set_errno(GetLastError());
89 return -1;
90 }
91
92 switch(flags)
93 {
94 case _P_WAIT:
95 WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
96 GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
97 CloseHandle(pi.hProcess);
98 CloseHandle(pi.hThread);
99 return pi.dwProcessId;
100 case _P_DETACH:
101 CloseHandle(pi.hProcess);
102 pi.hProcess = 0;
103 /* fall through */
104 case _P_NOWAIT:
105 case _P_NOWAITO:
106 CloseHandle(pi.hThread);
107 return pi.hProcess;
108 case _P_OVERLAY:
109 CRTDLL__exit(0);
110 }
111 return -1; /* cant reach here */
112}
113
114
115/* INTERNAL: Convert argv list to a single 'delim'-seperated string */
116static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim);
117static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
118{
119 LPSTR *search = arg;
120 LONG size = 0;
121 LPSTR ret;
122
123 if (!arg && !delim)
124 return NULL;
125
126 /* get length */
127 while(*search)
128 {
129 size += strlen(*search) + 1;
130 search++;
131 }
132
133 if (!(ret = (LPSTR)CRTDLL_calloc(size + 1, 1)))
134 return NULL;
135
136 /* fill string */
137 search = arg;
138 size = 0;
139 while(*search)
140 {
141 int strsize = strlen(*search);
142 memcpy(ret+size,*search,strsize);
143 ret[size+strsize] = delim;
144 size += strsize + 1;
145 search++;
146 }
147 return ret;
148}
149
150
151/*********************************************************************
152 * _spawnve (CRTDLL.274)
153 *
154 * Spawn a process.
155 *
156 */
157HANDLE CDECL CRTDLL__spawnve(INT flags, LPSTR name, LPSTR *argv, LPSTR *envv)
158{
159 // return (_spawnve(i, s1, s2, s3));
160
161 LPSTR args = __CRTDLL__argvtos(argv,' ');
162 LPSTR envs = __CRTDLL__argvtos(envv,0);
163 LPSTR fullname = name;
164
165 FIXME(":not translating name %s to locate program\n",fullname);
166 TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
167
168 if (args)
169 {
170 HANDLE ret = __CRTDLL__spawn(flags, fullname, args, envs);
171 CRTDLL_free(args);
172 CRTDLL_free(envs);
173 return ret;
174 }
175 if (envs)
176 CRTDLL_free(envs);
177
178 WARN(":No argv[0] passed - process will not be executed");
179 return -1;
180}
181
182
183/*********************************************************************
184 * system (CRTDLL.485)
185 */
186INT CDECL CRTDLL_system(LPSTR x)
187{
188 // return system(string);
189
190 /* FIXME: should probably launch cmd interpreter in COMSPEC */
191 return __CRTDLL__spawn(_P_WAIT, NULL, x, NULL);
192}
Note: See TracBrowser for help on using the repository browser.