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 | |
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)
-rw-r--r-- | configs/mingw32_defconfig | 4 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 4 | ||||
-rw-r--r-- | configs/mingw64u_defconfig | 4 | ||||
-rw-r--r-- | include/mingw.h | 2 | ||||
-rw-r--r-- | networking/httpd.c | 117 | ||||
-rw-r--r-- | win32/process.c | 60 |
6 files changed, 176 insertions, 15 deletions
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index ee01330d1..0f674d45c 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.37.0.git | 3 | # Busybox version: 1.37.0.git |
4 | # Sat Dec 9 09:38:58 2023 | 4 | # Wed Dec 20 13:23:38 2023 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -916,7 +916,7 @@ CONFIG_FEATURE_HTTPD_RANGES=y | |||
916 | # CONFIG_FEATURE_HTTPD_SETUID is not set | 916 | # CONFIG_FEATURE_HTTPD_SETUID is not set |
917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y | 917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y |
918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set | 918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set |
919 | # CONFIG_FEATURE_HTTPD_CGI is not set | 919 | CONFIG_FEATURE_HTTPD_CGI=y |
920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set | 920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set |
921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set | 921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set |
922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y | 922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index 3fed1c99b..37f95f4c8 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.37.0.git | 3 | # Busybox version: 1.37.0.git |
4 | # Sat Dec 9 09:38:58 2023 | 4 | # Wed Dec 20 13:23:38 2023 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -916,7 +916,7 @@ CONFIG_FEATURE_HTTPD_RANGES=y | |||
916 | # CONFIG_FEATURE_HTTPD_SETUID is not set | 916 | # CONFIG_FEATURE_HTTPD_SETUID is not set |
917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y | 917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y |
918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set | 918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set |
919 | # CONFIG_FEATURE_HTTPD_CGI is not set | 919 | CONFIG_FEATURE_HTTPD_CGI=y |
920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set | 920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set |
921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set | 921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set |
922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y | 922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y |
diff --git a/configs/mingw64u_defconfig b/configs/mingw64u_defconfig index f3391a206..f26b17ec9 100644 --- a/configs/mingw64u_defconfig +++ b/configs/mingw64u_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.37.0.git | 3 | # Busybox version: 1.37.0.git |
4 | # Sat Dec 9 09:38:58 2023 | 4 | # Wed Dec 20 13:23:38 2023 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -916,7 +916,7 @@ CONFIG_FEATURE_HTTPD_RANGES=y | |||
916 | # CONFIG_FEATURE_HTTPD_SETUID is not set | 916 | # CONFIG_FEATURE_HTTPD_SETUID is not set |
917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y | 917 | CONFIG_FEATURE_HTTPD_BASIC_AUTH=y |
918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set | 918 | # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set |
919 | # CONFIG_FEATURE_HTTPD_CGI is not set | 919 | CONFIG_FEATURE_HTTPD_CGI=y |
920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set | 920 | # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set |
921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set | 921 | # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set |
922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y | 922 | CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y |
diff --git a/include/mingw.h b/include/mingw.h index 46cbe03f8..88da85243 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -552,12 +552,14 @@ pid_t FAST_FUNC mingw_spawn(char **argv); | |||
552 | intptr_t FAST_FUNC mingw_spawn_detach(char **argv); | 552 | intptr_t FAST_FUNC mingw_spawn_detach(char **argv); |
553 | intptr_t FAST_FUNC mingw_spawn_proc(const char **argv); | 553 | intptr_t FAST_FUNC mingw_spawn_proc(const char **argv); |
554 | int mingw_execv(const char *cmd, char *const *argv); | 554 | int mingw_execv(const char *cmd, char *const *argv); |
555 | int httpd_execv_detach(const char *cmd, char *const *argv); | ||
555 | int mingw_execvp(const char *cmd, char *const *argv); | 556 | int mingw_execvp(const char *cmd, char *const *argv); |
556 | int mingw_execve(const char *cmd, char *const *argv, char *const *envp); | 557 | int mingw_execve(const char *cmd, char *const *argv, char *const *envp); |
557 | #define spawn mingw_spawn | 558 | #define spawn mingw_spawn |
558 | #define execvp mingw_execvp | 559 | #define execvp mingw_execvp |
559 | #define execve mingw_execve | 560 | #define execve mingw_execve |
560 | #define execv mingw_execv | 561 | #define execv mingw_execv |
562 | #define HTTPD_DETACH (8) | ||
561 | 563 | ||
562 | #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':') | 564 | #define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':') |
563 | 565 | ||
diff --git a/networking/httpd.c b/networking/httpd.c index 0de56a47a..d049e3842 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -461,6 +461,13 @@ static const struct { | |||
461 | 461 | ||
462 | struct globals { | 462 | struct globals { |
463 | int verbose; /* must be int (used by getopt32) */ | 463 | int verbose; /* must be int (used by getopt32) */ |
464 | #if ENABLE_PLATFORM_MINGW32 | ||
465 | smallint foreground; | ||
466 | # if ENABLE_FEATURE_HTTPD_CGI | ||
467 | int server_argc; | ||
468 | char **server_argv; | ||
469 | # endif | ||
470 | #endif | ||
464 | smallint flg_deny_all; | 471 | smallint flg_deny_all; |
465 | #if ENABLE_FEATURE_HTTPD_GZIP | 472 | #if ENABLE_FEATURE_HTTPD_GZIP |
466 | /* client can handle gzip / we are going to send gzip */ | 473 | /* client can handle gzip / we are going to send gzip */ |
@@ -518,6 +525,11 @@ struct globals { | |||
518 | }; | 525 | }; |
519 | #define G (*ptr_to_globals) | 526 | #define G (*ptr_to_globals) |
520 | #define verbose (G.verbose ) | 527 | #define verbose (G.verbose ) |
528 | #if ENABLE_PLATFORM_MINGW32 | ||
529 | #define foreground (G.foreground ) | ||
530 | #define server_argc (G.server_argc ) | ||
531 | #define server_argv (G.server_argv ) | ||
532 | #endif | ||
521 | #define flg_deny_all (G.flg_deny_all ) | 533 | #define flg_deny_all (G.flg_deny_all ) |
522 | #if ENABLE_FEATURE_HTTPD_GZIP | 534 | #if ENABLE_FEATURE_HTTPD_GZIP |
523 | # define content_gzip (G.content_gzip ) | 535 | # define content_gzip (G.content_gzip ) |
@@ -1563,6 +1575,52 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post | |||
1563 | #endif | 1575 | #endif |
1564 | 1576 | ||
1565 | #if ENABLE_FEATURE_HTTPD_CGI | 1577 | #if ENABLE_FEATURE_HTTPD_CGI |
1578 | # if ENABLE_PLATFORM_MINGW32 | ||
1579 | static void cgi_handler(char **argv) | ||
1580 | { | ||
1581 | struct fd_pair fromCgi; /* CGI -> httpd pipe */ | ||
1582 | struct fd_pair toCgi; /* httpd -> CGI pipe */ | ||
1583 | char *dir, *script; | ||
1584 | |||
1585 | xfunc_error_retval = 242; | ||
1586 | |||
1587 | if (sscanf(argv[0], "%d:%d:%d:%d", &toCgi.wr, &toCgi.rd, | ||
1588 | &fromCgi.wr, &fromCgi.rd) != 4) { | ||
1589 | exit(242); | ||
1590 | } | ||
1591 | |||
1592 | /* NB: close _first_, then move fds! */ | ||
1593 | close(toCgi.wr); | ||
1594 | close(fromCgi.rd); | ||
1595 | xmove_fd(toCgi.rd, 0); /* replace stdin with the pipe */ | ||
1596 | xmove_fd(fromCgi.wr, 1); /* replace stdout with the pipe */ | ||
1597 | |||
1598 | dir = argv[1]; | ||
1599 | script = argv[2]; | ||
1600 | |||
1601 | if (chdir_or_warn(dir) != 0) { | ||
1602 | goto error_execing_cgi; | ||
1603 | } | ||
1604 | |||
1605 | /* set argv[0] to name without path */ | ||
1606 | argv[0] = script; | ||
1607 | argv[1] = NULL; | ||
1608 | |||
1609 | /* _NOT_ execvp. We do not search PATH. argv[0] is a filename | ||
1610 | * without any dir components and will only match a file | ||
1611 | * in the current directory */ | ||
1612 | if (foreground) | ||
1613 | execv(argv[0], argv); | ||
1614 | else | ||
1615 | httpd_execv_detach(argv[0], argv); | ||
1616 | if (verbose) | ||
1617 | bb_perror_msg("can't execute '%s'", argv[0]); | ||
1618 | error_execing_cgi: | ||
1619 | /* send to stdout */ | ||
1620 | iobuf = xmalloc(IOBUF_SIZE); | ||
1621 | send_headers_and_exit(HTTP_NOT_FOUND); | ||
1622 | } | ||
1623 | # endif | ||
1566 | 1624 | ||
1567 | static void setenv1(const char *name, const char *value) | 1625 | static void setenv1(const char *name, const char *value) |
1568 | { | 1626 | { |
@@ -1596,6 +1654,10 @@ static void send_cgi_and_exit( | |||
1596 | struct fd_pair toCgi; /* httpd -> CGI pipe */ | 1654 | struct fd_pair toCgi; /* httpd -> CGI pipe */ |
1597 | char *script, *last_slash; | 1655 | char *script, *last_slash; |
1598 | int pid; | 1656 | int pid; |
1657 | #if ENABLE_PLATFORM_MINGW32 | ||
1658 | char **argv; | ||
1659 | int i; | ||
1660 | #endif | ||
1599 | 1661 | ||
1600 | /* Make a copy. NB: caller guarantees: | 1662 | /* Make a copy. NB: caller guarantees: |
1601 | * url[0] == '/', url[1] != '/' */ | 1663 | * url[0] == '/', url[1] != '/' */ |
@@ -1682,6 +1744,32 @@ static void send_cgi_and_exit( | |||
1682 | xpiped_pair(fromCgi); | 1744 | xpiped_pair(fromCgi); |
1683 | xpiped_pair(toCgi); | 1745 | xpiped_pair(toCgi); |
1684 | 1746 | ||
1747 | #if ENABLE_PLATFORM_MINGW32 | ||
1748 | /* Find script's dir */ | ||
1749 | script = last_slash; | ||
1750 | if (script != url) { /* paranoia */ | ||
1751 | *script = '\0'; | ||
1752 | } | ||
1753 | script++; | ||
1754 | |||
1755 | argv = xzalloc((server_argc + 9) * sizeof(char *)); | ||
1756 | argv[0] = (char *)bb_busybox_exec_path; | ||
1757 | argv[1] = (char *)"--busybox"; | ||
1758 | argv[2] = (char *)"-httpd" + 1; // skip '-' | ||
1759 | argv[3] = (char *)"-I"; | ||
1760 | argv[4] = (char *)"0"; | ||
1761 | for (i = 0; i < server_argc; ++i) | ||
1762 | argv[i + 5] = server_argv[i]; | ||
1763 | argv[server_argc + 5] = xasprintf("%d:%d:%d:%d", toCgi.wr, toCgi.rd, | ||
1764 | fromCgi.wr, fromCgi.rd); | ||
1765 | argv[server_argc + 6] = (char *)url + 1; // script directory | ||
1766 | argv[server_argc + 7] = (char *)script; // script name | ||
1767 | /* argv[server_argc + 8] = NULL; - xzalloc did it */ | ||
1768 | |||
1769 | pid = foreground ? mingw_spawn(argv) : mingw_spawn_detach(argv); | ||
1770 | if (pid == -1) | ||
1771 | log_and_exit(); | ||
1772 | #else | ||
1685 | pid = vfork(); | 1773 | pid = vfork(); |
1686 | if (pid < 0) { | 1774 | if (pid < 0) { |
1687 | /* TODO: log perror? */ | 1775 | /* TODO: log perror? */ |
@@ -1759,6 +1847,7 @@ static void send_cgi_and_exit( | |||
1759 | 1847 | ||
1760 | /* Restore variables possibly changed by child */ | 1848 | /* Restore variables possibly changed by child */ |
1761 | xfunc_error_retval = 0; | 1849 | xfunc_error_retval = 0; |
1850 | #endif | ||
1762 | 1851 | ||
1763 | /* Pump data */ | 1852 | /* Pump data */ |
1764 | close(fromCgi.wr); | 1853 | close(fromCgi.wr); |
@@ -2797,8 +2886,8 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv) | |||
2797 | } | 2886 | } |
2798 | #endif | 2887 | #endif |
2799 | #else /* ENABLE_PLATFORM_MINGW32 */ | 2888 | #else /* ENABLE_PLATFORM_MINGW32 */ |
2800 | static void mini_httpd_win32(int fg, int sock, int argc, char **argv) NORETURN; | 2889 | static void mini_httpd_win32(int sock, int argc, char **argv) NORETURN; |
2801 | static void mini_httpd_win32(int fg, int sock, int argc, char **argv) | 2890 | static void mini_httpd_win32(int sock, int argc, char **argv) |
2802 | { | 2891 | { |
2803 | char *argv_copy[argc + 5]; | 2892 | char *argv_copy[argc + 5]; |
2804 | 2893 | ||
@@ -2820,7 +2909,8 @@ static void mini_httpd_win32(int fg, int sock, int argc, char **argv) | |||
2820 | setsockopt_keepalive(n); | 2909 | setsockopt_keepalive(n); |
2821 | 2910 | ||
2822 | argv_copy[4] = itoa(n); | 2911 | argv_copy[4] = itoa(n); |
2823 | if ((fg ? spawn(argv_copy) : mingw_spawn_detach(argv_copy)) == -1) | 2912 | if ((foreground ? |
2913 | spawn(argv_copy) : mingw_spawn_detach(argv_copy)) == -1) | ||
2824 | bb_perror_msg_and_die("can't execute 'httpd'"); | 2914 | bb_perror_msg_and_die("can't execute 'httpd'"); |
2825 | 2915 | ||
2826 | /* parent, or spawn failed */ | 2916 | /* parent, or spawn failed */ |
@@ -2936,7 +3026,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2936 | "\0" | 3026 | "\0" |
2937 | /* -v counts, -i implies -f */ | 3027 | /* -v counts, -i implies -f */ |
2938 | IF_NOT_PLATFORM_MINGW32("vv:if",) | 3028 | IF_NOT_PLATFORM_MINGW32("vv:if",) |
2939 | IF_PLATFORM_MINGW32("vv:If",) | 3029 | IF_PLATFORM_MINGW32("vv:",) |
2940 | &opt_c_configFile, &url_for_decode, &home_httpd | 3030 | &opt_c_configFile, &url_for_decode, &home_httpd |
2941 | IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | 3031 | IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
2942 | IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) | 3032 | IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
@@ -2981,7 +3071,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2981 | } | 3071 | } |
2982 | #endif | 3072 | #endif |
2983 | #else /* ENABLE_PLATFORM_MINGW32 */ | 3073 | #else /* ENABLE_PLATFORM_MINGW32 */ |
2984 | if (!(opt & OPT_FOREGROUND) && argv[0][0] != '-') | 3074 | foreground = (opt & OPT_FOREGROUND) == OPT_FOREGROUND; |
3075 | if (!foreground && argv[0][0] != '-') | ||
2985 | mingw_daemonize(argv); | 3076 | mingw_daemonize(argv); |
2986 | #endif | 3077 | #endif |
2987 | 3078 | ||
@@ -3032,7 +3123,14 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
3032 | #endif | 3123 | #endif |
3033 | 3124 | ||
3034 | parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); | 3125 | parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); |
3035 | #if !ENABLE_PLATFORM_MINGW32 | 3126 | #if ENABLE_PLATFORM_MINGW32 |
3127 | # if ENABLE_FEATURE_HTTPD_CGI | ||
3128 | if ((opt & OPT_INETD) && fd == 0) { | ||
3129 | cgi_handler(argv + optind); | ||
3130 | return 0; | ||
3131 | } | ||
3132 | # endif | ||
3133 | #else | ||
3036 | if (!(opt & OPT_INETD)) | 3134 | if (!(opt & OPT_INETD)) |
3037 | signal(SIGHUP, sighup_handler); | 3135 | signal(SIGHUP, sighup_handler); |
3038 | #endif | 3136 | #endif |
@@ -3044,6 +3142,11 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
3044 | xdup2(0, 1); | 3142 | xdup2(0, 1); |
3045 | while (--fd > 2) | 3143 | while (--fd > 2) |
3046 | close(fd); | 3144 | close(fd); |
3145 | # if ENABLE_FEATURE_HTTPD_CGI | ||
3146 | /* Skip 'httpd -I N' and omit any non-option arguments */ | ||
3147 | server_argc = optind - 3; | ||
3148 | server_argv = argv + 3; | ||
3149 | # endif | ||
3047 | } | 3150 | } |
3048 | #endif | 3151 | #endif |
3049 | if (opt & OPT_INETD) | 3152 | if (opt & OPT_INETD) |
@@ -3057,7 +3160,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
3057 | mini_httpd_nommu(server_socket, argc, argv); /* never returns */ | 3160 | mini_httpd_nommu(server_socket, argc, argv); /* never returns */ |
3058 | #endif | 3161 | #endif |
3059 | #else /* ENABLE_PLATFORM_MINGW32 */ | 3162 | #else /* ENABLE_PLATFORM_MINGW32 */ |
3060 | mini_httpd_win32(opt & OPT_FOREGROUND, server_socket, argc, argv); | 3163 | mini_httpd_win32(server_socket, argc, argv); |
3061 | #endif | 3164 | #endif |
3062 | /* return 0; */ | 3165 | /* return 0; */ |
3063 | } | 3166 | } |
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)/ |