httpd shrink and logging update, part 5 of 7

text    data     bss     dec     hex filename
   9836       0       0    9836    266c busybox.t1/networking/httpd.o.orig
   9724       0       0    9724    25fc busybox.t2/networking/httpd.o
   9657       0       0    9657    25b9 busybox.t3/networking/httpd.o
   9342       0       0    9342    247e busybox.t4/networking/httpd.o
   9342       0       0    9342    247e busybox.t5/networking/httpd.o
   9262       0       0    9262    242e busybox.t6/networking/httpd.o
   9283       0       0    9283    2443 busybox.t7/networking/httpd.o
   9334       0       0    9334    2476 busybox.t8/networking/httpd.o
This commit is contained in:
Denis Vlasenko 2007-08-17 19:20:07 +00:00
parent 91adf7d587
commit 073214f894

View File

@ -20,7 +20,7 @@
* httpd -p 80 -u 80 -h /www -c /etc/httpd.conf -r "Web Server Authentication"
*
*
* When a url contains "cgi-bin" it is assumed to be a cgi script. The
* When a url starts by "/cgi-bin/" it is assumed to be a cgi script. The
* server changes directory to the location of the script and executes it
* after setting QUERY_STRING and other environment variables.
*
@ -96,37 +96,38 @@
#include <sys/sendfile.h>
#endif
//#define DEBUG 1
#define DEBUG 0
/* amount of buffering in a pipe */
#ifndef PIPE_BUF
# define PIPE_BUF 4096
#endif
#define MAX_MEMORY_BUF 8192 /* IO buffer */
#define HEADER_READ_TIMEOUT 60
static const char default_path_httpd_conf[] ALIGN1 = "/etc";
static const char httpd_conf[] ALIGN1 = "httpd.conf";
#define TIMEOUT 60
// Note: busybox xfuncs are not used because we want the server to keep running
// if something bad happens due to a malformed user request.
// As a result, all memory allocations after daemonize
// are checked rigorously
//#define DEBUG 1
#define DEBUG 0
#define MAX_MEMORY_BUF 8192 /* IO buffer */
typedef struct has_next_ptr {
struct has_next_ptr *next;
} has_next_ptr;
/* Must have "next" as a first member */
typedef struct Htaccess {
char *after_colon;
struct Htaccess *next;
char *after_colon;
char before_colon[1]; /* really bigger, must be last */
} Htaccess;
/* Must have "next" as a first member */
typedef struct Htaccess_IP {
struct Htaccess_IP *next;
unsigned ip;
unsigned mask;
int allow_deny;
struct Htaccess_IP *next;
} Htaccess_IP;
struct globals {
@ -199,30 +200,6 @@ struct globals {
ContentLength = -1; \
} while (0)
static const char request_GET[] ALIGN1 = "GET"; /* size algorithmic optimize */
static const char *const suffixTable[] = {
/* Warning: shorter equivalent suffix in one line must be first */
".htm.html", "text/html",
".jpg.jpeg", "image/jpeg",
".gif", "image/gif",
".png", "image/png",
".txt.h.c.cc.cpp", "text/plain",
".css", "text/css",
".wav", "audio/wav",
".avi", "video/x-msvideo",
".qt.mov", "video/quicktime",
".mpe.mpeg", "video/mpeg",
".mid.midi", "audio/midi",
".mp3", "audio/mpeg",
#if 0 /* unpopular */
".au", "audio/basic",
".pac", "application/x-ns-proxy-autoconfig",
".vrml.wrl", "model/vrml",
#endif
0, "application/octet-stream" /* default */
};
typedef enum {
HTTP_OK = 200,
HTTP_MOVED_TEMPORARILY = 302,
@ -285,11 +262,32 @@ static const HttpEnumString httpResponseNames[] = {
};
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
static void free_llist(has_next_ptr **pptr)
{
has_next_ptr *cur = *pptr;
while (cur) {
has_next_ptr *t = cur;
cur = cur->next;
free(t);
}
*pptr = NULL;
}
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
static ALWAYS_INLINE void free_Htaccess_list(Htaccess **pptr)
{
free_llist((has_next_ptr**)pptr);
}
#endif
static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr)
{
free_llist((has_next_ptr**)pptr);
}
static int scan_ip(const char **ep, unsigned *ip, unsigned char endc)
{
@ -365,33 +363,8 @@ static int scan_ip_mask(const char *ipm, unsigned *ip, unsigned *mask)
return 0;
}
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
static void free_config_lines(Htaccess **pprev)
{
Htaccess *prev = *pprev;
while (prev) {
Htaccess *cur = prev;
prev = cur->next;
free(cur);
}
*pprev = NULL;
}
#endif
/* flag */
#define FIRST_PARSE 0
#define SUBDIR_PARSE 1
#define SIGNALED_PARSE 2
#define FIND_FROM_HTTPD_ROOT 3
/****************************************************************************
*
> $Function: parse_conf()
*
* $Description: parse configuration file into in-memory linked list.
/*
* Parse configuration file into in-memory linked list.
*
* The first non-white character is examined to determine if the config line
* is one of the following:
@ -404,14 +377,14 @@ static void free_config_lines(Htaccess **pprev)
* are also discarded. That is, previous settings are retained if flag is
* SUBDIR_PARSE.
*
* $Parameters:
* (const char *) path . . null for ip address checks, path for password
* checks.
* (int) flag . . . . . . the source of the parse request.
*
* $Return: (None)
*
****************************************************************************/
* path Path where to look for httpd.conf (without filename).
* flag Type of the parse request.
*/
/* flag */
#define FIRST_PARSE 0
#define SUBDIR_PARSE 1
#define SIGNALED_PARSE 2
#define FIND_FROM_HTTPD_ROOT 3
static void parse_conf(const char *path, int flag)
{
FILE *f;
@ -423,38 +396,28 @@ static void parse_conf(const char *path, int flag)
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
Htaccess *cur;
#endif
const char *cf = configFile;
char buf[160];
char *p0 = NULL;
char *c, *p;
Htaccess_IP *pip;
/* free previous ip setup if present */
Htaccess_IP *pip = ip_a_d;
while (pip) {
Htaccess_IP *cur_ipl = pip;
pip = cur_ipl->next;
free(cur_ipl);
}
ip_a_d = NULL;
/* discard old rules */
free_Htaccess_IP_list(&ip_a_d);
flg_deny_all = 0;
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
|| ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
/* retain previous auth and mime config only for subdir parse */
if (flag != SUBDIR_PARSE) {
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
free_config_lines(&g_auth);
free_Htaccess_list(&g_auth);
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
free_config_lines(&mime_a);
free_Htaccess_list(&mime_a);
#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
free_config_lines(&script_i);
free_Htaccess_list(&script_i);
#endif
}
#endif
@ -486,17 +449,17 @@ static void parse_conf(const char *path, int flag)
/* This could stand some work */
while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) {
c = NULL;
for (p = p0; *p0 != 0 && *p0 != '#'; p0++) {
for (p = p0; *p0 != '\0' && *p0 != '#'; p0++) {
if (!isspace(*p0)) {
*p++ = *p0;
if (*p0 == ':' && c == NULL)
c = p;
}
}
*p = 0;
*p = '\0';
/* test for empty or strange line */
if (c == NULL || *c == 0)
if (c == NULL || *c == '\0')
continue;
p0 = buf;
if (*p0 == 'd')
@ -535,7 +498,7 @@ static void parse_conf(const char *path, int flag)
}
pip->allow_deny = *p0;
if (*p0 == 'D') {
/* Deny:form_IP move top */
/* Deny:from_IP move top */
pip->next = ip_a_d;
ip_a_d = pip;
} else {
@ -555,12 +518,12 @@ static void parse_conf(const char *path, int flag)
}
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
if (*p0 == '/') {
/* make full path from httpd root / curent_path / config_line_path */
cf = flag == SUBDIR_PARSE ? path : "";
/* make full path from httpd root / current_path / config_line_path */
cf = (flag == SUBDIR_PARSE ? path : "");
p0 = malloc(strlen(cf) + (c - buf) + 2 + strlen(c));
if (p0 == NULL)
continue;
c[-1] = 0;
c[-1] = '\0';
sprintf(p0, "/%s%s", cf, buf);
/* another call bb_simplify_path */
@ -571,9 +534,9 @@ static void parse_conf(const char *path, int flag)
if (*cf == '/') { /* skip duplicate (or initial) slash */
continue;
} else if (*cf == '.') {
if (cf[1] == '/' || cf[1] == 0) { /* remove extra '.' */
if (cf[1] == '/' || cf[1] == '\0') { /* remove extra '.' */
continue;
} else if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == 0)) {
} else if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == '\0')) {
++cf;
if (p > p0) {
while (*--p != '/') /* omit previous dir */;
@ -588,7 +551,7 @@ static void parse_conf(const char *path, int flag)
if ((p == p0) || (*p != '/')) { /* not a trailing slash */
++p; /* so keep last character */
}
*p = 0;
*p = '\0';
sprintf(p0, "%s:%s", p0, c);
}
#endif
@ -658,23 +621,14 @@ static void parse_conf(const char *path, int flag)
}
#if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
/****************************************************************************
*
> $Function: encodeString()
*
* $Description: Given a string, html encode special characters.
/*
* Given a string, html-encode special characters.
* This is used for the -e command line option to provide an easy way
* for scripts to encode result data without confusing browsers. The
* returned string pointer is memory allocated by malloc().
*
* $Parameters:
* (const char *) string . . The first string to encode.
*
* $Return: (char *) . . . .. . . A pointer to the encoded string.
*
* $Errors: Returns a null string ("") if memory is not available.
*
****************************************************************************/
* Returns a pointer to the encoded string (malloced).
*/
static char *encodeString(const char *string)
{
/* take the simple route and encode everything */
@ -694,25 +648,18 @@ static char *encodeString(const char *string)
}
#endif /* FEATURE_HTTPD_ENCODE_URL_STR */
/****************************************************************************
*
> $Function: decodeString()
*
* $Description: Given a URL encoded string, convert it to plain ascii.
/*
* Given a URL encoded string, convert it to plain ascii.
* Since decoding always makes strings smaller, the decode is done in-place.
* Thus, callers should strdup() the argument if they do not want the
* argument modified. The return is the original pointer, allowing this
* function to be easily used as arguments to other functions.
*
* $Parameters:
* (char *) string . . . The first string to decode.
* (int) option_d . . 1 if called for httpd -d
* string The first string to decode.
* option_d 1 if called for httpd -d
*
* $Return: (char *) . . . . A pointer to the decoded string (same as input).
*
* $Errors: None
*
****************************************************************************/
* Returns a pointer to the decoded string (same as input).
*/
static char *decodeString(char *orig, int option_d)
{
/* note that decoded string is always shorter than original */
@ -754,9 +701,9 @@ static char *decodeString(char *orig, int option_d)
#if ENABLE_FEATURE_HTTPD_CGI
/****************************************************************************
/*
* setenv helpers
****************************************************************************/
*/
static void setenv1(const char *name, const char *value)
{
if (!value)
@ -775,8 +722,8 @@ static void setenv_long(const char *name, long value)
/*
* Decode a base64 data stream as per rfc1521.
* Note that the rfc states that non base64 chars are to be ignored.
* Since the decode always results in a shorter size than the input, it is
* OK to pass the input arg as an output arg.
* Since the decode always results in a shorter size than the input,
* it is OK to pass the input arg as an output arg.
* Parameter: a pointer to a base64 encoded string.
* Decoded data is stored in-place.
*/
@ -818,18 +765,9 @@ static void decodeBase64(char *Data)
}
#endif
/****************************************************************************
*
> $Function: openServer()
*
* $Description: create a listen server socket on the designated port.
*
* $Return: (int) . . . A connection socket. -1 for errors.
*
* $Errors: None
*
****************************************************************************/
/*
* Create a listen server socket on the designated port.
*/
#if BB_MMU
static int openServer(void)
{
@ -853,6 +791,8 @@ static int openServer(void)
*/
static int sendHeaders(HttpResponseNum responseNum)
{
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
const char *responseString = "";
const char *infoString = NULL;
const char *mime_type;
@ -1318,6 +1258,28 @@ static void send_cgi_and_exit(
static void send_file_and_exit(const char *url) ATTRIBUTE_NORETURN;
static void send_file_and_exit(const char *url)
{
static const char *const suffixTable[] = {
/* Warning: shorter equivalent suffix in one line must be first */
".htm.html", "text/html",
".jpg.jpeg", "image/jpeg",
".gif", "image/gif",
".png", "image/png",
".txt.h.c.cc.cpp", "text/plain",
".css", "text/css",
".wav", "audio/wav",
".avi", "video/x-msvideo",
".qt.mov", "video/quicktime",
".mpe.mpeg", "video/mpeg",
".mid.midi", "audio/midi",
".mp3", "audio/mpeg",
#if 0 /* unpopular */
".au", "audio/basic",
".pac", "application/x-ns-proxy-autoconfig",
".vrml.wrl", "model/vrml",
#endif
NULL
};
char *suffix;
int f;
int fd;
@ -1330,25 +1292,31 @@ static void send_file_and_exit(const char *url)
suffix = strrchr(url, '.');
for (table = suffixTable; *table; table += 2)
if (suffix != NULL && (try_suffix = strstr(*table, suffix)) != 0) {
/* If not found, set default as "application/octet-stream"; */
found_mime_type = "application/octet-stream";
if (suffix) {
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
Htaccess *cur;
#endif
for (table = suffixTable; *table; table += 2) {
try_suffix = strstr(table[0], suffix);
if (try_suffix) {
try_suffix += strlen(suffix);
if (*try_suffix == 0 || *try_suffix == '.')
if (*try_suffix == '\0' || *try_suffix == '.') {
found_mime_type = table[1];
break;
}
/* also, if not found, set default as "application/octet-stream"; */
found_mime_type = table[1];
}
}
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
if (suffix) {
Htaccess * cur;
for (cur = mime_a; cur; cur = cur->next) {
if (strcmp(cur->before_colon, suffix) == 0) {
found_mime_type = cur->after_colon;
break;
}
}
#endif
}
#endif /* FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES */
if (DEBUG)
bb_error_msg("sending file '%s' content-type: %s",
@ -1426,23 +1394,17 @@ static int checkPermIP(void)
return !flg_deny_all;
}
/****************************************************************************
*
> $Function: checkPerm()
*
* $Description: Check the permission file for access password protected.
/*
* Check the permission file for access password protected.
*
* If config file isn't present, everything is allowed.
* Entries are of the form you can see example from header source
*
* $Parameters:
* (const char *) path . . . . The file path.
* (const char *) request . . . User information to validate.
* path The file path.
* request User information to validate.
*
* $Return: (int) . . . . . . . . . 1 if request OK, 0 otherwise.
*
****************************************************************************/
* Returns 1 if request is OK.
*/
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
static int checkPerm(const char *path, const char *request)
{
@ -1528,15 +1490,17 @@ static void exit_on_signal(int sig)
static void handle_incoming_and_exit(void) ATTRIBUTE_NORETURN;
static void handle_incoming_and_exit(void)
{
static const char request_GET[] ALIGN1 = "GET";
char *url;
char *purl;
int count;
int blank = -1;
int http_major_version;
char *test;
struct stat sb;
int ip_allowed;
#if ENABLE_FEATURE_HTTPD_CGI
const char *prequest = request_GET;
const char *prequest;
unsigned long length = 0;
char *cookie = 0;
char *content_type = 0;
@ -1546,21 +1510,24 @@ static void handle_incoming_and_exit(void)
int credentials = -1; /* if not required this is Ok */
#endif
/* Install timeout handler */
sa.sa_handler = exit_on_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; /* no SA_RESTART */
sigaction(SIGALRM, &sa, NULL);
alarm(HEADER_READ_TIMEOUT);
alarm(TIMEOUT);
if (!get_line())
_exit(0); /* EOF or error or empty line */
/* Determine type of request (GET/POST) */
purl = strpbrk(iobuf, " \t");
if (purl == NULL) {
send_headers_and_exit(HTTP_BAD_REQUEST);
}
*purl = '\0';
#if ENABLE_FEATURE_HTTPD_CGI
prequest = request_GET;
if (strcasecmp(iobuf, prequest) != 0) {
prequest = "POST";
if (strcasecmp(iobuf, prequest) != 0) {
@ -1573,8 +1540,10 @@ static void handle_incoming_and_exit(void)
}
#endif
*purl = ' ';
count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
/* Copy URL from after "GET "/"POST " to stack-allocated char[] */
http_major_version = -1;
count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &http_major_version);
if (count < 1 || iobuf[0] != '/') {
/* Garbled request/URL */
send_headers_and_exit(HTTP_BAD_REQUEST);
@ -1584,7 +1553,8 @@ static void handle_incoming_and_exit(void)
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
}
strcpy(url, iobuf);
/* extract url args if present */
/* Extract url args if present */
test = strchr(url, '?');
g_query = NULL;
if (test) {
@ -1592,6 +1562,7 @@ static void handle_incoming_and_exit(void)
g_query = test;
}
/* Decode URL escape sequences */
test = decodeString(url, 0);
if (test == NULL)
send_headers_and_exit(HTTP_BAD_REQUEST);
@ -1600,7 +1571,8 @@ static void handle_incoming_and_exit(void)
send_headers_and_exit(HTTP_NOT_FOUND);
}
/* algorithm stolen from libbb bb_simplify_path(),
/* Canonicalize path */
/* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup and reducing trailing slash and protect out root */
purl = test = url;
do {
@ -1631,13 +1603,14 @@ static void handle_incoming_and_exit(void)
*++purl = '\0'; /* so keep last character */
test = purl; /* end ptr */
/* If URL is directory, adding '/' */
/* If URL is a directory, add '/' */
if (test[-1] != '/') {
if (is_directory(url + 1, 1, &sb)) {
found_moved_temporarily = url;
}
}
/* Log it */
if (verbose > 1)
bb_error_msg("url:%s", url);
@ -1653,15 +1626,17 @@ static void handle_incoming_and_exit(void)
}
*test = '/';
}
if (blank >= 0) {
/* read until blank line for HTTP version specified, else parse immediate */
if (http_major_version >= 0) {
/* Request was with "... HTTP/n.m", and n >= 0 */
/* Read until blank line for HTTP version specified, else parse immediate */
while (1) {
alarm(TIMEOUT);
alarm(HEADER_READ_TIMEOUT);
if (!get_line())
break; /* EOF or error or empty line */
if (DEBUG)
bb_error_msg("header: '%s'", iobuf);
#if ENABLE_FEATURE_HTTPD_CGI
/* try and do our best to parse more lines */
if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
@ -1707,6 +1682,7 @@ static void handle_incoming_and_exit(void)
} /* while extra header reading */
}
/* We read everything, disable peer timeout */
alarm(0);
if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) {
@ -1727,9 +1703,9 @@ static void handle_incoming_and_exit(void)
test = url + 1; /* skip first '/' */
#if ENABLE_FEATURE_HTTPD_CGI
if (strncmp(test, "cgi-bin", 7) == 0) {
if (test[7] == '/' && test[8] == '\0') {
/* protect listing cgi-bin/ */
if (strncmp(test, "cgi-bin/", 8) == 0) {
if (test[8] == '\0') {
/* protect listing "cgi-bin/" */
send_headers_and_exit(HTTP_FORBIDDEN);
}
send_cgi_and_exit(url, prequest, length, cookie, content_type);
@ -1768,7 +1744,11 @@ static void handle_incoming_and_exit(void)
send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
}
}
#endif /* FEATURE_HTTPD_CGI */
#endif
/* else {
* fall through to send_file, it errors out if open fails
* }
*/
send_file_and_exit(test);
@ -1813,6 +1793,11 @@ static void handle_incoming_and_exit(void)
static void mini_httpd(int server) ATTRIBUTE_NORETURN;
static void mini_httpd(int server)
{
/* NB: it's best to not use xfuncs in this loop before fork().
* Otherwise server may die on transient errors (temporary
* out-of-memory condition, etc), which is Bad(tm).
* Try to do any dangerous calls after fork.
*/
while (1) {
int n;
len_and_sockaddr fromAddr;
@ -1825,18 +1810,6 @@ static void mini_httpd(int server)
continue;
/* set the KEEPALIVE option to cull dead connections */
setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
accepted_socket = n;
n = get_nport(&fromAddr.sa);
tcp_port = ntohs(n);
rmt_ip = 0;
if (fromAddr.sa.sa_family == AF_INET) {
rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
}
if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
free(rmt_ip_str);
rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddr.len);
}
if (fork() == 0) {
/* child */
@ -1844,6 +1817,16 @@ static void mini_httpd(int server)
/* Do not reload config on HUP */
signal(SIGHUP, SIG_IGN);
#endif
accepted_socket = n;
n = get_nport(&fromAddr.sa);
tcp_port = ntohs(n);
rmt_ip = 0;
if (fromAddr.sa.sa_family == AF_INET) {
rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
}
if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddr.len);
}
if (verbose) {
/* this trick makes -v logging much simpler */
applet_name = rmt_ip_str;
@ -1853,7 +1836,7 @@ static void mini_httpd(int server)
handle_incoming_and_exit();
}
/* parent, or fork failed */
close(accepted_socket);
close(n);
} /* while (1) */
/* never reached */
}
@ -1883,12 +1866,13 @@ static void mini_httpd_inetd(void)
#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
static void sighup_handler(int sig)
{
/* set and reset */
struct sigaction sa;
parse_conf(default_path_httpd_conf, sig == SIGHUP ? SIGNALED_PARSE : FIRST_PARSE);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sighup_handler;
sigemptyset(&sa.sa_mask);
/*sigemptyset(&sa.sa_mask); - memset should be enough */
sa.sa_flags = SA_RESTART;
sigaction(SIGHUP, &sa, NULL);
}
@ -1930,12 +1914,13 @@ int httpd_main(int argc, char **argv)
USE_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;)
USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
INIT_G();
#if ENABLE_LOCALE_SUPPORT
/* Undo busybox.c: we want to speak English in http (dates etc) */
setlocale(LC_TIME, "C");
#endif
INIT_G();
home_httpd = xrealloc_getcwd_or_warn(NULL);
opt_complementary = "vv"; /* counter */
/* We do not "absolutize" path given by -h (home) opt.
@ -2012,13 +1997,12 @@ int httpd_main(int argc, char **argv)
}
#endif
#if BB_MMU
#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
sighup_handler(0);
#else
parse_conf(default_path_httpd_conf, FIRST_PARSE);
#endif
#if BB_MMU
if (opt & OPT_INETD)
mini_httpd_inetd();
if (!(opt & OPT_FOREGROUND))