httpd: move data off bss. httpd: do not realpath() for SCRIPT_FILENAME - it resolves symlinks but it should not:
No binary (build failed)
—
(log yok)
| @@ -98,10 +98,8 @@ | |
| # define PIPE_BUF 4096 | |
| #endif | |
| - | static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004"; |
| static const char default_path_httpd_conf[] = "/etc"; | |
| static const char httpd_conf[] = "httpd.conf"; | |
| - | static const char home[] = "./"; |
| #define TIMEOUT 60 | |
| @@ -122,55 +120,85 @@ typedef struct HT_ACCESS { | |
| } Htaccess; | |
| typedef struct HT_ACCESS_IP { | |
| - | unsigned int ip; |
| - | unsigned int mask; |
| + | unsigned ip; |
| + | unsigned mask; |
| int allow_deny; | |
| struct HT_ACCESS_IP *next; | |
| } Htaccess_IP; | |
| - | typedef struct { |
| - | char buf[MAX_MEMORY_BUFF]; |
| - | |
| - | USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;) |
| - | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) |
| - | |
| - | const char *query; |
| - | |
| - | USE_FEATURE_HTTPD_CGI(char *referer;) |
| - | |
| + | struct globals { |
| + | int server_socket; |
| + | int accepted_socket; |
| + | volatile smallint alarm_signaled; |
| + | smallint flg_deny_all; |
| + | const char *g_query; |
| const char *configFile; | |
| + | const char *home_httpd; |
| + | unsigned rmt_ip; |
| - | unsigned int rmt_ip; |
| - | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
| - | char *rmt_ip_str; /* for set env REMOTE_ADDR */ |
| - | #endif |
| - | unsigned port; /* server initial port and for |
| - | set env REMOTE_PORT */ |
| const char *found_mime_type; | |
| const char *found_moved_temporarily; | |
| - | |
| off_t ContentLength; /* -1 - unknown */ | |
| time_t last_mod; | |
| - | |
| Htaccess_IP *ip_a_d; /* config allow/deny lines */ | |
| - | int flg_deny_all; |
| + | |
| + | USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) |
| + | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) |
| + | USE_FEATURE_HTTPD_CGI(char *referer;) |
| + | |
| + | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
| + | char *rmt_ip_str; /* for set env REMOTE_ADDR */ |
| + | #endif |
| + | unsigned tcp_port; /* server initial port and for |
| + | set env REMOTE_PORT */ |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| - | Htaccess *auth; /* config user:password lines */ |
| + | Htaccess *g_auth; /* config user:password lines */ |
| #endif | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | |
| Htaccess *mime_a; /* config mime types */ | |
| #endif | |
| - | |
| - | int server_socket; |
| - | int accepted_socket; |
| - | volatile int alarm_signaled; |
| - | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | |
| Htaccess *script_i; /* config script interpreters */ | |
| #endif | |
| - | } HttpdConfig; |
| - | |
| - | static HttpdConfig *config; |
| + | char iobuf[MAX_MEMORY_BUFF]; |
| + | }; |
| + | #define G (*ptr_to_globals) |
| + | #define server_socket (G.server_socket ) |
| + | #define accepted_socket (G.accepted_socket) |
| + | #define alarm_signaled (G.alarm_signaled ) |
| + | #define flg_deny_all (G.flg_deny_all ) |
| + | #define g_query (G.g_query ) |
| + | #define configFile (G.configFile ) |
| + | #define home_httpd (G.home_httpd ) |
| + | #define rmt_ip (G.rmt_ip ) |
| + | #define found_mime_type (G.found_mime_type) |
| + | #define found_moved_temporarily (G.found_moved_temporarily) |
| + | #define ContentLength (G.ContentLength ) |
| + | #define last_mod (G.last_mod ) |
| + | #define ip_a_d (G.ip_a_d ) |
| + | #define g_realm (G.g_realm ) |
| + | #define remoteuser (G.remoteuser ) |
| + | #define referer (G.referer ) |
| + | #if ENABLE_FEATURE_HTTPD_CGI || DEBUG |
| + | #define rmt_ip_str (G.rmt_ip_str ) |
| + | #endif |
| + | #define tcp_port (G.tcp_port ) |
| + | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| + | #define g_auth (G.g_auth ) |
| + | #endif |
| + | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
| + | #define mime_a (G.mime_a ) |
| + | #endif |
| + | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
| + | #define script_i (G.script_i ) |
| + | #endif |
| + | #define iobuf (G.iobuf ) |
| + | #define INIT_G() do { \ |
| + | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ |
| + | USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ |
| + | tcp_port = 80; \ |
| + | ContentLength = -1; \ |
| + | } while (0) |
| static const char request_GET[] = "GET"; /* size algorithmic optimize */ | |
| @@ -264,7 +292,7 @@ static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT"; | |
| #define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) | |
| - | static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) |
| + | static int scan_ip(const char **ep, unsigned *ip, unsigned char endc) |
| { | |
| const char *p = *ep; | |
| int auto_mask = 8; | |
| @@ -272,7 +300,7 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) | |
| *ip = 0; | |
| for (j = 0; j < 4; j++) { | |
| - | unsigned int octet; |
| + | unsigned octet; |
| if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) | |
| return -auto_mask; | |
| @@ -301,10 +329,10 @@ static int scan_ip(const char **ep, unsigned int *ip, unsigned char endc) | |
| return auto_mask; | |
| } | |
| - | static int scan_ip_mask(const char *ipm, unsigned int *ip, unsigned int *mask) |
| + | static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask) |
| { | |
| int i; | |
| - | unsigned int msk; |
| + | unsigned msk; |
| i = scan_ip(&ipm, ip, '/'); | |
| if (i < 0) | |
| @@ -397,13 +425,13 @@ static void parse_conf(const char *path, int flag) | |
| Htaccess *cur; | |
| #endif | |
| - | const char *cf = config->configFile; |
| + | const char *cf = configFile; |
| char buf[160]; | |
| char *p0 = NULL; | |
| char *c, *p; | |
| /* free previous ip setup if present */ | |
| - | Htaccess_IP *pip = config->ip_a_d; |
| + | Htaccess_IP *pip = ip_a_d; |
| while (pip) { | |
| Htaccess_IP *cur_ipl = pip; | |
| @@ -411,9 +439,9 @@ static void parse_conf(const char *path, int flag) | |
| pip = cur_ipl->next; | |
| free(cur_ipl); | |
| } | |
| - | config->ip_a_d = NULL; |
| + | ip_a_d = NULL; |
| - | config->flg_deny_all = 0; |
| + | flg_deny_all = 0; |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH \ | |
| || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \ | |
| @@ -421,13 +449,13 @@ static void parse_conf(const char *path, int flag) | |
| /* retain previous auth and mime config only for subdir parse */ | |
| if (flag != SUBDIR_PARSE) { | |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| - | free_config_lines(&config->auth); |
| + | free_config_lines(&g_auth); |
| #endif | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | |
| - | free_config_lines(&config->mime_a); |
| + | free_config_lines(&mime_a); |
| #endif | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | |
| - | free_config_lines(&config->script_i); |
| + | free_config_lines(&script_i); |
| #endif | |
| } | |
| #endif | |
| @@ -447,16 +475,16 @@ static void parse_conf(const char *path, int flag) | |
| /* config file not found, no changes to config */ | |
| return; | |
| } | |
| - | if (config->configFile && flag == FIRST_PARSE) /* if -c option given */ |
| + | if (configFile && flag == FIRST_PARSE) /* if -c option given */ |
| bb_perror_msg_and_die("%s", cf); | |
| flag = FIND_FROM_HTTPD_ROOT; | |
| cf = httpd_conf; | |
| } | |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| - | prev = config->auth; |
| + | prev = g_auth; |
| #endif | |
| - | /* This could stand some work */ |
| + | /* This could stand some work */ |
| while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { | |
| c = NULL; | |
| for (p = p0; *p0 != 0 && *p0 != '#'; p0++) { | |
| @@ -477,7 +505,7 @@ static void parse_conf(const char *path, int flag) | |
| if (*c == '*') { | |
| if (*p0 == 'D') { | |
| /* memorize deny all */ | |
| - | config->flg_deny_all++; |
| + | flg_deny_all = 1; |
| } | |
| /* skip default other "word:*" config lines */ | |
| continue; | |
| @@ -509,14 +537,14 @@ static void parse_conf(const char *path, int flag) | |
| pip->allow_deny = *p0; | |
| if (*p0 == 'D') { | |
| /* Deny:form_IP move top */ | |
| - | pip->next = config->ip_a_d; |
| - | config->ip_a_d = pip; |
| + | pip->next = ip_a_d; |
| + | ip_a_d = pip; |
| } else { | |
| /* add to bottom A:form_IP config line */ | |
| - | Htaccess_IP *prev_IP = config->ip_a_d; |
| + | Htaccess_IP *prev_IP = ip_a_d; |
| if (prev_IP == NULL) { | |
| - | config->ip_a_d = pip; |
| + | ip_a_d = pip; |
| } else { | |
| while (prev_IP->next) | |
| prev_IP = prev_IP->next; | |
| @@ -579,16 +607,16 @@ static void parse_conf(const char *path, int flag) | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | |
| if (*cf == '.') { | |
| /* config .mime line move top for overwrite previous */ | |
| - | cur->next = config->mime_a; |
| - | config->mime_a = cur; |
| + | cur->next = mime_a; |
| + | mime_a = cur; |
| continue; | |
| } | |
| #endif | |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | |
| if (*cf == '*' && cf[1] == '.') { | |
| /* config script interpreter line move top for overwrite previous */ | |
| - | cur->next = config->script_i; |
| - | config->script_i = cur; |
| + | cur->next = script_i; |
| + | script_i = cur; |
| continue; | |
| } | |
| #endif | |
| @@ -596,10 +624,10 @@ static void parse_conf(const char *path, int flag) | |
| free(p0); | |
| if (prev == NULL) { | |
| /* first line */ | |
| - | config->auth = prev = cur; |
| + | g_auth = prev = cur; |
| } else { | |
| /* sort path, if current lenght eq or bigger then move up */ | |
| - | Htaccess *prev_hti = config->auth; |
| + | Htaccess *prev_hti = g_auth; |
| size_t l = strlen(cf); | |
| Htaccess *hti; | |
| @@ -611,7 +639,7 @@ static void parse_conf(const char *path, int flag) | |
| prev_hti->next = cur; | |
| } else { | |
| /* insert as top */ | |
| - | config->auth = cur; |
| + | g_auth = cur; |
| } | |
| break; | |
| } | |
| @@ -818,7 +846,7 @@ static int openServer(void) | |
| int fd; | |
| /* create the socket right now */ | |
| - | fd = create_and_bind_stream_or_die(NULL, config->port); |
| + | fd = create_and_bind_stream_or_die(NULL, tcp_port); |
| xlisten(fd, 9); | |
| return fd; | |
| } | |
| @@ -840,7 +868,7 @@ static int openServer(void) | |
| ****************************************************************************/ | |
| static int sendHeaders(HttpResponseNum responseNum) | |
| { | |
| - | char *buf = config->buf; |
| + | char *buf = iobuf; |
| const char *responseString = ""; | |
| const char *infoString = 0; | |
| const char *mime_type; | |
| @@ -861,7 +889,7 @@ static int sendHeaders(HttpResponseNum responseNum) | |
| } | |
| /* error message is HTML */ | |
| mime_type = responseNum == HTTP_OK ? | |
| - | config->found_mime_type : "text/html"; |
| + | found_mime_type : "text/html"; |
| /* emit the current date */ | |
| strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); | |
| @@ -874,20 +902,20 @@ static int sendHeaders(HttpResponseNum responseNum) | |
| if (responseNum == HTTP_UNAUTHORIZED) { | |
| len += sprintf(buf+len, | |
| "WWW-Authenticate: Basic realm=\"%s\"\r\n", | |
| - | config->realm); |
| + | g_realm); |
| } | |
| #endif | |
| if (responseNum == HTTP_MOVED_TEMPORARILY) { | |
| len += sprintf(buf+len, "Location: %s/%s%s\r\n", | |
| - | config->found_moved_temporarily, |
| - | (config->query ? "?" : ""), |
| - | (config->query ? config->query : "")); |
| + | found_moved_temporarily, |
| + | (g_query ? "?" : ""), |
| + | (g_query ? g_query : "")); |
| } | |
| - | if (config->ContentLength != -1) { /* file */ |
| - | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); |
| + | if (ContentLength != -1) { /* file */ |
| + | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&last_mod)); |
| len += sprintf(buf+len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", | |
| - | timeStr, "Content-length:", config->ContentLength); |
| + | timeStr, "Content-length:", ContentLength); |
| } | |
| strcat(buf, "\r\n"); | |
| len += 2; | |
| @@ -900,7 +928,7 @@ static int sendHeaders(HttpResponseNum responseNum) | |
| } | |
| if (DEBUG) | |
| fprintf(stderr, "headers: '%s'\n", buf); | |
| - | i = config->accepted_socket; |
| + | i = accepted_socket; |
| if (i == 0) i++; /* write to fd# 1 in inetd mode */ | |
| return full_write(i, buf, len); | |
| } | |
| @@ -919,9 +947,9 @@ static int sendHeaders(HttpResponseNum responseNum) | |
| static int getLine(void) | |
| { | |
| int count = 0; | |
| - | char *buf = config->buf; |
| + | char *buf = iobuf; |
| - | while (read(config->accepted_socket, buf + count, 1) == 1) { |
| + | while (read(accepted_socket, buf + count, 1) == 1) { |
| if (buf[count] == '\r') continue; | |
| if (buf[count] == '\n') { | |
| buf[count] = 0; | |
| @@ -962,8 +990,8 @@ static int sendCgi(const char *url, | |
| { | |
| int fromCgi[2]; /* pipe for reading data from CGI */ | |
| int toCgi[2]; /* pipe for sending data to CGI */ | |
| - | |
| - | static char * argp[] = { 0, 0 }; |
| + | char *fullpath; |
| + | char *argp[] = { NULL, NULL }; |
| int pid = 0; | |
| int inFd; | |
| int outFd; | |
| @@ -985,7 +1013,14 @@ static int sendCgi(const char *url, | |
| * since httpd is run from inetd (and it can't run standalone | |
| * in uClinux). | |
| */ | |
| + | |
| + | // FIXME: setenv leaks memory! (old values of env vars are leaked) |
| + | // Thus we have a bug on NOMMU. |
| + | // Need to use this instead: |
| + | // [malloc +] putenv + (in child: exec) + (in parent: unsetenv [+ free]) |
| + | |
| #if !BB_MMU | |
| + | fullpath = NULL; |
| pid = vfork(); | |
| #else | |
| pid = fork(); | |
| @@ -997,25 +1032,19 @@ static int sendCgi(const char *url, | |
| /* child process */ | |
| char *script; | |
| char *purl; | |
| - | char realpath_buff[MAXPATHLEN]; |
| - | if (config->accepted_socket > 1) |
| - | close(config->accepted_socket); |
| - | if (config->server_socket > 1) |
| - | close(config->server_socket); |
| + | if (accepted_socket > 1) |
| + | close(accepted_socket); |
| + | if (server_socket > 1) |
| + | close(server_socket); |
| - | dup2(toCgi[0], 0); // replace stdin with the pipe |
| - | dup2(fromCgi[1], 1); // replace stdout with the pipe |
| - | /* Huh? User seeing stderr can be a security problem... |
| - | * and if CGI really wants that, it can always dup2(1,2)... |
| - | if (!DEBUG) |
| - | dup2(fromCgi[1], 2); // replace stderr with the pipe |
| - | */ |
| - | /* I think we cannot inadvertently close 0, 1 here... */ |
| - | close(toCgi[0]); |
| - | close(toCgi[1]); |
| + | xmove_fd(toCgi[0], 0); /* replace stdin with the pipe */ |
| + | xmove_fd(fromCgi[1], 1); /* replace stdout with the pipe */ |
| close(fromCgi[0]); | |
| close(fromCgi[1]); | |
| + | /* Huh? User seeing stderr can be a security problem... |
| + | * and if CGI really wants that, it can always dup2(1,2)... |
| + | * dup2(fromCgi[1], 2); */ |
| /* | |
| * Find PATH_INFO. | |
| @@ -1036,22 +1065,21 @@ static int sendCgi(const char *url, | |
| *script = '/'; /* is directory, find next '/' */ | |
| } | |
| setenv1("PATH_INFO", script); /* set /PATH_INFO or "" */ | |
| - | /* setenv1("PATH", getenv("PATH")); redundant */ |
| setenv1("REQUEST_METHOD", request); | |
| - | if (config->query) { |
| - | char *uri = alloca(strlen(purl) + 2 + strlen(config->query)); |
| + | if (g_query) { |
| + | char *uri = alloca(strlen(purl) + 2 + strlen(g_query)); |
| if (uri) | |
| - | sprintf(uri, "%s?%s", purl, config->query); |
| + | sprintf(uri, "%s?%s", purl, g_query); |
| setenv1("REQUEST_URI", uri); | |
| } else { | |
| setenv1("REQUEST_URI", purl); | |
| } | |
| if (script != NULL) | |
| *script = '\0'; /* cut off /PATH_INFO */ | |
| - | /* 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); |
| /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ | |
| setenv1("SCRIPT_NAME", purl); | |
| /* http://hoohoo.ncsa.uiuc.edu/cgi/env.html: | |
| @@ -1061,8 +1089,8 @@ static int sendCgi(const char *url, | |
| * should always be set when there is query information, | |
| * regardless of command line decoding. */ | |
| /* (Older versions of bbox seem to do some decoding) */ | |
| - | setenv1("QUERY_STRING", config->query); |
| - | setenv1("SERVER_SOFTWARE", httpdVersion); |
| + | setenv1("QUERY_STRING", g_query); |
| + | putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER); |
| putenv((char*)"SERVER_PROTOCOL=HTTP/1.0"); | |
| putenv((char*)"GATEWAY_INTERFACE=CGI/1.1"); | |
| /* Having _separate_ variables for IP and port defeats | |
| @@ -1071,15 +1099,16 @@ static int sendCgi(const char *url, | |
| * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense. | |
| * Oh well... */ | |
| { | |
| - | char *p = config->rmt_ip_str ? : (char*)""; |
| + | char *p = rmt_ip_str ? : (char*)""; |
| char *cp = strrchr(p, ':'); | |
| if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']')) | |
| cp = NULL; | |
| if (cp) *cp = '\0'; /* delete :PORT */ | |
| setenv1("REMOTE_ADDR", p); | |
| + | if (cp) *cp = ':'; |
| } | |
| #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | |
| - | setenv_long("REMOTE_PORT", config->port); |
| + | setenv_long("REMOTE_PORT", tcp_port); |
| #endif | |
| if (bodyLen) | |
| setenv_long("CONTENT_LENGTH", bodyLen); | |
| @@ -1088,22 +1117,22 @@ static int sendCgi(const char *url, | |
| if (content_type) | |
| setenv1("CONTENT_TYPE", content_type); | |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| - | if (config->remoteuser) { |
| - | setenv1("REMOTE_USER", config->remoteuser); |
| + | if (remoteuser) { |
| + | setenv1("REMOTE_USER", remoteuser); |
| putenv((char*)"AUTH_TYPE=Basic"); | |
| } | |
| #endif | |
| - | if (config->referer) |
| - | setenv1("HTTP_REFERER", config->referer); |
| + | if (referer) |
| + | setenv1("HTTP_REFERER", referer); |
| /* set execve argp[0] without path */ | |
| argp[0] = strrchr(purl, '/') + 1; | |
| /* but script argp[0] must have absolute path and chdiring to this */ | |
| - | script = strrchr(realpath_buff, '/'); |
| + | script = strrchr(fullpath, '/'); |
| if (!script) | |
| goto error_execing_cgi; | |
| *script = '\0'; | |
| - | if (chdir(realpath_buff) == 0) { |
| + | if (chdir(fullpath) == 0) { |
| // Now run the program. If it fails, | |
| // use _exit() so no destructors | |
| // get called and make a mess. | |
| @@ -1113,7 +1142,7 @@ static int sendCgi(const char *url, | |
| if (suffix) { | |
| Htaccess *cur; | |
| - | for (cur = config->script_i; cur; cur = cur->next) { |
| + | for (cur = script_i; cur; cur = cur->next) { |
| if (strcmp(cur->before_colon + 1, suffix) == 0) { | |
| interpr = cur->after_colon; | |
| break; | |
| @@ -1127,16 +1156,19 @@ static int sendCgi(const char *url, | |
| execv(interpr, argp); | |
| else | |
| #endif | |
| - | execv(realpath_buff, argp); |
| + | execv(fullpath, argp); |
| } | |
| error_execing_cgi: | |
| /* send to stdout (even if we are not from inetd) */ | |
| - | config->accepted_socket = 1; |
| + | accepted_socket = 1; |
| sendHeaders(HTTP_NOT_FOUND); | |
| _exit(242); | |
| } /* end child */ | |
| /* parent process */ | |
| + | #if !BB_MMU |
| + | free(fullpath); |
| + | #endif |
| buf_count = 0; | |
| post_read_size = 0; | |
| @@ -1161,9 +1193,9 @@ static int sendCgi(const char *url, | |
| FD_SET(outFd, &writeSet); | |
| nfound = outFd > inFd ? outFd : inFd; | |
| if (post_read_size == 0) { | |
| - | FD_SET(config->accepted_socket, &readSet); |
| - | if (nfound < config->accepted_socket) |
| - | nfound = config->accepted_socket; |
| + | FD_SET(accepted_socket, &readSet); |
| + | if (nfound < accepted_socket) |
| + | nfound = accepted_socket; |
| } | |
| /* Now wait on the set of sockets! */ | |
| nfound = select(nfound + 1, &readSet, &writeSet, NULL, NULL); | |
| @@ -1201,13 +1233,13 @@ static int sendCgi(const char *url, | |
| post_read_size = bodyLen = 0; /* broken pipe to CGI */ | |
| } | |
| } else if (bodyLen > 0 && post_read_size == 0 | |
| - | && FD_ISSET(config->accepted_socket, &readSet) |
| + | && FD_ISSET(accepted_socket, &readSet) |
| ) { | |
| /* We expect data, prev data portion is eaten by CGI | |
| * and there *is* data to read from the peer | |
| * (POSTDATA?) */ | |
| count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; | |
| - | count = safe_read(config->accepted_socket, wbuf, count); |
| + | count = safe_read(accepted_socket, wbuf, count); |
| if (count > 0) { | |
| post_read_size = count; | |
| post_read_idx = 0; | |
| @@ -1223,8 +1255,8 @@ static int sendCgi(const char *url, | |
| #endif | |
| if (FD_ISSET(inFd, &readSet)) { | |
| /* There is something to read from CGI */ | |
| - | int s = config->accepted_socket; |
| - | char *rbuf = config->buf; |
| + | int s = accepted_socket; |
| + | char *rbuf = iobuf; |
| /* Are we still buffering CGI output? */ | |
| if (buf_count >= 0) { | |
| @@ -1306,14 +1338,14 @@ static int sendFile(const char *url) | |
| break; | |
| } | |
| /* also, if not found, set default as "application/octet-stream"; */ | |
| - | config->found_mime_type = table[1]; |
| + | found_mime_type = table[1]; |
| #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | |
| if (suffix) { | |
| Htaccess * cur; | |
| - | for (cur = config->mime_a; cur; cur = cur->next) { |
| + | for (cur = mime_a; cur; cur = cur->next) { |
| if (strcmp(cur->before_colon, suffix) == 0) { | |
| - | config->found_mime_type = cur->after_colon; |
| + | found_mime_type = cur->after_colon; |
| break; | |
| } | |
| } | |
| @@ -1322,17 +1354,17 @@ static int sendFile(const char *url) | |
| if (DEBUG) | |
| fprintf(stderr, "sending file '%s' content-type: %s\n", | |
| - | url, config->found_mime_type); |
| + | url, found_mime_type); |
| f = open(url, O_RDONLY); | |
| if (f >= 0) { | |
| int count; | |
| - | char *buf = config->buf; |
| + | char *buf = iobuf; |
| sendHeaders(HTTP_OK); | |
| /* TODO: sendfile() */ | |
| while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { | |
| - | int fd = config->accepted_socket; |
| + | int fd = accepted_socket; |
| if (fd == 0) fd++; /* write to fd# 1 in inetd mode */ | |
| if (full_write(fd, buf, count) != count) | |
| break; | |
| @@ -1352,9 +1384,9 @@ static int checkPermIP(void) | |
| Htaccess_IP * cur; | |
| /* This could stand some work */ | |
| - | for (cur = config->ip_a_d; cur; cur = cur->next) { |
| + | for (cur = ip_a_d; cur; cur = cur->next) { |
| #if ENABLE_FEATURE_HTTPD_CGI && DEBUG | |
| - | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); |
| + | fprintf(stderr, "checkPermIP: '%s' ? ", rmt_ip_str); |
| #endif | |
| #if DEBUG | |
| fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | |
| @@ -1368,12 +1400,12 @@ static int checkPermIP(void) | |
| (unsigned char)(cur->mask) | |
| ); | |
| #endif | |
| - | if ((config->rmt_ip & cur->mask) == cur->ip) |
| + | if ((rmt_ip & cur->mask) == cur->ip) |
| return cur->allow_deny == 'A'; /* Allow/Deny */ | |
| } | |
| /* if unconfigured, return 1 - access from all */ | |
| - | return !config->flg_deny_all; |
| + | return !flg_deny_all; |
| } | |
| /**************************************************************************** | |
| @@ -1403,7 +1435,7 @@ static int checkPerm(const char *path, const char *request) | |
| const char *prev = NULL; | |
| /* This could stand some work */ | |
| - | for (cur = config->auth; cur; cur = cur->next) { |
| + | for (cur = g_auth; cur; cur = cur->next) { |
| size_t l; | |
| p0 = cur->before_colon; | |
| @@ -1449,9 +1481,9 @@ static int checkPerm(const char *path, const char *request) | |
| if (strcmp(p, request) == 0) { | |
| set_remoteuser_var: | |
| - | config->remoteuser = strdup(request); |
| - | if (config->remoteuser) |
| - | config->remoteuser[(u - request)] = 0; |
| + | remoteuser = strdup(request); |
| + | if (remoteuser) |
| + | remoteuser[(u - request)] = 0; |
| return 1; /* Ok */ | |
| } | |
| /* unauthorized */ | |
| @@ -1474,7 +1506,7 @@ set_remoteuser_var: | |
| static void handle_sigalrm(int sig) | |
| { | |
| sendHeaders(HTTP_REQUEST_TIMEOUT); | |
| - | config->alarm_signaled = sig; |
| + | alarm_signaled = 1; |
| } | |
| /**************************************************************************** | |
| @@ -1486,7 +1518,7 @@ static void handle_sigalrm(int sig) | |
| ****************************************************************************/ | |
| static void handleIncoming(void) | |
| { | |
| - | char *buf = config->buf; |
| + | char *buf = iobuf; |
| char *url; | |
| char *purl; | |
| int blank = -1; | |
| @@ -1556,10 +1588,10 @@ static void handleIncoming(void) | |
| strcpy(url, buf); | |
| /* extract url args if present */ | |
| test = strchr(url, '?'); | |
| - | config->query = NULL; |
| + | g_query = NULL; |
| if (test) { | |
| *test++ = '\0'; | |
| - | config->query = test; |
| + | g_query = test; |
| } | |
| test = decodeString(url, 0); | |
| @@ -1605,11 +1637,11 @@ static void handleIncoming(void) | |
| /* If URL is directory, adding '/' */ | |
| if (test[-1] != '/') { | |
| if (is_directory(url + 1, 1, &sb)) { | |
| - | config->found_moved_temporarily = url; |
| + | found_moved_temporarily = url; |
| } | |
| } | |
| if (DEBUG) | |
| - | fprintf(stderr, "url='%s', args=%s\n", url, config->query); |
| + | fprintf(stderr, "url='%s', args=%s\n", url, g_query); |
| test = url; | |
| ip_allowed = checkPermIP(); | |
| @@ -1656,7 +1688,7 @@ static void handleIncoming(void) | |
| } else if ((STRNCASECMP(buf, "Content-Type:") == 0)) { | |
| content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1)); | |
| } else if ((STRNCASECMP(buf, "Referer:") == 0)) { | |
| - | config->referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); |
| + | referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1)); |
| } | |
| #endif | |
| @@ -1679,7 +1711,7 @@ static void handleIncoming(void) | |
| } /* while extra header reading */ | |
| } | |
| alarm(0); | |
| - | if (config->alarm_signaled) |
| + | if (alarm_signaled) |
| break; | |
| if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { | |
| @@ -1698,10 +1730,10 @@ static void handleIncoming(void) | |
| } | |
| #endif | |
| - | if (config->found_moved_temporarily) { |
| + | if (found_moved_temporarily) { |
| sendHeaders(HTTP_MOVED_TEMPORARILY); | |
| /* clear unforked memory flag */ | |
| - | config->found_moved_temporarily = NULL; |
| + | found_moved_temporarily = NULL; |
| break; | |
| } | |
| @@ -1719,7 +1751,7 @@ static void handleIncoming(void) | |
| char *suffix = strrchr(test, '.'); | |
| if (suffix) { | |
| Htaccess *cur; | |
| - | for (cur = config->script_i; cur; cur = cur->next) { |
| + | for (cur = script_i; cur; cur = cur->next) { |
| if (strcmp(cur->before_colon + 1, suffix) == 0) { | |
| sendCgi(url, prequest, length, cookie, content_type); | |
| goto bail_out; | |
| @@ -1737,8 +1769,8 @@ static void handleIncoming(void) | |
| strcpy(purl, "index.html"); | |
| if (stat(test, &sb) == 0) { | |
| /* It's a dir URL and there is index.html */ | |
| - | config->ContentLength = sb.st_size; |
| - | config->last_mod = sb.st_mtime; |
| + | ContentLength = sb.st_size; |
| + | last_mod = sb.st_mtime; |
| } | |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| else if (purl[-1] == '/') { | |
| @@ -1746,14 +1778,14 @@ static void handleIncoming(void) | |
| * Try cgi-bin/index.cgi */ | |
| if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | |
| purl[0] = '\0'; | |
| - | config->query = url; |
| + | g_query = url; |
| sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | |
| break; | |
| } | |
| } | |
| #endif /* FEATURE_HTTPD_CGI */ | |
| sendFile(test); | |
| - | config->ContentLength = -1; |
| + | ContentLength = -1; |
| } while (0); | |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| @@ -1765,28 +1797,28 @@ static void handleIncoming(void) | |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| free(cookie); | |
| free(content_type); | |
| - | free(config->referer); |
| - | config->referer = NULL; |
| + | free(referer); |
| + | referer = NULL; |
| # if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| - | free(config->remoteuser); |
| - | config->remoteuser = NULL; |
| + | free(remoteuser); |
| + | remoteuser = NULL; |
| # endif | |
| #endif | |
| - | shutdown(config->accepted_socket, SHUT_WR); |
| + | shutdown(accepted_socket, SHUT_WR); |
| /* Properly wait for remote to closed */ | |
| FD_ZERO(&s_fd); | |
| - | FD_SET(config->accepted_socket, &s_fd); |
| + | FD_SET(accepted_socket, &s_fd); |
| do { | |
| tv.tv_sec = 2; | |
| tv.tv_usec = 0; | |
| - | retval = select(config->accepted_socket + 1, &s_fd, NULL, NULL, &tv); |
| - | } while (retval > 0 && read(config->accepted_socket, buf, sizeof(config->buf) > 0)); |
| + | retval = select(accepted_socket + 1, &s_fd, NULL, NULL, &tv); |
| + | } while (retval > 0 && read(accepted_socket, buf, sizeof(iobuf) > 0)); |
| - | shutdown(config->accepted_socket, SHUT_RD); |
| + | shutdown(accepted_socket, SHUT_RD); |
| /* In inetd case, we close fd 1 (stdout) here. We will exit soon anyway */ | |
| - | close(config->accepted_socket); |
| + | close(accepted_socket); |
| } | |
| /**************************************************************************** | |
| @@ -1830,24 +1862,24 @@ static int miniHttpd(int server) | |
| s = accept(server, &fromAddr.sa, &fromAddrLen); | |
| if (s < 0) | |
| continue; | |
| - | config->accepted_socket = s; |
| - | config->rmt_ip = 0; |
| - | config->port = 0; |
| + | accepted_socket = s; |
| + | rmt_ip = 0; |
| + | tcp_port = 0; |
| #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | |
| - | free(config->rmt_ip_str); |
| - | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| + | free(rmt_ip_str); |
| + | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| #if DEBUG | |
| - | bb_error_msg("connection from '%s'", config->rmt_ip_str); |
| + | bb_error_msg("connection from '%s'", rmt_ip_str); |
| #endif | |
| #endif /* FEATURE_HTTPD_CGI */ | |
| if (fromAddr.sa.sa_family == AF_INET) { | |
| - | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| - | config->port = ntohs(fromAddr.sin.sin_port); |
| + | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| + | tcp_port = ntohs(fromAddr.sin.sin_port); |
| } | |
| #if ENABLE_FEATURE_IPV6 | |
| if (fromAddr.sa.sa_family == AF_INET6) { | |
| - | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| - | config->port = ntohs(fromAddr.sin6.sin6_port); |
| + | //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| + | tcp_port = ntohs(fromAddr.sin6.sin6_port); |
| } | |
| #endif | |
| @@ -1880,20 +1912,20 @@ static int miniHttpd_inetd(void) | |
| socklen_t fromAddrLen = sizeof(fromAddr); | |
| getpeername(0, &fromAddr.sa, &fromAddrLen); | |
| - | config->rmt_ip = 0; |
| - | config->port = 0; |
| + | rmt_ip = 0; |
| + | tcp_port = 0; |
| #if ENABLE_FEATURE_HTTPD_CGI || DEBUG | |
| - | free(config->rmt_ip_str); |
| - | config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| + | free(rmt_ip_str); |
| + | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen); |
| #endif | |
| if (fromAddr.sa.sa_family == AF_INET) { | |
| - | config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| - | config->port = ntohs(fromAddr.sin.sin_port); |
| + | rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| + | tcp_port = ntohs(fromAddr.sin.sin_port); |
| } | |
| #if ENABLE_FEATURE_IPV6 | |
| if (fromAddr.sa.sa_family == AF_INET6) { | |
| - | //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| - | config->port = ntohs(fromAddr.sin6.sin6_port); |
| + | //rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr); |
| + | tcp_port = ntohs(fromAddr.sin6.sin6_port); |
| } | |
| #endif | |
| handleIncoming(); | |
| @@ -1942,7 +1974,6 @@ int httpd_main(int argc, char **argv); | |
| int httpd_main(int argc, char **argv) | |
| { | |
| unsigned opt; | |
| - | const char *home_httpd = home; |
| char *url_for_decode; | |
| USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) | |
| const char *s_port; | |
| @@ -1955,22 +1986,20 @@ int httpd_main(int argc, char **argv) | |
| setlocale(LC_TIME, "C"); | |
| #endif | |
| - | config = xzalloc(sizeof(*config)); |
| - | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| - | config->realm = "Web Server Authentication"; |
| - | #endif |
| - | config->port = 80; |
| - | config->ContentLength = -1; |
| - | |
| + | INIT_G(); |
| + | home_httpd = xrealloc_getcwd_or_warn(NULL); |
| + | /* We do not "absolutize" path given by -h (home) opt. |
| + | * If user gives relative path in -h, $SCRIPT_FILENAME can end up |
| + | * relative too. */ |
| opt = getopt32(argc, argv, "c:d:h:" | |
| USE_FEATURE_HTTPD_ENCODE_URL_STR("e:") | |
| USE_FEATURE_HTTPD_BASIC_AUTH("r:") | |
| USE_FEATURE_HTTPD_AUTH_MD5("m:") | |
| USE_FEATURE_HTTPD_SETUID("u:") | |
| "p:if", | |
| - | &(config->configFile), &url_for_decode, &home_httpd |
| + | &(configFile), &url_for_decode, &home_httpd |
| USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | |
| - | USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) |
| + | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
| USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | |
| USE_FEATURE_HTTPD_SETUID(, &s_ugid) | |
| , &s_port | |
| @@ -1992,7 +2021,7 @@ int httpd_main(int argc, char **argv) | |
| } | |
| #endif | |
| if (opt & OPT_PORT) | |
| - | config->port = xatou16(s_port); |
| + | tcp_port = xatou16(s_port); |
| #if ENABLE_FEATURE_HTTPD_SETUID | |
| if (opt & OPT_SETUID) { | |
| @@ -2005,7 +2034,7 @@ int httpd_main(int argc, char **argv) | |
| xchdir(home_httpd); | |
| if (!(opt & OPT_INETD)) { | |
| signal(SIGCHLD, SIG_IGN); | |
| - | config->server_socket = openServer(); |
| + | server_socket = openServer(); |
| #if ENABLE_FEATURE_HTTPD_SETUID | |
| /* drop privileges */ | |
| if (opt & OPT_SETUID) { | |
| @@ -2022,12 +2051,12 @@ int httpd_main(int argc, char **argv) | |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| { | |
| char *p = getenv("PATH"); | |
| - | p = xstrdup(p); /* if gets NULL, returns NULL */ |
| + | /* env strings themself are not freed, no need to strdup(p): */ |
| clearenv(); | |
| if (p) | |
| - | setenv1("PATH", p); |
| + | putenv(p - 5); |
| if (!(opt & OPT_INETD)) | |
| - | setenv_long("SERVER_PORT", config->port); |
| + | setenv_long("SERVER_PORT", tcp_port); |
| } | |
| #endif | |
| @@ -2042,5 +2071,5 @@ int httpd_main(int argc, char **argv) | |
| if (!(opt & OPT_FOREGROUND)) | |
| bb_daemonize(0); /* don't change current directory */ | |
| - | return miniHttpd(config->server_socket); |
| + | return miniHttpd(server_socket); |
| } | |