From c52d0879cc03345a6c41c724db6a3de59cca7d07 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 26 Oct 2008 06:53:05 +0300 Subject: [PATCH] * Add main logging functions (log to file, syslog and console) * Handle log reopening --- cfg_file.h | 12 ++++++ cfg_file.l | 14 +++++++ cfg_file.y | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 29 +++++++++++++++ main.h | 2 + util.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ util.h | 5 +++ worker.c | 1 + 8 files changed, 265 insertions(+) diff --git a/cfg_file.h b/cfg_file.h index d664a15f0..1eb71476d 100644 --- a/cfg_file.h +++ b/cfg_file.h @@ -60,6 +60,12 @@ enum rspamd_regexp_type { REGEXP_URL, }; +enum rspamd_log_type { + RSPAMD_LOG_CONSOLE, + RSPAMD_LOG_SYSLOG, + RSPAMD_LOG_FILE, +}; + struct rspamd_regexp { enum rspamd_regexp_type type; char *regexp_text; @@ -107,6 +113,12 @@ struct config_file { int no_fork; unsigned int workers_number; + enum rspamd_log_type log_type; + int log_facility; + int log_level; + char *log_file; + int log_fd; + struct memcached_server memcached_servers[MAX_MEMCACHED_SERVERS]; size_t memcached_servers_num; memc_proto_t memcached_protocol; diff --git a/cfg_file.l b/cfg_file.l index e52f2585b..fefd11237 100644 --- a/cfg_file.l +++ b/cfg_file.l @@ -49,6 +49,20 @@ required_score return REQUIRED_SCORE; function return FUNCTION; control return CONTROL; password return PASSWORD; +logging return LOGGING; + +log_type return LOG_TYPE; +console return LOG_TYPE_CONSOLE; +syslog return LOG_TYPE_SYSLOG; +file return LOG_TYPE_FILE; + +log_level return LOG_LEVEL; +DEBUG return LOG_LEVEL_DEBUG; +INFO return LOG_LEVEL_INFO; +WARNING return LOG_LEVEL_WARNING; +ERROR return LOG_LEVEL_ERROR; +log_facility return LOG_FACILITY; +log_file return LOG_FILENAME; \{ return OBRACE; \} return EBRACE; diff --git a/cfg_file.y b/cfg_file.y index 1ccb928b7..1838c0f6e 100644 --- a/cfg_file.y +++ b/cfg_file.y @@ -50,6 +50,8 @@ struct metric *cur_metric = NULL; %token MODULE_OPT PARAM VARIABLE %token HEADER_FILTERS MIME_FILTERS MESSAGE_FILTERS URL_FILTERS FACTORS METRIC NAME %token REQUIRED_SCORE FUNCTION FRACT COMPOSITES CONTROL PASSWORD +%token LOGGING LOG_TYPE LOG_TYPE_CONSOLE LOG_TYPE_SYSLOG LOG_TYPE_FILE +%token LOG_LEVEL LOG_LEVEL_DEBUG LOG_LEVEL_INFO LOG_LEVEL_WARNING LOG_LEVEL_ERROR LOG_FACILITY LOG_FILENAME %type STRING %type VARIABLE @@ -88,6 +90,7 @@ command : | factors | metric | composites + | logging ; tempdir : @@ -435,6 +438,110 @@ variable: } ; +logging: + LOGGING OBRACE loggingbody EBRACE + ; + +loggingbody: + loggingcmd SEMICOLON + | loggingbody loggingcmd SEMICOLON + ; + +loggingcmd: + loggingtype + | logginglevel + | loggingfacility + | loggingfile + ; + +loggingtype: + LOG_TYPE EQSIGN LOG_TYPE_CONSOLE { + cfg->log_type = RSPAMD_LOG_CONSOLE; + } + LOG_TYPE EQSIGN LOG_TYPE_SYSLOG { + cfg->log_type = RSPAMD_LOG_SYSLOG; + } + LOG_TYPE EQSIGN LOG_TYPE_FILE { + cfg->log_type = RSPAMD_LOG_FILE; + } + ; + +logginglevel: + LOG_LEVEL EQSIGN LOG_LEVEL_DEBUG { + cfg->log_level = G_LOG_LEVEL_DEBUG; + } + LOG_LEVEL EQSIGN LOG_LEVEL_INFO { + cfg->log_level = G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE; + } + LOG_LEVEL EQSIGN LOG_LEVEL_WARNING { + cfg->log_level = G_LOG_LEVEL_WARNING; + } + LOG_LEVEL EQSIGN LOG_LEVEL_ERROR { + cfg->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL; + } + ; + +loggingfacility: + LOG_FACILITY EQSIGN QUOTEDSTRING { + if (strncasecmp ($3, "LOG_AUTH", sizeof ("LOG_AUTH") - 1) == 0) { + cfg->log_facility = LOG_AUTH; + } + else if (strncasecmp ($3, "LOG_CONSOLE", sizeof ("LOG_CONSOLE") - 1) == 0) { + cfg->log_facility = LOG_CONSOLE; + } + else if (strncasecmp ($3, "LOG_CRON", sizeof ("LOG_CRON") - 1) == 0) { + cfg->log_facility = LOG_CRON; + } + else if (strncasecmp ($3, "LOG_DAEMON", sizeof ("LOG_DAEMON") - 1) == 0) { + cfg->log_facility = LOG_DAEMON; + } + else if (strncasecmp ($3, "LOG_MAIL", sizeof ("LOG_MAIL") - 1) == 0) { + cfg->log_facility = LOG_MAIL; + } + else if (strncasecmp ($3, "LOG_USER", sizeof ("LOG_USER") - 1) == 0) { + cfg->log_facility = LOG_USER; + } + else if (strncasecmp ($3, "LOG_LOCAL0", sizeof ("LOG_LOCAL0") - 1) == 0) { + cfg->log_facility = LOG_LOCAL0; + } + else if (strncasecmp ($3, "LOG_LOCAL1", sizeof ("LOG_LOCAL1") - 1) == 0) { + cfg->log_facility = LOG_LOCAL1; + } + else if (strncasecmp ($3, "LOG_LOCAL2", sizeof ("LOG_LOCAL2") - 1) == 0) { + cfg->log_facility = LOG_LOCAL2; + } + else if (strncasecmp ($3, "LOG_LOCAL3", sizeof ("LOG_LOCAL3") - 1) == 0) { + cfg->log_facility = LOG_LOCAL3; + } + else if (strncasecmp ($3, "LOG_LOCAL4", sizeof ("LOG_LOCAL4") - 1) == 0) { + cfg->log_facility = LOG_LOCAL4; + } + else if (strncasecmp ($3, "LOG_LOCAL5", sizeof ("LOG_LOCAL5") - 1) == 0) { + cfg->log_facility = LOG_LOCAL5; + } + else if (strncasecmp ($3, "LOG_LOCAL6", sizeof ("LOG_LOCAL6") - 1) == 0) { + cfg->log_facility = LOG_LOCAL6; + } + else if (strncasecmp ($3, "LOG_LOCAL7", sizeof ("LOG_LOCAL7") - 1) == 0) { + cfg->log_facility = LOG_LOCAL7; + } + else { + yyerror ("yyparse: invalid logging facility: %s", $3); + YYERROR; + } + + free ($3); + } + ; + +loggingfile: + LOG_FILENAME EQSIGN QUOTEDSTRING { + cfg->log_file = memory_pool_strdup (cfg->cfg_pool, $3); + + free ($3); + } + ; + %% /* * vi:ts=4 diff --git a/main.c b/main.c index a88662085..81effd61d 100644 --- a/main.c +++ b/main.c @@ -48,6 +48,7 @@ void sig_handler (int signo) switch (signo) { case SIGHUP: do_restart = 1; + do_reopen_log = 1; break; case SIGINT: case SIGTERM: @@ -182,6 +183,7 @@ main (int argc, char **argv) do_restart = 0; child_dead = 0; child_ready = 0; + do_reopen_log = 0; active_worker = NULL; bzero (rspamd->cfg, sizeof (struct config_file)); @@ -225,6 +227,33 @@ main (int argc, char **argv) } } + switch (cfg->log_type) { + case RSPAMD_LOG_CONSOLE: + if (!rspamd->cfg->no_fork) { + fprintf (stderr, "Cannot log to console while daemonized, disable logging"); + cfg->log_fd = -1; + } + else { + cfg->log_fd = 2; + } + g_log_set_default_handler (file_log_function, cfg); + break; + case RSPAMD_LOG_FILE: + if (cfg->log_file == NULL || open_log (cfg) == -1) { + fprintf (stderr, "Fatal error, cannot open logfile, exiting"); + exit (EXIT_FAILURE); + } + g_log_set_default_handler (file_log_function, cfg); + break; + case RSPAMD_LOG_SYSLOG: + if (open_log (cfg) == -1) { + fprintf (stderr, "Fatal error, cannot open syslog facility, exiting"); + exit (EXIT_FAILURE); + } + g_log_set_default_handler (syslog_log_function, cfg); + break; + } + if (!rspamd->cfg->no_fork && daemon (1, 1) == -1) { fprintf (stderr, "Cannot daemonize\n"); exit (-errno); diff --git a/main.h b/main.h index 3c519463f..3a4671bfb 100644 --- a/main.h +++ b/main.h @@ -179,6 +179,8 @@ struct c_module { void start_worker (struct rspamd_worker *worker, int listen_sock); void start_controller (struct rspamd_worker *worker); +extern sig_atomic_t do_reopen_log; + #endif /* diff --git a/util.c b/util.c index b0d40daf0..90a536359 100644 --- a/util.c +++ b/util.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "config.h" #ifdef HAVE_LIBUTIL_H @@ -17,6 +19,8 @@ #include "util.h" #include "cfg_file.h" +sig_atomic_t do_reopen_log = 0; + int event_make_socket_nonblocking (int fd) { @@ -734,6 +738,97 @@ parse_expression (memory_pool_t *pool, char *line) return expr; } +/* Logging utility functions */ +int +open_log (struct config_file *cfg) +{ + switch (cfg->log_type) { + case RSPAMD_LOG_CONSOLE: + /* Do nothing with console */ + return 0; + case RSPAMD_LOG_SYSLOG: + openlog ("rspamd", LOG_NDELAY | LOG_PID, cfg->log_facility); + return 0; + case RSPAMD_LOG_FILE: + cfg->log_fd = open (cfg->log_file, O_CREAT | O_WRONLY | O_APPEND); + if (cfg->log_fd == -1) { + msg_err ("open_log: cannot open desired log file: %s, %m", cfg->log_file); + return -1; + } + return 0; + } +} + +int +reopen_log (struct config_file *cfg) +{ + do_reopen_log = 0; + switch (cfg->log_type) { + case RSPAMD_LOG_CONSOLE: + /* Do nothing with console */ + return 0; + case RSPAMD_LOG_SYSLOG: + closelog (); + break; + case RSPAMD_LOG_FILE: + close (cfg->log_fd); + break; + } + return open_log (cfg); +} + +void +syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) +{ + struct config_file *cfg = (struct config_file *)arg; + if (do_reopen_log) { + reopen_log (cfg); + } + + if (log_level <= cfg->log_level) { + if (log_level >= G_LOG_LEVEL_DEBUG) { + syslog (LOG_DEBUG, message); + } + else if (log_level >= G_LOG_LEVEL_INFO) { + syslog (LOG_INFO, message); + } + else if (log_level >= G_LOG_LEVEL_WARNING) { + syslog (LOG_WARNING, message); + } + else if (log_level >= G_LOG_LEVEL_CRITICAL) { + syslog (LOG_ERR, message); + } + } +} + +void +file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) +{ + struct config_file *cfg = (struct config_file *)arg; + char tmpbuf[128]; + int r; + struct iovec out[3]; + + if (cfg->log_fd == -1) { + return; + } + + if (do_reopen_log) { + reopen_log (cfg); + } + + if (log_level <= cfg->log_level) { + r = snprintf (tmpbuf, sizeof (tmpbuf), "#%d: %d rspamd ", (int)getpid (), (int)time (NULL)); + out[0].iov_base = tmpbuf; + out[0].iov_len = r; + out[1].iov_base = (char *)message; + out[1].iov_len = strlen (message); + out[2].iov_base = "\r\n"; + out[2].iov_len = 2; + + writev (cfg->log_fd, out, sizeof (out) / sizeof (out[0])); + } +} /* * vi:ts=4 */ diff --git a/util.h b/util.h index e88521281..1791f4635 100644 --- a/util.h +++ b/util.h @@ -52,4 +52,9 @@ int pidfile_close(struct pidfh *pfh); int pidfile_remove(struct pidfh *pfh); #endif +int open_log (struct config_file *cfg); +int reopen_log (struct config_file *cfg); +void syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg); +void file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg); + #endif diff --git a/worker.c b/worker.c index efa95c105..741a351a1 100644 --- a/worker.c +++ b/worker.c @@ -59,6 +59,7 @@ sigusr_handler (int fd, short what, void *arg) tv.tv_usec = 0; event_del (&worker->sig_ev); event_del (&worker->bind_ev); + do_reopen_log = 1; msg_info ("worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME); event_loopexit (&tv); return; -- 2.39.5