Mon, 06 Mar 2017 17:32:26 +0100
merge srvctrl into default branch
--- a/make/install.mk Fri Feb 24 11:17:53 2017 +0100 +++ b/make/install.mk Mon Mar 06 17:32:26 2017 +0100 @@ -46,7 +46,9 @@ sed s:%%WS_HOST%%:$(HOST):g ../templates/config/server.template > $(INSTALL_DIR)/config/server.conf @echo "copy binaries" cp ../build/bin/webservd$(APP_EXT) $(INSTALL_DIR)/bin/ + cp ../build/bin/wstool$(APP_EXT) $(INSTALL_DIR)/bin/ cp ../build/lib/libucx$(LIB_EXT) $(INSTALL_DIR)/lib/ + cp ../build/lib/libwscfg$(LIB_EXT) $(INSTALL_DIR)/lib/ @echo "copy includes" cp ../src/server/public/nsapi.h $(INSTALL_DIR)/include/nsapi.h cp ../src/server/public/auth.h $(INSTALL_DIR)/include/auth.h
--- a/src/Makefile Fri Feb 24 11:17:53 2017 +0100 +++ b/src/Makefile Mon Mar 06 17:32:26 2017 +0100 @@ -28,11 +28,17 @@ BUILD_ROOT = ../ -all: _ucx _server +all: ucx server tools -_ucx: +ucx: .FORCE cd ucx; $(MAKE) -_server: +server: ucx .FORCE cd server; $(MAKE) + +tools: server .FORCE + cd tools; $(MAKE) + +.FORCE: + \ No newline at end of file
--- a/src/server/Makefile Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/Makefile Mon Mar 06 17:32:26 2017 +0100 @@ -33,7 +33,9 @@ MAIN_TARGET = $(BUILD_ROOT)/build/bin/webservd -all: preparation $(MAIN_TARGET) $(PLUGINS) +LIB_WSCFG = $(BUILD_ROOT)/build/lib/libwscfg$(LIB_EXT) + +all: preparation $(MAIN_TARGET) $(LIB_WSCFG) $(PLUGINS) include util/objs.mk include safs/objs.mk @@ -65,6 +67,9 @@ $(MAIN_TARGET): $(MAINOBJS) $(CXX) -o $(MAIN_TARGET) $(MAINOBJS) -L$(BUILD_ROOT)/build/lib $(LDFLAGS) +$(LIB_WSCFG): $(CONFOBJS) + $(CC) $(SHLIB_LDFLAGS) -o $@ $(CONFOBJS) + ../../build/server/ucx/%.o: %.c $(CC) -o $@ -c $(CFLAGS) $<
--- a/src/server/config/Makefile Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/config/Makefile Mon Mar 06 17:32:26 2017 +0100 @@ -27,8 +27,5 @@ # $(CONF_OBJPRE)%.o: config/%.c - $(CC) -o $@ -c $(CFLAGS) $< + $(CC) -o $@ -c $(CFLAGS) $(SHLIB_CFLAGS) $< -$(CONF_OBJPRE)%.o: config/%.cpp - $(CXX) -o $@ -c $(CFLAGS) $< -
--- a/src/server/daemon/log.c Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/log.c Mon Mar 06 17:32:26 2017 +0100 @@ -36,6 +36,7 @@ #include <unistd.h> #include <aio.h> #include <time.h> +#include <pthread.h> #include "log.h" #include "../util/strbuf.h" @@ -43,12 +44,17 @@ #include "../util/atomic.h" #include <ucx/map.h> +#include <ucx/list.h> static int is_initialized = 0; static int log_file_fd; static int log_level = 0; +static uint32_t log_dup_count = 0; +static UcxList *log_dup_list = NULL; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + WSBool main_is_daemon(void); /* @@ -84,7 +90,8 @@ "failure", "catastrophe", "info", - "verbose" + "verbose", + "debug" }; static int can_log[] = { @@ -94,7 +101,8 @@ 1, // failure 1, // catastrophe 1, // info - 0 // verbose + 0, // verbose + 0 // debug }; int init_log_file(LogConfig *cfg) { @@ -114,10 +122,11 @@ can_log[LOG_INFORM] = 0; } else if(!strcmp(cfg->level, "WARNING")) { can_log[LOG_INFORM] = 0; - } else if(!strcmp(cfg->level, "INFO")) { - } else if(!strcmp(cfg->level, "VERBOSE")) { can_log[LOG_VERBOSE] = 1; + } else if(!strcmp(cfg->level, "DEBUG")) { + can_log[LOG_VERBOSE] = 1; + can_log[LOG_DEBUG] = 1; } if(cfg->log_stdout) { @@ -178,6 +187,21 @@ if(!main_is_daemon()) { writev(STDOUT_FILENO, io, 2); } + + if(log_dup_count > 0) { + char *msg = malloc(len + 1); + memcpy(msg, str, len); + msg[len] = '\n'; + + pthread_mutex_lock(&mutex); + UCX_FOREACH(elm, log_dup_list) { + LogDup *dup = elm->data; + dup->write(dup->cookie, msg, len + 1); + } + pthread_mutex_unlock(&mutex); + + free(msg); + } } sstr_t log_get_prefix(int level) { @@ -211,6 +235,27 @@ return d; } +void log_add_logdup(LogDup *dup) { + pthread_mutex_lock(&mutex); + log_dup_list = ucx_list_append(log_dup_list, dup); + ws_atomic_inc32(&log_dup_count); + pthread_mutex_unlock(&mutex); +} + +void log_remove_logdup(LogDup *ldup) { + pthread_mutex_lock(&mutex); + UcxList *elm = log_dup_list; + while(elm) { + if(elm->data == ldup) { + log_dup_list = ucx_list_remove(log_dup_list, elm); + ws_atomic_dec32(&log_dup_count); + break; + } + elm = elm->next; + } + pthread_mutex_unlock(&mutex); +} + /* * log api functions @@ -225,10 +270,10 @@ } int log_ereport_v(int degree, const char *format, va_list args) { - if(degree > 6) { + if(degree < 0 || degree > 7) { return 0; } - if(degree > 0 && !can_log[degree]) { + if(!can_log[degree]) { return 0; }
--- a/src/server/daemon/log.h Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/log.h Mon Mar 06 17:32:26 2017 +0100 @@ -31,6 +31,7 @@ #include "../public/nsapi.h" #include <ucx/string.h> +#include <ucx/utils.h> #include <inttypes.h> @@ -56,6 +57,11 @@ LogFile *log; } AccessLog; +typedef void (*log_writefunc)(void *cookie, char *msg, size_t length); +typedef struct { + log_writefunc write; + void *cookie; +} LogDup; // server logging int init_log_file(LogConfig *cfg); @@ -65,6 +71,8 @@ sstr_t log_get_prefix(int level); +void log_add_logdup(LogDup *dup); +void log_remove_logdup(LogDup *dup); // access logging LogFile* get_access_log_file(sstr_t file);
--- a/src/server/daemon/main.c Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/main.c Mon Mar 06 17:32:26 2017 +0100 @@ -39,10 +39,13 @@ #include "../util/plist.h" #include "../util/date.h" +#include "../../ucx/string.h" + #include "webserver.h" #include "log.h" #include "httprequest.h" #include "httplistener.h" +#include "srvctrl.h" #include "configmanager.h" @@ -81,7 +84,7 @@ */ void sig_term(int sig) { webserver_shutdown(); - exit(EXIT_SUCCESS); + //exit(EXIT_SUCCESS); } void* log_pipe_thread(void *data) { @@ -164,17 +167,22 @@ 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; } - + + if(srvctrl_wait()) { + return EXIT_FAILURE; + } + /* TODO: join threads (or not?) */ +/* while(1) { if(is_daemon) { fflush(stdout); @@ -185,6 +193,7 @@ break; } } +*/ return EXIT_SUCCESS; }
--- a/src/server/daemon/objs.mk Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/objs.mk Mon Mar 06 17:32:26 2017 +0100 @@ -44,6 +44,7 @@ DAEMONOBJ += sessionhandler.o DAEMONOBJ += vserver.o DAEMONOBJ += webserver.o +DAEMONOBJ += srvctrl.o DAEMONOBJ += ws-fn.o DAEMONOBJ += configmanager.o DAEMONOBJ += log.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/srvctrl.c Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,220 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include "log.h" +#include "webserver.h" + +#include "../util/systhr.h" + +#include "../../ucx/utils.h" +#include "../../ucx/buffer.h" + +#include "srvctrl.h" + +#define SRVCTRL_THREAD_STACKSIZE 8192 + +static int srvctrl; +static sstr_t srvctrl_path; + +static WSBool srv_shutdown; + +int srvctrl_init(ServerConfiguration *cfg) { + // create srvctrl unix domain socket + // this socket is used for stop, reconfigure and other operations + srvctrl_path = ucx_sprintf("%s/private/srvctrl.sock", cfg->tmp.ptr); + struct sockaddr_un addr; + if(srvctrl_path.length > sizeof(addr.sun_path)-1) { + log_ereport( + LOG_CATASTROPHE, + "path '%s' too long for unix domain socket", + srvctrl_path.ptr); + return -1; + } + + // make sure there is no old srvctrl socket file + // otherweise bind would fail + if(unlink(srvctrl_path.ptr)) { + if(errno != ENOENT) { + log_ereport( + LOG_CATASTROPHE, + "cannot unlink old srvctrl socket '%s': %s", + srvctrl_path.ptr, + strerror(errno)); + return -1; + } + } + + ZERO(&addr, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, srvctrl_path.ptr, srvctrl_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; + } + + return 0; +} + +int srvctrl_wait() { + listen(srvctrl, 8); + + for(;;) { + int fd = accept(srvctrl, NULL, 0); + if(fd < 0) { + if(srv_shutdown) break; + log_ereport( + LOG_FAILURE, + "srvctrl: accept failed: %s", + strerror(errno)); + break; + } + + SrvCtrlClient *client = srvctrl_create_client(fd); + SYS_THREAD t = systhread_start( + SYSTHREAD_DEFAULT_PRIORITY, + SRVCTRL_THREAD_STACKSIZE, + (thrstartfunc)srvctrl_thread, + client); + systhread_detach(t); + + } + + close(srvctrl); + unlink(srvctrl_path.ptr); + free(srvctrl_path.ptr); + + return 0; +} + +void srvctrl_shutdown() { + srv_shutdown = TRUE; + shutdown(srvctrl, SHUT_RDWR); +} + +SrvCtrlClient* srvctrl_create_client(int fd) { + SrvCtrlClient *client = malloc(sizeof(SrvCtrlClient)); + ZERO(client, sizeof(SrvCtrlClient)); + client->fd = fd; + return client; +} + +void* srvctrl_thread(SrvCtrlClient *client) { + LogDup log; + log.write = (log_writefunc)srvctrl_log; + log.cookie = client; + log_add_logdup(&log); + + char buf[64]; + UcxBuffer *line = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); + + ssize_t r; + WSBool br = FALSE; + while((r = read(client->fd, buf, 64)) > 0) { + for(int i=0;i<r;i++) { + char c = buf[i]; + if(c == '\n') { + sstr_t ln = sstrn(line->space, line->pos); + if(srvctrl_handle_cmd(client, ln)) { + br = TRUE; + break; + } + } else { + ucx_buffer_putc(line, c); + } + } + if(br) { + break; + } + } + log_remove_logdup(&log); + + ucx_buffer_free(line); + close(client->fd); + free(client); + return NULL; +} + +int srvctrl_handle_cmd(SrvCtrlClient *client, sstr_t cmd) { + if(!sstrcmp(cmd, S("reconfig"))) { + log_ereport(LOG_INFORM, "reconfigure server"); + if(webserver_reconfig()) { + log_ereport(LOG_FAILURE, "cannot reload config"); + } else { + log_ereport(LOG_INFORM, "reconfig: success"); + } + } else if(!sstrcmp(cmd, S("shutdown"))) { + webserver_shutdown(); + } else if(!sstrcmp(cmd, S("stat"))) { + // TODO: implement + } else if(!sstrcmp(cmd, S("log"))) { + return 0; + } else { + log_ereport( + LOG_FAILURE, + "unknown srvctrl command: %.*s", + (int)cmd.length, + cmd.ptr); + } + return 1; +} + +void srvctrl_log(SrvCtrlClient *client, char *msg, size_t len) { + char msgheader[4]; + msgheader[0] = SRV_MSG_LOG; + uint16_t msglen = len; + memcpy(&msgheader[1], &msglen, 2); + write(client->fd, msgheader, 3); + + size_t pos = 0; + ssize_t w = 0; + while(pos < len) { + w = write(client->fd, msg + pos, len - pos); + if(w <= 0) { + break; + } + pos += w; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/srvctrl.h Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,67 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRVCTRL_H +#define SRVCTRL_H + +#include "../public/nsapi.h" + +#include "../../ucx/string.h" + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRV_MSG_RESPONSE 0 +#define SRV_MSG_LOG 1 + +typedef struct { + int fd; +} SrvCtrlClient; + +int srvctrl_init(ServerConfiguration *cfg); + +int srvctrl_wait(); + +void srvctrl_shutdown(); + +SrvCtrlClient* srvctrl_create_client(int fd); + +void* srvctrl_thread(SrvCtrlClient *client); +int srvctrl_handle_cmd(SrvCtrlClient *client, sstr_t cmd); +void srvctrl_log(SrvCtrlClient *client, char *msg, size_t len); + + +#ifdef __cplusplus +} +#endif + +#endif /* SRVCTRL_H */ +
--- a/src/server/daemon/webserver.c Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/webserver.c Mon Mar 06 17:32:26 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" @@ -57,6 +59,7 @@ #include "webserver.h" #include "log.h" #include "auth.h" +#include "srvctrl.h" extern struct FuncStruct webserver_funcs[]; @@ -91,20 +94,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 +157,50 @@ "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 + if(srvctrl_init(cfg)) { + return -1; + } + //endpwent(); // TODO: close or not? //free(pwbuf); // TODO: ? @@ -190,6 +223,8 @@ void webserver_shutdown() { log_ereport(LOG_INFORM, "webserver shutdown"); + srvctrl_shutdown(); + // execute restart callbacks RestartCallback *re = atrestart; while(re) { @@ -198,6 +233,16 @@ } } +int webserver_reconfig() { + if(cfgmgr_load_config(NULL) != 0) { + return -1; + } + // start newly created listeners + start_all_listener(); + + return 0; +} + void webserver_atrestart(void (*fn)(void *), void *data) { RestartCallback *cb = malloc(sizeof(RestartCallback)); cb->func = fn;
--- a/src/server/daemon/webserver.h Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/daemon/webserver.h Mon Mar 06 17:32:26 2017 +0100 @@ -45,6 +45,7 @@ int webserver_init(); int webserver_run(); void webserver_shutdown(); +int webserver_reconfig(); void webserver_atrestart(void (*fn)(void *), void *data);
--- a/src/server/plugins/java/Makefile Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/plugins/java/Makefile Mon Mar 06 17:32:26 2017 +0100 @@ -60,7 +60,7 @@ $(CC) -o $(NSAPI_JNI_LIB) $(JNI_OBJS) $(LDFLAGS) $(JAVA_WSRT): $(JAVASRC) - ant -Dbuild.compiler=javac1.7 compile jar + ant compile jar ../../../../build/server/plugins/java/%.o: %.c
--- a/src/server/public/nsapi.h Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/public/nsapi.h Mon Mar 06 17:32:26 2017 +0100 @@ -176,6 +176,9 @@ */ #define LOG_VERBOSE 6 +// new +#define LOG_DEBUG 7 + /* * The time format to use in the error log */
--- a/src/server/util/system.c Fri Feb 24 11:17:53 2017 +0100 +++ b/src/server/util/system.c Mon Mar 06 17:32:26 2017 +0100 @@ -401,4 +401,4 @@ #endif } -*/ \ No newline at end of file +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/Makefile Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,51 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2013 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +BUILD_ROOT = ../.. + +include $(BUILD_ROOT)/config.mk + +CFLAGS += -I.. +LDFLAGS += -L../../build/lib -lucx -lwscfg + +# list of source files +WSTOOL_SRC = wstool.c +WSTOOL_SRC += srvctrlsocket.c + +WSTOOL_OBJ = $(WSTOOL_SRC:%.c=$(BUILD_ROOT)/build/tools/%$(OBJ_EXT)) + +all: $(BUILD_ROOT)/build/tools $(BUILD_ROOT)/build/bin/wstool + +$(BUILD_ROOT)/build/bin/wstool: $(BUILD_ROOT)/build/tools $(WSTOOL_OBJ) + $(CC) -o $@ $(WSTOOL_OBJ) $(LDFLAGS) + +$(BUILD_ROOT)/build/tools/%$(OBJ_EXT): %.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_ROOT)/build/tools: + mkdir -p $(BUILD_ROOT)/build/tools
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/srvctrlsocket.c Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,112 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "srvctrlsocket.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> + +SrvConnection* srvctrl_connet(char *socketfile) { + if(!socketfile) { + fprintf(stderr, "srvctrl_connect: no socketfile\n"); + return NULL; + } + size_t len = strlen(socketfile); + if(len == 0) { + fprintf(stderr, "srvctrl_connect: invalid socket path\n"); + return NULL; + } + if(len > 100) { + fprintf(stderr, "srvctrl_connect: socket path too long\n"); + return NULL; + } + + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(fd == -1) { + perror("srvctrl_connect: cannot create socket"); + return NULL; + } + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, socketfile, len); + + if(connect(fd, (struct sockaddr*)&addr, sizeof(addr))) { + perror("srvctrl_connect"); + close(fd); + return NULL; + } + + FILE *stream = fdopen(fd, "r+"); + if(!stream) { + close(fd); + return NULL; + } + + SrvConnection *conn = calloc(1, sizeof(SrvConnection)); + conn->socket = fd; + conn->stream = stream; + + return conn; +} + +void srvctrl_close(SrvConnection *conn) { + fclose(conn->stream); + free(conn); +} + +int srvctrl_readmsg(SrvConnection *conn, SrvMsg *msg) { + int type = 0; + uint16_t length; + + type = fgetc(conn->stream); + if(type == EOF) { + return 1; + } + + if(fread(&length, 1, 2, conn->stream) != 2) { + return -1; + } + + msg->type = type; + msg->length = length; + msg->message = malloc(length); + + size_t r = fread(msg->message, 1, length, conn->stream); + if(r != length) { + free(msg->message); + return -1; + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/srvctrlsocket.h Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,75 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRVCTRLSOCKET_H +#define SRVCTRLSOCKET_H + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SrvConnection { + int socket; + FILE *stream; +} SrvConnection; + +typedef struct SrvMsg { + /* + * message type + * 0: cmd response + * 1: log message + */ + int type; + + /* + * message data + */ + char *message; + + /* + * message length + */ + size_t length; +} SrvMsg; + +SrvConnection* srvctrl_connet(char *socketfile); + +void srvctrl_close(SrvConnection *conn); + +int srvctrl_readmsg(SrvConnection *conn, SrvMsg *msg); + +#ifdef __cplusplus +} +#endif + +#endif /* SRVCTRLSOCKET_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/wstool.c Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,123 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wstool.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../server/config/serverconf.h" + +#include "srvctrlsocket.h" + +static void print_info(char *cmd) { + fprintf(stderr, "usage:\n"); + fprintf(stderr, "%s -t <srvconfigfile>\n", cmd); + fprintf(stderr, "%s -s <socketpath> <command>\n", cmd); + fprintf(stderr, "Commands: reconfig, shutdown, stat, log\n"); +} + +int main(int argc, char **argv) { + if(argc > 2) { + if(!strcmp(argv[1], "-t")) { + return tool_get_tmpdir(argv[2]); + } else if(!strcmp(argv[1], "-s")) { + if(argc != 4) { + print_info(argv[0]); + return -2; + } + return tool_srvctrl(argv[2], argv[3]); + } + } + + print_info(argv[0]); + return -2; +} + +int tool_get_tmpdir(char *configfile) { + ServerConfig *serverconf = load_server_config(configfile); + UcxList *list = ucx_map_sstr_get(serverconf->objects, sstrn("Runtime", 7)); + if(!list) { + fprintf(stderr, "Error: No Runtime element in %s\n", configfile); + return -1; + } + if(ucx_list_size(list) != 1) { + fprintf(stderr, "Error: Multiple Runtime elements in %s\n", configfile); + return -1; + } + ServerConfigObject *runtime = list->data; + sstr_t tmp = cfg_directivelist_get_str(runtime->directives, sstr("Temp")); + if(!tmp.ptr) { + fprintf(stderr, "Error: No Temp directive in Runtime Object\n"); + return -1; + } + + printf("%.*s\n", (int)tmp.length, tmp.ptr); + + return 0; +} + +int tool_srvctrl(char *socketfile, char *cmd) { + SrvConnection *srv = srvctrl_connet(socketfile); + if(!srv) { + return -1; + } + + fprintf(srv->stream, "%s\n", cmd); + fflush(srv->stream); + + SrvMsg msg; + while(!srvctrl_readmsg(srv, &msg)) { + if(msg.type == 0) { + fprintf(stdout, "%.*s", (int)msg.length, msg.message); + fflush(stdout); + } else if(msg.type == 1) { + fprintf(stderr, "%.*s", (int)msg.length, msg.message); + fflush(stderr); + } + } + + srvctrl_close(srv); + + return 0; +} + + + +int log_ereport(int degree, const char *format, ...) { + va_list args; + va_start(args, format); + int ret = log_ereport_v(degree, format, args); + va_end(args); + return ret; +} + +int log_ereport_v(int degree, const char *format, va_list args) { + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/wstool.h Mon Mar 06 17:32:26 2017 +0100 @@ -0,0 +1,50 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WSTOOL_H +#define WSTOOL_H + +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int tool_get_tmpdir(char *configfile); + +int tool_srvctrl(char *socketfile, char *cmd); + +int log_ereport(int degree, const char *format, ...); +int log_ereport_v(int degree, const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* WSTOOL_H */ +
--- a/templates/bin/reconfig.template Fri Feb 24 11:17:53 2017 +0100 +++ b/templates/bin/reconfig.template Mon Mar 06 17:32:26 2017 +0100 @@ -1,6 +1,57 @@ #!/bin/sh -PID=`cat /tmp/webserver-rw6pgl8b/pid` +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2017 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# -kill -USR1 $PID +WS_INSTALL_DIR=%%WS_INSTALL_DIR%% + +cd $WS_INSTALL_DIR + +WS_TMP_DIR=`bin/wstool -t config/server.conf` +if [ $? -ne 0 ]; then + exit 1 +fi +WS_PID=`cat $WS_TMP_DIR/pid 2> /dev/null` +if [ $? -ne 0 ]; then + echo "cannot get server pid" + exit 1 +fi +if [ -z $WS_PID ]; then + echo "cannot get server pid" + exit 1 +fi + +kill -0 $WS_PID 2> /dev/null +if [ $? -ne 0 ]; then + echo "server not running" + exit 1 +fi + +bin/wstool -s $WS_TMP_DIR/private/srvctrl.sock reconfig +
--- a/templates/bin/startserv.template Fri Feb 24 11:17:53 2017 +0100 +++ b/templates/bin/startserv.template Mon Mar 06 17:32:26 2017 +0100 @@ -3,7 +3,7 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. # -# Copyright 2011 Olaf Wintermann. All rights reserved. +# Copyright 2017 Olaf Wintermann. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met:
--- a/templates/bin/stopserv.template Fri Feb 24 11:17:53 2017 +0100 +++ b/templates/bin/stopserv.template Mon Mar 06 17:32:26 2017 +0100 @@ -1,6 +1,56 @@ #!/bin/sh -PID=`cat /tmp/webserver-rw6pgl8b/pid` +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2017 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# -kill -TERM $PID +WS_INSTALL_DIR=%%WS_INSTALL_DIR%% + +cd $WS_INSTALL_DIR + +WS_TMP_DIR=`bin/wstool -t config/server.conf` +if [ $? -ne 0 ]; then + exit 1 +fi +WS_PID=`cat $WS_TMP_DIR/pid 2> /dev/null` +if [ $? -ne 0 ]; then + echo "cannot get server pid" + exit 1 +fi +if [ -z $WS_PID ]; then + echo "cannot get server pid" + exit 1 +fi + +kill -0 $WS_PID 2> /dev/null +if [ $? -ne 0 ]; then + echo "server not running" + exit 1 +fi + +bin/wstool -s $WS_TMP_DIR/private/srvctrl.sock shutdown