summaryrefslogtreecommitdiffhomepage
path: root/networking/httpd.c
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 /networking/httpd.c
parent66db264a5fd67ce4573c905c897a1e80ff26a461 (diff)
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);
Diffstat (limited to 'networking/httpd.c')
-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 @@
# 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);
}