aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-rw-r--r--networking/ftpgetput.c6
-rw-r--r--networking/httpd.c297
-rw-r--r--networking/nc.c12
-rw-r--r--networking/ssl_client.c21
-rw-r--r--networking/tls.c2
-rw-r--r--networking/wget.c53
6 files changed, 383 insertions, 8 deletions
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index 1172850ce..86342769b 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -106,6 +106,9 @@ static int ftpcmd(const char *s1, const char *s2)
106 fprintf(control_stream, (s2 ? "%s %s\r\n" : "%s %s\r\n"+3), 106 fprintf(control_stream, (s2 ? "%s %s\r\n" : "%s %s\r\n"+3),
107 s1, s2); 107 s1, s2);
108 fflush(control_stream); 108 fflush(control_stream);
109#if ENABLE_PLATFORM_MINGW32
110 fseek(control_stream, 0L, SEEK_CUR);
111#endif
109 } 112 }
110 113
111 do { 114 do {
@@ -114,6 +117,9 @@ static int ftpcmd(const char *s1, const char *s2)
114 ftp_die(NULL); 117 ftp_die(NULL);
115 } 118 }
116 } while (!isdigit(buf[0]) || buf[3] != ' '); 119 } while (!isdigit(buf[0]) || buf[3] != ' ');
120#if ENABLE_PLATFORM_MINGW32
121 fseek(control_stream, 0L, SEEK_CUR);
122#endif
117 123
118 buf[3] = '\0'; 124 buf[3] = '\0';
119 n = xatou(buf); 125 n = xatou(buf);
diff --git a/networking/httpd.c b/networking/httpd.c
index ddcb03bca..1dae602ee 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -264,7 +264,12 @@
264//kbuild:lib-$(CONFIG_HTTPD) += httpd.o 264//kbuild:lib-$(CONFIG_HTTPD) += httpd.o
265 265
266//usage:#define httpd_trivial_usage 266//usage:#define httpd_trivial_usage
267//usage: IF_NOT_PLATFORM_MINGW32(
267//usage: "[-ifv[v]]" 268//usage: "[-ifv[v]]"
269//usage: )
270//usage: IF_PLATFORM_MINGW32(
271//usage: "[-fv[v]]"
272//usage: )
268//usage: " [-c CONFFILE]" 273//usage: " [-c CONFFILE]"
269//usage: " [-p [IP:]PORT]" 274//usage: " [-p [IP:]PORT]"
270//usage: IF_FEATURE_HTTPD_SETUID(" [-u USER[:GRP]]") 275//usage: IF_FEATURE_HTTPD_SETUID(" [-u USER[:GRP]]")
@@ -273,7 +278,9 @@
273//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" 278//usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
274//usage:#define httpd_full_usage "\n\n" 279//usage:#define httpd_full_usage "\n\n"
275//usage: "Listen for incoming HTTP requests\n" 280//usage: "Listen for incoming HTTP requests\n"
281//usage: IF_NOT_PLATFORM_MINGW32(
276//usage: "\n -i Inetd mode" 282//usage: "\n -i Inetd mode"
283//usage: )
277//usage: "\n -f Run in foreground" 284//usage: "\n -f Run in foreground"
278//usage: "\n -v[v] Verbose" 285//usage: "\n -v[v] Verbose"
279//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")" 286//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")"
@@ -292,6 +299,9 @@
292 299
293#include "libbb.h" 300#include "libbb.h"
294#include "common_bufsiz.h" 301#include "common_bufsiz.h"
302#if ENABLE_PLATFORM_MINGW32
303# include "BB_VER.h"
304#endif
295#if ENABLE_PAM 305#if ENABLE_PAM
296/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */ 306/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */
297# undef setlocale 307# undef setlocale
@@ -322,6 +332,8 @@
322 332
323#define HEADER_READ_TIMEOUT 60 333#define HEADER_READ_TIMEOUT 60
324 334
335static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
336
325#define STR1(s) #s 337#define STR1(s) #s
326#define STR(s) STR1(s) 338#define STR(s) STR1(s)
327 339
@@ -452,6 +464,13 @@ static const struct {
452 464
453struct globals { 465struct globals {
454 int verbose; /* must be int (used by getopt32) */ 466 int verbose; /* must be int (used by getopt32) */
467#if ENABLE_PLATFORM_MINGW32
468 smallint foreground;
469# if ENABLE_FEATURE_HTTPD_CGI
470 int server_argc;
471 char **server_argv;
472# endif
473#endif
455 smallint flg_deny_all; 474 smallint flg_deny_all;
456#if ENABLE_FEATURE_HTTPD_GZIP 475#if ENABLE_FEATURE_HTTPD_GZIP
457 /* client can handle gzip / we are going to send gzip */ 476 /* client can handle gzip / we are going to send gzip */
@@ -509,6 +528,11 @@ struct globals {
509}; 528};
510#define G (*ptr_to_globals) 529#define G (*ptr_to_globals)
511#define verbose (G.verbose ) 530#define verbose (G.verbose )
531#if ENABLE_PLATFORM_MINGW32
532#define foreground (G.foreground )
533#define server_argc (G.server_argc )
534#define server_argv (G.server_argv )
535#endif
512#define flg_deny_all (G.flg_deny_all ) 536#define flg_deny_all (G.flg_deny_all )
513#if ENABLE_FEATURE_HTTPD_GZIP 537#if ENABLE_FEATURE_HTTPD_GZIP
514# define content_gzip (G.content_gzip ) 538# define content_gzip (G.content_gzip )
@@ -557,7 +581,12 @@ enum {
557} while (0) 581} while (0)
558 582
559 583
584#if !ENABLE_PLATFORM_MINGW32
560#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) 585#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
586#else
587/* Not exactly equivalent to strncasecmp(), but OK for its use here */
588#define STRNCASECMP(a, str) (!is_prefixed_with_case((a), (str)))
589#endif
561 590
562/* Prototypes */ 591/* Prototypes */
563enum { 592enum {
@@ -721,8 +750,16 @@ static int parse_conf(const char *path, int flag)
721 750
722 filename = opt_c_configFile; 751 filename = opt_c_configFile;
723 if (flag == SUBDIR_PARSE || filename == NULL) { 752 if (flag == SUBDIR_PARSE || filename == NULL) {
753#if !ENABLE_PLATFORM_MINGW32
724 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2); 754 filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2);
725 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF); 755 sprintf((char *)filename, "%s/%s", path, HTTPD_CONF);
756#else
757 const char *sd = "";
758 if (root_len(path) == 0 && (path[0] == '/' || path[0] == '\\'))
759 sd = get_system_drive();
760
761 filename = auto_string(xasprintf("%s%s/%s", sd, path, HTTPD_CONF));
762#endif
726 } 763 }
727 764
728 while ((f = fopen_for_read(filename)) == NULL) { 765 while ((f = fopen_for_read(filename)) == NULL) {
@@ -771,6 +808,7 @@ static int parse_conf(const char *path, int flag)
771 * without needless copying, therefore we don't merge 808 * without needless copying, therefore we don't merge
772 * this operation into next while loop. */ 809 * this operation into next while loop. */
773 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#' 810 while ((ch = *p0) != '\0' && ch != '\n' && ch != '#'
811 IF_PLATFORM_MINGW32(&& ch != '\r')
774 && ch != ' ' && ch != '\t' 812 && ch != ' ' && ch != '\t'
775 ) { 813 ) {
776 p0++; 814 p0++;
@@ -778,7 +816,11 @@ static int parse_conf(const char *path, int flag)
778 p = p0; 816 p = p0;
779 /* if we enter this loop, we have some whitespace. 817 /* if we enter this loop, we have some whitespace.
780 * discard it */ 818 * discard it */
819#if !ENABLE_PLATFORM_MINGW32
781 while (ch != '\0' && ch != '\n' && ch != '#') { 820 while (ch != '\0' && ch != '\n' && ch != '#') {
821#else
822 while (ch != '\0' && ch != '\n' && ch != '\r' && ch != '#') {
823#endif
782 if (ch != ' ' && ch != '\t') { 824 if (ch != ' ' && ch != '\t') {
783 *p++ = ch; 825 *p++ = ch;
784 } 826 }
@@ -1311,7 +1353,21 @@ static unsigned get_line(void)
1311 count = 0; 1353 count = 0;
1312 while (1) { 1354 while (1) {
1313 if (hdr_cnt <= 0) { 1355 if (hdr_cnt <= 0) {
1356#if ENABLE_PLATFORM_MINGW32
1357 int nfds = 1;
1358 struct pollfd fds = {STDIN_FILENO, POLLIN, 0};
1359
1360 switch (poll(&fds, nfds, HEADER_READ_TIMEOUT*1000)) {
1361 case 0:
1362 send_REQUEST_TIMEOUT_and_exit(0);
1363 break;
1364 case -1:
1365 bb_simple_perror_msg_and_die("poll");
1366 break;
1367 }
1368#else
1314 alarm(HEADER_READ_TIMEOUT); 1369 alarm(HEADER_READ_TIMEOUT);
1370#endif
1315 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf); 1371 hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
1316 if (hdr_cnt <= 0) 1372 if (hdr_cnt <= 0)
1317 goto ret; 1373 goto ret;
@@ -1523,6 +1579,47 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1523#endif 1579#endif
1524 1580
1525#if ENABLE_FEATURE_HTTPD_CGI 1581#if ENABLE_FEATURE_HTTPD_CGI
1582# if ENABLE_PLATFORM_MINGW32
1583static void cgi_handler(char **argv)
1584{
1585 struct fd_pair fromCgi; /* CGI -> httpd pipe */
1586 struct fd_pair toCgi; /* httpd -> CGI pipe */
1587
1588 xfunc_error_retval = 242;
1589
1590 if (sscanf(argv[0], "%d:%d:%d:%d", &toCgi.wr, &toCgi.rd,
1591 &fromCgi.wr, &fromCgi.rd) != 4) {
1592 exit(242);
1593 }
1594
1595 /* NB: close _first_, then move fds! */
1596 close(toCgi.wr);
1597 close(fromCgi.rd);
1598 xmove_fd(toCgi.rd, 0); /* replace stdin with the pipe */
1599 xmove_fd(fromCgi.wr, 1); /* replace stdout with the pipe */
1600
1601 if (argv[1][0] && chdir_or_warn(argv[1]) != 0) {
1602 goto error_execing_cgi;
1603 }
1604
1605 /* set argv[0] to name without path */
1606 argv += 2;
1607
1608 /* _NOT_ execvp. We do not search PATH. argv[0] is a filename
1609 * without any dir components and will only match a file
1610 * in the current directory */
1611 if (foreground)
1612 execv(argv[0], argv);
1613 else
1614 httpd_execv_detach(argv[0], argv);
1615 if (verbose)
1616 bb_perror_msg("can't execute '%s'", argv[0]);
1617 error_execing_cgi:
1618 /* send to stdout */
1619 iobuf = xmalloc(IOBUF_SIZE);
1620 send_headers_and_exit(HTTP_NOT_FOUND);
1621}
1622# endif
1526 1623
1527static void setenv1(const char *name, const char *value) 1624static void setenv1(const char *name, const char *value)
1528{ 1625{
@@ -1556,6 +1653,10 @@ static void send_cgi_and_exit(
1556 struct fd_pair toCgi; /* httpd -> CGI pipe */ 1653 struct fd_pair toCgi; /* httpd -> CGI pipe */
1557 char *script, *last_slash; 1654 char *script, *last_slash;
1558 int pid; 1655 int pid;
1656#if ENABLE_PLATFORM_MINGW32
1657 const char *script_dir;
1658 char **argv;
1659#endif
1559 1660
1560 /* Make a copy. NB: caller guarantees: 1661 /* Make a copy. NB: caller guarantees:
1561 * url[0] == '/', url[1] != '/' */ 1662 * url[0] == '/', url[1] != '/' */
@@ -1592,7 +1693,11 @@ static void send_cgi_and_exit(
1592 *script = '\0'; /* cut off /PATH_INFO */ 1693 *script = '\0'; /* cut off /PATH_INFO */
1593 1694
1594 /* SCRIPT_FILENAME is required by PHP in CGI mode */ 1695 /* SCRIPT_FILENAME is required by PHP in CGI mode */
1696#if ENABLE_PLATFORM_MINGW32
1697 if (!is_relative_path(home_httpd)) {
1698#else
1595 if (home_httpd[0] == '/') { 1699 if (home_httpd[0] == '/') {
1700#endif
1596 char *fullpath = concat_path_file(home_httpd, url); 1701 char *fullpath = concat_path_file(home_httpd, url);
1597 setenv1("SCRIPT_FILENAME", fullpath); 1702 setenv1("SCRIPT_FILENAME", fullpath);
1598 } 1703 }
@@ -1642,6 +1747,50 @@ static void send_cgi_and_exit(
1642 xpiped_pair(fromCgi); 1747 xpiped_pair(fromCgi);
1643 xpiped_pair(toCgi); 1748 xpiped_pair(toCgi);
1644 1749
1750#if ENABLE_PLATFORM_MINGW32
1751 /* Find script's dir */
1752 script_dir = "";
1753 script = last_slash;
1754 if (script != url) { /* paranoia */
1755 *script = '\0';
1756 script_dir = url + 1;
1757 }
1758 script++;
1759
1760 argv = xzalloc((server_argc + 9) * sizeof(char *));
1761 argv[0] = (char *)bb_busybox_exec_path;
1762 argv[1] = (char *)"--busybox";
1763 argv[2] = (char *)"-httpd"; // don't daemonise in main()
1764 argv[3] = (char *)"-I0";
1765 memcpy(argv + 4, server_argv, sizeof(*argv) * server_argc);
1766 argv[server_argc + 4] = xasprintf("%d:%d:%d:%d", toCgi.wr, toCgi.rd,
1767 fromCgi.wr, fromCgi.rd);
1768 argv[server_argc + 5] = (char *)script_dir; // script directory
1769 argv[server_argc + 6] = (char *)script; // script name
1770
1771#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
1772 {
1773 char *suffix = strrchr(script, '.');
1774
1775 if (suffix) {
1776 Htaccess *cur;
1777 for (cur = script_i; cur; cur = cur->next) {
1778 if (strcmp(cur->before_colon + 1, suffix) == 0) {
1779 /* found interpreter name */
1780 argv[server_argc + 6] = (char *)cur->after_colon;
1781 argv[server_argc + 7] = (char *)script;
1782 break;
1783 }
1784 }
1785 }
1786 }
1787#endif
1788 /* argv[server_argc + N] = NULL; - xzalloc did it */
1789
1790 pid = foreground ? mingw_spawn(argv) : mingw_spawn_detach(argv);
1791 if (pid == -1)
1792 log_and_exit();
1793#else
1645 pid = vfork(); 1794 pid = vfork();
1646 if (pid < 0) { 1795 if (pid < 0) {
1647 /* TODO: log perror? */ 1796 /* TODO: log perror? */
@@ -1719,6 +1868,7 @@ static void send_cgi_and_exit(
1719 1868
1720 /* Restore variables possibly changed by child */ 1869 /* Restore variables possibly changed by child */
1721 xfunc_error_retval = 0; 1870 xfunc_error_retval = 0;
1871#endif
1722 1872
1723 /* Pump data */ 1873 /* Pump data */
1724 close(fromCgi.wr); 1874 close(fromCgi.wr);
@@ -1770,7 +1920,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1770 } 1920 }
1771#if ENABLE_FEATURE_HTTPD_ETAG 1921#if ENABLE_FEATURE_HTTPD_ETAG
1772 /* ETag is "hex(last_mod)-hex(file_size)" e.g. "5e132e20-417" */ 1922 /* ETag is "hex(last_mod)-hex(file_size)" e.g. "5e132e20-417" */
1773 sprintf(G.etag, "\"%llx-%llx\"", (unsigned long long)last_mod, (unsigned long long)file_size); 1923 sprintf(G.etag, "\"%"LL_FMT"x-%"LL_FMT"x\"", (unsigned long long)last_mod, (unsigned long long)file_size);
1774 1924
1775 if (G.if_none_match) { 1925 if (G.if_none_match) {
1776 dbg("If-None-Match:'%s' file's ETag:'%s'\n", G.if_none_match, G.etag); 1926 dbg("If-None-Match:'%s' file's ETag:'%s'\n", G.if_none_match, G.etag);
@@ -2025,7 +2175,11 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2025 2175
2026 /* WHY? */ 2176 /* WHY? */
2027 /* If already saw a match, don't accept other different matches */ 2177 /* If already saw a match, don't accept other different matches */
2178#if !ENABLE_PLATFORM_MINGW32
2028 if (prev && strcmp(prev, dir_prefix) != 0) 2179 if (prev && strcmp(prev, dir_prefix) != 0)
2180#else
2181 if (prev && strcasecmp(prev, dir_prefix) != 0)
2182#endif
2029 continue; 2183 continue;
2030 2184
2031 dbg("checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd); 2185 dbg("checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
@@ -2033,7 +2187,11 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2033 /* If it's not a prefix match, continue searching */ 2187 /* If it's not a prefix match, continue searching */
2034 len = strlen(dir_prefix); 2188 len = strlen(dir_prefix);
2035 if (len != 1 /* dir_prefix "/" matches all, don't need to check */ 2189 if (len != 1 /* dir_prefix "/" matches all, don't need to check */
2190#if !ENABLE_PLATFORM_MINGW32
2036 && (strncmp(dir_prefix, path, len) != 0 2191 && (strncmp(dir_prefix, path, len) != 0
2192#else
2193 && (strncasecmp(dir_prefix, path, len) != 0
2194#endif
2037 || (path[len] != '/' && path[len] != '\0') 2195 || (path[len] != '/' && path[len] != '\0')
2038 ) 2196 )
2039 ) { 2197 ) {
@@ -2055,6 +2213,7 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2055 goto bad_input; 2213 goto bad_input;
2056 2214
2057 /* compare "user:" */ 2215 /* compare "user:" */
2216# if !ENABLE_PLATFORM_MINGW32
2058 if (cur->after_colon[0] != '*' 2217 if (cur->after_colon[0] != '*'
2059 && strncmp(cur->after_colon, user_and_passwd, 2218 && strncmp(cur->after_colon, user_and_passwd,
2060 colon_after_user - user_and_passwd + 1) != 0 2219 colon_after_user - user_and_passwd + 1) != 0
@@ -2062,11 +2221,20 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2062 continue; 2221 continue;
2063 } 2222 }
2064 /* this cfg entry is '*' or matches username from peer */ 2223 /* this cfg entry is '*' or matches username from peer */
2224# else
2225 if (strncmp(cur->after_colon, user_and_passwd,
2226 colon_after_user - user_and_passwd + 1) != 0
2227 ) {
2228 continue;
2229 }
2230 /* this cfg entry matches username from peer */
2231# endif
2065 2232
2066 passwd = strchr(cur->after_colon, ':'); 2233 passwd = strchr(cur->after_colon, ':');
2067 if (!passwd) 2234 if (!passwd)
2068 goto bad_input; 2235 goto bad_input;
2069 passwd++; 2236 passwd++;
2237# if !ENABLE_PLATFORM_MINGW32
2070 if (passwd[0] == '*') { 2238 if (passwd[0] == '*') {
2071# if ENABLE_PAM 2239# if ENABLE_PAM
2072 struct pam_userinfo userinfo; 2240 struct pam_userinfo userinfo;
@@ -2114,11 +2282,12 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
2114 goto check_encrypted; 2282 goto check_encrypted;
2115# endif /* ENABLE_PAM */ 2283# endif /* ENABLE_PAM */
2116 } 2284 }
2285# endif /* !ENABLE_PLATFORM_MINGW32 */
2117 /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */ 2286 /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */
2118 2287
2119 if (passwd[0] == '$' && isdigit(passwd[1])) { 2288 if (passwd[0] == '$' && isdigit(passwd[1])) {
2120 char *encrypted; 2289 char *encrypted;
2121# if !ENABLE_PAM 2290# if !ENABLE_PAM && !ENABLE_PLATFORM_MINGW32
2122 check_encrypted: 2291 check_encrypted:
2123# endif 2292# endif
2124 /* encrypt pwd from peer and check match with local one */ 2293 /* encrypt pwd from peer and check match with local one */
@@ -2167,7 +2336,6 @@ static Htaccess_Proxy *find_proxy_entry(const char *url)
2167/* 2336/*
2168 * Handle timeouts 2337 * Handle timeouts
2169 */ 2338 */
2170static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
2171static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM) 2339static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
2172{ 2340{
2173 send_headers_and_exit(HTTP_REQUEST_TIMEOUT); 2341 send_headers_and_exit(HTTP_REQUEST_TIMEOUT);
@@ -2231,17 +2399,29 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2231 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); 2399 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr);
2232 } 2400 }
2233# if ENABLE_FEATURE_IPV6 2401# if ENABLE_FEATURE_IPV6
2402# if !ENABLE_PLATFORM_MINGW32
2234 if (fromAddr->u.sa.sa_family == AF_INET6 2403 if (fromAddr->u.sa.sa_family == AF_INET6
2235 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 2404 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0
2236 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 2405 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0
2237 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) 2406 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff)
2238 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); 2407 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]);
2408# else
2409 if (fromAddr->u.sa.sa_family == AF_INET6
2410 && fromAddr->u.sin6.sin6_addr.s6_words[0] == 0
2411 && fromAddr->u.sin6.sin6_addr.s6_words[1] == 0
2412 && fromAddr->u.sin6.sin6_addr.s6_words[2] == 0
2413 && fromAddr->u.sin6.sin6_addr.s6_words[3] == 0
2414 && ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+4)) == 0xffff)
2415 remote_ip = ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+6));
2416# endif
2239# endif 2417# endif
2240 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); 2418 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip);
2241#endif 2419#endif
2242 2420
2421#ifdef SIGALRM
2243 /* Install timeout handler. get_line() needs it. */ 2422 /* Install timeout handler. get_line() needs it. */
2244 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); 2423 signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit);
2424#endif
2245 2425
2246 if (!get_line()) { /* EOF or error or empty line */ 2426 if (!get_line()) { /* EOF or error or empty line */
2247 /* Observed Firefox to "speculatively" open 2427 /* Observed Firefox to "speculatively" open
@@ -2580,7 +2760,11 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2580 /* We are done reading headers, disable peer timeout */ 2760 /* We are done reading headers, disable peer timeout */
2581 alarm(0); 2761 alarm(0);
2582 2762
2763#if !ENABLE_PLATFORM_MINGW32
2583 if (strcmp(bb_basename(urlcopy), HTTPD_CONF) == 0) { 2764 if (strcmp(bb_basename(urlcopy), HTTPD_CONF) == 0) {
2765#else
2766 if (strcasecmp(bb_basename(urlcopy), HTTPD_CONF) == 0) {
2767#endif
2584 /* protect listing [/path]/httpd.conf or IP deny */ 2768 /* protect listing [/path]/httpd.conf or IP deny */
2585 send_headers_and_exit(HTTP_FORBIDDEN); 2769 send_headers_and_exit(HTTP_FORBIDDEN);
2586 } 2770 }
@@ -2626,12 +2810,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2626 ); 2810 );
2627} 2811}
2628 2812
2813
2629/* 2814/*
2630 * The main http server function. 2815 * The main http server function.
2631 * Given a socket, listen for new connections and farm out 2816 * Given a socket, listen for new connections and farm out
2632 * the processing as a [v]forked process. 2817 * the processing as a [v]forked process.
2633 * Never returns. 2818 * Never returns.
2634 */ 2819 */
2820# if !ENABLE_PLATFORM_MINGW32
2635#if BB_MMU 2821#if BB_MMU
2636static void mini_httpd(int server_socket) NORETURN; 2822static void mini_httpd(int server_socket) NORETURN;
2637static void mini_httpd(int server_socket) 2823static void mini_httpd(int server_socket)
@@ -2720,6 +2906,40 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
2720 /* never reached */ 2906 /* never reached */
2721} 2907}
2722#endif 2908#endif
2909#else /* ENABLE_PLATFORM_MINGW32 */
2910static void mini_httpd_win32(int sock, int argc, char **argv) NORETURN;
2911static void mini_httpd_win32(int sock, int argc, char **argv)
2912{
2913 char *argv_copy[argc + 5];
2914
2915 argv_copy[0] = (char *)bb_busybox_exec_path;
2916 argv_copy[1] = (char *)"--busybox";
2917 argv_copy[2] = (char *)"-httpd"; // don't daemonise in main()
2918 argv_copy[3] = (char *)"-I";
2919 memcpy(&argv_copy[5], &argv[1], argc * sizeof(argv[0]));
2920
2921 while (1) {
2922 int n;
2923
2924 /* Wait for connections... */
2925 n = accept(sock, NULL, NULL);
2926 if (n < 0)
2927 continue;
2928
2929 /* set the KEEPALIVE option to cull dead connections */
2930 setsockopt_keepalive(n);
2931
2932 argv_copy[4] = itoa(n);
2933 if ((foreground ?
2934 spawn(argv_copy) : mingw_spawn_detach(argv_copy)) == -1)
2935 bb_perror_msg_and_die("can't execute 'httpd'");
2936
2937 /* parent, or spawn failed */
2938 close(n);
2939 } /* while (1) */
2940 /* never reached */
2941}
2942#endif
2723 2943
2724/* 2944/*
2725 * Process a HTTP connection on stdin/out. 2945 * Process a HTTP connection on stdin/out.
@@ -2737,12 +2957,36 @@ static void mini_httpd_inetd(void)
2737 handle_incoming_and_exit(&fromAddr); 2957 handle_incoming_and_exit(&fromAddr);
2738} 2958}
2739 2959
2960#if ENABLE_PLATFORM_MINGW32
2961static void mingw_daemonize(char **argv)
2962{
2963 char **new_argv;
2964 int fd;
2965
2966 new_argv = grow_argv(argv + 1, 3);
2967 new_argv[0] = (char *)bb_busybox_exec_path;
2968 new_argv[1] = (char *)"--busybox";
2969 // don't daemonise in main(), we explicitly detach below
2970 new_argv[2] = (char *)"-httpd";
2971
2972 fd = xopen(bb_dev_null, O_RDWR);
2973 xdup2(fd, 0);
2974 xdup2(fd, 1);
2975 xdup2(fd, 2);
2976 close(fd);
2977
2978 exit(mingw_spawn_detach(new_argv) == -1 ? EXIT_FAILURE : EXIT_SUCCESS);
2979}
2980#endif
2981
2982#if !ENABLE_PLATFORM_MINGW32
2740static void sighup_handler(int sig UNUSED_PARAM) 2983static void sighup_handler(int sig UNUSED_PARAM)
2741{ 2984{
2742 int sv = errno; 2985 int sv = errno;
2743 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE); 2986 parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE);
2744 errno = sv; 2987 errno = sv;
2745} 2988}
2989#endif
2746 2990
2747enum { 2991enum {
2748 c_opt_config_file = 0, 2992 c_opt_config_file = 0,
@@ -2780,6 +3024,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2780 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;) 3024 IF_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;)
2781 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;) 3025 IF_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;)
2782 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;) 3026 IF_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
3027 IF_PLATFORM_MINGW32(int fd;)
2783 3028
2784 INIT_G(); 3029 INIT_G();
2785 3030
@@ -2798,16 +3043,19 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2798 IF_FEATURE_HTTPD_BASIC_AUTH("r:") 3043 IF_FEATURE_HTTPD_BASIC_AUTH("r:")
2799 IF_FEATURE_HTTPD_AUTH_MD5("m:") 3044 IF_FEATURE_HTTPD_AUTH_MD5("m:")
2800 IF_FEATURE_HTTPD_SETUID("u:") 3045 IF_FEATURE_HTTPD_SETUID("u:")
2801 "p:ifv" 3046 IF_NOT_PLATFORM_MINGW32("p:ifv")
3047 IF_PLATFORM_MINGW32("p:I:+fv")
2802 "\0" 3048 "\0"
2803 /* -v counts, -i implies -f */ 3049 /* -v counts, -i implies -f */
2804 "vv:if", 3050 IF_NOT_PLATFORM_MINGW32("vv:if",)
3051 IF_PLATFORM_MINGW32("vv:",)
2805 &opt_c_configFile, &url_for_decode, &home_httpd 3052 &opt_c_configFile, &url_for_decode, &home_httpd
2806 IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) 3053 IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
2807 IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) 3054 IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
2808 IF_FEATURE_HTTPD_AUTH_MD5(, &pass) 3055 IF_FEATURE_HTTPD_AUTH_MD5(, &pass)
2809 IF_FEATURE_HTTPD_SETUID(, &s_ugid) 3056 IF_FEATURE_HTTPD_SETUID(, &s_ugid)
2810 , &bind_addr_or_port 3057 , &bind_addr_or_port
3058 IF_PLATFORM_MINGW32(, &fd)
2811 , &verbose 3059 , &verbose
2812 ); 3060 );
2813 if (opt & OPT_DECODE_URL) { 3061 if (opt & OPT_DECODE_URL) {
@@ -2837,20 +3085,33 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2837 } 3085 }
2838#endif 3086#endif
2839 3087
3088#if !ENABLE_PLATFORM_MINGW32
2840#if !BB_MMU 3089#if !BB_MMU
2841 if (!(opt & OPT_FOREGROUND)) { 3090 if (!(opt & OPT_FOREGROUND)) {
2842 bb_daemonize_or_rexec(0, argv); /* don't change current directory */ 3091 bb_daemonize_or_rexec(0, argv); /* don't change current directory */
2843 re_execed = 0; /* for the following chdir to work */ 3092 re_execed = 0; /* for the following chdir to work */
2844 } 3093 }
2845#endif 3094#endif
3095#else /* ENABLE_PLATFORM_MINGW32 */
3096 foreground = (opt & OPT_FOREGROUND) == OPT_FOREGROUND;
3097 if (!foreground && argv[0][0] != '-')
3098 mingw_daemonize(argv);
3099#endif
3100
2846 /* Chdir to home (unless we were re_exec()ed for NOMMU case 3101 /* Chdir to home (unless we were re_exec()ed for NOMMU case
2847 * in mini_httpd_nommu(): we are already in the home dir then). 3102 * in mini_httpd_nommu(): we are already in the home dir then).
2848 */ 3103 */
3104#if ENABLE_PLATFORM_MINGW32
3105 if (!(opt & OPT_INETD))
3106#else
2849 if (!re_execed) 3107 if (!re_execed)
3108#endif
2850 xchdir(home_httpd); 3109 xchdir(home_httpd);
2851 3110
2852 if (!(opt & OPT_INETD)) { 3111 if (!(opt & OPT_INETD)) {
3112#ifdef SIGCHLD
2853 signal(SIGCHLD, SIG_IGN); 3113 signal(SIGCHLD, SIG_IGN);
3114#endif
2854 server_socket = openServer(); 3115 server_socket = openServer();
2855#if ENABLE_FEATURE_HTTPD_SETUID 3116#if ENABLE_FEATURE_HTTPD_SETUID
2856 /* drop privileges */ 3117 /* drop privileges */
@@ -2884,12 +3145,35 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2884#endif 3145#endif
2885 3146
2886 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); 3147 parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE);
3148#if ENABLE_PLATFORM_MINGW32
3149# if ENABLE_FEATURE_HTTPD_CGI
3150 if ((opt & OPT_INETD) && fd == 0) {
3151 cgi_handler(argv + optind);
3152 return 0;
3153 }
3154# endif
3155#else
2887 if (!(opt & OPT_INETD)) 3156 if (!(opt & OPT_INETD))
2888 signal(SIGHUP, sighup_handler); 3157 signal(SIGHUP, sighup_handler);
3158#endif
2889 3159
2890 xfunc_error_retval = 0; 3160 xfunc_error_retval = 0;
3161#if ENABLE_PLATFORM_MINGW32
3162 if (opt & OPT_INETD) {
3163 xmove_fd(fd, 0);
3164 xdup2(0, 1);
3165 while (--fd > 2)
3166 close(fd);
3167# if ENABLE_FEATURE_HTTPD_CGI
3168 /* Skip 'httpd -I N' and omit any non-option arguments */
3169 server_argc = optind - 3;
3170 server_argv = argv + 3;
3171# endif
3172 }
3173#endif
2891 if (opt & OPT_INETD) 3174 if (opt & OPT_INETD)
2892 mini_httpd_inetd(); /* never returns */ 3175 mini_httpd_inetd(); /* never returns */
3176#if !ENABLE_PLATFORM_MINGW32
2893#if BB_MMU 3177#if BB_MMU
2894 if (!(opt & OPT_FOREGROUND)) 3178 if (!(opt & OPT_FOREGROUND))
2895 bb_daemonize(0); /* don't change current directory */ 3179 bb_daemonize(0); /* don't change current directory */
@@ -2897,5 +3181,8 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
2897#else 3181#else
2898 mini_httpd_nommu(server_socket, argc, argv); /* never returns */ 3182 mini_httpd_nommu(server_socket, argc, argv); /* never returns */
2899#endif 3183#endif
3184#else /* ENABLE_PLATFORM_MINGW32 */
3185 mini_httpd_win32(server_socket, argc, argv);
3186#endif
2900 /* return 0; */ 3187 /* return 0; */
2901} 3188}
diff --git a/networking/nc.c b/networking/nc.c
index ab1316339..ee008595d 100644
--- a/networking/nc.c
+++ b/networking/nc.c
@@ -30,7 +30,7 @@
30//config:config NC_EXTRA 30//config:config NC_EXTRA
31//config: bool "Netcat extensions (-eiw and -f FILE)" 31//config: bool "Netcat extensions (-eiw and -f FILE)"
32//config: default y 32//config: default y
33//config: depends on NC || NETCAT 33//config: depends on (NC || NETCAT) && PLATFORM_POSIX
34//config: help 34//config: help
35//config: Add -e (support for executing the rest of the command line after 35//config: Add -e (support for executing the rest of the command line after
36//config: making or receiving a successful connection), -i (delay interval for 36//config: making or receiving a successful connection), -i (delay interval for
@@ -110,10 +110,12 @@
110 * when compared to "standard" nc 110 * when compared to "standard" nc
111 */ 111 */
112 112
113#if !ENABLE_PLATFORM_MINGW32
113static void timeout(int signum UNUSED_PARAM) 114static void timeout(int signum UNUSED_PARAM)
114{ 115{
115 bb_simple_error_msg_and_die("timed out"); 116 bb_simple_error_msg_and_die("timed out");
116} 117}
118#endif
117 119
118int nc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 120int nc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
119int nc_main(int argc, char **argv) 121int nc_main(int argc, char **argv)
@@ -123,7 +125,9 @@ int nc_main(int argc, char **argv)
123 int cfd = 0; 125 int cfd = 0;
124 unsigned lport = 0; 126 unsigned lport = 0;
125 IF_NOT_NC_SERVER(const) unsigned do_listen = 0; 127 IF_NOT_NC_SERVER(const) unsigned do_listen = 0;
128#if !ENABLE_PLATFORM_MINGW32
126 IF_NOT_NC_EXTRA (const) unsigned wsecs = 0; 129 IF_NOT_NC_EXTRA (const) unsigned wsecs = 0;
130#endif
127 IF_NOT_NC_EXTRA (const) unsigned delay = 0; 131 IF_NOT_NC_EXTRA (const) unsigned delay = 0;
128 IF_NOT_NC_EXTRA (const int execparam = 0;) 132 IF_NOT_NC_EXTRA (const int execparam = 0;)
129 IF_NC_EXTRA (char **execparam = NULL;) 133 IF_NC_EXTRA (char **execparam = NULL;)
@@ -187,10 +191,12 @@ int nc_main(int argc, char **argv)
187 argv++; 191 argv++;
188 } 192 }
189 193
194#if !ENABLE_PLATFORM_MINGW32
190 if (wsecs) { 195 if (wsecs) {
191 signal(SIGALRM, timeout); 196 signal(SIGALRM, timeout);
192 alarm(wsecs); 197 alarm(wsecs);
193 } 198 }
199#endif
194 200
195 if (!cfd) { 201 if (!cfd) {
196 if (do_listen) { 202 if (do_listen) {
@@ -208,7 +214,7 @@ int nc_main(int argc, char **argv)
208 } 214 }
209#endif 215#endif
210 close_on_exec_on(sfd); 216 close_on_exec_on(sfd);
211 accept_again: 217 IF_NOT_PLATFORM_MINGW32(accept_again:)
212 cfd = accept(sfd, NULL, 0); 218 cfd = accept(sfd, NULL, 0);
213 if (cfd < 0) 219 if (cfd < 0)
214 bb_simple_perror_msg_and_die("accept"); 220 bb_simple_perror_msg_and_die("accept");
@@ -220,6 +226,7 @@ int nc_main(int argc, char **argv)
220 } 226 }
221 } 227 }
222 228
229#if !ENABLE_PLATFORM_MINGW32
223 if (wsecs) { 230 if (wsecs) {
224 alarm(0); 231 alarm(0);
225 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 232 /* Non-ignored signals revert to SIG_DFL on exec anyway */
@@ -244,6 +251,7 @@ int nc_main(int argc, char **argv)
244 IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);) 251 IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);)
245 IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);) 252 IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);)
246 } 253 }
254#endif
247 255
248 /* loop copying stdin to cfd, and cfd to stdout */ 256 /* loop copying stdin to cfd, and cfd to stdout */
249 257
diff --git a/networking/ssl_client.c b/networking/ssl_client.c
index 582fb0e71..757745896 100644
--- a/networking/ssl_client.c
+++ b/networking/ssl_client.c
@@ -15,7 +15,12 @@
15//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o 15//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o
16 16
17//usage:#define ssl_client_trivial_usage 17//usage:#define ssl_client_trivial_usage
18//usage: IF_NOT_PLATFORM_MINGW32(
18//usage: "[-e] -s FD [-r FD] [-n SNI]" 19//usage: "[-e] -s FD [-r FD] [-n SNI]"
20//usage: )
21//usage: IF_PLATFORM_MINGW32(
22//usage: "[-e] -h handle [-n SNI]"
23//usage: )
19//usage:#define ssl_client_full_usage "" 24//usage:#define ssl_client_full_usage ""
20 25
21#include "libbb.h" 26#include "libbb.h"
@@ -26,15 +31,23 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv)
26 tls_state_t *tls; 31 tls_state_t *tls;
27 const char *sni = NULL; 32 const char *sni = NULL;
28 int opt; 33 int opt;
34#if ENABLE_PLATFORM_MINGW32
35 char *hstr = NULL;
36 HANDLE h;
37#endif
29 38
30 // INIT_G(); 39 // INIT_G();
31 40
32 tls = new_tls_state(); 41 tls = new_tls_state();
42#if !ENABLE_PLATFORM_MINGW32
33 opt = getopt32(argv, "es:+r:+n:", &tls->ofd, &tls->ifd, &sni); 43 opt = getopt32(argv, "es:+r:+n:", &tls->ofd, &tls->ifd, &sni);
34 if (!(opt & (1<<2))) { 44 if (!(opt & (1<<2))) {
35 /* -r N defaults to -s N */ 45 /* -r N defaults to -s N */
36 tls->ifd = tls->ofd; 46 tls->ifd = tls->ofd;
37 } 47 }
48#else
49 opt = getopt32(argv, "eh:n:", &hstr, &sni);
50#endif
38 51
39 if (!(opt & (3<<1))) { 52 if (!(opt & (3<<1))) {
40 if (!argv[1]) 53 if (!argv[1])
@@ -47,6 +60,14 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv)
47 sni = argv[1]; 60 sni = argv[1];
48 tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); 61 tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443);
49 } 62 }
63#if ENABLE_PLATFORM_MINGW32
64 else {
65 if (!hstr || sscanf(hstr, "%p", &h) != 1)
66 bb_error_msg_and_die("invalid handle");
67 init_winsock();
68 tls->ifd = tls->ofd = _open_osfhandle((intptr_t)h, _O_RDWR|_O_BINARY);
69 }
70#endif
50 71
51 tls_handshake(tls, sni); 72 tls_handshake(tls, sni);
52 73
diff --git a/networking/tls.c b/networking/tls.c
index 8d074c058..9f1dd67ec 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -331,7 +331,7 @@ static void dump_tls_record(const void *vp, int len)
331 331
332void FAST_FUNC tls_get_random(void *buf, unsigned len) 332void FAST_FUNC tls_get_random(void *buf, unsigned len)
333{ 333{
334 if (len != open_read_close("/dev/urandom", buf, len)) 334 if (len != MINGW_SPECIAL(open_read_close)("/dev/urandom", buf, len))
335 xfunc_die(); 335 xfunc_die();
336} 336}
337 337
diff --git a/networking/wget.c b/networking/wget.c
index ec3767793..6a64836fb 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -214,6 +214,9 @@ enum {
214 HDR_CONTENT_TYPE = (1<<3), 214 HDR_CONTENT_TYPE = (1<<3),
215 HDR_AUTH = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION, 215 HDR_AUTH = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION,
216 HDR_PROXY_AUTH = (1<<5) * ENABLE_FEATURE_WGET_AUTHENTICATION, 216 HDR_PROXY_AUTH = (1<<5) * ENABLE_FEATURE_WGET_AUTHENTICATION,
217# if ENABLE_PLATFORM_MINGW32
218 HDR_CONTENT_LENGTH = (1<<(4 + 2 * ENABLE_FEATURE_WGET_AUTHENTICATION)),
219# endif
217}; 220};
218static const char wget_user_headers[] ALIGN1 = 221static const char wget_user_headers[] ALIGN1 =
219 "Host:\0" 222 "Host:\0"
@@ -224,6 +227,9 @@ static const char wget_user_headers[] ALIGN1 =
224 "Authorization:\0" 227 "Authorization:\0"
225 "Proxy-Authorization:\0" 228 "Proxy-Authorization:\0"
226# endif 229# endif
230# if ENABLE_PLATFORM_MINGW32
231 "Content-Length:\0"
232# endif
227 ; 233 ;
228# define USR_HEADER_HOST (G.user_headers & HDR_HOST) 234# define USR_HEADER_HOST (G.user_headers & HDR_HOST)
229# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT) 235# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT)
@@ -231,6 +237,7 @@ static const char wget_user_headers[] ALIGN1 =
231# define USR_HEADER_CONTENT_TYPE (G.user_headers & HDR_CONTENT_TYPE) 237# define USR_HEADER_CONTENT_TYPE (G.user_headers & HDR_CONTENT_TYPE)
232# define USR_HEADER_AUTH (G.user_headers & HDR_AUTH) 238# define USR_HEADER_AUTH (G.user_headers & HDR_AUTH)
233# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH) 239# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH)
240# define USR_HEADER_CONTENT_LENGTH (G.user_headers & HDR_CONTENT_LENGTH)
234#else /* No long options, no user-headers :( */ 241#else /* No long options, no user-headers :( */
235# define USR_HEADER_HOST 0 242# define USR_HEADER_HOST 0
236# define USR_HEADER_USER_AGENT 0 243# define USR_HEADER_USER_AGENT 0
@@ -238,6 +245,7 @@ static const char wget_user_headers[] ALIGN1 =
238# define USR_HEADER_CONTENT_TYPE 0 245# define USR_HEADER_CONTENT_TYPE 0
239# define USR_HEADER_AUTH 0 246# define USR_HEADER_AUTH 0
240# define USR_HEADER_PROXY_AUTH 0 247# define USR_HEADER_PROXY_AUTH 0
248# define USR_HEADER_CONTENT_LENGTH 0
241#endif 249#endif
242 250
243/* Globals */ 251/* Globals */
@@ -517,6 +525,9 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
517 fprintf(stderr, "--> %s%s\n\n", s1, s2); 525 fprintf(stderr, "--> %s%s\n\n", s1, s2);
518 fflush(fp); 526 fflush(fp);
519 log_io("> %s%s", s1, s2); 527 log_io("> %s%s", s1, s2);
528#if ENABLE_PLATFORM_MINGW32
529 fseek(fp, 0L, SEEK_CUR);
530#endif
520 } 531 }
521 532
522 /* Read until "Nxx something" is received */ 533 /* Read until "Nxx something" is received */
@@ -524,6 +535,9 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
524 do { 535 do {
525 fgets_trim_sanitize(fp, "%s\n"); 536 fgets_trim_sanitize(fp, "%s\n");
526 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); 537 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');
538#if ENABLE_PLATFORM_MINGW32
539 fseek(fp, 0L, SEEK_CUR);
540#endif
527 541
528 G.wget_buf[3] = '\0'; 542 G.wget_buf[3] = '\0';
529 result = xatoi_positive(G.wget_buf); 543 result = xatoi_positive(G.wget_buf);
@@ -766,6 +780,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
766#endif 780#endif
767 781
768#if ENABLE_FEATURE_WGET_HTTPS 782#if ENABLE_FEATURE_WGET_HTTPS
783# if !ENABLE_PLATFORM_MINGW32
769static void spawn_ssl_client(const char *host, int network_fd, int flags) 784static void spawn_ssl_client(const char *host, int network_fd, int flags)
770{ 785{
771 int sp[2]; 786 int sp[2];
@@ -820,6 +835,31 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags)
820 close(sp[1]); 835 close(sp[1]);
821 xmove_fd(sp[0], network_fd); 836 xmove_fd(sp[0], network_fd);
822} 837}
838# else
839static void spawn_ssl_client(const char *host, int network_fd, int flags)
840{
841 int fd1;
842 char *servername, *p, *cmd;
843
844 servername = xstrdup(host);
845 p = strrchr(servername, ':');
846 if (p) *p = '\0';
847
848 fflush_all();
849
850 cmd = xasprintf("ssl_client -h %p -n %s%s",
851 (void *)_get_osfhandle(network_fd), servername,
852 flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? " -e" : "");
853
854 if ((fd1=mingw_popen_fd("ssl_client", cmd, "b", -1, NULL)) == -1) {
855 bb_perror_msg_and_die("can't execute ssl_client");
856 }
857
858 free(cmd);
859 free(servername);
860 xmove_fd(fd1, network_fd);
861}
862# endif
823#endif 863#endif
824 864
825#if ENABLE_FEATURE_WGET_FTP 865#if ENABLE_FEATURE_WGET_FTP
@@ -1273,6 +1313,18 @@ static void download_one_url(const char *url)
1273 "Content-Type: application/x-www-form-urlencoded\r\n" 1313 "Content-Type: application/x-www-form-urlencoded\r\n"
1274 ); 1314 );
1275 } 1315 }
1316# if ENABLE_PLATFORM_MINGW32
1317 if (!USR_HEADER_CONTENT_LENGTH)
1318 SENDFMT(sfp, "Content-Length: %u\r\n",
1319 (int)strlen(G.post_data)
1320 );
1321 SENDFMT(sfp,
1322 "\r\n"
1323 "%s",
1324 G.post_data
1325 );
1326 } else
1327# else
1276 SENDFMT(sfp, 1328 SENDFMT(sfp,
1277 "Content-Length: %u\r\n" 1329 "Content-Length: %u\r\n"
1278 "\r\n" 1330 "\r\n"
@@ -1280,6 +1332,7 @@ static void download_one_url(const char *url)
1280 (int) strlen(G.post_data), G.post_data 1332 (int) strlen(G.post_data), G.post_data
1281 ); 1333 );
1282 } else 1334 } else
1335# endif
1283#endif 1336#endif
1284 { 1337 {
1285 SENDFMT(sfp, "\r\n"); 1338 SENDFMT(sfp, "\r\n");