aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/mingw32_defconfig4
-rw-r--r--configs/mingw64_defconfig4
-rw-r--r--configs/mingw64u_defconfig4
-rw-r--r--include/mingw.h2
-rw-r--r--networking/httpd.c117
-rw-r--r--win32/process.c60
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#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_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
917CONFIG_FEATURE_HTTPD_BASIC_AUTH=y 917CONFIG_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 919CONFIG_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
922CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y 922CONFIG_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#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_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
917CONFIG_FEATURE_HTTPD_BASIC_AUTH=y 917CONFIG_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 919CONFIG_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
922CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y 922CONFIG_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#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_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
917CONFIG_FEATURE_HTTPD_BASIC_AUTH=y 917CONFIG_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 919CONFIG_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
922CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y 922CONFIG_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);
552intptr_t FAST_FUNC mingw_spawn_detach(char **argv); 552intptr_t FAST_FUNC mingw_spawn_detach(char **argv);
553intptr_t FAST_FUNC mingw_spawn_proc(const char **argv); 553intptr_t FAST_FUNC mingw_spawn_proc(const char **argv);
554int mingw_execv(const char *cmd, char *const *argv); 554int mingw_execv(const char *cmd, char *const *argv);
555int httpd_execv_detach(const char *cmd, char *const *argv);
555int mingw_execvp(const char *cmd, char *const *argv); 556int mingw_execvp(const char *cmd, char *const *argv);
556int mingw_execve(const char *cmd, char *const *argv, char *const *envp); 557int 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
462struct globals { 462struct 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
1579static 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
1567static void setenv1(const char *name, const char *value) 1625static 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 */
2800static void mini_httpd_win32(int fg, int sock, int argc, char **argv) NORETURN; 2889static void mini_httpd_win32(int sock, int argc, char **argv) NORETURN;
2801static void mini_httpd_win32(int fg, int sock, int argc, char **argv) 2890static 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
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)/