diff options
author | Ron Yorston <rmy@pobox.com> | 2023-12-20 13:45:32 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-12-20 13:59:17 +0000 |
commit | 8d85a4a5be88931978fad594b94e762313d37afc (patch) | |
tree | 0f964f6cd9b0c71b02de5011a2f815e1470c8740 /win32/process.c | |
parent | 4f9b703c31e6360d1e7ffe7d3410e42e5118b4fd (diff) | |
download | busybox-w32-8d85a4a5be88931978fad594b94e762313d37afc.tar.gz busybox-w32-8d85a4a5be88931978fad594b94e762313d37afc.tar.bz2 busybox-w32-8d85a4a5be88931978fad594b94e762313d37afc.zip |
httpd: enable support for CGI
The upstream code uses fork/exec when running a CGI process.
Emulate this by:
- Spawning a child httpd process with the special '-I 0' option,
along with the options provided on the server command line. This
sets up the proper state then calls the cgi_handler() function.
- The cgi_handler() function fixes the pipe file descriptors and
starts another child process to run the CGI script.
These processes are detached from the console on creation. When
spawn() functions are run in P_DETACH mode they don't connect to
the standard file descriptors. Normally this doesn't matter but
the process which runs the CGI scripts needs to inherit the pipe
endpoints. The create_detached_process() function handles this.
See:
https://github.com/rprichard/win32-console-docs/blob/master/README.md
Adds about 2.9Kb to the size of the binary.
(GitHub issue #266)
Diffstat (limited to 'win32/process.c')
-rw-r--r-- | win32/process.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/win32/process.c b/win32/process.c index b51f25d5c..35480e08d 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -248,6 +248,51 @@ grow_argv(char **argv, int n) | |||
248 | return new_argv; | 248 | return new_argv; |
249 | } | 249 | } |
250 | 250 | ||
251 | #if ENABLE_FEATURE_HTTPD_CGI | ||
252 | static int | ||
253 | create_detached_process(const char *prog, char *const *argv) | ||
254 | { | ||
255 | int argc, i; | ||
256 | char *command = NULL; | ||
257 | STARTUPINFO siStartInfo; | ||
258 | PROCESS_INFORMATION piProcInfo; | ||
259 | int success; | ||
260 | |||
261 | argc = string_array_len((char **)argv); | ||
262 | for (i = 0; i < argc; i++) | ||
263 | command = xappendword(command, quote_arg(argv[i])); | ||
264 | |||
265 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); | ||
266 | siStartInfo.cb = sizeof(STARTUPINFO); | ||
267 | siStartInfo.hStdInput = (HANDLE)_get_osfhandle(STDIN_FILENO); | ||
268 | siStartInfo.hStdOutput = (HANDLE)_get_osfhandle(STDOUT_FILENO); | ||
269 | siStartInfo.dwFlags = STARTF_USESTDHANDLES; | ||
270 | |||
271 | success = CreateProcess((LPCSTR)prog, | ||
272 | (LPSTR)command, /* command line */ | ||
273 | NULL, /* process security attributes */ | ||
274 | NULL, /* primary thread security attributes */ | ||
275 | TRUE, /* handles are inherited */ | ||
276 | DETACHED_PROCESS, /* creation flags */ | ||
277 | NULL, /* use parent's environment */ | ||
278 | NULL, /* use parent's current directory */ | ||
279 | &siStartInfo, /* STARTUPINFO pointer */ | ||
280 | &piProcInfo); /* receives PROCESS_INFORMATION */ | ||
281 | |||
282 | free(command); | ||
283 | |||
284 | if (!success) | ||
285 | return -1; | ||
286 | exit(0); | ||
287 | } | ||
288 | |||
289 | # define SPAWNVEQ(m, p, a, e) \ | ||
290 | ((m != HTTPD_DETACH) ? spawnveq(m, p, a, e) : \ | ||
291 | create_detached_process(p, a)) | ||
292 | #else | ||
293 | # define SPAWNVEQ(m, p, a, e) spawnveq(m, p, a, e) | ||
294 | #endif | ||
295 | |||
251 | static intptr_t | 296 | static intptr_t |
252 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, | 297 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, |
253 | char *const *envp, int level) | 298 | char *const *envp, int level) |
@@ -259,7 +304,7 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, | |||
259 | char *path = NULL; | 304 | char *path = NULL; |
260 | 305 | ||
261 | if (!parse_interpreter(prog, &interp)) | 306 | if (!parse_interpreter(prog, &interp)) |
262 | return spawnveq(mode, prog, argv, envp); | 307 | return SPAWNVEQ(mode, prog, argv, envp); |
263 | 308 | ||
264 | if (++level > 4) { | 309 | if (++level > 4) { |
265 | errno = ELOOP; | 310 | errno = ELOOP; |
@@ -275,7 +320,7 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, | |||
275 | if (unix_path(interp.path) && find_applet_by_name(interp.name) >= 0) { | 320 | if (unix_path(interp.path) && find_applet_by_name(interp.name) >= 0) { |
276 | /* the fake path indicates the index of the script */ | 321 | /* the fake path indicates the index of the script */ |
277 | new_argv[0] = path = xasprintf("%d:/%s", nopts+1, interp.name); | 322 | new_argv[0] = path = xasprintf("%d:/%s", nopts+1, interp.name); |
278 | ret = mingw_spawn_applet(mode, new_argv, envp); | 323 | ret = SPAWNVEQ(mode, bb_busybox_exec_path, new_argv, envp); |
279 | goto done; | 324 | goto done; |
280 | } | 325 | } |
281 | #endif | 326 | #endif |
@@ -428,6 +473,17 @@ mingw_execv(const char *cmd, char *const *argv) | |||
428 | return mingw_execve(cmd, argv, NULL); | 473 | return mingw_execve(cmd, argv, NULL); |
429 | } | 474 | } |
430 | 475 | ||
476 | #if ENABLE_FEATURE_HTTPD_CGI | ||
477 | int httpd_execv_detach(const char *script, char *const *argv) | ||
478 | { | ||
479 | intptr_t ret = mingw_spawn_interpreter(HTTPD_DETACH, script, | ||
480 | (char *const *)argv, NULL, 0); | ||
481 | if (ret != -1) | ||
482 | exit(0); | ||
483 | return ret; | ||
484 | } | ||
485 | #endif | ||
486 | |||
431 | static inline long long filetime_to_ticks(const FILETIME *ft) | 487 | static inline long long filetime_to_ticks(const FILETIME *ft) |
432 | { | 488 | { |
433 | return (((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime)/ | 489 | return (((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime)/ |