#include "libbb.h"
#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
-#include <sys/sendfile.h>
+# include <sys/sendfile.h>
#endif
//#define DEBUG 1
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
Htaccess *g_auth; /* config user:password lines */
#endif
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
Htaccess *mime_a; /* config mime types */
-#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
Htaccess *script_i; /* config script interpreters */
#endif
#define range_start (G.range_start )
#define range_end (G.range_end )
#define range_len (G.range_len )
+#else
+enum {
+ range_start = 0,
+ range_end = MAXINT(off_t) - 1,
+ range_len = MAXINT(off_t),
+};
#endif
#define rmt_ip_str (G.rmt_ip_str )
#define g_auth (G.g_auth )
file_size = -1; \
} while (0)
-#if !ENABLE_FEATURE_HTTPD_RANGES
-enum {
- range_start = 0,
- range_end = MAXINT(off_t) - 1,
- range_len = MAXINT(off_t),
-};
-#endif
-
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
*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)
{
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
Htaccess *prev;
#endif
-#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
- || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
- || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
Htaccess *cur;
-#endif
const char *filename = configFile;
char buf[160];
char *p, *p0;
/* 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_Htaccess_list(&g_auth);
#endif
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
free_Htaccess_list(&mime_a);
-#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
free_Htaccess_list(&script_i);
#endif
}
-#endif
if (flag == SUBDIR_PARSE || filename == NULL) {
filename = alloca(strlen(path) + sizeof(httpd_conf) + 2);
continue;
}
-#if ENABLE_FEATURE_HTTPD_BASIC_AUTH \
- || ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES \
- || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
/* storing current config line */
cur = xzalloc(sizeof(Htaccess) + strlen(p0));
strcpy(cur->before_colon, p0);
#endif
cur->after_colon = strchr(cur->before_colon, ':');
*cur->after_colon++ = '\0';
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
if (cur->before_colon[0] == '.') {
/* .mime line: prepend to mime_a list */
cur->next = mime_a;
mime_a = cur;
continue;
}
-#endif
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
if (cur->before_colon[0] == '*' && cur->before_colon[1] == '.') {
/* script interpreter line: prepend to script_i list */
}
}
#endif /* BASIC_AUTH */
-#endif /* BASIC_AUTH || MIME_TYPES || SCRIPT_INTERPR */
} /* while (fgets) */
fclose(f);
}
* const char *url The requested URL (with leading /).
* what What to send (headers/body/both).
*/
-static void send_file_and_exit(const char *url, int what)
+static NOINLINE void send_file_and_exit(const char *url, int what)
{
static const char *const suffixTable[] = {
/* Warning: shorter equivalent suffix in one line must be first */
};
char *suffix;
- int f;
+ int fd;
const char *const *table;
const char *try_suffix;
ssize_t count;
-#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
- off_t offset;
-#endif
+
+ fd = open(url, O_RDONLY);
+ if (fd < 0) {
+ if (DEBUG)
+ bb_perror_msg("can't open '%s'", url);
+ /* Error pages are sent by using send_file_and_exit(SEND_BODY).
+ * IOW: it is unsafe to call send_headers_and_exit
+ * if what is SEND_BODY! Can recurse! */
+ if (what != SEND_BODY)
+ send_headers_and_exit(HTTP_NOT_FOUND);
+ log_and_exit();
+ }
+
+ if (DEBUG)
+ bb_error_msg("sending file '%s' content-type: %s",
+ url, found_mime_type);
/* If you want to know about EPIPE below
* (happens if you abort downloads from local httpd): */
/* 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) {
}
}
}
-#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
for (cur = mime_a; cur; cur = cur->next) {
if (strcmp(cur->before_colon, suffix) == 0) {
found_mime_type = cur->after_colon;
break;
}
}
-#endif
- }
-
- if (DEBUG)
- bb_error_msg("sending file '%s' content-type: %s",
- url, found_mime_type);
-
- f = open(url, O_RDONLY);
- if (f < 0) {
- if (DEBUG)
- bb_perror_msg("can't open '%s'", url);
- /* Error pages are sent by using send_file_and_exit(SEND_BODY).
- * IOW: it is unsafe to call send_headers_and_exit
- * if what is SEND_BODY! Can recurse! */
- if (what != SEND_BODY)
- send_headers_and_exit(HTTP_NOT_FOUND);
- log_and_exit();
}
#if ENABLE_FEATURE_HTTPD_RANGES
if (what == SEND_BODY)
range_end = file_size - 1;
}
if (range_end < range_start
- || lseek(f, range_start, SEEK_SET) != range_start
+ || lseek(fd, range_start, SEEK_SET) != range_start
) {
- lseek(f, 0, SEEK_SET);
+ lseek(fd, 0, SEEK_SET);
range_start = 0;
} else {
range_len = range_end - range_start + 1;
}
}
#endif
-
if (what & SEND_HEADERS)
send_headers(HTTP_OK);
-
#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
- offset = range_start;
- do {
- /* sz is rounded down to 64k */
- ssize_t sz = MAXINT(ssize_t) - 0xffff;
- USE_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;)
- count = sendfile(1, f, &offset, sz);
- if (count < 0) {
- if (offset == range_start)
- goto fallback;
- goto fin;
+ {
+ off_t offset = range_start;
+ while (1) {
+ /* sz is rounded down to 64k */
+ ssize_t sz = MAXINT(ssize_t) - 0xffff;
+ USE_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;)
+ count = sendfile(STDOUT_FILENO, fd, &offset, sz);
+ if (count < 0) {
+ if (offset == range_start)
+ break; /* fall back to read/write loop */
+ goto fin;
+ }
+ USE_FEATURE_HTTPD_RANGES(range_len -= sz;)
+ if (count == 0 || range_len == 0)
+ log_and_exit();
}
- USE_FEATURE_HTTPD_RANGES(range_len -= sz;)
- } while (count > 0 && range_len);
- log_and_exit();
-
- fallback:
+ }
#endif
- while ((count = safe_read(f, iobuf, IOBUF_SIZE)) > 0) {
+ while ((count = safe_read(fd, iobuf, IOBUF_SIZE)) > 0) {
ssize_t n;
USE_FEATURE_HTTPD_RANGES(if (count > range_len) count = range_len;)
n = full_write(STDOUT_FILENO, iobuf, count);
if (count != n)
break;
USE_FEATURE_HTTPD_RANGES(range_len -= count;)
- if (!range_len)
+ if (range_len == 0)
break;
}
-#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
- fin:
-#endif
- if (count < 0 && verbose > 1)
- bb_perror_msg("error");
+ if (count < 0) {
+ USE_FEATURE_HTTPD_USE_SENDFILE(fin:)
+ if (verbose > 1)
+ bb_perror_msg("error");
+ }
log_and_exit();
}
if (fork() == 0) {
/* child */
-#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
/* Do not reload config on HUP */
signal(SIGHUP, SIG_IGN);
-#endif
close(server_socket);
xmove_fd(n, 0);
xdup2(0, 1);
if (vfork() == 0) {
/* child */
-#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
/* Do not reload config on HUP */
signal(SIGHUP, SIG_IGN);
-#endif
close(server_socket);
xmove_fd(n, 0);
xdup2(0, 1);
handle_incoming_and_exit(&fromAddr);
}
-#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
-static void sighup_handler(int sig)
+static void sighup_handler(int sig UNUSED_PARAM)
{
- parse_conf(default_path_httpd_conf, sig ? SIGNALED_PARSE : FIRST_PARSE);
- signal_SA_RESTART_empty_mask(SIGHUP, sighup_handler);
+ parse_conf(default_path_httpd_conf, SIGNALED_PARSE);
}
-#endif
enum {
c_opt_config_file = 0,
#endif
}
-#if 0 /*was #if ENABLE_FEATURE_HTTPD_CGI*/
+#if 0
/* User can do it himself: 'env - PATH="$PATH" httpd'
* We don't do it because we don't want to screw users
* which want to do
}
#endif
-#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
- if (!(opt & OPT_INETD)) {
- /* runs parse_conf() inside */
- sighup_handler(0);
- } else
-#endif
- {
- parse_conf(default_path_httpd_conf, FIRST_PARSE);
- }
+ parse_conf(default_path_httpd_conf, FIRST_PARSE);
+ if (!(opt & OPT_INETD))
+ signal(SIGHUP, sighup_handler);
xfunc_error_retval = 0;
if (opt & OPT_INETD)