aboutsummaryrefslogtreecommitdiff
path: root/win32/process.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-12-20 13:45:32 +0000
committerRon Yorston <rmy@pobox.com>2023-12-20 13:59:17 +0000
commit8d85a4a5be88931978fad594b94e762313d37afc (patch)
tree0f964f6cd9b0c71b02de5011a2f815e1470c8740 /win32/process.c
parent4f9b703c31e6360d1e7ffe7d3410e42e5118b4fd (diff)
downloadbusybox-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.c60
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
252static int
253create_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
251static intptr_t 296static intptr_t
252mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, 297mingw_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
477int 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
431static inline long long filetime_to_ticks(const FILETIME *ft) 487static 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)/