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

Last change on this file since 5120 was 4672, checked in by phaller, 25 years ago

.

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