diff options
author | Ron Yorston <rmy@pobox.com> | 2018-03-15 15:35:24 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-03-15 15:35:24 +0000 |
commit | 701cea96c43d185ebe433df9ecca39ecc9742ef3 (patch) | |
tree | b9b0dcc699f5319f0055d5d29aded690ff37258b | |
parent | 7cc082e2370da69c8783812c251190d316ce82b3 (diff) | |
download | busybox-w32-701cea96c43d185ebe433df9ecca39ecc9742ef3.tar.gz busybox-w32-701cea96c43d185ebe433df9ecca39ecc9742ef3.tar.bz2 busybox-w32-701cea96c43d185ebe433df9ecca39ecc9742ef3.zip |
win32: tidy up popen implementation
Make mingw_popen_fd sufficiently general that it can be used to
implement the other two popen routines.
mingw_popen now just creates a command line and passes it to
mingw_popen_fd. The one call to mingw_popen2 has been replaced
by a call to mingw_popen_fd.
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | networking/wget.c | 3 | ||||
-rw-r--r-- | win32/popen.c | 281 |
3 files changed, 76 insertions, 209 deletions
diff --git a/include/mingw.h b/include/mingw.h index e56e8f03d..386540b37 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -111,7 +111,6 @@ int mingw_rename(const char*, const char*); | |||
111 | 111 | ||
112 | FILE *mingw_popen(const char *cmd, const char *mode); | 112 | FILE *mingw_popen(const char *cmd, const char *mode); |
113 | int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid); | 113 | int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid); |
114 | int mingw_popen2(const char *cmd, pid_t *pid); | ||
115 | int mingw_pclose(FILE *fd); | 114 | int mingw_pclose(FILE *fd); |
116 | #undef popen | 115 | #undef popen |
117 | #undef pclose | 116 | #undef pclose |
diff --git a/networking/wget.c b/networking/wget.c index 776894dca..194bf457a 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -768,7 +768,6 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) | |||
768 | static void spawn_ssl_client(const char *host, int network_fd, int flags) | 768 | static void spawn_ssl_client(const char *host, int network_fd, int flags) |
769 | { | 769 | { |
770 | int fd1; | 770 | int fd1; |
771 | pid_t pid; | ||
772 | char *servername, *p, *cmd; | 771 | char *servername, *p, *cmd; |
773 | 772 | ||
774 | servername = xstrdup(host); | 773 | servername = xstrdup(host); |
@@ -781,7 +780,7 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) | |||
781 | (void *)_get_osfhandle(network_fd), servername, | 780 | (void *)_get_osfhandle(network_fd), servername, |
782 | flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? " -e" : ""); | 781 | flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? " -e" : ""); |
783 | 782 | ||
784 | if ( (fd1=mingw_popen2(cmd, &pid)) == -1 ) { | 783 | if ( (fd1=mingw_popen_fd(cmd, "b", -1, NULL)) == -1 ) { |
785 | bb_perror_msg_and_die("can't execute ssl_client"); | 784 | bb_perror_msg_and_die("can't execute ssl_client"); |
786 | } | 785 | } |
787 | 786 | ||
diff --git a/win32/popen.c b/win32/popen.c index c075e2144..6fc04e169 100644 --- a/win32/popen.c +++ b/win32/popen.c | |||
@@ -12,19 +12,47 @@ typedef struct { | |||
12 | static pipe_data *pipes = NULL; | 12 | static pipe_data *pipes = NULL; |
13 | static int num_pipes = 0; | 13 | static int num_pipes = 0; |
14 | 14 | ||
15 | static int mingw_pipe(HANDLE *readwrite) | 15 | static int mingw_pipe(pipe_data *p, int bidi) |
16 | { | 16 | { |
17 | int ret = 0; | ||
17 | SECURITY_ATTRIBUTES sa; | 18 | SECURITY_ATTRIBUTES sa; |
18 | 19 | ||
19 | sa.nLength = sizeof(sa); /* Length in bytes */ | 20 | sa.nLength = sizeof(sa); /* Length in bytes */ |
20 | sa.bInheritHandle = 1; /* the child must inherit these handles */ | 21 | sa.bInheritHandle = 1; /* the child must inherit these handles */ |
21 | sa.lpSecurityDescriptor = NULL; | 22 | sa.lpSecurityDescriptor = NULL; |
22 | 23 | ||
23 | if ( !CreatePipe (&readwrite[0], &readwrite[1], &sa, 1 << 13) ) { | 24 | if (!bidi) { |
24 | return -1; | 25 | /* pipe[0] is the read handle, pipe[i] the write handle */ |
26 | if ( !CreatePipe (&p->pipe[0], &p->pipe[1], &sa, 1 << 13) ) { | ||
27 | return -1; | ||
28 | } | ||
29 | } | ||
30 | else { | ||
31 | char *name; | ||
32 | const int ip = 1; /* index of parent end of pipe */ | ||
33 | const int ic = 0; /* index of child end of pipe */ | ||
34 | |||
35 | name = xasprintf("\\\\.\\pipe\\bb_pipe.%d.%d", getpid(), | ||
36 | (int)(p-pipes)); | ||
37 | |||
38 | p->pipe[ip] = CreateNamedPipe(name, | ||
39 | PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, | ||
40 | PIPE_TYPE_BYTE|PIPE_WAIT, | ||
41 | 1, 4096, 4096, 0, &sa); | ||
42 | |||
43 | p->pipe[ic] = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, &sa, | ||
44 | OPEN_EXISTING, | ||
45 | FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, | ||
46 | NULL); | ||
47 | if (p->pipe[ip] == INVALID_HANDLE_VALUE || | ||
48 | p->pipe[ic] == INVALID_HANDLE_VALUE) { | ||
49 | ret = -1; | ||
50 | } | ||
51 | |||
52 | free(name); | ||
25 | } | 53 | } |
26 | 54 | ||
27 | return 0; | 55 | return ret; |
28 | } | 56 | } |
29 | 57 | ||
30 | static pipe_data *find_pipe(void) | 58 | static pipe_data *find_pipe(void) |
@@ -56,19 +84,16 @@ static pipe_data *find_pipe(void) | |||
56 | 84 | ||
57 | p->pipe[0] = INVALID_HANDLE_VALUE; | 85 | p->pipe[0] = INVALID_HANDLE_VALUE; |
58 | p->pipe[1] = INVALID_HANDLE_VALUE; | 86 | p->pipe[1] = INVALID_HANDLE_VALUE; |
87 | p->fd = -1; | ||
59 | 88 | ||
60 | return p; | 89 | return p; |
61 | } | 90 | } |
62 | 91 | ||
63 | FILE *mingw_popen(const char *cmd, const char *mode) | 92 | FILE *mingw_popen(const char *cmd, const char *mode) |
64 | { | 93 | { |
65 | pipe_data *p; | ||
66 | FILE *fptr = NULL; | 94 | FILE *fptr = NULL; |
67 | STARTUPINFO siStartInfo; | ||
68 | int success; | ||
69 | int fd; | 95 | int fd; |
70 | int len, count; | 96 | int len, count; |
71 | int ip, ic; | ||
72 | char *cmd_buff = NULL; | 97 | char *cmd_buff = NULL; |
73 | const char *s; | 98 | const char *s; |
74 | char *t; | 99 | char *t; |
@@ -78,11 +103,6 @@ FILE *mingw_popen(const char *cmd, const char *mode) | |||
78 | return NULL; | 103 | return NULL; |
79 | } | 104 | } |
80 | 105 | ||
81 | /* find an unused pipe structure */ | ||
82 | if ( (p=find_pipe()) == NULL ) { | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | /* count double quotes */ | 106 | /* count double quotes */ |
87 | count = 0; | 107 | count = 0; |
88 | for ( s=cmd; *s; ++s ) { | 108 | for ( s=cmd; *s; ++s ) { |
@@ -117,84 +137,25 @@ FILE *mingw_popen(const char *cmd, const char *mode) | |||
117 | *t = '\0'; | 137 | *t = '\0'; |
118 | 138 | ||
119 | /* Create the pipe */ | 139 | /* Create the pipe */ |
120 | if ( mingw_pipe(p->pipe) == -1 ) { | 140 | if ((fd=mingw_popen_fd(cmd_buff, mode, -1, NULL)) != -1) { |
121 | goto finito; | 141 | fptr = _fdopen(fd, *mode == 'r' ? "rb" : "wb"); |
122 | } | ||
123 | |||
124 | /* index of parent end of pipe */ | ||
125 | ip = !(*mode == 'r'); | ||
126 | /* index of child end of pipe */ | ||
127 | ic = (*mode == 'r'); | ||
128 | |||
129 | /* Make the parent end of the pipe non-inheritable */ | ||
130 | SetHandleInformation(p->pipe[ip], HANDLE_FLAG_INHERIT, 0); | ||
131 | |||
132 | /* Now create the child process */ | ||
133 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); | ||
134 | siStartInfo.cb = sizeof(STARTUPINFO); | ||
135 | if ( *mode == 'r' ) { | ||
136 | siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | ||
137 | siStartInfo.hStdOutput = p->pipe[ic]; | ||
138 | } | 142 | } |
139 | else { | ||
140 | siStartInfo.hStdInput = p->pipe[ic]; | ||
141 | siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); | ||
142 | } | ||
143 | siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); | ||
144 | siStartInfo.wShowWindow = SW_HIDE; | ||
145 | siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; | ||
146 | |||
147 | success = CreateProcess(NULL, | ||
148 | (LPTSTR)cmd_buff, /* command line */ | ||
149 | NULL, /* process security attributes */ | ||
150 | NULL, /* primary thread security attributes */ | ||
151 | TRUE, /* handles are inherited */ | ||
152 | 0, /* creation flags */ | ||
153 | NULL, /* use parent's environment */ | ||
154 | NULL, /* use parent's current directory */ | ||
155 | &siStartInfo, /* STARTUPINFO pointer */ | ||
156 | &p->piProcInfo); /* receives PROCESS_INFORMATION */ | ||
157 | 143 | ||
158 | if ( !success ) { | ||
159 | goto finito; | ||
160 | } | ||
161 | |||
162 | /* close child end of pipe */ | ||
163 | CloseHandle(p->pipe[ic]); | ||
164 | p->pipe[ic] = INVALID_HANDLE_VALUE; | ||
165 | |||
166 | if ( *mode == 'r' ) { | ||
167 | fd = _open_osfhandle((intptr_t)p->pipe[ip], _O_RDONLY|_O_BINARY); | ||
168 | fptr = _fdopen(fd, "rb"); | ||
169 | } | ||
170 | else { | ||
171 | fd = _open_osfhandle((intptr_t)p->pipe[ip], _O_WRONLY|_O_BINARY); | ||
172 | fptr = _fdopen(fd, "wb"); | ||
173 | } | ||
174 | |||
175 | finito: | ||
176 | if ( !fptr ) { | ||
177 | if ( p->pipe[0] != INVALID_HANDLE_VALUE ) { | ||
178 | CloseHandle(p->pipe[0]); | ||
179 | } | ||
180 | if ( p->pipe[1] != INVALID_HANDLE_VALUE ) { | ||
181 | CloseHandle(p->pipe[1]); | ||
182 | } | ||
183 | } | ||
184 | else { | ||
185 | p->mode = *mode; | ||
186 | p->fd = fd; | ||
187 | } | ||
188 | free(cmd_buff); | 144 | free(cmd_buff); |
189 | 145 | ||
190 | return fptr; | 146 | return fptr; |
191 | } | 147 | } |
192 | 148 | ||
193 | /* | 149 | /* |
194 | * Open a pipe to a command where the file descriptor fd0 is used | 150 | * Open a pipe to a command. |
195 | * as input to the command (read mode) or as the destination of the | 151 | * |
196 | * output from the command (write mode). The pid of the command is | 152 | * - mode may be "r", "w" or "b" for read-only, write-only or |
197 | * returned in the variable pid, which can be NULL. | 153 | * bidirectional (from the perspective of the parent). |
154 | * - if fd0 is a valid file descriptor it's used as input to the | ||
155 | * command ("r") or as the destination of the output from the | ||
156 | * command ("w"). Otherwise (and if not "b") use stdin or stdout. | ||
157 | * - the pid of the command is returned in the variable pid, which | ||
158 | * can be NULL if the pid is not required. | ||
198 | */ | 159 | */ |
199 | int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) | 160 | int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) |
200 | { | 161 | { |
@@ -202,110 +163,29 @@ int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) | |||
202 | STARTUPINFO siStartInfo; | 163 | STARTUPINFO siStartInfo; |
203 | int success; | 164 | int success; |
204 | int fd = -1; | 165 | int fd = -1; |
205 | int ip, ic; | 166 | int ip, ic, flags; |
206 | 167 | ||
207 | if ( cmd == NULL || *cmd == '\0' || mode == NULL || | 168 | if ( cmd == NULL || *cmd == '\0' || mode == NULL ) { |
208 | (*mode != 'r' && *mode != 'w') ) { | ||
209 | return -1; | 169 | return -1; |
210 | } | 170 | } |
211 | 171 | ||
212 | /* find an unused pipe structure */ | 172 | switch (*mode) { |
213 | if ( (p=find_pipe()) == NULL ) { | 173 | case 'r': |
214 | return -1; | 174 | ip = 0; |
215 | } | 175 | flags = _O_RDONLY|_O_BINARY; |
216 | 176 | break; | |
217 | /* Create the pipe */ | 177 | case 'w': |
218 | if ( mingw_pipe(p->pipe) == -1 ) { | 178 | ip = 1; |
219 | goto finito; | 179 | flags = _O_WRONLY|_O_BINARY; |
220 | } | 180 | break; |
221 | 181 | case 'b': | |
222 | /* index of parent end of pipe */ | 182 | ip = 1; |
223 | ip = !(*mode == 'r'); | 183 | flags = _O_RDWR|_O_BINARY; |
224 | /* index of child end of pipe */ | 184 | break; |
225 | ic = (*mode == 'r'); | 185 | default: |
226 | |||
227 | /* Make the parent end of the pipe non-inheritable */ | ||
228 | SetHandleInformation(p->pipe[ip], HANDLE_FLAG_INHERIT, 0); | ||
229 | |||
230 | /* Now create the child process */ | ||
231 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); | ||
232 | siStartInfo.cb = sizeof(STARTUPINFO); | ||
233 | if ( *mode == 'r' ) { | ||
234 | siStartInfo.hStdInput = (HANDLE)_get_osfhandle(fd0); | ||
235 | siStartInfo.hStdOutput = p->pipe[ic]; | ||
236 | } | ||
237 | else { | ||
238 | siStartInfo.hStdInput = p->pipe[ic]; | ||
239 | siStartInfo.hStdOutput = (HANDLE)_get_osfhandle(fd0); | ||
240 | } | ||
241 | siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); | ||
242 | siStartInfo.wShowWindow = SW_HIDE; | ||
243 | siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; | ||
244 | |||
245 | success = CreateProcess(NULL, | ||
246 | (LPTSTR)cmd, /* command line */ | ||
247 | NULL, /* process security attributes */ | ||
248 | NULL, /* primary thread security attributes */ | ||
249 | TRUE, /* handles are inherited */ | ||
250 | 0, /* creation flags */ | ||
251 | NULL, /* use parent's environment */ | ||
252 | NULL, /* use parent's current directory */ | ||
253 | &siStartInfo, /* STARTUPINFO pointer */ | ||
254 | &p->piProcInfo); /* receives PROCESS_INFORMATION */ | ||
255 | |||
256 | if ( !success ) { | ||
257 | goto finito; | ||
258 | } | ||
259 | |||
260 | /* close child end of pipe */ | ||
261 | CloseHandle(p->pipe[ic]); | ||
262 | p->pipe[ic] = INVALID_HANDLE_VALUE; | ||
263 | |||
264 | if ( *mode == 'r' ) { | ||
265 | fd = _open_osfhandle((intptr_t)p->pipe[ip], _O_RDONLY|_O_BINARY); | ||
266 | } | ||
267 | else { | ||
268 | fd = _open_osfhandle((intptr_t)p->pipe[ip], _O_WRONLY|_O_BINARY); | ||
269 | } | ||
270 | |||
271 | finito: | ||
272 | if ( fd == -1 ) { | ||
273 | if ( p->pipe[0] != INVALID_HANDLE_VALUE ) { | ||
274 | CloseHandle(p->pipe[0]); | ||
275 | } | ||
276 | if ( p->pipe[1] != INVALID_HANDLE_VALUE ) { | ||
277 | CloseHandle(p->pipe[1]); | ||
278 | } | ||
279 | } | ||
280 | else { | ||
281 | p->mode = *mode; | ||
282 | p->fd = fd; | ||
283 | if ( pid ) { | ||
284 | *pid = (pid_t)p->piProcInfo.dwProcessId; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return fd; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Open a bidirectional pipe to a command. The pid of the command is | ||
293 | * returned in the variable pid, which can be NULL. | ||
294 | */ | ||
295 | int mingw_popen2(const char *cmd, pid_t *pid) | ||
296 | { | ||
297 | pipe_data *p; | ||
298 | char *name = NULL; | ||
299 | SECURITY_ATTRIBUTES sa; | ||
300 | STARTUPINFO siStartInfo; | ||
301 | int success; | ||
302 | int fd = -1; | ||
303 | const int ip = 1; /* index of parent end of pipe */ | ||
304 | const int ic = 0; /* index of child end of pipe */ | ||
305 | |||
306 | if ( cmd == NULL || *cmd == '\0' ) { | ||
307 | return -1; | 186 | return -1; |
308 | } | 187 | } |
188 | ic = !ip; | ||
309 | 189 | ||
310 | /* find an unused pipe structure */ | 190 | /* find an unused pipe structure */ |
311 | if ( (p=find_pipe()) == NULL ) { | 191 | if ( (p=find_pipe()) == NULL ) { |
@@ -313,26 +193,7 @@ int mingw_popen2(const char *cmd, pid_t *pid) | |||
313 | } | 193 | } |
314 | 194 | ||
315 | /* Create the pipe */ | 195 | /* Create the pipe */ |
316 | name = xasprintf("\\\\.\\pipe\\bb_pipe.%d.%d", getpid(), (int)(p-pipes)); | 196 | if ( mingw_pipe(p, *mode == 'b') == -1 ) { |
317 | |||
318 | sa.nLength = sizeof(sa); /* Length in bytes */ | ||
319 | sa.bInheritHandle = 1; /* the child must inherit these handles */ | ||
320 | sa.lpSecurityDescriptor = NULL; | ||
321 | |||
322 | p->pipe[ip] = CreateNamedPipe(name, | ||
323 | PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, | ||
324 | PIPE_TYPE_BYTE|PIPE_WAIT, | ||
325 | 1, 4096, 4096, 0, &sa); | ||
326 | if (p->pipe[ip] == INVALID_HANDLE_VALUE) { | ||
327 | goto finito; | ||
328 | } | ||
329 | |||
330 | /* Connect to the pipe */ | ||
331 | p->pipe[ic] = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, &sa, | ||
332 | OPEN_EXISTING, | ||
333 | FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, | ||
334 | NULL); | ||
335 | if (p->pipe[ic] == INVALID_HANDLE_VALUE) { | ||
336 | goto finito; | 197 | goto finito; |
337 | } | 198 | } |
338 | 199 | ||
@@ -342,10 +203,20 @@ int mingw_popen2(const char *cmd, pid_t *pid) | |||
342 | /* Now create the child process */ | 203 | /* Now create the child process */ |
343 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); | 204 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); |
344 | siStartInfo.cb = sizeof(STARTUPINFO); | 205 | siStartInfo.cb = sizeof(STARTUPINFO); |
345 | siStartInfo.wShowWindow = SW_HIDE; | 206 | /* default settings for a bidirectional pipe */ |
346 | siStartInfo.hStdInput = p->pipe[ic]; | 207 | siStartInfo.hStdInput = p->pipe[ic]; |
347 | siStartInfo.hStdOutput = p->pipe[ic]; | 208 | siStartInfo.hStdOutput = p->pipe[ic]; |
209 | /* override for read-only or write-only */ | ||
210 | if ( *mode == 'r' ) { | ||
211 | siStartInfo.hStdInput = fd0 >= 0 ? (HANDLE)_get_osfhandle(fd0) : | ||
212 | GetStdHandle(STD_INPUT_HANDLE); | ||
213 | } | ||
214 | else if ( *mode == 'w' ) { | ||
215 | siStartInfo.hStdOutput = fd0 >= 0 ? (HANDLE)_get_osfhandle(fd0) : | ||
216 | GetStdHandle(STD_OUTPUT_HANDLE); | ||
217 | } | ||
348 | siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); | 218 | siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
219 | siStartInfo.wShowWindow = SW_HIDE; | ||
349 | siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; | 220 | siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; |
350 | 221 | ||
351 | success = CreateProcess(NULL, | 222 | success = CreateProcess(NULL, |
@@ -367,12 +238,10 @@ int mingw_popen2(const char *cmd, pid_t *pid) | |||
367 | CloseHandle(p->pipe[ic]); | 238 | CloseHandle(p->pipe[ic]); |
368 | p->pipe[ic] = INVALID_HANDLE_VALUE; | 239 | p->pipe[ic] = INVALID_HANDLE_VALUE; |
369 | 240 | ||
370 | fd = _open_osfhandle((intptr_t)p->pipe[ip], _O_RDWR|_O_BINARY); | 241 | fd = _open_osfhandle((intptr_t)p->pipe[ip], flags); |
371 | 242 | ||
372 | finito: | 243 | finito: |
373 | free(name); | ||
374 | if ( fd == -1 ) { | 244 | if ( fd == -1 ) { |
375 | errno = err_win_to_posix(GetLastError()); | ||
376 | if ( p->pipe[0] != INVALID_HANDLE_VALUE ) { | 245 | if ( p->pipe[0] != INVALID_HANDLE_VALUE ) { |
377 | CloseHandle(p->pipe[0]); | 246 | CloseHandle(p->pipe[0]); |
378 | } | 247 | } |
@@ -381,7 +250,7 @@ finito: | |||
381 | } | 250 | } |
382 | } | 251 | } |
383 | else { | 252 | else { |
384 | p->mode = 'r'; | 253 | p->mode = *mode; |
385 | p->fd = fd; | 254 | p->fd = fd; |
386 | if ( pid ) { | 255 | if ( pid ) { |
387 | *pid = (pid_t)p->piProcInfo.dwProcessId; | 256 | *pid = (pid_t)p->piProcInfo.dwProcessId; |