aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-04-05 09:51:56 +0100
committerRon Yorston <rmy@pobox.com>2020-04-05 10:05:01 +0100
commitfbfb02e8637409f1367cb0d8a3d02f6366261ab4 (patch)
treebc930441e13d7e27c2aa60436a8346dde0d31ec5 /networking
parent2b4c25bd2cac034cdc52d29d6bb8c675c87a731c (diff)
downloadbusybox-w32-fbfb02e8637409f1367cb0d8a3d02f6366261ab4.tar.gz
busybox-w32-fbfb02e8637409f1367cb0d8a3d02f6366261ab4.tar.bz2
busybox-w32-fbfb02e8637409f1367cb0d8a3d02f6366261ab4.zip
httpd: WIN32 port
Use mingw_spawn_detach() to daemonize the server. Pass the open socket to the child process on the command line. Omit handling of SIGHUP and SIGALRM. Timeouts are handled using poll(2) instead of alarm(2).
Diffstat (limited to 'networking')
-rw-r--r--networking/httpd.c135
1 files changed, 133 insertions, 2 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index 1757e09c9..7e1c187a5 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -229,7 +229,12 @@
229//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" 229//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
230//usage:#define httpd_full_usage "\n\n" 230//usage:#define httpd_full_usage "\n\n"
231//usage: "Listen for incoming HTTP requests\n" 231//usage: "Listen for incoming HTTP requests\n"
232//usage: IF_NOT_PLATFORM_MINGW32(
232//usage: "\n -i Inetd mode" 233//usage: "\n -i Inetd mode"
234//usage: )
235//usage: IF_PLATFORM_MINGW32(
236//usage: "\n -i fd Inetd mode file descriptor"
237//usage: )
233//usage: "\n -f Don't daemonize" 238//usage: "\n -f Don't daemonize"
234//usage: "\n -v[v] Verbose" 239//usage: "\n -v[v] Verbose"
235//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:80)" 240//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:80)"
@@ -267,6 +272,8 @@
267 272
268#define HEADER_READ_TIMEOUT 60 273#define HEADER_READ_TIMEOUT 60
269 274
275static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
276
270static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; 277static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc";
271static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; 278static const char HTTPD_CONF[] ALIGN1 = "httpd.conf";
272static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; 279static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n";
@@ -652,8 +659,16 @@ static void parse_conf(const char *path, int flag)
652 659
653 filename = opt_c_configFile; 660 filename = opt_c_configFile;
654 if (flag == SUBDIR_PARSE || filename == NULL) { 661 if (flag == SUBDIR_PARSE || filename == NULL) {
662#if !ENABLE_PLATFORM_MINGW32
655 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2); 663 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2);
656 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF); 664 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF);
665#else
666 char *sd = get_system_drive();
667
668 filename = auto_string(xasprintf("%s%s/%s",
669 (sd && path[0] == '/' && root_len(path) == 0) ? sd : "",
670 path, HTTPD_CONF));
671#endif
657 } 672 }
658 673
659 while ((f = fopen_for_read(filename)) == NULL) { 674 while ((f = fopen_for_read(filename)) == NULL) {
@@ -702,6 +717,7 @@ static void parse_conf(const char *path, int flag)
702 * without needless copying, therefore we don't merge 717 * without needless copying, therefore we don't merge
703 * this operation into next while loop. */ 718 * this operation into next while loop. */
704 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#' 719 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#'
720 IF_PLATFORM_MINGW32(&& ch != '\r')
705 && ch != ' ' && ch != '\t' 721 && ch != ' ' && ch != '\t'
706 ) { 722 ) {
707 p0++; 723 p0++;
@@ -709,7 +725,11 @@ static void parse_conf(const char *path, int flag)
709 p = p0; 725 p = p0;
710 /* if we enter this loop, we have some whitespace. 726 /* if we enter this loop, we have some whitespace.
711 * discard it */ 727 * discard it */
728#if !ENABLE_PLATFORM_MINGW32
712 while (ch != '\0' && ch != '\n' && ch != '#') { 729 while (ch != '\0' && ch != '\n' && ch != '#') {
730#else
731 while (ch != '\0' && ch != '\n' && ch != '\r' && ch != '#') {
732#endif
713 if (ch != ' ' && ch != '\t') { 733 if (ch != ' ' && ch != '\t') {
714 *p++ = ch; 734 *p++ = ch;
715 } 735 }
@@ -1249,7 +1269,21 @@ static unsigned get_line(void)
1249 count = 0; 1269 count = 0;
1250 while (1) { 1270 while (1) {
1251 if (hdr_cnt <= 0) { 1271 if (hdr_cnt <= 0) {
1272#if ENABLE_PLATFORM_MINGW32
1273 int nfds = 1;
1274 struct pollfd fds = {STDIN_FILENO, POLLIN, 0};
1275
1276 switch (poll(&fds, nfds, HEADER_READ_TIMEOUT*1000)) {
1277 case 0:
1278 send_REQUEST_TIMEOUT_and_exit(0);
1279 break;
1280 case -1:
1281 bb_simple_perror_msg_and_die("poll");
1282 break;
1283 }
1284#else
1252 alarm(HEADER_READ_TIMEOUT); 1285 alarm(HEADER_READ_TIMEOUT);
1286#endif
1253 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf); 1287 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
1254 if (hdr_cnt <= 0) 1288 if (hdr_cnt <= 0)
1255 goto ret; 1289 goto ret;
@@ -2090,7 +2124,6 @@ static Htaccess_Proxy *find_proxy_entry(const char *url)
2090/* 2124/*
2091 * Handle timeouts 2125 * Handle timeouts
2092 */ 2126 */
2093static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
2094static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM) 2127static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
2095{ 2128{
2096 send_headers_and_exit(HTTP_REQUEST_TIMEOUT); 2129 send_headers_and_exit(HTTP_REQUEST_TIMEOUT);
@@ -2134,11 +2167,21 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2134 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); 2167 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr);
2135 } 2168 }
2136#if ENABLE_FEATURE_IPV6 2169#if ENABLE_FEATURE_IPV6
2170# if !ENABLE_PLATFORM_MINGW32
2137 if (fromAddr->u.sa.sa_family == AF_INET6 2171 if (fromAddr->u.sa.sa_family == AF_INET6
2138 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 2172 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0
2139 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 2173 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0
2140 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) 2174 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff)
2141 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); 2175 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]);
2176# else
2177 if (fromAddr->u.sa.sa_family == AF_INET6
2178 && fromAddr->u.sin6.sin6_addr.s6_words[0] == 0
2179 && fromAddr->u.sin6.sin6_addr.s6_words[1] == 0
2180 && fromAddr->u.sin6.sin6_addr.s6_words[2] == 0
2181 && fromAddr->u.sin6.sin6_addr.s6_words[3] == 0
2182 && ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+4)) == 0xffff)
2183 remote_ip = ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+6));
2184# endif
2142#endif 2185#endif
2143 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { 2186 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
2144 /* NB: can be NULL (user runs httpd -i by hand?) */ 2187 /* NB: can be NULL (user runs httpd -i by hand?) */
@@ -2153,8 +2196,10 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2153 } 2196 }
2154 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); 2197 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip);
2155 2198
2199#ifdef SIGALRM
2156 /* Install timeout handler. get_line() needs it. */ 2200 /* Install timeout handler. get_line() needs it. */
2157 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); 2201 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit);
2202#endif
2158 2203
2159 if (!get_line()) /* EOF or error or empty line */ 2204 if (!get_line()) /* EOF or error or empty line */
2160 send_headers_and_exit(HTTP_BAD_REQUEST); 2205 send_headers_and_exit(HTTP_BAD_REQUEST);
@@ -2527,12 +2572,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2527#endif 2572#endif
2528} 2573}
2529 2574
2575
2530/* 2576/*
2531 * The main http server function. 2577 * The main http server function.
2532 * Given a socket, listen for new connections and farm out 2578 * Given a socket, listen for new connections and farm out
2533 * the processing as a [v]forked process. 2579 * the processing as a [v]forked process.
2534 * Never returns. 2580 * Never returns.
2535 */ 2581 */
2582# if !ENABLE_PLATFORM_MINGW32
2536#if BB_MMU 2583#if BB_MMU
2537static void mini_httpd(int server_socket) NORETURN; 2584static void mini_httpd(int server_socket) NORETURN;
2538static void mini_httpd(int server_socket) 2585static void mini_httpd(int server_socket)
@@ -2614,6 +2661,39 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
2614 /* never reached */ 2661 /* never reached */
2615} 2662}
2616#endif 2663#endif
2664#else /* ENABLE_PLATFORM_MINGW32 */
2665static void mini_httpd_win32(int fg, int sock, int argc, char **argv) NORETURN;
2666static void mini_httpd_win32(int fg, int sock, int argc, char **argv)
2667{
2668 char *argv_copy[argc + 5];
2669
2670 argv_copy[0] = (char *)bb_busybox_exec_path;
2671 argv_copy[1] = (char *)"--busybox";
2672 argv_copy[2] = (char *)"httpd";
2673 argv_copy[3] = (char *)"-i";
2674 memcpy(&argv_copy[5], &argv[1], argc * sizeof(argv[0]));
2675
2676 while (1) {
2677 int n;
2678
2679 /* Wait for connections... */
2680 n = accept(sock, NULL, NULL);
2681 if (n < 0)
2682 continue;
2683
2684 /* set the KEEPALIVE option to cull dead connections */
2685 setsockopt_keepalive(n);
2686
2687 argv_copy[4] = itoa(n);
2688 if ((fg ? spawn(argv_copy) : mingw_spawn_detach(argv_copy)) == -1)
2689 bb_perror_msg_and_die("can't execute 'httpd'");
2690
2691 /* parent, or spawn failed */
2692 close(n);
2693 } /* while (1) */
2694 /* never reached */
2695}
2696#endif
2617 2697
2618/* 2698/*
2619 * Process a HTTP connection on stdin/out. 2699 * Process a HTTP connection on stdin/out.
@@ -2631,12 +2711,39 @@ static void mini_httpd_inetd(void)
2631 handle_incoming_and_exit(&fromAddr); 2711 handle_incoming_and_exit(&fromAddr);
2632} 2712}
2633 2713
2714#if ENABLE_PLATFORM_MINGW32
2715static void mingw_daemonize(char **argv)
2716{
2717 char **new_argv;
2718 int argc, fd;
2719
2720 argc = string_array_len((char **)argv);
2721 new_argv = xmalloc(sizeof(*argv)*(argc+3));
2722 new_argv[0] = (char *)bb_busybox_exec_path;
2723 new_argv[1] = (char *)"--busybox";
2724 new_argv[2] = (char *)"-httpd";
2725 memcpy(&new_argv[3], &argv[1], sizeof(*argv)*argc);
2726
2727 fd = xopen(bb_dev_null, O_RDWR);
2728 xdup2(fd, 0);
2729 xdup2(fd, 1);
2730 xdup2(fd, 2);
2731 close(fd);
2732
2733 if (mingw_spawn_detach(new_argv))
2734 exit(EXIT_SUCCESS); /* parent */
2735 exit(EXIT_FAILURE); /* parent */
2736}
2737#endif
2738
2739#ifdef SIGHUP
2634static void sighup_handler(int sig UNUSED_PARAM) 2740static void sighup_handler(int sig UNUSED_PARAM)
2635{ 2741{
2636 int sv = errno; 2742 int sv = errno;
2637 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE); 2743 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE);
2638 errno = sv; 2744 errno = sv;
2639} 2745}
2746#endif
2640 2747
2641enum { 2748enum {
2642 c_opt_config_file = 0, 2749 c_opt_config_file = 0,
@@ -2674,6 +2781,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2674 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;) 2781 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;)
2675 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;) 2782 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;)
2676 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;) 2783 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
2784 IF_PLATFORM_MINGW32(int fd;)
2677 2785
2678 INIT_G(); 2786 INIT_G();
2679 2787
@@ -2692,7 +2800,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2692 IF_FEATURE_HTTPD_BASIC_AUTH("r:") 2800 IF_FEATURE_HTTPD_BASIC_AUTH("r:")
2693 IF_FEATURE_HTTPD_AUTH_MD5("m:") 2801 IF_FEATURE_HTTPD_AUTH_MD5("m:")
2694 IF_FEATURE_HTTPD_SETUID("u:") 2802 IF_FEATURE_HTTPD_SETUID("u:")
2695 "p:ifv" 2803 IF_NOT_PLATFORM_MINGW32("p:ifv")
2804 IF_PLATFORM_MINGW32("p:i:+fv")
2696 "\0" 2805 "\0"
2697 /* -v counts, -i implies -f */ 2806 /* -v counts, -i implies -f */
2698 "vv:if", 2807 "vv:if",
@@ -2702,6 +2811,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2702 IF_FEATURE_HTTPD_AUTH_MD5(, &pass) 2811 IF_FEATURE_HTTPD_AUTH_MD5(, &pass)
2703 IF_FEATURE_HTTPD_SETUID(, &s_ugid) 2812 IF_FEATURE_HTTPD_SETUID(, &s_ugid)
2704 , &bind_addr_or_port 2813 , &bind_addr_or_port
2814 IF_PLATFORM_MINGW32(, &fd)
2705 , &verbose 2815 , &verbose
2706 ); 2816 );
2707 if (opt & OPT_DECODE_URL) { 2817 if (opt & OPT_DECODE_URL) {
@@ -2731,15 +2841,22 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2731 } 2841 }
2732#endif 2842#endif
2733 2843
2844#if !ENABLE_PLATFORM_MINGW32
2734#if !BB_MMU 2845#if !BB_MMU
2735 if (!(opt & OPT_FOREGROUND)) { 2846 if (!(opt & OPT_FOREGROUND)) {
2736 bb_daemonize_or_rexec(0, argv); /* don't change current directory */ 2847 bb_daemonize_or_rexec(0, argv); /* don't change current directory */
2737 } 2848 }
2738#endif 2849#endif
2850#else /* ENABLE_PLATFORM_MINGW32 */
2851 if (!(opt & OPT_FOREGROUND) && argv[0][0] != '-')
2852 mingw_daemonize(argv);
2853#endif
2739 2854
2740 xchdir(home_httpd); 2855 xchdir(home_httpd);
2741 if (!(opt & OPT_INETD)) { 2856 if (!(opt & OPT_INETD)) {
2857#ifdef SIGCHLD
2742 signal(SIGCHLD, SIG_IGN); 2858 signal(SIGCHLD, SIG_IGN);
2859#endif
2743 server_socket = openServer(); 2860 server_socket = openServer();
2744#if ENABLE_FEATURE_HTTPD_SETUID 2861#if ENABLE_FEATURE_HTTPD_SETUID
2745 /* drop privileges */ 2862 /* drop privileges */
@@ -2773,12 +2890,23 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2773#endif 2890#endif
2774 2891
2775 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); 2892 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE);
2893#ifdef SIGHUP
2776 if (!(opt & OPT_INETD)) 2894 if (!(opt & OPT_INETD))
2777 signal(SIGHUP, sighup_handler); 2895 signal(SIGHUP, sighup_handler);
2896#endif
2778 2897
2779 xfunc_error_retval = 0; 2898 xfunc_error_retval = 0;
2899#if ENABLE_PLATFORM_MINGW32
2900 if (opt & OPT_INETD) {
2901 xmove_fd(fd, 0);
2902 xdup2(0, 1);
2903 while (--fd > 2)
2904 close(fd);
2905 }
2906#endif
2780 if (opt & OPT_INETD) 2907 if (opt & OPT_INETD)
2781 mini_httpd_inetd(); /* never returns */ 2908 mini_httpd_inetd(); /* never returns */
2909#if !ENABLE_PLATFORM_MINGW32
2782#if BB_MMU 2910#if BB_MMU
2783 if (!(opt & OPT_FOREGROUND)) 2911 if (!(opt & OPT_FOREGROUND))
2784 bb_daemonize(0); /* don't change current directory */ 2912 bb_daemonize(0); /* don't change current directory */
@@ -2786,5 +2914,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2786#else 2914#else
2787 mini_httpd_nommu(server_socket, argc, argv); /* never returns */ 2915 mini_httpd_nommu(server_socket, argc, argv); /* never returns */
2788#endif 2916#endif
2917#else /* ENABLE_PLATFORM_MINGW32 */
2918 mini_httpd_win32(opt & OPT_FOREGROUND, server_socket, argc, argv);
2919#endif
2789 /* return 0; */ 2920 /* return 0; */
2790} 2921}