Sun, 06 May 2012 10:09:27 +0200
added logging
--- a/src/server/daemon/config.c Mon Feb 27 17:20:42 2012 +0100 +++ b/src/server/daemon/config.c Sun May 06 10:09:27 2012 +0200 @@ -42,6 +42,7 @@ #include "httplistener.h" #include "config.h" #include "func.h" +#include "log.h" #include "configmanager.h" #include "vserver.h" @@ -195,9 +196,25 @@ } int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj) { - /* TODO: log files */ + sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); + sstr_t lvl = cfg_directivelist_get_str(obj->directives, sstr("Level")); + + if(file.ptr == NULL || lvl.ptr == NULL) { + /* missing log file parameters */ + return -1; + } + + LogConfig logcfg; + logcfg.file = sstrdup(file).ptr; + logcfg.level = sstrdub(lvl).ptr; + /* TODO: stdout, stderr config */ + + int ret = init_log_file(&logcfg); + + free(logcfg.file); + free(logcfg.level); - return 0; + return ret; } int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/log.c Sun May 06 10:09:27 2012 +0200 @@ -0,0 +1,212 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 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 <string.h> +#include <unistd.h> +#include <aio.h> +#include <time.h> + +#include "log.h" +#include "../util/strbuf.h" + +int is_initialized = 0; + +int log_file_fd; +int log_level = 0; + +/* + * if the log file is uninitialized, output is written to the ui_buffer + */ +sbuf_t *ui_buffer = NULL; + +char *log_date_month[] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" +}; + +char *log_levels[] = { + "error", + "warning", + "info" +}; + +int init_log_file(LogConfig *cfg) { + if(is_initialized) { + return 0; + } + + /* open the log file */ + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + log_file_fd = open(cfg->file, O_WRONLY | O_CREAT | O_APPEND, mode); + if(log_file_fd == -1) { + return -1; + } + + if(!strcmp(cfg->level, "ERROR")) { + log_level = LOG_LEVEL_ERROR; + } else if(!strcmp(cfg->level, "WARNING")) { + log_level = LOG_LEVEL_WARNING; + } else if(!strcmp(cfg->level, "INFO")) { + log_level = LOG_LEVEL_INFO; + } + + if(cfg->log_stdout) { + // TODO + } + if(cfg->log_stderr) { + // TODO + } + + + is_initialized = 1; + + /* if ui_buffer is not NULL, write it to the log file */ + if(ui_buffer) { + size_t len = ui_buffer->length; + size_t r; + while(len > 0) { + r = write(log_file_fd, ui_buffer->ptr, ui_buffer->length); + len -= r; + } + + sbuf_free(ui_buffer); + } + + return 0; +} + +void log_uninitialized_writeln(char *str, size_t len) { + if(ui_buffer == NULL) { + ui_buffer = sbuf_new(1024); + if(ui_buffer == NULL) { + return; /* TODO: critical error, exit */ + } + } + + sstr_t s; + s.ptr = str; + s.length = len; + + sbuf_append(ui_buffer, s); + sbuf_put(ui_buffer, '\n'); +} + +void log_file_writeln(char *str, size_t len) { + if(!is_initialized) { + log_uninitialized_writeln(str, len); + } + + struct iovec io[] = { + { str, len }, + { "\n", 1} + }; + + writev(log_file_fd, io, 2); /* TODO: aio */ +} + +sstr_t log_get_prefix(int level) { + time_t t = time(NULL); + + sstr_t d; + d.ptr = NULL; + d.length = 0; + + struct tm date; + localtime_r(&t, &date); + + char *buf = malloc(64); + int len = snprintf( + buf, + 64, + "[%02d/%s/%d:%02d:%02d:%02d] %s : ", + date.tm_mday, + log_date_month[date.tm_mon], + 1900 + date.tm_year, + date.tm_hour, + date.tm_min, + date.tm_sec, + log_levels[level]); + + if(len > 0) { + d.ptr = buf; + d.length = len; + } + + return d; +} + + +/* + * log api functions + */ + +int log_ereport(int degree, const char *format, ...) { + if(degree > log_level) { + return 0; + } + + sstr_t lmsg; + lmsg.ptr = NULL; + va_list ap; + va_start(ap, format); + + /* create log message prefix */ + sstr_t lpre = log_get_prefix(degree); + + /* format message */ + int len = vasprintf(&lmsg.ptr, format, ap); + lmsg.length = len; + + /* create message string */ + sstr_t message; + message.length = lpre.length + len; + message.ptr = malloc(message.length + 1); + + message = sstrncat(2, message, lpre, lmsg); + + /* write message to the log file */ + log_file_writeln(message.ptr, message.length); + + /* cleanup */ + free(lmsg.ptr); + free(message.ptr); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/log.h Sun May 06 10:09:27 2012 +0200 @@ -0,0 +1,66 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 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 LOG_H +#define LOG_H + +#include "../public/nsapi.h" +#include "../ucx/string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOG_LEVEL_ERROR 0 +#define LOG_LEVEL_WARNING 1 +#define LOG_LEVEL_INFO 2 + +typedef struct { + char *file; + char *level; + int log_stdout; + int log_stderr; +} LogConfig; + +int init_log_file(LogConfig *cfg); + +void log_uninitialized_writeln(char *str, size_t len); + +void log_file_writeln(char *str, size_t len); + +sstr_t log_get_prefix(int level); + +int log_ereport(int degree, const char *format, ...); + + +#ifdef __cplusplus +} +#endif + +#endif /* LOG_H */ +
--- a/src/server/daemon/objs.mk Mon Feb 27 17:20:42 2012 +0100 +++ b/src/server/daemon/objs.mk Sun May 06 10:09:27 2012 +0200 @@ -44,6 +44,7 @@ DAEMONOBJ += webserver.o DAEMONOBJ += ws-fn.o DAEMONOBJ += configmanager.o +DAEMONOBJ += log.o DAEMONOBJS = $(DAEMONOBJ:%=$(DMN_OBJPRE)%) DAEMONSOURCE = $(DAEMONOBJ:%.o=daemon/%.c)
--- a/src/server/daemon/webserver.c Mon Feb 27 17:20:42 2012 +0100 +++ b/src/server/daemon/webserver.c Sun May 06 10:09:27 2012 +0200 @@ -38,6 +38,7 @@ #include "configmanager.h" #include "httplistener.h" #include "webserver.h" +#include "log.h" extern struct FuncStruct webserver_funcs[]; @@ -46,7 +47,7 @@ int webserver_init() { // init NSPR systhread_init("webserver"); - + // init NSAPI functions func_init(); add_functions(webserver_funcs); @@ -78,7 +79,7 @@ // init NSAPI functions - + return 0; }
--- a/src/server/ucx/string.c Mon Feb 27 17:20:42 2012 +0100 +++ b/src/server/ucx/string.c Sun May 06 10:09:27 2012 +0200 @@ -99,6 +99,16 @@ return newstring; } +sstr_t sstrdup(sstr_t s) { + sstr_t newstring; + newstring.ptr = malloc(s.length + 1); + newstring.length = s.length; + newstring.ptr[newstring.length] = 0; + + memcpy(newstring.ptr, s.ptr, s.length); + + return newstring; +} // webserver extension sstr_t sstrtrim(sstr_t string) {
--- a/src/server/ucx/string.h Mon Feb 27 17:20:42 2012 +0100 +++ b/src/server/ucx/string.h Sun May 06 10:09:27 2012 +0200 @@ -72,6 +72,7 @@ int sstrcmp(sstr_t s1, sstr_t s2); sstr_t sstrdub(sstr_t s); +sstr_t sstrdup(sstr_t s); sstr_t sstrtrim(sstr_t string); sstr_t sstrdup_mp(UcxMempool *mp, sstr_t s);