# HG changeset patch # User Olaf Wintermann # Date 1485294494 -3600 # Node ID 724e107983e957c63d24aa6a5429f6d2efaf039b # Parent 36cd2e280386cb8b919303cc81cb61c47c663965 adds unix domain socket for server control ops diff -r 36cd2e280386 -r 724e107983e9 src/server/daemon/main.c --- a/src/server/daemon/main.c Tue Jan 24 17:36:28 2017 +0100 +++ b/src/server/daemon/main.c Tue Jan 24 22:48:14 2017 +0100 @@ -39,6 +39,8 @@ #include "../util/plist.h" #include "../util/date.h" +#include "../../ucx/string.h" + #include "webserver.h" #include "log.h" #include "httprequest.h" @@ -99,6 +101,29 @@ return NULL; } +void handle_srvctrl() { + int srvctrl = webserver_srvctrl_fd(); + listen(srvctrl, 8); + + for(;;) { + int admin_client = accept(srvctrl, NULL, 0); + if(admin_client < 0) { + log_ereport( + LOG_FAILURE, + "srvctrl: accept failed: %s", + strerror(errno)); + continue; + } + + // TODO: read commands + webserver_shutdown(); + + close(admin_client); + + break; + } +} + int main(int argc, char **argv) { //test(); @@ -164,17 +189,20 @@ int status; status = webserver_init(); if(status != 0) { - log_ereport(LOG_FAILURE, "Cannot initialize server."); + log_ereport(LOG_FAILURE, "cannot initialize server."); return EXIT_FAILURE; } status = webserver_run(); if(status != 0) { - log_ereport(LOG_FAILURE, "Cannot run server."); + log_ereport(LOG_FAILURE, "cannot run server."); return EXIT_FAILURE; } - + + handle_srvctrl(); + /* TODO: join threads (or not?) */ +/* while(1) { if(is_daemon) { fflush(stdout); @@ -185,6 +213,7 @@ break; } } +*/ return EXIT_SUCCESS; } diff -r 36cd2e280386 -r 724e107983e9 src/server/daemon/webserver.c --- a/src/server/daemon/webserver.c Tue Jan 24 17:36:28 2017 +0100 +++ b/src/server/daemon/webserver.c Tue Jan 24 22:48:14 2017 +0100 @@ -48,6 +48,8 @@ #include "../util/io.h" #include "../util/util.h" +#include "../../ucx/utils.h" + #include "../safs/common.h" #include "func.h" @@ -62,6 +64,8 @@ static RestartCallback *atrestart; +static int srvctrl; + int webserver_init() { // init NSPR systhread_init("webserver"); @@ -91,20 +95,6 @@ // init caches auth_cache_init(); - // create tmp dir and pid file - char *mkdir_cmd = NULL; - asprintf(&mkdir_cmd, "mkdir -p %s", cfg->tmp.ptr); - system(mkdir_cmd); - free(mkdir_cmd); - - char *pid_file_path = NULL; - asprintf(&pid_file_path, "%s/pid", cfg->tmp.ptr); - FILE *pidfile = fopen(pid_file_path, "w"); // TODO: check error - pid_t pid = getpid(); - fprintf(pidfile, "%d", pid); - fclose(pidfile); - free(pid_file_path); - // init SAFs common_saf_init(); @@ -168,6 +158,92 @@ "server must be started as root to change uid"); } + // create tmp dir and pid file + char *mkdir_cmd = NULL; + asprintf(&mkdir_cmd, "mkdir -p %s", cfg->tmp.ptr); + system(mkdir_cmd); + free(mkdir_cmd); + + char *pid_file_path = NULL; + asprintf(&pid_file_path, "%s/pid", cfg->tmp.ptr); + FILE *pidfile = fopen(pid_file_path, "w"); // TODO: check error + pid_t pid = getpid(); + fprintf(pidfile, "%d", pid); + fclose(pidfile); + free(pid_file_path); + + // create unix domain socket for server control + sstr_t tmp_priv = ucx_sprintf("%s/private", cfg->tmp.ptr); + // TODO: remove existing private dir + if(mkdir(tmp_priv.ptr, S_IRWXU)) { + if(errno == EEXIST) { + if(chmod(tmp_priv.ptr, S_IRWXU)) { + log_ereport( + LOG_CATASTROPHE, + "cannot change permissions of tmp dir %s:", + tmp_priv.ptr, + strerror(errno)); + return 0; + } + } else { + log_ereport( + LOG_CATASTROPHE, + "cannot create tmp dir %s:", + tmp_priv.ptr, + strerror(errno)); + return -1; + } + } + + + // create srvctrl unix domain socket + // this socket is used for stop, reconfigure and other operations + sstr_t uds_path = ucx_sprintf("%s/private/srvctrl.sock", cfg->tmp.ptr); + struct sockaddr_un addr; + if(uds_path.length > sizeof(addr.sun_path)-1) { + log_ereport( + LOG_CATASTROPHE, + "path '%s' too long for unix domain socket", + uds_path.ptr); + return -1; + } + + // make sure there is no old srvctrl socket file + // otherweise bind would fail + if(unlink(uds_path.ptr)) { + if(errno != ENOENT) { + log_ereport( + LOG_CATASTROPHE, + "cannot unlink old srvctrl socket '%s': %s", + uds_path.ptr, + strerror(errno)); + return -1; + } + } + + ZERO(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, uds_path.ptr, uds_path.length); + + srvctrl = socket(AF_UNIX, SOCK_STREAM, 0); + if(srvctrl == -1) { + log_ereport( + LOG_CATASTROPHE, + "Cannot create server control socket: %s", + strerror(errno)); + return -1; + } + if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) { + log_ereport( + LOG_CATASTROPHE, + "srvctrl socket bind failed: %s", + strerror(errno)); + return -1; + } + + free(uds_path.ptr); + + //endpwent(); // TODO: close or not? //free(pwbuf); // TODO: ? @@ -198,6 +274,10 @@ } } +int webserver_srvctrl_fd() { + return srvctrl; +} + void webserver_atrestart(void (*fn)(void *), void *data) { RestartCallback *cb = malloc(sizeof(RestartCallback)); cb->func = fn; diff -r 36cd2e280386 -r 724e107983e9 src/server/daemon/webserver.h --- a/src/server/daemon/webserver.h Tue Jan 24 17:36:28 2017 +0100 +++ b/src/server/daemon/webserver.h Tue Jan 24 22:48:14 2017 +0100 @@ -46,6 +46,8 @@ int webserver_run(); void webserver_shutdown(); +int webserver_srvctrl_fd(); + void webserver_atrestart(void (*fn)(void *), void *data); int ws_init_ssl();