aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-06-09 23:49:05 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-06-09 23:49:05 +0000
commit77e44d60e698c2164f610072e9f7e2bacefdd589 (patch)
treeaead8cb0cf31e55735bd7681544f0c61290cbbae
parent66db264a5fd67ce4573c905c897a1e80ff26a461 (diff)
downloadbusybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.tar.gz
busybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.tar.bz2
busybox-w32-77e44d60e698c2164f610072e9f7e2bacefdd589.zip
httpd: move data off bss.
httpd: do not realpath() for SCRIPT_FILENAME - it resolves symlinks but it should not: - /* SCRIPT_FILENAME required by PHP in CGI mode */ - if (!realpath(purl + 1, realpath_buff)) - goto error_execing_cgi; - setenv1("SCRIPT_FILENAME", realpath_buff); + + /* SCRIPT_FILENAME required by PHP in CGI mode */ + fullpath = concat_path_file(home_httpd, purl); + setenv1("SCRIPT_FILENAME", fullpath);
-rw-r--r--networking/httpd.c407
1 files changed, 218 insertions, 189 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index f47e2c11f..529f66bc4 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -98,10 +98,8 @@
98# define PIPE_BUF 4096 98# define PIPE_BUF 4096
99#endif 99#endif
100 100
101static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004";
102static const char default_path_httpd_conf[] = "/etc"; 101static const char default_path_httpd_conf[] = "/etc";
103static const char httpd_conf[] = "httpd.conf"; 102static const char httpd_conf[] = "httpd.conf";
104static const char home[] = "./";
105 103
106#define TIMEOUT 60 104#define TIMEOUT 60
107 105
@@ -122,55 +120,85 @@ typedef struct HT_ACCESS {
122} Htaccess; 120} Htaccess;
123 121
124typedef struct HT_ACCESS_IP { 122typedef struct HT_ACCESS_IP {
125 unsigned int ip; 123 unsigned ip;
126 unsigned int mask; 124 unsigned mask;
127 int allow_deny; 125 int allow_deny;
128 struct HT_ACCESS_IP *next; 126 struct HT_ACCESS_IP *next;
129} Htaccess_IP; 127} Htaccess_IP;
130 128
131typedef struct { 129struct globals {
132 char buf[MAX_MEMORY_BUFF]; 130 int server_socket;
133 131 int accepted_socket;
134 USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;) 132 volatile smallint alarm_signaled;
135 USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) 133 smallint flg_deny_all;
136 134 const char *g_query;
137 const char *query;
138
139 USE_FEATURE_HTTPD_CGI(char *referer;)
140
141 const char *configFile; 135 const char *configFile;
136 const char *home_httpd;
137 unsigned rmt_ip;
142 138
143 unsigned int rmt_ip;
144#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
145 char *rmt_ip_str; /* for set env REMOTE_ADDR */
146#endif
147 unsigned port; /* server initial port and for
148 set env REMOTE_PORT */
149 const char *found_mime_type; 139 const char *found_mime_type;
150 const char *found_moved_temporarily; 140 const char *found_moved_temporarily;
151
152 off_t ContentLength; /* -1 - unknown */ 141 off_t ContentLength; /* -1 - unknown */
153 time_t last_mod; 142 time_t last_mod;
154
155 Htaccess_IP *ip_a_d; /* config allow/deny lines */ 143 Htaccess_IP *ip_a_d; /* config allow/deny lines */
156 int flg_deny_all; 144
145 USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
146 USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;)
147 USE_FEATURE_HTTPD_CGI(char *referer;)
148
149#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
150 char *rmt_ip_str; /* for set env REMOTE_ADDR */
151#endif
152 unsigned tcp_port; /* server initial port and for
153 set env REMOTE_PORT */
157#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 154#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
158 Htaccess *auth; /* config user:password lines */ 155 Htaccess *g_auth; /* config user:password lines */
159#endif 156#endif
160#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 157#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
161 Htaccess *mime_a; /* config mime types */ 158 Htaccess *mime_a; /* config mime types */
162#endif 159#endif
163
164 int server_socket;
165 int accepted_socket;
166 volatile int alarm_signaled;
167
168#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 160#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
169 Htaccess *script_i; /* config script interpreters */ 161 Htaccess *script_i; /* config script interpreters */
170#endif 162#endif
171} HttpdConfig; 163 char iobuf[MAX_MEMORY_BUFF];
172 164};
173static HttpdConfig *config; 165#define G (*ptr_to_globals)
166#define server_socket (G.server_socket )
167#define accepted_socket (G.accepted_socket)
168#define alarm_signaled (G.alarm_signaled )
169#define flg_deny_all (G.flg_deny_all )
170#define g_query (G.g_query )
171#define configFile (G.configFile )
172#define home_httpd (G.home_httpd )
173#define rmt_ip (G.rmt_ip )
174#define found_mime_type (G.found_mime_type)
175#define found_moved_temporarily (G.found_moved_temporarily)
176#define ContentLength (G.ContentLength )
177#define last_mod (G.last_mod )
178#define ip_a_d (G.ip_a_d )
179#define g_realm (G.g_realm )
180#define remoteuser (G.remoteuser )
181#define referer (G.referer )
182#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
183#define rmt_ip_str (G.rmt_ip_str )
184#endif
185#define tcp_port (G.tcp_port )
186#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
187#define g_auth (G.g_auth )
188#endif
189#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
190#define mime_a (G.mime_a )
191#endif
192#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
193#define script_i (G.script_i )
194#endif
195#define iobuf (G.iobuf )
196#define INIT_G() do { \
197 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
198 USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
199 tcp_port = 80; \
200 ContentLength = -1; \
201} while (0)
174 202
175static const char request_GET[] = "GET"; /* size algorithmic optimize */ 203static const char request_GET[] = "GET"; /* size algorithmic optimize */
176 204
@@ -264,7 +292,7 @@ static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT";
264#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) 292#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
265 293
266 294
267static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) 295static int scan_ip(const char **ep, unsigned *ip, unsigned char endc)
268{ 296{
269 const char *p = *ep; 297 const char *p = *ep;
270 int auto_mask = 8; 298 int auto_mask = 8;
@@ -272,7 +300,7 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc)
272 300
273 *ip = 0; 301 *ip = 0;
274 for (j = 0; j < 4; j++) { 302 for (j = 0; j < 4; j++) {
275 unsigned int octet; 303 unsigned octet;
276 304
277 if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) 305 if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0)
278 return -auto_mask; 306 return -auto_mask;
@@ -301,10 +329,10 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc)
301 return auto_mask; 329 return auto_mask;
302} 330}
303 331
304static int scan_ip_mask(const char *ipm, unsigned int *ip, unsigned int *mask) 332static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask)
305{ 333{
306 int i; 334 int i;
307 unsigned int msk; 335 unsigned msk;
308 336
309 i = scan_ip(&ipm, ip, '/'); 337 i = scan_ip(&ipm, ip, '/');
310 if (i < 0) 338 if (i < 0)
@@ -397,13 +425,13 @@ static void parse_conf(const char *path, int flag)
397 Htaccess *cur; 425 Htaccess *cur;
398#endif 426#endif
399 427
400 const char *cf = config->configFile; 428 const char *cf = configFile;
401 char buf[160]; 429 char buf[160];
402 char *p0 = NULL; 430 char *p0 = NULL;
403 char *c, *p; 431 char *c, *p;
404 432
405 /* free previous ip setup if present */ 433 /* free previous ip setup if present */
406 Htaccess_IP *pip = config->ip_a_d; 434 Htaccess_IP *pip = ip_a_d;
407 435
408 while (pip) { 436 while (pip) {
409 Htaccess_IP *cur_ipl = pip; 437 Htaccess_IP *cur_ipl = pip;
@@ -411,9 +439,9 @@ static void parse_conf(const char *path, int flag)
411 pip = cur_ipl->next; 439 pip = cur_ipl->next;
412 free(cur_ipl); 440 free(cur_ipl);
413 } 441 }
414 config->ip_a_d = NULL; 442 ip_a_d = NULL;
415 443
416 config->flg_deny_all = 0; 444 flg_deny_all = 0;
417 445
418#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \ 446#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
419 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \ 447 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
@@ -421,13 +449,13 @@ static void parse_conf(const char *path, int flag)
421 /* retain previous auth and mime config only for subdir parse */ 449 /* retain previous auth and mime config only for subdir parse */
422 if (flag != SUBDIR_PARSE) { 450 if (flag != SUBDIR_PARSE) {
423#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 451#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
424 free_config_lines(&config->auth); 452 free_config_lines(&g_auth);
425#endif 453#endif
426#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 454#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
427 free_config_lines(&config->mime_a); 455 free_config_lines(&mime_a);
428#endif 456#endif
429#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 457#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
430 free_config_lines(&config->script_i); 458 free_config_lines(&script_i);
431#endif 459#endif
432 } 460 }
433#endif 461#endif
@@ -447,16 +475,16 @@ static void parse_conf(const char *path, int flag)
447 /* config file not found, no changes to config */ 475 /* config file not found, no changes to config */
448 return; 476 return;
449 } 477 }
450 if (config->configFile && flag == FIRST_PARSE) /* if -c option given */ 478 if (configFile && flag == FIRST_PARSE) /* if -c option given */
451 bb_perror_msg_and_die("%s", cf); 479 bb_perror_msg_and_die("%s", cf);
452 flag = FIND_FROM_HTTPD_ROOT; 480 flag = FIND_FROM_HTTPD_ROOT;
453 cf = httpd_conf; 481 cf = httpd_conf;
454 } 482 }
455 483
456#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 484#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
457 prev = config->auth; 485 prev = g_auth;
458#endif 486#endif
459 /* This could stand some work */ 487 /* This could stand some work */
460 while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { 488 while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) {
461 c = NULL; 489 c = NULL;
462 for (p = p0; *p0 != 0 && *p0 != '#'; p0++) { 490 for (p = p0; *p0 != 0 && *p0 != '#'; p0++) {
@@ -477,7 +505,7 @@ static void parse_conf(const char *path, int flag)
477 if (*c == '*') { 505 if (*c == '*') {
478 if (*p0 == 'D') { 506 if (*p0 == 'D') {
479 /* memorize deny all */ 507 /* memorize deny all */
480 config->flg_deny_all++; 508 flg_deny_all = 1;
481 } 509 }
482 /* skip default other "word:*" config lines */ 510 /* skip default other "word:*" config lines */
483 continue; 511 continue;
@@ -509,14 +537,14 @@ static void parse_conf(const char *path, int flag)
509 pip->allow_deny = *p0; 537 pip->allow_deny = *p0;
510 if (*p0 == 'D') { 538 if (*p0 == 'D') {
511 /* Deny:form_IP move top */ 539 /* Deny:form_IP move top */
512 pip->next = config->ip_a_d; 540 pip->next = ip_a_d;
513 config->ip_a_d = pip; 541 ip_a_d = pip;
514 } else { 542 } else {
515 /* add to bottom A:form_IP config line */ 543 /* add to bottom A:form_IP config line */
516 Htaccess_IP *prev_IP = config->ip_a_d; 544 Htaccess_IP *prev_IP = ip_a_d;
517 545
518 if (prev_IP == NULL) { 546 if (prev_IP == NULL) {
519 config->ip_a_d = pip; 547 ip_a_d = pip;
520 } else { 548 } else {
521 while (prev_IP->next) 549 while (prev_IP->next)
522 prev_IP = prev_IP->next; 550 prev_IP = prev_IP->next;
@@ -579,16 +607,16 @@ static void parse_conf(const char *path, int flag)
579#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 607#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
580 if (*cf == '.') { 608 if (*cf == '.') {
581 /* config .mime line move top for overwrite previous */ 609 /* config .mime line move top for overwrite previous */
582 cur->next = config->mime_a; 610 cur->next = mime_a;
583 config->mime_a = cur; 611 mime_a = cur;
584 continue; 612 continue;
585 } 613 }
586#endif 614#endif
587#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 615#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
588 if (*cf == '*' && cf[1] == '.') { 616 if (*cf == '*' && cf[1] == '.') {
589 /* config script interpreter line move top for overwrite previous */ 617 /* config script interpreter line move top for overwrite previous */
590 cur->next = config->script_i; 618 cur->next = script_i;
591 config->script_i = cur; 619 script_i = cur;
592 continue; 620 continue;
593 } 621 }
594#endif 622#endif
@@ -596,10 +624,10 @@ static void parse_conf(const char *path, int flag)
596 free(p0); 624 free(p0);
597 if (prev == NULL) { 625 if (prev == NULL) {
598 /* first line */ 626 /* first line */
599 config->auth = prev = cur; 627 g_auth = prev = cur;
600 } else { 628 } else {
601 /* sort path, if current lenght eq or bigger then move up */ 629 /* sort path, if current lenght eq or bigger then move up */
602 Htaccess *prev_hti = config->auth; 630 Htaccess *prev_hti = g_auth;
603 size_t l = strlen(cf); 631 size_t l = strlen(cf);
604 Htaccess *hti; 632 Htaccess *hti;
605 633
@@ -611,7 +639,7 @@ static void parse_conf(const char *path, int flag)
611 prev_hti->next = cur; 639 prev_hti->next = cur;
612 } else { 640 } else {
613 /* insert as top */ 641 /* insert as top */
614 config->auth = cur; 642 g_auth = cur;
615 } 643 }
616 break; 644 break;
617 } 645 }
@@ -818,7 +846,7 @@ static int openServer(void)
818 int fd; 846 int fd;
819 847
820 /* create the socket right now */ 848 /* create the socket right now */
821 fd = create_and_bind_stream_or_die(NULL, config->port); 849 fd = create_and_bind_stream_or_die(NULL, tcp_port);
822 xlisten(fd, 9); 850 xlisten(fd, 9);
823 return fd; 851 return fd;
824} 852}
@@ -840,7 +868,7 @@ static int openServer(void)
840 ****************************************************************************/ 868 ****************************************************************************/
841static int sendHeaders(HttpResponseNum responseNum) 869static int sendHeaders(HttpResponseNum responseNum)
842{ 870{
843 char *buf = config->buf; 871 char *buf = iobuf;
844 const char *responseString = ""; 872 const char *responseString = "";
845 const char *infoString = 0; 873 const char *infoString = 0;
846 const char *mime_type; 874 const char *mime_type;
@@ -861,7 +889,7 @@ static int sendHeaders(HttpResponseNum responseNum)
861 } 889 }
862 /* error message is HTML */ 890 /* error message is HTML */
863 mime_type = responseNum == HTTP_OK ? 891 mime_type = responseNum == HTTP_OK ?
864 config->found_mime_type : "text/html"; 892 found_mime_type : "text/html";
865 893
866 /* emit the current date */ 894 /* emit the current date */
867 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); 895 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
@@ -874,20 +902,20 @@ static int sendHeaders(HttpResponseNum responseNum)
874 if (responseNum == HTTP_UNAUTHORIZED) { 902 if (responseNum == HTTP_UNAUTHORIZED) {
875 len += sprintf(buf+len, 903 len += sprintf(buf+len,
876 "WWW-Authenticate: Basic realm=\"%s\"\r\n", 904 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
877 config->realm); 905 g_realm);
878 } 906 }
879#endif 907#endif
880 if (responseNum == HTTP_MOVED_TEMPORARILY) { 908 if (responseNum == HTTP_MOVED_TEMPORARILY) {
881 len += sprintf(buf+len, "Location: %s/%s%s\r\n", 909 len += sprintf(buf+len, "Location: %s/%s%s\r\n",
882 config->found_moved_temporarily, 910 found_moved_temporarily,
883 (config->query ? "?" : ""), 911 (g_query ? "?" : ""),
884 (config->query ? config->query : "")); 912 (g_query ? g_query : ""));
885 } 913 }
886 914
887 if (config->ContentLength != -1) { /* file */ 915 if (ContentLength != -1) { /* file */
888 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); 916 strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod));
889 len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", 917 len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
890 timeStr, "Content-length:", config->ContentLength); 918 timeStr, "Content-length:", ContentLength);
891 } 919 }
892 strcat(buf, "\r\n"); 920 strcat(buf, "\r\n");
893 len += 2; 921 len += 2;
@@ -900,7 +928,7 @@ static int sendHeaders(HttpResponseNum responseNum)
900 } 928 }
901 if (DEBUG) 929 if (DEBUG)
902 fprintf(stderr, "headers: '%s'\n", buf); 930 fprintf(stderr, "headers: '%s'\n", buf);
903 i = config->accepted_socket; 931 i = accepted_socket;
904 if (i == 0) i++; /* write to fd# 1 in inetd mode */ 932 if (i == 0) i++; /* write to fd# 1 in inetd mode */
905 return full_write(i, buf, len); 933 return full_write(i, buf, len);
906} 934}
@@ -919,9 +947,9 @@ static int sendHeaders(HttpResponseNum responseNum)
919static int getLine(void) 947static int getLine(void)
920{ 948{
921 int count = 0; 949 int count = 0;
922 char *buf = config->buf; 950 char *buf = iobuf;
923 951
924 while (read(config->accepted_socket, buf + count, 1) == 1) { 952 while (read(accepted_socket, buf + count, 1) == 1) {
925 if (buf[count] == '\r') continue; 953 if (buf[count] == '\r') continue;
926 if (buf[count] == '\n') { 954 if (buf[count] == '\n') {
927 buf[count] = 0; 955 buf[count] = 0;
@@ -962,8 +990,8 @@ static int sendCgi(const char *url,
962{ 990{
963 int fromCgi[2]; /* pipe for reading data from CGI */ 991 int fromCgi[2]; /* pipe for reading data from CGI */
964 int toCgi[2]; /* pipe for sending data to CGI */ 992 int toCgi[2]; /* pipe for sending data to CGI */
965 993 char *fullpath;
966 static char * argp[] = { 0, 0 }; 994 char *argp[] = { NULL, NULL };
967 int pid = 0; 995 int pid = 0;
968 int inFd; 996 int inFd;
969 int outFd; 997 int outFd;
@@ -985,7 +1013,14 @@ static int sendCgi(const char *url,
985 * since httpd is run from inetd (and it can't run standalone 1013 * since httpd is run from inetd (and it can't run standalone
986 * in uClinux). 1014 * in uClinux).
987 */ 1015 */
1016
1017// FIXME: setenv leaks memory! (old values of env vars are leaked)
1018// Thus we have a bug on NOMMU.
1019// Need to use this instead:
1020// [malloc +] putenv + (in child: exec) + (in parent: unsetenv [+ free])
1021
988#if !BB_MMU 1022#if !BB_MMU
1023 fullpath = NULL;
989 pid = vfork(); 1024 pid = vfork();
990#else 1025#else
991 pid = fork(); 1026 pid = fork();
@@ -997,25 +1032,19 @@ static int sendCgi(const char *url,
997 /* child process */ 1032 /* child process */
998 char *script; 1033 char *script;
999 char *purl; 1034 char *purl;
1000 char realpath_buff[MAXPATHLEN];
1001 1035
1002 if (config->accepted_socket > 1) 1036 if (accepted_socket > 1)
1003 close(config->accepted_socket); 1037 close(accepted_socket);
1004 if (config->server_socket > 1) 1038 if (server_socket > 1)
1005 close(config->server_socket); 1039 close(server_socket);
1006 1040
1007 dup2(toCgi[0], 0); // replace stdin with the pipe 1041 xmove_fd(toCgi[0], 0); /* replace stdin with the pipe */
1008 dup2(fromCgi[1], 1); // replace stdout with the pipe 1042 xmove_fd(fromCgi[1], 1); /* replace stdout with the pipe */
1009 /* Huh? User seeing stderr can be a security problem...
1010 * and if CGI really wants that, it can always dup2(1,2)...
1011 if (!DEBUG)
1012 dup2(fromCgi[1], 2); // replace stderr with the pipe
1013 */
1014 /* I think we cannot inadvertently close 0, 1 here... */
1015 close(toCgi[0]);
1016 close(toCgi[1]);
1017 close(fromCgi[0]); 1043 close(fromCgi[0]);
1018 close(fromCgi[1]); 1044 close(fromCgi[1]);
1045 /* Huh? User seeing stderr can be a security problem...
1046 * and if CGI really wants that, it can always dup2(1,2)...
1047 * dup2(fromCgi[1], 2); */
1019 1048
1020 /* 1049 /*
1021 * Find PATH_INFO. 1050 * Find PATH_INFO.
@@ -1036,22 +1065,21 @@ static int sendCgi(const char *url,
1036 *script = '/'; /* is directory, find next '/' */ 1065 *script = '/'; /* is directory, find next '/' */
1037 } 1066 }
1038 setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */ 1067 setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */
1039 /* setenv1("PATH", getenv("PATH")); redundant */
1040 setenv1("REQUEST_METHOD", request); 1068 setenv1("REQUEST_METHOD", request);
1041 if (config->query) { 1069 if (g_query) {
1042 char *uri = alloca(strlen(purl) + 2 + strlen(config->query)); 1070 char *uri = alloca(strlen(purl) + 2 + strlen(g_query));
1043 if (uri) 1071 if (uri)
1044 sprintf(uri, "%s?%s", purl, config->query); 1072 sprintf(uri, "%s?%s", purl, g_query);
1045 setenv1("REQUEST_URI", uri); 1073 setenv1("REQUEST_URI", uri);
1046 } else { 1074 } else {
1047 setenv1("REQUEST_URI", purl); 1075 setenv1("REQUEST_URI", purl);
1048 } 1076 }
1049 if (script != NULL) 1077 if (script != NULL)
1050 *script = '\0'; /* cut off /PATH_INFO */ 1078 *script = '\0'; /* cut off /PATH_INFO */
1051 /* SCRIPT_FILENAME required by PHP in CGI mode */ 1079
1052 if (!realpath(purl + 1, realpath_buff)) 1080 /* SCRIPT_FILENAME required by PHP in CGI mode */
1053 goto error_execing_cgi; 1081 fullpath = concat_path_file(home_httpd, purl);
1054 setenv1("SCRIPT_FILENAME", realpath_buff); 1082 setenv1("SCRIPT_FILENAME", fullpath);
1055 /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ 1083 /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
1056 setenv1("SCRIPT_NAME", purl); 1084 setenv1("SCRIPT_NAME", purl);
1057 /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html: 1085 /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html:
@@ -1061,8 +1089,8 @@ static int sendCgi(const char *url,
1061 * should always be set when there is query information, 1089 * should always be set when there is query information,
1062 * regardless of command line decoding. */ 1090 * regardless of command line decoding. */
1063 /* (Older versions of bbox seem to do some decoding) */ 1091 /* (Older versions of bbox seem to do some decoding) */
1064 setenv1("QUERY_STRING", config->query); 1092 setenv1("QUERY_STRING", g_query);
1065 setenv1("SERVER_SOFTWARE", httpdVersion); 1093 putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER);
1066 putenv((char*)"SERVER_PROTOCOL=HTTP/1.0"); 1094 putenv((char*)"SERVER_PROTOCOL=HTTP/1.0");
1067 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1"); 1095 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1");
1068 /* Having _separate_ variables for IP and port defeats 1096 /* Having _separate_ variables for IP and port defeats
@@ -1071,15 +1099,16 @@ static int sendCgi(const char *url,
1071 * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense. 1099 * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense.
1072 * Oh well... */ 1100 * Oh well... */
1073 { 1101 {
1074 char *p = config->rmt_ip_str ? : (char*)""; 1102 char *p = rmt_ip_str ? : (char*)"";
1075 char *cp = strrchr(p, ':'); 1103 char *cp = strrchr(p, ':');
1076 if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']')) 1104 if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']'))
1077 cp = NULL; 1105 cp = NULL;
1078 if (cp) *cp = '\0'; /* delete :PORT */ 1106 if (cp) *cp = '\0'; /* delete :PORT */
1079 setenv1("REMOTE_ADDR", p); 1107 setenv1("REMOTE_ADDR", p);
1108 if (cp) *cp = ':';
1080 } 1109 }
1081#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV 1110#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
1082 setenv_long("REMOTE_PORT", config->port); 1111 setenv_long("REMOTE_PORT", tcp_port);
1083#endif 1112#endif
1084 if (bodyLen) 1113 if (bodyLen)
1085 setenv_long("CONTENT_LENGTH", bodyLen); 1114 setenv_long("CONTENT_LENGTH", bodyLen);
@@ -1088,22 +1117,22 @@ static int sendCgi(const char *url,
1088 if (content_type) 1117 if (content_type)
1089 setenv1("CONTENT_TYPE", content_type); 1118 setenv1("CONTENT_TYPE", content_type);
1090#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1119#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1091 if (config->remoteuser) { 1120 if (remoteuser) {
1092 setenv1("REMOTE_USER", config->remoteuser); 1121 setenv1("REMOTE_USER", remoteuser);
1093 putenv((char*)"AUTH_TYPE=Basic"); 1122 putenv((char*)"AUTH_TYPE=Basic");
1094 } 1123 }
1095#endif 1124#endif
1096 if (config->referer) 1125 if (referer)
1097 setenv1("HTTP_REFERER", config->referer); 1126 setenv1("HTTP_REFERER", referer);
1098 1127
1099 /* set execve argp[0] without path */ 1128 /* set execve argp[0] without path */
1100 argp[0] = strrchr(purl, '/') + 1; 1129 argp[0] = strrchr(purl, '/') + 1;
1101 /* but script argp[0] must have absolute path and chdiring to this */ 1130 /* but script argp[0] must have absolute path and chdiring to this */
1102 script = strrchr(realpath_buff, '/'); 1131 script = strrchr(fullpath, '/');
1103 if (!script) 1132 if (!script)
1104 goto error_execing_cgi; 1133 goto error_execing_cgi;
1105 *script = '\0'; 1134 *script = '\0';
1106 if (chdir(realpath_buff) == 0) { 1135 if (chdir(fullpath) == 0) {
1107 // Now run the program. If it fails, 1136 // Now run the program. If it fails,
1108 // use _exit() so no destructors 1137 // use _exit() so no destructors
1109 // get called and make a mess. 1138 // get called and make a mess.
@@ -1113,7 +1142,7 @@ static int sendCgi(const char *url,
1113 1142
1114 if (suffix) { 1143 if (suffix) {
1115 Htaccess *cur; 1144 Htaccess *cur;
1116 for (cur = config->script_i; cur; cur = cur->next) { 1145 for (cur = script_i; cur; cur = cur->next) {
1117 if (strcmp(cur->before_colon + 1, suffix) == 0) { 1146 if (strcmp(cur->before_colon + 1, suffix) == 0) {
1118 interpr = cur->after_colon; 1147 interpr = cur->after_colon;
1119 break; 1148 break;
@@ -1127,16 +1156,19 @@ static int sendCgi(const char *url,
1127 execv(interpr, argp); 1156 execv(interpr, argp);
1128 else 1157 else
1129#endif 1158#endif
1130 execv(realpath_buff, argp); 1159 execv(fullpath, argp);
1131 } 1160 }
1132 error_execing_cgi: 1161 error_execing_cgi:
1133 /* send to stdout (even if we are not from inetd) */ 1162 /* send to stdout (even if we are not from inetd) */
1134 config->accepted_socket = 1; 1163 accepted_socket = 1;
1135 sendHeaders(HTTP_NOT_FOUND); 1164 sendHeaders(HTTP_NOT_FOUND);
1136 _exit(242); 1165 _exit(242);
1137 } /* end child */ 1166 } /* end child */
1138 1167
1139 /* parent process */ 1168 /* parent process */
1169#if !BB_MMU
1170 free(fullpath);
1171#endif
1140 1172
1141 buf_count = 0; 1173 buf_count = 0;
1142 post_read_size = 0; 1174 post_read_size = 0;
@@ -1161,9 +1193,9 @@ static int sendCgi(const char *url,
1161 FD_SET(outFd, &writeSet); 1193 FD_SET(outFd, &writeSet);
1162 nfound = outFd > inFd ? outFd : inFd; 1194 nfound = outFd > inFd ? outFd : inFd;
1163 if (post_read_size == 0) { 1195 if (post_read_size == 0) {
1164 FD_SET(config->accepted_socket, &readSet); 1196 FD_SET(accepted_socket, &readSet);
1165 if (nfound < config->accepted_socket) 1197 if (nfound < accepted_socket)
1166 nfound = config->accepted_socket; 1198 nfound = accepted_socket;
1167 } 1199 }
1168 /* Now wait on the set of sockets! */ 1200 /* Now wait on the set of sockets! */
1169 nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL); 1201 nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL);
@@ -1201,13 +1233,13 @@ static int sendCgi(const char *url,
1201 post_read_size = bodyLen = 0; /* broken pipe to CGI */ 1233 post_read_size = bodyLen = 0; /* broken pipe to CGI */
1202 } 1234 }
1203 } else if (bodyLen > 0 && post_read_size == 0 1235 } else if (bodyLen > 0 && post_read_size == 0
1204 && FD_ISSET(config->accepted_socket, &readSet) 1236 && FD_ISSET(accepted_socket, &readSet)
1205 ) { 1237 ) {
1206 /* We expect data, prev data portion is eaten by CGI 1238 /* We expect data, prev data portion is eaten by CGI
1207 * and there *is* data to read from the peer 1239 * and there *is* data to read from the peer
1208 * (POSTDATA?) */ 1240 * (POSTDATA?) */
1209 count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; 1241 count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
1210 count = safe_read(config->accepted_socket, wbuf, count); 1242 count = safe_read(accepted_socket, wbuf, count);
1211 if (count > 0) { 1243 if (count > 0) {
1212 post_read_size = count; 1244 post_read_size = count;
1213 post_read_idx = 0; 1245 post_read_idx = 0;
@@ -1223,8 +1255,8 @@ static int sendCgi(const char *url,
1223#endif 1255#endif
1224 if (FD_ISSET(inFd, &readSet)) { 1256 if (FD_ISSET(inFd, &readSet)) {
1225 /* There is something to read from CGI */ 1257 /* There is something to read from CGI */
1226 int s = config->accepted_socket; 1258 int s = accepted_socket;
1227 char *rbuf = config->buf; 1259 char *rbuf = iobuf;
1228 1260
1229 /* Are we still buffering CGI output? */ 1261 /* Are we still buffering CGI output? */
1230 if (buf_count >= 0) { 1262 if (buf_count >= 0) {
@@ -1306,14 +1338,14 @@ static int sendFile(const char *url)
1306 break; 1338 break;
1307 } 1339 }
1308 /* also, if not found, set default as "application/octet-stream"; */ 1340 /* also, if not found, set default as "application/octet-stream"; */
1309 config->found_mime_type = table[1]; 1341 found_mime_type = table[1];
1310#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 1342#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
1311 if (suffix) { 1343 if (suffix) {
1312 Htaccess * cur; 1344 Htaccess * cur;
1313 1345
1314 for (cur = config->mime_a; cur; cur = cur->next) { 1346 for (cur = mime_a; cur; cur = cur->next) {
1315 if (strcmp(cur->before_colon, suffix) == 0) { 1347 if (strcmp(cur->before_colon, suffix) == 0) {
1316 config->found_mime_type = cur->after_colon; 1348 found_mime_type = cur->after_colon;
1317 break; 1349 break;
1318 } 1350 }
1319 } 1351 }
@@ -1322,17 +1354,17 @@ static int sendFile(const char *url)
1322 1354
1323 if (DEBUG) 1355 if (DEBUG)
1324 fprintf(stderr, "sending file '%s' content-type: %s\n", 1356 fprintf(stderr, "sending file '%s' content-type: %s\n",
1325 url, config->found_mime_type); 1357 url, found_mime_type);
1326 1358
1327 f = open(url, O_RDONLY); 1359 f = open(url, O_RDONLY);
1328 if (f >= 0) { 1360 if (f >= 0) {
1329 int count; 1361 int count;
1330 char *buf = config->buf; 1362 char *buf = iobuf;
1331 1363
1332 sendHeaders(HTTP_OK); 1364 sendHeaders(HTTP_OK);
1333 /* TODO: sendfile() */ 1365 /* TODO: sendfile() */
1334 while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { 1366 while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) {
1335 int fd = config->accepted_socket; 1367 int fd = accepted_socket;
1336 if (fd == 0) fd++; /* write to fd# 1 in inetd mode */ 1368 if (fd == 0) fd++; /* write to fd# 1 in inetd mode */
1337 if (full_write(fd, buf, count) != count) 1369 if (full_write(fd, buf, count) != count)
1338 break; 1370 break;
@@ -1352,9 +1384,9 @@ static int checkPermIP(void)
1352 Htaccess_IP * cur; 1384 Htaccess_IP * cur;
1353 1385
1354 /* This could stand some work */ 1386 /* This could stand some work */
1355 for (cur = config->ip_a_d; cur; cur = cur->next) { 1387 for (cur = ip_a_d; cur; cur = cur->next) {
1356#if ENABLE_FEATURE_HTTPD_CGI && DEBUG 1388#if ENABLE_FEATURE_HTTPD_CGI && DEBUG
1357 fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); 1389 fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str);
1358#endif 1390#endif
1359#if DEBUG 1391#if DEBUG
1360 fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", 1392 fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
@@ -1368,12 +1400,12 @@ static int checkPermIP(void)
1368 (unsigned char)(cur->mask) 1400 (unsigned char)(cur->mask)
1369 ); 1401 );
1370#endif 1402#endif
1371 if ((config->rmt_ip & cur->mask) == cur->ip) 1403 if ((rmt_ip & cur->mask) == cur->ip)
1372 return cur->allow_deny == 'A'; /* Allow/Deny */ 1404 return cur->allow_deny == 'A'; /* Allow/Deny */
1373 } 1405 }
1374 1406
1375 /* if unconfigured, return 1 - access from all */ 1407 /* if unconfigured, return 1 - access from all */
1376 return !config->flg_deny_all; 1408 return !flg_deny_all;
1377} 1409}
1378 1410
1379/**************************************************************************** 1411/****************************************************************************
@@ -1403,7 +1435,7 @@ static int checkPerm(const char *path, const char *request)
1403 const char *prev = NULL; 1435 const char *prev = NULL;
1404 1436
1405 /* This could stand some work */ 1437 /* This could stand some work */
1406 for (cur = config->auth; cur; cur = cur->next) { 1438 for (cur = g_auth; cur; cur = cur->next) {
1407 size_t l; 1439 size_t l;
1408 1440
1409 p0 = cur->before_colon; 1441 p0 = cur->before_colon;
@@ -1449,9 +1481,9 @@ static int checkPerm(const char *path, const char *request)
1449 1481
1450 if (strcmp(p, request) == 0) { 1482 if (strcmp(p, request) == 0) {
1451set_remoteuser_var: 1483set_remoteuser_var:
1452 config->remoteuser = strdup(request); 1484 remoteuser = strdup(request);
1453 if (config->remoteuser) 1485 if (remoteuser)
1454 config->remoteuser[(u - request)] = 0; 1486 remoteuser[(u - request)] = 0;
1455 return 1; /* Ok */ 1487 return 1; /* Ok */
1456 } 1488 }
1457 /* unauthorized */ 1489 /* unauthorized */
@@ -1474,7 +1506,7 @@ set_remoteuser_var:
1474static void handle_sigalrm(int sig) 1506static void handle_sigalrm(int sig)
1475{ 1507{
1476 sendHeaders(HTTP_REQUEST_TIMEOUT); 1508 sendHeaders(HTTP_REQUEST_TIMEOUT);
1477 config->alarm_signaled = sig; 1509 alarm_signaled = 1;
1478} 1510}
1479 1511
1480/**************************************************************************** 1512/****************************************************************************
@@ -1486,7 +1518,7 @@ static void handle_sigalrm(int sig)
1486 ****************************************************************************/ 1518 ****************************************************************************/
1487static void handleIncoming(void) 1519static void handleIncoming(void)
1488{ 1520{
1489 char *buf = config->buf; 1521 char *buf = iobuf;
1490 char *url; 1522 char *url;
1491 char *purl; 1523 char *purl;
1492 int blank = -1; 1524 int blank = -1;
@@ -1556,10 +1588,10 @@ static void handleIncoming(void)
1556 strcpy(url, buf); 1588 strcpy(url, buf);
1557 /* extract url args if present */ 1589 /* extract url args if present */
1558 test = strchr(url, '?'); 1590 test = strchr(url, '?');
1559 config->query = NULL; 1591 g_query = NULL;
1560 if (test) { 1592 if (test) {
1561 *test++ = '\0'; 1593 *test++ = '\0';
1562 config->query = test; 1594 g_query = test;
1563 } 1595 }
1564 1596
1565 test = decodeString(url, 0); 1597 test = decodeString(url, 0);
@@ -1605,11 +1637,11 @@ static void handleIncoming(void)
1605 /* If URL is directory, adding '/' */ 1637 /* If URL is directory, adding '/' */
1606 if (test[-1] != '/') { 1638 if (test[-1] != '/') {
1607 if (is_directory(url + 1, 1, &sb)) { 1639 if (is_directory(url + 1, 1, &sb)) {
1608 config->found_moved_temporarily = url; 1640 found_moved_temporarily = url;
1609 } 1641 }
1610 } 1642 }
1611 if (DEBUG) 1643 if (DEBUG)
1612 fprintf(stderr, "url='%s', args=%s\n", url, config->query); 1644 fprintf(stderr, "url='%s', args=%s\n", url, g_query);
1613 1645
1614 test = url; 1646 test = url;
1615 ip_allowed = checkPermIP(); 1647 ip_allowed = checkPermIP();
@@ -1656,7 +1688,7 @@ static void handleIncoming(void)
1656 } else if ((STRNCASECMP(buf, "Content-Type:") == 0)) { 1688 } else if ((STRNCASECMP(buf, "Content-Type:") == 0)) {
1657 content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); 1689 content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1));
1658 } else if ((STRNCASECMP(buf, "Referer:") == 0)) { 1690 } else if ((STRNCASECMP(buf, "Referer:") == 0)) {
1659 config->referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); 1691 referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1));
1660 } 1692 }
1661#endif 1693#endif
1662 1694
@@ -1679,7 +1711,7 @@ static void handleIncoming(void)
1679 } /* while extra header reading */ 1711 } /* while extra header reading */
1680 } 1712 }
1681 alarm(0); 1713 alarm(0);
1682 if (config->alarm_signaled) 1714 if (alarm_signaled)
1683 break; 1715 break;
1684 1716
1685 if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { 1717 if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) {
@@ -1698,10 +1730,10 @@ static void handleIncoming(void)
1698 } 1730 }
1699#endif 1731#endif
1700 1732
1701 if (config->found_moved_temporarily) { 1733 if (found_moved_temporarily) {
1702 sendHeaders(HTTP_MOVED_TEMPORARILY); 1734 sendHeaders(HTTP_MOVED_TEMPORARILY);
1703 /* clear unforked memory flag */ 1735 /* clear unforked memory flag */
1704 config->found_moved_temporarily = NULL; 1736 found_moved_temporarily = NULL;
1705 break; 1737 break;
1706 } 1738 }
1707 1739
@@ -1719,7 +1751,7 @@ static void handleIncoming(void)
1719 char *suffix = strrchr(test, '.'); 1751 char *suffix = strrchr(test, '.');
1720 if (suffix) { 1752 if (suffix) {
1721 Htaccess *cur; 1753 Htaccess *cur;
1722 for (cur = config->script_i; cur; cur = cur->next) { 1754 for (cur = script_i; cur; cur = cur->next) {
1723 if (strcmp(cur->before_colon + 1, suffix) == 0) { 1755 if (strcmp(cur->before_colon + 1, suffix) == 0) {
1724 sendCgi(url, prequest, length, cookie, content_type); 1756 sendCgi(url, prequest, length, cookie, content_type);
1725 goto bail_out; 1757 goto bail_out;
@@ -1737,8 +1769,8 @@ static void handleIncoming(void)
1737 strcpy(purl, "index.html"); 1769 strcpy(purl, "index.html");
1738 if (stat(test, &sb) == 0) { 1770 if (stat(test, &sb) == 0) {
1739 /* It's a dir URL and there is index.html */ 1771 /* It's a dir URL and there is index.html */
1740 config->ContentLength = sb.st_size; 1772 ContentLength = sb.st_size;
1741 config->last_mod = sb.st_mtime; 1773 last_mod = sb.st_mtime;
1742 } 1774 }
1743#if ENABLE_FEATURE_HTTPD_CGI 1775#if ENABLE_FEATURE_HTTPD_CGI
1744 else if (purl[-1] == '/') { 1776 else if (purl[-1] == '/') {
@@ -1746,14 +1778,14 @@ static void handleIncoming(void)
1746 * Try cgi-bin/index.cgi */ 1778 * Try cgi-bin/index.cgi */
1747 if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { 1779 if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
1748 purl[0] = '\0'; 1780 purl[0] = '\0';
1749 config->query = url; 1781 g_query = url;
1750 sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); 1782 sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
1751 break; 1783 break;
1752 } 1784 }
1753 } 1785 }
1754#endif /* FEATURE_HTTPD_CGI */ 1786#endif /* FEATURE_HTTPD_CGI */
1755 sendFile(test); 1787 sendFile(test);
1756 config->ContentLength = -1; 1788 ContentLength = -1;
1757 } while (0); 1789 } while (0);
1758 1790
1759#if ENABLE_FEATURE_HTTPD_CGI 1791#if ENABLE_FEATURE_HTTPD_CGI
@@ -1765,28 +1797,28 @@ static void handleIncoming(void)
1765#if ENABLE_FEATURE_HTTPD_CGI 1797#if ENABLE_FEATURE_HTTPD_CGI
1766 free(cookie); 1798 free(cookie);
1767 free(content_type); 1799 free(content_type);
1768 free(config->referer); 1800 free(referer);
1769 config->referer = NULL; 1801 referer = NULL;
1770# if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1802# if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1771 free(config->remoteuser); 1803 free(remoteuser);
1772 config->remoteuser = NULL; 1804 remoteuser = NULL;
1773# endif 1805# endif
1774#endif 1806#endif
1775 shutdown(config->accepted_socket, SHUT_WR); 1807 shutdown(accepted_socket, SHUT_WR);
1776 1808
1777 /* Properly wait for remote to closed */ 1809 /* Properly wait for remote to closed */
1778 FD_ZERO(&s_fd); 1810 FD_ZERO(&s_fd);
1779 FD_SET(config->accepted_socket, &s_fd); 1811 FD_SET(accepted_socket, &s_fd);
1780 1812
1781 do { 1813 do {
1782 tv.tv_sec = 2; 1814 tv.tv_sec = 2;
1783 tv.tv_usec = 0; 1815 tv.tv_usec = 0;
1784 retval = select(config->accepted_socket + 1, &s_fd, NULL, NULL, &tv); 1816 retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv);
1785 } while (retval > 0 && read(config->accepted_socket, buf, sizeof(config->buf) > 0)); 1817 } while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0));
1786 1818
1787 shutdown(config->accepted_socket, SHUT_RD); 1819 shutdown(accepted_socket, SHUT_RD);
1788 /* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */ 1820 /* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */
1789 close(config->accepted_socket); 1821 close(accepted_socket);
1790} 1822}
1791 1823
1792/**************************************************************************** 1824/****************************************************************************
@@ -1830,24 +1862,24 @@ static int miniHttpd(int server)
1830 s = accept(server, &fromAddr.sa, &fromAddrLen); 1862 s = accept(server, &fromAddr.sa, &fromAddrLen);
1831 if (s < 0) 1863 if (s < 0)
1832 continue; 1864 continue;
1833 config->accepted_socket = s; 1865 accepted_socket = s;
1834 config->rmt_ip = 0; 1866 rmt_ip = 0;
1835 config->port = 0; 1867 tcp_port = 0;
1836#if ENABLE_FEATURE_HTTPD_CGI || DEBUG 1868#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
1837 free(config->rmt_ip_str); 1869 free(rmt_ip_str);
1838 config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); 1870 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
1839#if DEBUG 1871#if DEBUG
1840 bb_error_msg("connection from '%s'", config->rmt_ip_str); 1872 bb_error_msg("connection from '%s'", rmt_ip_str);
1841#endif 1873#endif
1842#endif /* FEATURE_HTTPD_CGI */ 1874#endif /* FEATURE_HTTPD_CGI */
1843 if (fromAddr.sa.sa_family == AF_INET) { 1875 if (fromAddr.sa.sa_family == AF_INET) {
1844 config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1876 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1845 config->port = ntohs(fromAddr.sin.sin_port); 1877 tcp_port = ntohs(fromAddr.sin.sin_port);
1846 } 1878 }
1847#if ENABLE_FEATURE_IPV6 1879#if ENABLE_FEATURE_IPV6
1848 if (fromAddr.sa.sa_family == AF_INET6) { 1880 if (fromAddr.sa.sa_family == AF_INET6) {
1849 //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1881 //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1850 config->port = ntohs(fromAddr.sin6.sin6_port); 1882 tcp_port = ntohs(fromAddr.sin6.sin6_port);
1851 } 1883 }
1852#endif 1884#endif
1853 1885
@@ -1880,20 +1912,20 @@ static int miniHttpd_inetd(void)
1880 socklen_t fromAddrLen = sizeof(fromAddr); 1912 socklen_t fromAddrLen = sizeof(fromAddr);
1881 1913
1882 getpeername(0, &fromAddr.sa, &fromAddrLen); 1914 getpeername(0, &fromAddr.sa, &fromAddrLen);
1883 config->rmt_ip = 0; 1915 rmt_ip = 0;
1884 config->port = 0; 1916 tcp_port = 0;
1885#if ENABLE_FEATURE_HTTPD_CGI || DEBUG 1917#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
1886 free(config->rmt_ip_str); 1918 free(rmt_ip_str);
1887 config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); 1919 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
1888#endif 1920#endif
1889 if (fromAddr.sa.sa_family == AF_INET) { 1921 if (fromAddr.sa.sa_family == AF_INET) {
1890 config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1922 rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1891 config->port = ntohs(fromAddr.sin.sin_port); 1923 tcp_port = ntohs(fromAddr.sin.sin_port);
1892 } 1924 }
1893#if ENABLE_FEATURE_IPV6 1925#if ENABLE_FEATURE_IPV6
1894 if (fromAddr.sa.sa_family == AF_INET6) { 1926 if (fromAddr.sa.sa_family == AF_INET6) {
1895 //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); 1927 //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
1896 config->port = ntohs(fromAddr.sin6.sin6_port); 1928 tcp_port = ntohs(fromAddr.sin6.sin6_port);
1897 } 1929 }
1898#endif 1930#endif
1899 handleIncoming(); 1931 handleIncoming();
@@ -1942,7 +1974,6 @@ int httpd_main(int argc, char **argv);
1942int httpd_main(int argc, char **argv) 1974int httpd_main(int argc, char **argv)
1943{ 1975{
1944 unsigned opt; 1976 unsigned opt;
1945 const char *home_httpd = home;
1946 char *url_for_decode; 1977 char *url_for_decode;
1947 USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) 1978 USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;)
1948 const char *s_port; 1979 const char *s_port;
@@ -1955,22 +1986,20 @@ int httpd_main(int argc, char **argv)
1955 setlocale(LC_TIME, "C"); 1986 setlocale(LC_TIME, "C");
1956#endif 1987#endif
1957 1988
1958 config = xzalloc(sizeof(*config)); 1989 INIT_G();
1959#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1990 home_httpd = xrealloc_getcwd_or_warn(NULL);
1960 config->realm = "Web Server Authentication"; 1991 /* We do not "absolutize" path given by -h (home) opt.
1961#endif 1992 * If user gives relative path in -h, $SCRIPT_FILENAME can end up
1962 config->port = 80; 1993 * relative too. */
1963 config->ContentLength = -1;
1964
1965 opt = getopt32(argc, argv, "c:d:h:" 1994 opt = getopt32(argc, argv, "c:d:h:"
1966 USE_FEATURE_HTTPD_ENCODE_URL_STR("e:") 1995 USE_FEATURE_HTTPD_ENCODE_URL_STR("e:")
1967 USE_FEATURE_HTTPD_BASIC_AUTH("r:") 1996 USE_FEATURE_HTTPD_BASIC_AUTH("r:")
1968 USE_FEATURE_HTTPD_AUTH_MD5("m:") 1997 USE_FEATURE_HTTPD_AUTH_MD5("m:")
1969 USE_FEATURE_HTTPD_SETUID("u:") 1998 USE_FEATURE_HTTPD_SETUID("u:")
1970 "p:if", 1999 "p:if",
1971 &(config->configFile), &url_for_decode, &home_httpd 2000 &(configFile), &url_for_decode, &home_httpd
1972 USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) 2001 USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
1973 USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) 2002 USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
1974 USE_FEATURE_HTTPD_AUTH_MD5(, &pass) 2003 USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
1975 USE_FEATURE_HTTPD_SETUID(, &s_ugid) 2004 USE_FEATURE_HTTPD_SETUID(, &s_ugid)
1976 , &s_port 2005 , &s_port
@@ -1992,7 +2021,7 @@ int httpd_main(int argc, char **argv)
1992 } 2021 }
1993#endif 2022#endif
1994 if (opt & OPT_PORT) 2023 if (opt & OPT_PORT)
1995 config->port = xatou16(s_port); 2024 tcp_port = xatou16(s_port);
1996 2025
1997#if ENABLE_FEATURE_HTTPD_SETUID 2026#if ENABLE_FEATURE_HTTPD_SETUID
1998 if (opt & OPT_SETUID) { 2027 if (opt & OPT_SETUID) {
@@ -2005,7 +2034,7 @@ int httpd_main(int argc, char **argv)
2005 xchdir(home_httpd); 2034 xchdir(home_httpd);
2006 if (!(opt & OPT_INETD)) { 2035 if (!(opt & OPT_INETD)) {
2007 signal(SIGCHLD, SIG_IGN); 2036 signal(SIGCHLD, SIG_IGN);
2008 config->server_socket = openServer(); 2037 server_socket = openServer();
2009#if ENABLE_FEATURE_HTTPD_SETUID 2038#if ENABLE_FEATURE_HTTPD_SETUID
2010 /* drop privileges */ 2039 /* drop privileges */
2011 if (opt & OPT_SETUID) { 2040 if (opt & OPT_SETUID) {
@@ -2022,12 +2051,12 @@ int httpd_main(int argc, char **argv)
2022#if ENABLE_FEATURE_HTTPD_CGI 2051#if ENABLE_FEATURE_HTTPD_CGI
2023 { 2052 {
2024 char *p = getenv("PATH"); 2053 char *p = getenv("PATH");
2025 p = xstrdup(p); /* if gets NULL, returns NULL */ 2054 /* env strings themself are not freed, no need to strdup(p): */
2026 clearenv(); 2055 clearenv();
2027 if (p) 2056 if (p)
2028 setenv1("PATH", p); 2057 putenv(p - 5);
2029 if (!(opt & OPT_INETD)) 2058 if (!(opt & OPT_INETD))
2030 setenv_long("SERVER_PORT", config->port); 2059 setenv_long("SERVER_PORT", tcp_port);
2031 } 2060 }
2032#endif 2061#endif
2033 2062
@@ -2042,5 +2071,5 @@ int httpd_main(int argc, char **argv)
2042 2071
2043 if (!(opt & OPT_FOREGROUND)) 2072 if (!(opt & OPT_FOREGROUND))
2044 bb_daemonize(0); /* don't change current directory */ 2073 bb_daemonize(0); /* don't change current directory */
2045 return miniHttpd(config->server_socket); 2074 return miniHttpd(server_socket);
2046} 2075}