run = 0;
}
+static void uh_sigchld(int sig)
+{
+ while( waitpid(-1, NULL, WNOHANG) > 0 ) { }
+}
+
static void uh_config_parse(const char *path)
{
FILE *c;
if( !uh_auth_add(line, user, pass) )
{
fprintf(stderr,
- "Can not manage more than %i basic auth realms, "
- "will skip the rest\n", UH_LIMIT_AUTHREALMS
+ "Notice: No password set for user %s, ignoring "
+ "authentication on %s\n", user, line
);
break;
/* add socket to server fd set */
FD_SET(sock, serv_fds);
+ fd_cloexec(sock);
*max_fd = max(*max_fd, sock);
bound++;
struct sigaction sa;
struct config conf;
+ /* signal mask */
+ sigset_t ss;
+
/* maximum file descriptor number */
int new_fd, cur_fd, max_fd = 0;
+#ifdef HAVE_TLS
int tls = 0;
int keys = 0;
+#endif
+
int bound = 0;
int nofork = 0;
/* args */
- char opt;
+ int opt;
char bind[128];
char *port = NULL;
- /* library handles */
- void *tls_lib;
- void *lua_lib;
+#if defined(HAVE_TLS) || defined(HAVE_LUA)
+ /* library handle */
+ void *lib;
+#endif
/* clear the master and temp sets */
FD_ZERO(&used_fds);
FD_ZERO(&serv_fds);
FD_ZERO(&read_fds);
- /* handle SIGPIPE, SIGCHILD */
+ /* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = uh_sigchld;
sigaction(SIGCHLD, &sa, NULL);
sa.sa_handler = uh_sigterm;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
+ /* defer SIGCHLD */
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &ss, NULL);
+
/* prepare addrinfo hints */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
#ifdef HAVE_TLS
/* load TLS plugin */
- if( ! (tls_lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) )
+ if( ! (lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) )
{
fprintf(stderr,
"Notice: Unable to load TLS plugin - disabling SSL support! "
else
{
/* resolve functions */
- if( !(conf.tls_init = dlsym(tls_lib, "uh_tls_ctx_init")) ||
- !(conf.tls_cert = dlsym(tls_lib, "uh_tls_ctx_cert")) ||
- !(conf.tls_key = dlsym(tls_lib, "uh_tls_ctx_key")) ||
- !(conf.tls_free = dlsym(tls_lib, "uh_tls_ctx_free")) ||
- !(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) ||
- !(conf.tls_close = dlsym(tls_lib, "uh_tls_client_close")) ||
- !(conf.tls_recv = dlsym(tls_lib, "uh_tls_client_recv")) ||
- !(conf.tls_send = dlsym(tls_lib, "uh_tls_client_send"))
+ if( !(conf.tls_init = dlsym(lib, "uh_tls_ctx_init")) ||
+ !(conf.tls_cert = dlsym(lib, "uh_tls_ctx_cert")) ||
+ !(conf.tls_key = dlsym(lib, "uh_tls_ctx_key")) ||
+ !(conf.tls_free = dlsym(lib, "uh_tls_ctx_free")) ||
+ !(conf.tls_accept = dlsym(lib, "uh_tls_client_accept")) ||
+ !(conf.tls_close = dlsym(lib, "uh_tls_client_close")) ||
+ !(conf.tls_recv = dlsym(lib, "uh_tls_client_recv")) ||
+ !(conf.tls_send = dlsym(lib, "uh_tls_client_send"))
) {
fprintf(stderr,
"Error: Failed to lookup required symbols "
}
#endif
- while( (opt = getopt(argc, argv, "fC:K:p:s:h:c:l:L:d:r:m:x:")) > 0 )
+ while( (opt = getopt(argc, argv, "fSC:K:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 )
{
switch(opt)
{
port = optarg;
}
+#ifdef HAVE_TLS
if( opt == 's' )
{
if( !conf.tls )
tls = 1;
}
+#endif
/* bind sockets */
bound += uh_socket_bind(
&hints, (opt == 's'), &conf
);
+ memset(bind, 0, sizeof(bind));
break;
#ifdef HAVE_TLS
}
break;
+ /* don't follow symlinks */
+ case 'S':
+ conf.no_symlinks = 1;
+ break;
+
#ifdef HAVE_CGI
/* cgi prefix */
case 'x':
break;
#endif
+#if defined(HAVE_CGI) || defined(HAVE_LUA)
+ /* script timeout */
+ case 't':
+ conf.script_timeout = atoi(optarg);
+ break;
+#endif
+
+ /* network timeout */
+ case 'T':
+ conf.network_timeout = atoi(optarg);
+ break;
+
/* no fork */
case 'f':
nofork = 1;
" -K file ASN.1 server private key file\n"
#endif
" -h directory Specify the document root, default is '.'\n"
+ " -S Do not follow symbolic links outside of the docroot\n"
#ifdef HAVE_LUA
" -l string URL prefix for Lua handler, default is '/lua'\n"
" -L file Lua handler script, omit to disable Lua\n"
#ifdef HAVE_CGI
" -x string URL prefix for CGI handler, default is '/cgi-bin'\n"
#endif
+#if defined(HAVE_CGI) || defined(HAVE_LUA)
+ " -t seconds CGI and Lua script timeout in seconds, default is 60\n"
+#endif
+ " -T seconds Network timeout in seconds, default is 30\n"
" -d string URL decode given string\n"
" -r string Specify basic auth realm\n"
" -m string MD5 crypt given string\n"
/* config file */
uh_config_parse(conf.file);
+ /* default network timeout */
+ if( conf.network_timeout <= 0 )
+ conf.network_timeout = 30;
+
+#if defined(HAVE_CGI) || defined(HAVE_LUA)
+ /* default script timeout */
+ if( conf.script_timeout <= 0 )
+ conf.script_timeout = 60;
+#endif
+
#ifdef HAVE_CGI
/* default cgi prefix */
if( ! conf.cgi_prefix )
#ifdef HAVE_LUA
/* load Lua plugin */
- if( ! (lua_lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) )
+ if( ! (lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) )
{
fprintf(stderr,
"Notice: Unable to load Lua plugin - disabling Lua support! "
else
{
/* resolve functions */
- if( !(conf.lua_init = dlsym(lua_lib, "uh_lua_init")) ||
- !(conf.lua_close = dlsym(lua_lib, "uh_lua_close")) ||
- !(conf.lua_request = dlsym(lua_lib, "uh_lua_request"))
+ if( !(conf.lua_init = dlsym(lib, "uh_lua_init")) ||
+ !(conf.lua_close = dlsym(lib, "uh_lua_close")) ||
+ !(conf.lua_request = dlsym(lib, "uh_lua_request"))
) {
fprintf(stderr,
"Error: Failed to lookup required symbols "
/* add client socket to global fdset */
FD_SET(new_fd, &used_fds);
+ fd_cloexec(new_fd);
max_fd = max(max_fd, new_fd);
}