RSPAMD_LOG_FLAG_USEC = (1 << 3),
RSPAMD_LOG_FLAG_RSPAMADM = (1 << 4),
RSPAMD_LOG_FLAG_ENFORCED = (1 << 5),
- RSPAMD_LOG_FLAG_TTY = (1 << 6),
};
struct rspamd_worker_log_pipe {
${CMAKE_CURRENT_SOURCE_DIR}/http_context.c
${CMAKE_CURRENT_SOURCE_DIR}/logger.c
${CMAKE_CURRENT_SOURCE_DIR}/logger_file.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger_syslog.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger_console.c
${CMAKE_CURRENT_SOURCE_DIR}/map.c
${CMAKE_CURRENT_SOURCE_DIR}/map_helpers.c
${CMAKE_CURRENT_SOURCE_DIR}/mem_pool.c
#include "unix-std.h"
#include "logger_private.h"
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-
static rspamd_logger_t *default_logger = NULL;
static struct rspamd_log_modules *log_modules = NULL;
}
logger->log_type = cfg->log_type;
- logger->log_facility = cfg->log_facility;
if (!(logger->flags & RSPAMD_LOG_FLAG_ENFORCED)) {
logger->log_level = cfg->log_level;
rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *rspamd_log)
{
rspamd_log->pid = getpid ();
- rspamd_log->process_type = ptype;
-
- /* We also need to clear all messages pending */
- if (rspamd_log->repeats > 0) {
- rspamd_log->repeats = 0;
- if (rspamd_log->saved_message) {
- g_free (rspamd_log->saved_message);
- g_free (rspamd_log->saved_function);
- g_free (rspamd_log->saved_module);
- g_free (rspamd_log->saved_id);
- rspamd_log->saved_message = NULL;
- rspamd_log->saved_function = NULL;
- rspamd_log->saved_module = NULL;
- rspamd_log->saved_id = NULL;
- }
- }
-}
-
-/**
- * Flush logging buffer
- */
-void
-rspamd_log_flush (rspamd_logger_t *rspamd_log)
-{
- if (rspamd_log->is_buffered &&
- (rspamd_log->type == RSPAMD_LOG_CONSOLE ||
- rspamd_log->type == RSPAMD_LOG_FILE)) {
- direct_write_log_line (rspamd_log,
- rspamd_log->io_buf.buf,
- rspamd_log->io_buf.used,
- FALSE, rspamd_log->log_level);
- rspamd_log->io_buf.used = 0;
- }
+ rspamd_log->process_type = g_quark_to_string (ptype);
}
static inline gboolean
};
typedef struct rspamd_logger_s rspamd_logger_t;
-typedef void (*rspamd_log_func_t) (const gchar *module, const gchar *id,
+typedef bool (*rspamd_log_func_t) (const gchar *module, const gchar *id,
const gchar *function,
gint level_flags,
const gchar *message,
/**
* Open log file or initialize other structures
*/
-gint rspamd_log_open (rspamd_logger_t *logger);
+bool rspamd_log_open (rspamd_logger_t *logger);
/**
* Close log file or destroy other structures
*/
-void rspamd_log_close (rspamd_logger_t *logger, gboolean termination);
+bool rspamd_log_close (rspamd_logger_t *logger, gboolean termination);
/**
* Close and open log again
*/
-gint rspamd_log_reopen (rspamd_logger_t *logger);
+bool rspamd_log_reopen (rspamd_logger_t *logger);
/**
* Open log file or initialize other structures for privileged processes
*/
-gint rspamd_log_open_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
+bool rspamd_log_open_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
/**
* Close log file or destroy other structures for privileged processes
/**
* Close and open log again for privileged processes
*/
-gint rspamd_log_reopen_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
+bool rspamd_log_reopen_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
/**
* Set log pid
*/
void rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *logger);
-/**
- * Flush log buffer for some types of logging
- */
-void rspamd_log_flush (rspamd_logger_t *logger);
-
/**
* Log function that is compatible for glib messages
*/
/**
* Function with variable number of arguments support
*/
-void rspamd_common_log_function (rspamd_logger_t *logger,
+bool rspamd_common_log_function (rspamd_logger_t *logger,
gint level_flags,
const gchar *module, const gchar *id,
const gchar *function, const gchar *fmt, ...);
-void rspamd_common_logv (rspamd_logger_t *logger, gint level_flags,
+bool rspamd_common_logv (rspamd_logger_t *logger, gint level_flags,
const gchar *module, const gchar *id, const gchar *function,
const gchar *fmt, va_list args);
/**
* Conditional debug function
*/
-void rspamd_conditional_debug (rspamd_logger_t *logger,
+bool rspamd_conditional_debug (rspamd_logger_t *logger,
rspamd_inet_addr_t *addr, const gchar *module, const gchar *id,
const gchar *function, const gchar *fmt, ...);
-void rspamd_conditional_debug_fast (rspamd_logger_t *logger,
+bool rspamd_conditional_debug_fast (rspamd_logger_t *logger,
rspamd_inet_addr_t *addr,
guint mod_id,
const gchar *module, const gchar *id,
const gchar *function, const gchar *fmt, ...);
-void rspamd_conditional_debug_fast_num_id (rspamd_logger_t *logger,
+bool rspamd_conditional_debug_fast_num_id (rspamd_logger_t *logger,
rspamd_inet_addr_t *addr,
guint mod_id,
const gchar *module, guint64 id,
/**
* Function with variable number of arguments support that uses static default logger
*/
-void rspamd_default_log_function (gint level_flags,
+bool rspamd_default_log_function (gint level_flags,
const gchar *module, const gchar *id,
const gchar *function,
const gchar *fmt,
* @param fmt
* @param args
*/
-void rspamd_default_logv (gint level_flags,
+bool rspamd_default_logv (gint level_flags,
const gchar *module, const gchar *id,
const gchar *function,
const gchar *fmt,
--- /dev/null
+/*-
+ * Copyright 2020 Vsevolod Stakhov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "logger.h"
+#include "libserver/cfg_file.h"
+#include "libcryptobox/cryptobox.h"
+#include "unix-std.h"
+
+#include "logger_private.h"
+
+#define CONSOLE_LOG_QUARK g_quark_from_static_string ("console_logger")
+
+static const gchar lf_chr = '\n';
+struct rspamd_console_logger_priv {
+ gint fd;
+ gint crit_fd;
+ gboolean log_color;
+ gboolean log_rspamadm;
+ gboolean log_tty;
+};
+
+/* Copy & paste :( */
+static inline void
+log_time (gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf,
+ size_t len)
+{
+ time_t sec = (time_t)now;
+ gsize r;
+ struct tm tms;
+
+ rspamd_localtime (sec, &tms);
+ r = strftime (timebuf, len, "%F %H:%M:%S", &tms);
+
+ if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) {
+ gchar usec_buf[16];
+
+ rspamd_snprintf (usec_buf, sizeof (usec_buf), "%.5f",
+ now - (gdouble)sec);
+ rspamd_snprintf (timebuf + r, len - r,
+ "%s", usec_buf + 1);
+ }
+}
+
+void *
+rspamd_log_console_init (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ uid_t uid, gid_t gid, GError **err)
+{
+ struct rspamd_console_logger_priv *priv;
+
+ priv = g_malloc0 (sizeof (*priv));
+ priv->log_color = (logger->flags & RSPAMD_LOG_FLAG_COLOR);
+ priv->log_rspamadm (logger->flags & RSPAMD_LOG_FLAG_RSPAMADM);
+
+ if (priv->log_rspamadm) {
+ priv->fd = dup (STDOUT_FILENO);
+ priv->crit_fd = dup (STDERR_FILENO);
+ }
+ else {
+ priv->fd = dup (STDERR_FILENO);
+ priv->crit_fd = priv->fd;
+ }
+
+ if (priv->fd == -1) {
+ g_set_error (err, CONSOLE_LOG_QUARK, errno,
+ "open_log: cannot dup console fd: %s, %s\n",
+ strerror (errno));
+ rspamd_log_console_dtor (priv);
+
+ return NULL;
+ }
+
+ if (isatty (priv->fd)) {
+ priv->log_tty = true;
+ }
+
+ return priv;
+}
+
+void *
+rspamd_log_console_reload (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ gpointer arg, uid_t uid, gid_t gid, GError **err)
+{
+ struct rspamd_console_logger_priv *npriv;
+
+ npriv = rspamd_log_console_init (logger, cfg, uid, gid, err);
+
+ if (npriv) {
+ /* Close old */
+ rspamd_log_console_dtor (logger, arg);
+ }
+
+ return npriv;
+}
+
+void
+rspamd_log_console_dtor (rspamd_logger_t *logger, gpointer arg)
+{
+ struct rspamd_console_logger_priv *priv = (struct rspamd_console_logger_priv *)arg;
+
+ if (priv->fd != -1) {
+ if (priv->fd != priv->crit_fd) {
+ /* Two different FD case */
+ if (close (priv->crit_fd) == -1) {
+ rspamd_fprintf (stderr, "cannot close log crit_fd %d: %s\n",
+ priv->crit_fd, strerror (errno));
+ }
+ }
+
+ if (close (priv->fd) == -1) {
+ rspamd_fprintf (stderr, "cannot close log fd %d: %s\n",
+ priv->fd, strerror (errno));
+ }
+
+ /* Avoid the next if to be executed as crit_fd is equal to fd */
+ priv->crit_fd = -1;
+ }
+
+ if (priv->crit_fd != -1) {
+ if (close (priv->crit_fd) == -1) {
+ rspamd_fprintf (stderr, "cannot close log crit_fd %d: %s\n",
+ priv->crit_fd, strerror (errno));
+ }
+ }
+
+ g_free (priv);
+}
+
+bool
+rspamd_log_console_log (const gchar *module, const gchar *id,
+ const gchar *function,
+ gint level_flags,
+ const gchar *message,
+ gsize mlen,
+ rspamd_logger_t *rspamd_log,
+ gpointer arg)
+{
+ struct rspamd_console_logger_priv *priv = (struct rspamd_console_logger_priv *)arg;
+ static gchar timebuf[64], modulebuf[64];
+ gchar tmpbuf[256];
+ gchar *m;
+ struct iovec iov[6];
+ gulong r = 0, mr = 0;
+ size_t mremain;
+ gint fd, niov = 0;
+
+ if (level_flags & G_LOG_LEVEL_CRITICAL) {
+ fd = priv->crit_fd;
+ }
+ else {
+ fd = priv->fd;
+ }
+
+#ifndef DISABLE_PTHREAD_MUTEX
+ if (rspamd_log->mtx) {
+ rspamd_mempool_lock_mutex (rspamd_log->mtx);
+ }
+ else {
+ rspamd_file_lock (fd, FALSE);
+ }
+#else
+ rspamd_file_lock (fd, FALSE);
+#endif
+
+ log_time (rspamd_get_calendar_ticks (),
+ rspamd_log, timebuf, sizeof (timebuf));
+ if (priv->log_color) {
+ if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
+ /* White */
+ r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
+ }
+ else if (level_flags & G_LOG_LEVEL_WARNING) {
+ /* Magenta */
+ r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
+ }
+ else if (level_flags & G_LOG_LEVEL_CRITICAL) {
+ /* Red */
+ r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
+ }
+ }
+ else {
+ r = 0;
+ }
+
+ if (priv->log_rspamadm) {
+ if (rspamd_log->log_level == G_LOG_LEVEL_DEBUG) {
+ log_time (rspamd_get_calendar_ticks (),
+ rspamd_log, timebuf, sizeof (timebuf));
+ iov[niov].iov_base = (void *) timebuf;
+ iov[niov++].iov_len = strlen (timebuf);
+ iov[niov].iov_base = (void *) " ";
+ iov[niov++].iov_len = 1;
+ }
+
+ iov[niov].iov_base = (void *) message;
+ iov[niov++].iov_len = mlen;
+ iov[niov].iov_base = (void *) &lf_chr;
+ iov[niov++].iov_len = 1;
+ }
+ else {
+ r += rspamd_snprintf (tmpbuf + r,
+ sizeof (tmpbuf) - r,
+ "%s #%P(%s) ",
+ timebuf,
+ rspamd_log->pid,
+ rspamd_log->process_type);
+
+ modulebuf[0] = '\0';
+ mremain = sizeof (modulebuf);
+ m = modulebuf;
+
+ if (id != NULL) {
+ guint slen = strlen (id);
+ slen = MIN (LOG_ID, slen);
+ mr = rspamd_snprintf (m, mremain, "<%*.s>; ", slen,
+ id);
+ m += mr;
+ mremain -= mr;
+ }
+ if (module != NULL) {
+ mr = rspamd_snprintf (m, mremain, "%s; ", module);
+ m += mr;
+ mremain -= mr;
+ }
+ if (function != NULL) {
+ mr = rspamd_snprintf (m, mremain, "%s: ", function);
+ m += mr;
+ mremain -= mr;
+ }
+ else {
+ mr = rspamd_snprintf (m, mremain, ": ");
+ m += mr;
+ mremain -= mr;
+ }
+
+ iov[niov].iov_base = tmpbuf;
+ iov[niov++].iov_len = r;
+ iov[niov].iov_base = modulebuf;
+ iov[niov++].iov_len = m - modulebuf;
+ iov[niov].iov_base = (void *) message;
+ iov[niov++].iov_len = mlen;
+ iov[niov].iov_base = (void *) &lf_chr;
+ iov[niov++].iov_len = 1;
+ }
+
+ if (priv->log_color) {
+ iov[niov].iov_base = "\033[0m";
+ iov[niov++].iov_len = sizeof ("\033[0m") - 1;
+ }
+
+again:
+ r = writev (fd, iov, niov);
+
+ if (r == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ goto again;
+ }
+
+ if (rspamd_log->mtx) {
+ rspamd_mempool_unlock_mutex (rspamd_log->mtx);
+ }
+ else {
+ rspamd_file_unlock (fd, FALSE);
+ }
+
+ return false;
+ }
+
+ if (rspamd_log->mtx) {
+ rspamd_mempool_unlock_mutex (rspamd_log->mtx);
+ }
+ else {
+ rspamd_file_unlock (fd, FALSE);
+ }
+
+ return true;
+}
\ No newline at end of file
gchar *saved_module;
gchar *saved_id;
guint saved_loglevel;
- guint64 log_cnt[4];
};
/**
/*
* Write a line to log file (unbuffered)
*/
-static void
+static bool
direct_write_log_line (rspamd_logger_t *rspamd_log,
struct rspamd_file_logger_priv *priv,
void *data,
tlen = count;
}
- if (tlen > PIPE_BUF || rspamd_log->flags & RSPAMD_LOG_FLAG_TTY) {
+ if (tlen > PIPE_BUF) {
locked = TRUE;
#ifndef DISABLE_PTHREAD_MUTEX
/* We cannot write message to file, so we need to detect error and make decision */
if (errno == EINTR) {
/* Try again */
- direct_write_log_line (rspamd_log, priv, data, count, is_iov, level_flags);
- return;
+ return direct_write_log_line (rspamd_log, priv, data, count, is_iov, level_flags);
}
- r = rspamd_snprintf (errmsg,
- sizeof (errmsg),
- "direct_write_log_line: cannot write log line: %s",
- strerror (errno));
if (errno == EFAULT || errno == EINVAL || errno == EFBIG ||
errno == ENOSPC) {
/* Rare case */
/* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */
rspamd_log->enabled = FALSE;
}
+
+ return false;
}
else if (priv->throttling) {
priv->throttling = FALSE;
}
+
+ return true;
}
/**
}
+static void
+rspamd_log_flush (rspamd_logger_t *rspamd_log, struct rspamd_file_logger_priv *priv)
+{
+ if (priv->is_buffered) {
+ direct_write_log_line (rspamd_log,
+ priv,
+ priv->io_buf.buf,
+ priv->io_buf.used,
+ FALSE,
+ rspamd_log->log_level);
+ priv->io_buf.used = 0;
+ }
+}
+
/*
* Write message to buffer or to file (using direct_write_log_line function)
*/
-static void
+static bool
file_log_helper (rspamd_logger_t *rspamd_log,
struct rspamd_file_logger_priv *priv,
const struct iovec *iov,
if (!priv->is_buffered) {
/* Write string directly */
- direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt,
+ return direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt,
TRUE, level_flags);
}
else {
/* Fill buffer */
if (priv->io_buf.size < len) {
/* Buffer is too small to hold this string, so write it directly */
- rspamd_log_flush (rspamd_log);
- direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt,
+ rspamd_log_flush (rspamd_log, priv);
+ return direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt,
TRUE, level_flags);
}
else if (priv->io_buf.used + len >= priv->io_buf.size) {
/* Buffer is full, try to write it directly */
- rspamd_log_flush (rspamd_log);
+ rspamd_log_flush (rspamd_log, priv);
fill_buffer (rspamd_log, priv, iov, iovcnt);
}
else {
fill_buffer (rspamd_log, priv, iov, iovcnt);
}
}
+
+ return true;
}
static void
r,
rspamd_log,
priv);
+ rspamd_log_flush (rspamd_log, priv);
}
}
}
struct rspamd_file_logger_priv *priv = (struct rspamd_file_logger_priv *)arg;
rspamd_log_reset_repeated (logger, priv);
+ rspamd_log_flush (logger, priv);
if (priv->fd != -1) {
if (close (priv->fd) == -1) {
g_free (priv);
}
-void
+bool
rspamd_log_file_log (const gchar *module, const gchar *id,
const gchar *function,
gint level_flags,
if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
- return;
+ return false;
}
/* Check throttling due to write errors */
if (!(level_flags & RSPAMD_LOG_FORCED) && priv->throttling) {
now = rspamd_get_calendar_ticks ();
+
if (priv->throttling_time != now) {
priv->throttling_time = now;
got_time = TRUE;
}
else {
/* Do not try to write to file too often while throttling */
- return;
+ return false;
}
}
priv->saved_loglevel = level_flags;
}
- return;
+ return true;
}
else if (priv->repeats > REPEATS_MAX) {
rspamd_log_reset_repeated (rspamd_log, priv);
- rspamd_log_file_log (module, id,
+ bool ret = rspamd_log_file_log (module, id,
function,
level_flags,
message,
/* Probably we have more repeats in future */
priv->repeats = REPEATS_MIN + 1;
- return;
+ return ret;
}
}
else {
if (priv->repeats > REPEATS_MIN) {
rspamd_log_reset_repeated (rspamd_log, priv);
- rspamd_log_file_log (module, id,
+ return rspamd_log_file_log (module, id,
function,
level_flags,
message,
mlen,
rspamd_log,
arg);
- return;
}
else {
priv->repeats = 0;
log_time (now, rspamd_log, timebuf, sizeof (timebuf));
}
- cptype = g_quark_to_string (rspamd_log->process_type);
-
- if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
- if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
- /* White */
- r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
- }
- else if (level_flags & G_LOG_LEVEL_WARNING) {
- /* Magenta */
- r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
- }
- else if (level_flags & G_LOG_LEVEL_CRITICAL) {
- /* Red */
- r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
- }
- }
- else {
- r = 0;
- }
+ cptype = rspamd_log->process_type;
+ r = 0;
if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) {
r += rspamd_snprintf (tmpbuf + r,
iov[3].iov_base = (void *) &lf_chr;
iov[3].iov_len = 1;
- file_log_helper (rspamd_log, priv, iov, 4, level_flags);
+ return file_log_helper (rspamd_log, priv, iov, 4, level_flags);
}
void *
*/
struct rspamd_logger_s {
struct rspamd_logger_funcs ops;
- gint log_facility;
gint log_level;
struct rspamd_logger_error_log *errlog;
gboolean opened;
pid_t pid;
- GQuark process_type;
+ const gchar *process_type;
struct rspamd_radix_map_helper *debug_ip;
rspamd_mempool_mutex_t *mtx;
+ guint64 log_cnt[4];
};
/*
void * rspamd_log_file_reload (rspamd_logger_t *logger, struct rspamd_config *cfg,
gpointer arg, uid_t uid, gid_t gid, GError **err);
void rspamd_log_file_dtor (rspamd_logger_t *logger, gpointer arg);
-void rspamd_log_file_log (const gchar *module, const gchar *id,
+bool rspamd_log_file_log (const gchar *module, const gchar *id,
const gchar *function,
gint level_flags,
const gchar *message,
.log = rspamd_log_file_log,
};
+/*
+ * Syslog logging
+ */
+void * rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ uid_t uid, gid_t gid, GError **err);
+void * rspamd_log_syslog_reload (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ gpointer arg, uid_t uid, gid_t gid, GError **err);
+void rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg);
+bool rspamd_log_syslog_log (const gchar *module, const gchar *id,
+ const gchar *function,
+ gint level_flags,
+ const gchar *message,
+ gsize mlen,
+ rspamd_logger_t *rspamd_log,
+ gpointer arg);
+
+const static struct rspamd_logger_funcs syslog_log_funcs = {
+ .init = rspamd_log_syslog_init,
+ .dtor = rspamd_log_syslog_dtor,
+ .reload = rspamd_log_syslog_reload,
+ .log = rspamd_log_syslog_log,
+};
+
+/*
+ * Console logging
+ */
+void * rspamd_log_console_init (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ uid_t uid, gid_t gid, GError **err);
+void * rspamd_log_console_reload (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ gpointer arg, uid_t uid, gid_t gid, GError **err);
+void rspamd_log_console_dtor (rspamd_logger_t *logger, gpointer arg);
+bool rspamd_log_console_log (const gchar *module, const gchar *id,
+ const gchar *function,
+ gint level_flags,
+ const gchar *message,
+ gsize mlen,
+ rspamd_logger_t *rspamd_log,
+ gpointer arg);
+
+const static struct rspamd_logger_funcs console_log_funcs = {
+ .init = rspamd_log_console_init,
+ .dtor = rspamd_log_console_dtor,
+ .reload = rspamd_log_console_reload,
+ .log = rspamd_log_console_log,
+};
+
#endif
--- /dev/null
+/*-
+ * Copyright 2020 Vsevolod Stakhov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "logger.h"
+#include "libserver/cfg_file.h"
+#include "logger_private.h"
+
+#define SYSLOG_LOG_QUARK g_quark_from_static_string ("syslog_logger")
+
+struct rspamd_syslog_logger_priv {
+ gint log_facility;
+};
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+
+void *
+rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ uid_t uid, gid_t gid, GError **err)
+{
+ struct rspamd_syslog_logger_priv *priv;
+
+ priv = g_malloc0 (sizeof (*priv));
+
+ priv->log_facility = cfg->log_facility;
+ openlog ("rspamd", LOG_NDELAY | LOG_PID, priv->log_facility);
+
+ return priv;
+}
+
+void
+rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg)
+{
+ struct rspamd_syslog_logger_priv *priv = (struct rspamd_syslog_logger_priv *)arg;
+
+ closelog ();
+ g_free (priv);
+}
+bool
+rspamd_log_syslog_log (const gchar *module, const gchar *id,
+ const gchar *function,
+ gint level_flags,
+ const gchar *message,
+ gsize mlen,
+ rspamd_logger_t *rspamd_log,
+ gpointer arg)
+{
+ static const struct {
+ GLogLevelFlags glib_level;
+ gint syslog_level;
+ } levels_match[] = {
+ {G_LOG_LEVEL_DEBUG, LOG_DEBUG},
+ {G_LOG_LEVEL_INFO, LOG_INFO},
+ {G_LOG_LEVEL_WARNING, LOG_WARNING},
+ {G_LOG_LEVEL_CRITICAL, LOG_ERR}
+ };
+ unsigned i;
+ gint syslog_level;
+
+ if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
+ return false;
+ }
+
+ /* Detect level */
+ syslog_level = LOG_DEBUG;
+
+ for (i = 0; i < G_N_ELEMENTS (levels_match); i ++) {
+ if (level_flags & levels_match[i].glib_level) {
+ syslog_level = levels_match[i].syslog_level;
+ break;
+ }
+ }
+
+ syslog (syslog_level, "<%.*s>; %s; %s: %*.s",
+ LOG_ID, id != NULL ? id : "",
+ module != NULL ? module : "",
+ function != NULL ? function : "",
+ (gint)mlen, message);
+
+ return true;
+}
+
+#else
+
+void *
+rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ uid_t uid, gid_t gid, GError **err)
+{
+ g_set_error (err, SYSLOG_LOG_QUARK, EINVAL, "syslog support is not compiled in");
+
+ return NULL;
+}
+
+bool
+rspamd_log_syslog_log (const gchar *module, const gchar *id,
+ const gchar *function,
+ gint level_flags,
+ const gchar *message,
+ gsize mlen,
+ rspamd_logger_t *rspamd_log,
+ gpointer arg)
+{
+ return false;
+}
+
+void
+rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg)
+{
+ /* Left blank intentionally */
+}
+
+#endif
+
+void *
+rspamd_log_syslog_reload (rspamd_logger_t *logger, struct rspamd_config *cfg,
+ gpointer arg, uid_t uid, gid_t gid, GError **err)
+{
+ struct rspamd_syslog_logger_priv *npriv;
+
+ npriv = rspamd_log_syslog_init (logger, cfg, uid, gid, err);
+
+ if (npriv) {
+ /* Close old */
+ rspamd_log_syslog_dtor (logger, arg);
+ }
+
+ return npriv;
+}