summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-14 16:55:01 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-14 16:55:01 +0000
commit384b1d12f957a3a4c80fb32bc29cb79c282ac361 (patch)
tree8011c52fb98f2613626edfcd879508bc5c45d66a
parent0372f0f1999ace825a2265ad03b80be627b039fb (diff)
downloadbusybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.tar.gz
busybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.tar.bz2
busybox-w32-384b1d12f957a3a4c80fb32bc29cb79c282ac361.zip
httpd: add -v[v]: prints client addresses, HTTP codes returned [and URLs]
get_line - 70 +70 packed_usage 22811 22863 +52 handle_incoming_and_exit 2246 2277 +31 httpd_main 1141 1155 +14 sendHeaders 489 482 -7 getLine 77 - -77 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 3/1 up/down: 167/-84) Total: 83 bytes text data bss dec hex filename 774335 1058 11092 786485 c0035 busybox_old 774447 1058 11092 786597 c00a5 busybox_unstripped
-rw-r--r--include/usage.h9
-rw-r--r--libbb/xfuncs.c12
-rw-r--r--networking/httpd.c242
3 files changed, 128 insertions, 135 deletions
diff --git a/include/usage.h b/include/usage.h
index 41459e8c3..d9e2857e8 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1344,8 +1344,8 @@
1344 1344
1345#define httpd_trivial_usage \ 1345#define httpd_trivial_usage \
1346 "[-c conffile]" \ 1346 "[-c conffile]" \
1347 " [-p port]" \ 1347 " [-p [ip:]port]" \
1348 " [-i] [-f]" \ 1348 " [-i] [-f] [-v[v]]" \
1349 USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \ 1349 USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \
1350 USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \ 1350 USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \
1351 USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \ 1351 USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \
@@ -1355,9 +1355,10 @@
1355 "Listen for incoming HTTP requests" \ 1355 "Listen for incoming HTTP requests" \
1356 "\n\nOptions:" \ 1356 "\n\nOptions:" \
1357 "\n -c FILE Configuration file (default httpd.conf)" \ 1357 "\n -c FILE Configuration file (default httpd.conf)" \
1358 "\n -p PORT Server port (default 80)" \ 1358 "\n -p [IP:]PORT Bind to ip:port (default *:80)" \
1359 "\n -i Inetd mode" \ 1359 "\n -i Inetd mode" \
1360 "\n -f Do not daemonize" \ 1360 "\n -f Do not daemonize" \
1361 "\n -v[v] Verbose" \
1361 USE_FEATURE_HTTPD_SETUID( \ 1362 USE_FEATURE_HTTPD_SETUID( \
1362 "\n -u USER[:GRP] Set uid/gid after binding to port") \ 1363 "\n -u USER[:GRP] Set uid/gid after binding to port") \
1363 USE_FEATURE_HTTPD_BASIC_AUTH( \ 1364 USE_FEATURE_HTTPD_BASIC_AUTH( \
@@ -1366,7 +1367,7 @@
1366 "\n -m PASS Crypt PASS with md5 algorithm") \ 1367 "\n -m PASS Crypt PASS with md5 algorithm") \
1367 "\n -h HOME Home directory (default .)" \ 1368 "\n -h HOME Home directory (default .)" \
1368 "\n -e STRING HTML encode STRING" \ 1369 "\n -e STRING HTML encode STRING" \
1369 "\n -d STRING URL decode STRING" 1370 "\n -d STRING URL decode STRING" \
1370 1371
1371#define hwclock_trivial_usage \ 1372#define hwclock_trivial_usage \
1372 "[-r|--show] [-s|--hctosys] [-w|--systohc]" \ 1373 "[-r|--show] [-s|--hctosys] [-w|--systohc]" \
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 67c986640..4e17c28bd 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -484,12 +484,14 @@ int fdprintf(int fd, const char *format, ...)
484#else 484#else
485 // Bloat for systems that haven't got the GNU extension. 485 // Bloat for systems that haven't got the GNU extension.
486 va_start(p, format); 486 va_start(p, format);
487 r = vsnprintf(NULL, 0, format, p); 487 r = vsnprintf(NULL, 0, format, p) + 1;
488 va_end(p);
489 string_ptr = xmalloc(r+1);
490 va_start(p, format);
491 r = vsnprintf(string_ptr, r+1, format, p);
492 va_end(p); 488 va_end(p);
489 string_ptr = malloc(r);
490 if (string_ptr) {
491 va_start(p, format);
492 r = vsnprintf(string_ptr, r, format, p);
493 va_end(p);
494 }
493#endif 495#endif
494 496
495 if (r >= 0) { 497 if (r >= 0) {
diff --git a/networking/httpd.c b/networking/httpd.c
index 875b9d641..9a9489ed5 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -132,17 +132,22 @@ typedef struct Htaccess_IP {
132struct globals { 132struct globals {
133 int server_socket; 133 int server_socket;
134 int accepted_socket; 134 int accepted_socket;
135 int verbose;
135 volatile smallint alarm_signaled; 136 volatile smallint alarm_signaled;
136 smallint flg_deny_all; 137 smallint flg_deny_all;
138
139 unsigned rmt_ip;
140 unsigned tcp_port; /* for set env REMOTE_PORT */
141 const char *bind_addr_or_port;
142
137 const char *g_query; 143 const char *g_query;
138 const char *configFile; 144 const char *configFile;
139 const char *home_httpd; 145 const char *home_httpd;
140 unsigned rmt_ip;
141 146
142 const char *found_mime_type; 147 const char *found_mime_type;
143 const char *found_moved_temporarily; 148 const char *found_moved_temporarily;
144 off_t ContentLength; /* -1 - unknown */
145 time_t last_mod; 149 time_t last_mod;
150 off_t ContentLength; /* -1 - unknown */
146 Htaccess_IP *ip_a_d; /* config allow/deny lines */ 151 Htaccess_IP *ip_a_d; /* config allow/deny lines */
147 152
148 USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) 153 USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
@@ -150,11 +155,7 @@ struct globals {
150 USE_FEATURE_HTTPD_CGI(char *referer;) 155 USE_FEATURE_HTTPD_CGI(char *referer;)
151 USE_FEATURE_HTTPD_CGI(char *user_agent;) 156 USE_FEATURE_HTTPD_CGI(char *user_agent;)
152 157
153#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
154 char *rmt_ip_str; /* for set env REMOTE_ADDR */ 158 char *rmt_ip_str; /* for set env REMOTE_ADDR */
155#endif
156 const char *bind_addr_or_port;
157 unsigned tcp_port; /* for set env REMOTE_PORT */
158 159
159#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 160#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
160 Htaccess *g_auth; /* config user:password lines */ 161 Htaccess *g_auth; /* config user:password lines */
@@ -168,38 +169,31 @@ struct globals {
168 char iobuf[MAX_MEMORY_BUF]; 169 char iobuf[MAX_MEMORY_BUF];
169}; 170};
170#define G (*ptr_to_globals) 171#define G (*ptr_to_globals)
171#define server_socket (G.server_socket ) 172#define server_socket (G.server_socket )
172#define accepted_socket (G.accepted_socket) 173#define accepted_socket (G.accepted_socket )
173#define alarm_signaled (G.alarm_signaled ) 174#define verbose (G.verbose )
174#define flg_deny_all (G.flg_deny_all ) 175#define alarm_signaled (G.alarm_signaled )
175#define g_query (G.g_query ) 176#define flg_deny_all (G.flg_deny_all )
176#define configFile (G.configFile ) 177#define rmt_ip (G.rmt_ip )
177#define home_httpd (G.home_httpd ) 178#define tcp_port (G.tcp_port )
178#define rmt_ip (G.rmt_ip )
179#define found_mime_type (G.found_mime_type)
180#define found_moved_temporarily (G.found_moved_temporarily)
181#define ContentLength (G.ContentLength )
182#define last_mod (G.last_mod )
183#define ip_a_d (G.ip_a_d )
184#define g_realm (G.g_realm )
185#define remoteuser (G.remoteuser )
186#define referer (G.referer )
187#define user_agent (G.user_agent )
188#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
189#define rmt_ip_str (G.rmt_ip_str )
190#endif
191#define bind_addr_or_port (G.bind_addr_or_port) 179#define bind_addr_or_port (G.bind_addr_or_port)
192#define tcp_port (G.tcp_port ) 180#define g_query (G.g_query )
193#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 181#define configFile (G.configFile )
194#define g_auth (G.g_auth ) 182#define home_httpd (G.home_httpd )
195#endif 183#define found_mime_type (G.found_mime_type )
196#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 184#define found_moved_temporarily (G.found_moved_temporarily)
197#define mime_a (G.mime_a ) 185#define ContentLength (G.ContentLength )
198#endif 186#define last_mod (G.last_mod )
199#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 187#define ip_a_d (G.ip_a_d )
200#define script_i (G.script_i ) 188#define g_realm (G.g_realm )
201#endif 189#define remoteuser (G.remoteuser )
202#define iobuf (G.iobuf ) 190#define referer (G.referer )
191#define user_agent (G.user_agent )
192#define rmt_ip_str (G.rmt_ip_str )
193#define g_auth (G.g_auth )
194#define mime_a (G.mime_a )
195#define script_i (G.script_i )
196#define iobuf (G.iobuf )
203#define INIT_G() do { \ 197#define INIT_G() do { \
204 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ 198 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
205 USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ 199 USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
@@ -210,7 +204,7 @@ struct globals {
210static const char request_GET[] ALIGN1 = "GET"; /* size algorithmic optimize */ 204static const char request_GET[] ALIGN1 = "GET"; /* size algorithmic optimize */
211 205
212static const char *const suffixTable[] = { 206static const char *const suffixTable[] = {
213/* Warning: shorted equivalent suffix in one line must be first */ 207/* Warning: shorter equivalent suffix in one line must be first */
214 ".htm.html", "text/html", 208 ".htm.html", "text/html",
215 ".jpg.jpeg", "image/jpeg", 209 ".jpg.jpeg", "image/jpeg",
216 ".gif", "image/gif", 210 ".gif", "image/gif",
@@ -780,24 +774,14 @@ static void setenv_long(const char *name, long value)
780#endif 774#endif
781 775
782#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 776#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
783/**************************************************************************** 777/*
784 * 778 * Decode a base 64 data stream as per rfc1521.
785 > $Function: decodeBase64() 779 * Note that the rfc states that non base64 chars are to be ignored.
786 * 780 * Since the decode always results in a shorter size than the input, it is
787 > $Description: Decode a base 64 data stream as per rfc1521. 781 * OK to pass the input arg as an output arg.
788 * Note that the rfc states that none base64 chars are to be ignored. 782 * Parameter: a pointer to a base64 encoded string.
789 * Since the decode always results in a shorter size than the input, it is 783 * Decoded data is stored in-place.
790 * OK to pass the input arg as an output arg. 784 */
791 *
792 * $Parameter:
793 * (char *) Data . . . . A pointer to a base64 encoded string.
794 * Where to place the decoded data.
795 *
796 * $Return: void
797 *
798 * $Errors: None
799 *
800 ****************************************************************************/
801static void decodeBase64(char *Data) 785static void decodeBase64(char *Data)
802{ 786{
803 const unsigned char *in = (const unsigned char *)Data; 787 const unsigned char *in = (const unsigned char *)Data;
@@ -871,13 +855,12 @@ static int openServer(void)
871 */ 855 */
872static int sendHeaders(HttpResponseNum responseNum) 856static int sendHeaders(HttpResponseNum responseNum)
873{ 857{
874 char *const buf = iobuf; // dont really need it?
875 const char *responseString = ""; 858 const char *responseString = "";
876 const char *infoString = 0; 859 const char *infoString = NULL;
877 const char *mime_type; 860 const char *mime_type;
878 unsigned i; 861 unsigned i;
879 time_t timer = time(0); 862 time_t timer = time(0);
880 char timeStr[80]; 863 char tmp_str[80];
881 int len; 864 int len;
882 865
883 for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) { 866 for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) {
@@ -891,54 +874,60 @@ static int sendHeaders(HttpResponseNum responseNum)
891 mime_type = responseNum == HTTP_OK ? 874 mime_type = responseNum == HTTP_OK ?
892 found_mime_type : "text/html"; 875 found_mime_type : "text/html";
893 876
877 if (verbose)
878 write(2, iobuf, sprintf(iobuf, "%s response:%u\n", rmt_ip_str, responseNum));
879
894 /* emit the current date */ 880 /* emit the current date */
895 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); 881 strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&timer));
896 len = sprintf(buf, 882 len = sprintf(iobuf,
897 "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" 883 "HTTP/1.0 %d %s\r\nContent-type: %s\r\n"
898 "Date: %s\r\nConnection: close\r\n", 884 "Date: %s\r\nConnection: close\r\n",
899 responseNum, responseString, mime_type, timeStr); 885 responseNum, responseString, mime_type, tmp_str);
900 886
901#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 887#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
902 if (responseNum == HTTP_UNAUTHORIZED) { 888 if (responseNum == HTTP_UNAUTHORIZED) {
903 len += sprintf(buf+len, 889 len += sprintf(iobuf + len,
904 "WWW-Authenticate: Basic realm=\"%s\"\r\n", 890 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
905 g_realm); 891 g_realm);
906 } 892 }
907#endif 893#endif
908 if (responseNum == HTTP_MOVED_TEMPORARILY) { 894 if (responseNum == HTTP_MOVED_TEMPORARILY) {
909 len += sprintf(buf+len, "Location: %s/%s%s\r\n", 895 len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
910 found_moved_temporarily, 896 found_moved_temporarily,
911 (g_query ? "?" : ""), 897 (g_query ? "?" : ""),
912 (g_query ? g_query : "")); 898 (g_query ? g_query : ""));
913 } 899 }
914 900
915 if (ContentLength != -1) { /* file */ 901 if (ContentLength != -1) { /* file */
916 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod)); 902 strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod));
917 len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", 903 len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
918 timeStr, "Content-length:", ContentLength); 904 tmp_str, "Content-length:", ContentLength);
919 } 905 }
920 strcat(buf, "\r\n"); 906 strcat(iobuf, "\r\n");
921 len += 2; 907 len += 2;
922 if (infoString) { 908 if (infoString) {
923 len += sprintf(buf+len, 909 len += sprintf(iobuf + len,
924 "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" 910 "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
925 "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n", 911 "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n",
926 responseNum, responseString, 912 responseNum, responseString,
927 responseNum, responseString, infoString); 913 responseNum, responseString, infoString);
928 } 914 }
929 if (DEBUG) 915 if (DEBUG)
930 fprintf(stderr, "headers: '%s'\n", buf); 916 fprintf(stderr, "headers: '%s'\n", iobuf);
931 i = accepted_socket; 917 i = accepted_socket;
932 if (i == 0) i++; /* write to fd #1 in inetd mode */ 918 if (i == 0)
933 return full_write(i, buf, len); 919 i++; /* write to fd #1 in inetd mode */
920 return full_write(i, iobuf, len);
934} 921}
935 922
936/* 923/*
937 * Read from the socket until '\n' or EOF. '\r' chars are removed. 924 * Read from the socket until '\n' or EOF. '\r' chars are removed.
938 * Return number of characters read or -1 if nothing is read. 925 * '\n' is replaced with NUL.
926 * Return number of characters read or 0 if nothing is read
927 * ('\r' and '\n' are not counted).
939 * Data is returned in iobuf. 928 * Data is returned in iobuf.
940 */ 929 */
941static int getLine(void) 930static int get_line(void)
942{ 931{
943 int count = 0; 932 int count = 0;
944 933
@@ -953,9 +942,7 @@ static int getLine(void)
953 if (count < (MAX_MEMORY_BUF - 1)) /* check overflow */ 942 if (count < (MAX_MEMORY_BUF - 1)) /* check overflow */
954 count++; 943 count++;
955 } 944 }
956 if (count) 945 return count;
957 return count;
958 return -1;
959} 946}
960 947
961#if ENABLE_FEATURE_HTTPD_CGI 948#if ENABLE_FEATURE_HTTPD_CGI
@@ -1414,11 +1401,10 @@ static int checkPermIP(void)
1414 1401
1415 /* This could stand some work */ 1402 /* This could stand some work */
1416 for (cur = ip_a_d; cur; cur = cur->next) { 1403 for (cur = ip_a_d; cur; cur = cur->next) {
1417#if ENABLE_FEATURE_HTTPD_CGI && DEBUG
1418 fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str);
1419#endif
1420#if DEBUG 1404#if DEBUG
1421 fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", 1405 fprintf(stderr,
1406 "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n",
1407 rmt_ip_str,
1422 (unsigned char)(cur->ip >> 24), 1408 (unsigned char)(cur->ip >> 24),
1423 (unsigned char)(cur->ip >> 16), 1409 (unsigned char)(cur->ip >> 16),
1424 (unsigned char)(cur->ip >> 8), 1410 (unsigned char)(cur->ip >> 8),
@@ -1539,7 +1525,6 @@ static void handle_sigalrm(int sig)
1539static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN; 1525static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN;
1540static void handle_incoming_and_exit(void) 1526static void handle_incoming_and_exit(void)
1541{ 1527{
1542 char *buf = iobuf;
1543 char *url; 1528 char *url;
1544 char *purl; 1529 char *purl;
1545 int blank = -1; 1530 int blank = -1;
@@ -1569,10 +1554,10 @@ static void handle_incoming_and_exit(void)
1569 int count; 1554 int count;
1570 1555
1571 alarm(TIMEOUT); 1556 alarm(TIMEOUT);
1572 if (getLine() <= 0) 1557 if (!get_line())
1573 break; /* closed */ 1558 break; /* EOF or error or empty line */
1574 1559
1575 purl = strpbrk(buf, " \t"); 1560 purl = strpbrk(iobuf, " \t");
1576 if (purl == NULL) { 1561 if (purl == NULL) {
1577 BAD_REQUEST: 1562 BAD_REQUEST:
1578 sendHeaders(HTTP_BAD_REQUEST); 1563 sendHeaders(HTTP_BAD_REQUEST);
@@ -1580,32 +1565,32 @@ static void handle_incoming_and_exit(void)
1580 } 1565 }
1581 *purl = '\0'; 1566 *purl = '\0';
1582#if ENABLE_FEATURE_HTTPD_CGI 1567#if ENABLE_FEATURE_HTTPD_CGI
1583 if (strcasecmp(buf, prequest) != 0) { 1568 if (strcasecmp(iobuf, prequest) != 0) {
1584 prequest = "POST"; 1569 prequest = "POST";
1585 if (strcasecmp(buf, prequest) != 0) { 1570 if (strcasecmp(iobuf, prequest) != 0) {
1586 sendHeaders(HTTP_NOT_IMPLEMENTED); 1571 sendHeaders(HTTP_NOT_IMPLEMENTED);
1587 break; 1572 break;
1588 } 1573 }
1589 } 1574 }
1590#else 1575#else
1591 if (strcasecmp(buf, request_GET) != 0) { 1576 if (strcasecmp(iobuf, request_GET) != 0) {
1592 sendHeaders(HTTP_NOT_IMPLEMENTED); 1577 sendHeaders(HTTP_NOT_IMPLEMENTED);
1593 break; 1578 break;
1594 } 1579 }
1595#endif 1580#endif
1596 *purl = ' '; 1581 *purl = ' ';
1597 count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank); 1582 count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
1598 1583
1599 if (count < 1 || buf[0] != '/') { 1584 if (count < 1 || iobuf[0] != '/') {
1600 /* Garbled request/URL */ 1585 /* Garbled request/URL */
1601 goto BAD_REQUEST; 1586 goto BAD_REQUEST;
1602 } 1587 }
1603 url = alloca(strlen(buf) + sizeof("/index.html")); 1588 url = alloca(strlen(iobuf) + sizeof("/index.html"));
1604 if (url == NULL) { 1589 if (url == NULL) {
1605 sendHeaders(HTTP_INTERNAL_SERVER_ERROR); 1590 sendHeaders(HTTP_INTERNAL_SERVER_ERROR);
1606 break; 1591 break;
1607 } 1592 }
1608 strcpy(url, buf); 1593 strcpy(url, iobuf);
1609 /* extract url args if present */ 1594 /* extract url args if present */
1610 test = strchr(url, '?'); 1595 test = strchr(url, '?');
1611 g_query = NULL; 1596 g_query = NULL;
@@ -1641,7 +1626,7 @@ static void handle_incoming_and_exit(void)
1641 if (test[1] == '.' && (test[2] == '/' || !test[2])) { 1626 if (test[1] == '.' && (test[2] == '/' || !test[2])) {
1642 ++test; 1627 ++test;
1643 if (purl == url) { 1628 if (purl == url) {
1644 /* protect out root */ 1629 /* protect root */
1645 goto BAD_REQUEST; 1630 goto BAD_REQUEST;
1646 } 1631 }
1647 while (*--purl != '/') /* omit previous dir */; 1632 while (*--purl != '/') /* omit previous dir */;
@@ -1660,8 +1645,11 @@ static void handle_incoming_and_exit(void)
1660 found_moved_temporarily = url; 1645 found_moved_temporarily = url;
1661 } 1646 }
1662 } 1647 }
1663 if (DEBUG) 1648 if (verbose > 1) {
1664 fprintf(stderr, "url='%s', args=%s\n", url, g_query); 1649 /* Hopefully does it with single write[v] */
1650 /* (uclibc does, glibc: ?) */
1651 fdprintf(2, "%s url:%s\n", rmt_ip_str, url);
1652 }
1665 1653
1666 test = url; 1654 test = url;
1667 ip_allowed = checkPermIP(); 1655 ip_allowed = checkPermIP();
@@ -1679,18 +1667,18 @@ static void handle_incoming_and_exit(void)
1679 /* read until blank line for HTTP version specified, else parse immediate */ 1667 /* read until blank line for HTTP version specified, else parse immediate */
1680 while (1) { 1668 while (1) {
1681 alarm(TIMEOUT); 1669 alarm(TIMEOUT);
1682 if (getLine() <= 0) 1670 if (!get_line())
1683 break; 1671 break; /* EOF or error or empty line */
1684 1672
1685 if (DEBUG) 1673 if (DEBUG)
1686 fprintf(stderr, "header: '%s'\n", buf); 1674 fprintf(stderr, "header: '%s'\n", iobuf);
1687 1675
1688#if ENABLE_FEATURE_HTTPD_CGI 1676#if ENABLE_FEATURE_HTTPD_CGI
1689 /* try and do our best to parse more lines */ 1677 /* try and do our best to parse more lines */
1690 if ((STRNCASECMP(buf, "Content-length:") == 0)) { 1678 if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
1691 /* extra read only for POST */ 1679 /* extra read only for POST */
1692 if (prequest != request_GET) { 1680 if (prequest != request_GET) {
1693 test = buf + sizeof("Content-length:") - 1; 1681 test = iobuf + sizeof("Content-length:") - 1;
1694 if (!test[0]) 1682 if (!test[0])
1695 goto bail_out; 1683 goto bail_out;
1696 errno = 0; 1684 errno = 0;
@@ -1702,24 +1690,24 @@ static void handle_incoming_and_exit(void)
1702 if (test[0] || errno || length > INT_MAX) 1690 if (test[0] || errno || length > INT_MAX)
1703 goto bail_out; 1691 goto bail_out;
1704 } 1692 }
1705 } else if (STRNCASECMP(buf, "Cookie:") == 0) { 1693 } else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
1706 cookie = strdup(skip_whitespace(buf + sizeof("Cookie:")-1)); 1694 cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
1707 } else if (STRNCASECMP(buf, "Content-Type:") == 0) { 1695 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
1708 content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); 1696 content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
1709 } else if (STRNCASECMP(buf, "Referer:") == 0) { 1697 } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
1710 referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); 1698 referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
1711 } else if (STRNCASECMP(buf, "User-Agent:") == 0) { 1699 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
1712 user_agent = strdup(skip_whitespace(buf + sizeof("User-Agent:")-1)); 1700 user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
1713 } 1701 }
1714#endif 1702#endif
1715 1703
1716#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1704#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1717 if (STRNCASECMP(buf, "Authorization:") == 0) { 1705 if (STRNCASECMP(iobuf, "Authorization:") == 0) {
1718 /* We only allow Basic credentials. 1706 /* We only allow Basic credentials.
1719 * It shows up as "Authorization: Basic <userid:password>" where 1707 * It shows up as "Authorization: Basic <userid:password>" where
1720 * the userid:password is base64 encoded. 1708 * the userid:password is base64 encoded.
1721 */ 1709 */
1722 test = skip_whitespace(buf + sizeof("Authorization:")-1); 1710 test = skip_whitespace(iobuf + sizeof("Authorization:")-1);
1723 if (STRNCASECMP(test, "Basic") != 0) 1711 if (STRNCASECMP(test, "Basic") != 0)
1724 continue; 1712 continue;
1725 test += sizeof("Basic")-1; 1713 test += sizeof("Basic")-1;
@@ -1762,7 +1750,7 @@ static void handle_incoming_and_exit(void)
1762 1750
1763#if ENABLE_FEATURE_HTTPD_CGI 1751#if ENABLE_FEATURE_HTTPD_CGI
1764 if (strncmp(test, "cgi-bin", 7) == 0) { 1752 if (strncmp(test, "cgi-bin", 7) == 0) {
1765 if (test[7] == '/' && test[8] == 0) 1753 if (test[7] == '/' && test[8] == '\0')
1766 goto FORBIDDEN; /* protect listing cgi-bin/ */ 1754 goto FORBIDDEN; /* protect listing cgi-bin/ */
1767 sendCgi(url, prequest, length, cookie, content_type); 1755 sendCgi(url, prequest, length, cookie, content_type);
1768 break; 1756 break;
@@ -1839,7 +1827,7 @@ static void handle_incoming_and_exit(void)
1839 tv.tv_sec = 2; 1827 tv.tv_sec = 2;
1840 tv.tv_usec = 0; 1828 tv.tv_usec = 0;
1841 retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv); 1829 retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv);
1842 } while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0)); 1830 } while (retval > 0 && read(accepted_socket, iobuf, sizeof(iobuf) > 0));
1843 shutdown(accepted_socket, SHUT_RD); 1831 shutdown(accepted_socket, SHUT_RD);
1844 close(accepted_socket); 1832 close(accepted_socket);
1845 exit(0); 1833 exit(0);
@@ -1883,13 +1871,12 @@ static void mini_httpd(int server)
1883 accepted_socket = s; 1871 accepted_socket = s;
1884 rmt_ip = 0; 1872 rmt_ip = 0;
1885 tcp_port = 0; 1873 tcp_port = 0;
1886#if ENABLE_FEATURE_HTTPD_CGI || DEBUG 1874 if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) {
1887 free(rmt_ip_str); 1875 free(rmt_ip_str);
1888 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); 1876 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
1889#if DEBUG 1877 if (DEBUG)
1890 bb_error_msg("connection from '%s'", rmt_ip_str); 1878 bb_error_msg("connection from '%s'", rmt_ip_str);
1891#endif 1879 }
1892#endif /* FEATURE_HTTPD_CGI */
1893 if (fromAddr.sa.sa_family == AF_INET) { 1880 if (fromAddr.sa.sa_family == AF_INET) {
1894 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1881 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1895 tcp_port = ntohs(fromAddr.sin.sin_port); 1882 tcp_port = ntohs(fromAddr.sin.sin_port);
@@ -1932,10 +1919,10 @@ static void mini_httpd_inetd(void)
1932 getpeername(0, &fromAddr.sa, &fromAddrLen); 1919 getpeername(0, &fromAddr.sa, &fromAddrLen);
1933 rmt_ip = 0; 1920 rmt_ip = 0;
1934 tcp_port = 0; 1921 tcp_port = 0;
1935#if ENABLE_FEATURE_HTTPD_CGI || DEBUG 1922 if (verbose || ENABLE_FEATURE_HTTPD_CGI || DEBUG) {
1936 free(rmt_ip_str); 1923 free(rmt_ip_str);
1937 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); 1924 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
1938#endif 1925 }
1939 if (fromAddr.sa.sa_family == AF_INET) { 1926 if (fromAddr.sa.sa_family == AF_INET) {
1940 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1927 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1941 tcp_port = ntohs(fromAddr.sin.sin_port); 1928 tcp_port = ntohs(fromAddr.sin.sin_port);
@@ -1974,6 +1961,7 @@ enum {
1974 p_opt_port , 1961 p_opt_port ,
1975 p_opt_inetd , 1962 p_opt_inetd ,
1976 p_opt_foreground, 1963 p_opt_foreground,
1964 p_opt_verbose ,
1977 OPT_CONFIG_FILE = 1 << c_opt_config_file, 1965 OPT_CONFIG_FILE = 1 << c_opt_config_file,
1978 OPT_DECODE_URL = 1 << d_opt_decode_url, 1966 OPT_DECODE_URL = 1 << d_opt_decode_url,
1979 OPT_HOME_HTTPD = 1 << h_opt_home_httpd, 1967 OPT_HOME_HTTPD = 1 << h_opt_home_httpd,
@@ -1984,6 +1972,7 @@ enum {
1984 OPT_PORT = 1 << p_opt_port, 1972 OPT_PORT = 1 << p_opt_port,
1985 OPT_INETD = 1 << p_opt_inetd, 1973 OPT_INETD = 1 << p_opt_inetd,
1986 OPT_FOREGROUND = 1 << p_opt_foreground, 1974 OPT_FOREGROUND = 1 << p_opt_foreground,
1975 OPT_VERBOSE = 1 << p_opt_verbose,
1987}; 1976};
1988 1977
1989 1978
@@ -2004,6 +1993,7 @@ int httpd_main(int argc, char **argv)
2004 1993
2005 INIT_G(); 1994 INIT_G();
2006 home_httpd = xrealloc_getcwd_or_warn(NULL); 1995 home_httpd = xrealloc_getcwd_or_warn(NULL);
1996 opt_complementary = "vv"; /* counter */
2007 /* We do not "absolutize" path given by -h (home) opt. 1997 /* We do not "absolutize" path given by -h (home) opt.
2008 * If user gives relative path in -h, $SCRIPT_FILENAME can end up 1998 * If user gives relative path in -h, $SCRIPT_FILENAME can end up
2009 * relative too. */ 1999 * relative too. */
@@ -2012,13 +2002,14 @@ int httpd_main(int argc, char **argv)
2012 USE_FEATURE_HTTPD_BASIC_AUTH("r:") 2002 USE_FEATURE_HTTPD_BASIC_AUTH("r:")
2013 USE_FEATURE_HTTPD_AUTH_MD5("m:") 2003 USE_FEATURE_HTTPD_AUTH_MD5("m:")
2014 USE_FEATURE_HTTPD_SETUID("u:") 2004 USE_FEATURE_HTTPD_SETUID("u:")
2015 "p:if", 2005 "p:ifv",
2016 &(configFile), &url_for_decode, &home_httpd 2006 &configFile, &url_for_decode, &home_httpd
2017 USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) 2007 USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
2018 USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) 2008 USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
2019 USE_FEATURE_HTTPD_AUTH_MD5(, &pass) 2009 USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
2020 USE_FEATURE_HTTPD_SETUID(, &s_ugid) 2010 USE_FEATURE_HTTPD_SETUID(, &s_ugid)
2021 , &bind_addr_or_port 2011 , &bind_addr_or_port
2012 , &verbose
2022 ); 2013 );
2023 if (opt & OPT_DECODE_URL) { 2014 if (opt & OPT_DECODE_URL) {
2024 printf("%s", decodeString(url_for_decode, 1)); 2015 printf("%s", decodeString(url_for_decode, 1));
@@ -2036,7 +2027,6 @@ int httpd_main(int argc, char **argv)
2036 return 0; 2027 return 0;
2037 } 2028 }
2038#endif 2029#endif
2039
2040#if ENABLE_FEATURE_HTTPD_SETUID 2030#if ENABLE_FEATURE_HTTPD_SETUID
2041 if (opt & OPT_SETUID) { 2031 if (opt & OPT_SETUID) {
2042 if (!get_uidgid(&ugid, s_ugid, 1)) 2032 if (!get_uidgid(&ugid, s_ugid, 1))