aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-03-15 15:35:24 +0000
committerRon Yorston <rmy@pobox.com>2018-03-15 15:35:24 +0000
commit701cea96c43d185ebe433df9ecca39ecc9742ef3 (patch)
treeb9b0dcc699f5319f0055d5d29aded690ff37258b
parent7cc082e2370da69c8783812c251190d316ce82b3 (diff)
downloadbusybox-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.h1
-rw-r--r--networking/wget.c3
-rw-r--r--win32/popen.c281
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
112FILE *mingw_popen(const char *cmd, const char *mode); 112FILE *mingw_popen(const char *cmd, const char *mode);
113int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid); 113int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid);
114int mingw_popen2(const char *cmd, pid_t *pid);
115int mingw_pclose(FILE *fd); 114int 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)
768static void spawn_ssl_client(const char *host, int network_fd, int flags) 768static 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 {
12static pipe_data *pipes = NULL; 12static pipe_data *pipes = NULL;
13static int num_pipes = 0; 13static int num_pipes = 0;
14 14
15static int mingw_pipe(HANDLE *readwrite) 15static 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
30static pipe_data *find_pipe(void) 58static 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
63FILE *mingw_popen(const char *cmd, const char *mode) 92FILE *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
175finito:
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 */
199int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) 160int 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
271finito:
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 */
295int 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
372finito: 243finito:
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;