/* This file is part of Mailfromd. Copyright (C) 2005-2020 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "libmf.h" #include #include #ifdef USE_SYSLOG_ASYNC # include "syslog_async.h" #endif static void syslog_default_close() { closelog(); } static void syslog_default_open() { mu_stdstream_strerr_setup(MU_STRERR_SYSLOG); } static void syslog_default_logtext(int prio, const char *text) { syslog(prio, "%s", text); } #ifdef USE_SYSLOG_ASYNC static void syslog_async_close() { closelog_async(); } static void syslog_async_open() { int rc; mu_stdstream_strerr_setup(MU_STRERR_SYSLOG); rc = mu_stream_ioctl(mu_strerr, MU_IOCTL_SYSLOGSTREAM, MU_IOCTL_SYSLOGSTREAM_SET_LOGGER, syslog_async); if (rc) mu_error(_("cannot configure asynchronous syslog: %s; " "falling back to system one"), mu_strerror (rc)); closelog(); /* we won't use it */ /* LOG_NDELAY ensures that the log descriptor is ready. It is needed for logger_fdset to work (see mf_srvcfg_log_setup). */ openlog_async(mu_log_tag, LOG_NDELAY|LOG_PID, mu_log_facility); mu_onexit(syslog_async_close, NULL); } static void syslog_async_fdset(fd_set *fds) { FD_SET(log_fd_async(), fds); } static void syslog_async_logtext(int prio, const char *text) { syslog_async(prio, "%s", text); } #endif static void stderr_open() { mu_stdstream_strerr_setup(MU_STRERR_STDERR); } static void stderr_fdset(fd_set *fds) { FD_SET(fileno(stderr), fds); } static void mf_gacopyz_log_printer(int level, char *fmt, va_list ap) { switch (level) { case SMI_LOG_PROTO: case SMI_LOG_DEBUG: level = MU_LOG_DEBUG; break; case SMI_LOG_INFO: level = MU_LOG_INFO; break; case SMI_LOG_WARN: level = MU_LOG_WARNING; break; case SMI_LOG_ERR: level = MU_LOG_ERROR; break; case SMI_LOG_FATAL: default: level = MU_LOG_EMERG; } mu_diag_voutput(level, fmt, ap); } static struct logger loggertab[] = { { "stderr", LOGF_STDERR, stderr_open, NULL, stderr_fdset, NULL }, { "syslog", 0, syslog_default_open, syslog_default_close, NULL, syslog_default_logtext }, #ifdef USE_SYSLOG_ASYNC { "syslog:async", 0, syslog_async_open, syslog_async_close, syslog_async_fdset, syslog_async_logtext }, #endif { NULL } }; static int current_logger; int logger_flags(int mask) { return loggertab[current_logger].flags & mask; } int logger_select(const char *name) { int i; for (i = 0; loggertab[i].name; i++) { if (strcmp(loggertab[i].name, name) == 0) { current_logger = i; return 0; } } return -1; } void logger_open() { int mode; struct logger *lp = loggertab + current_logger; if (lp->log_open) lp->log_open(); mu_stream_ioctl(mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_MODE, &mode); mode |= MU_LOGMODE_SEVERITY; mu_stream_ioctl(mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE, &mode); mode = MU_DEBUG_LEVEL_MASK(MU_LOG_ERROR); mu_stream_ioctl(mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK, &mode); gacopyz_set_logger(mf_gacopyz_log_printer); } void logger_close() { struct logger *lp = loggertab + current_logger; if (lp->log_close) lp->log_close(); } void logger_fdset(fd_set *set) { struct logger *lp = loggertab + current_logger; if (lp->log_fdset) lp->log_fdset(set); } void logger_text(int prio, const char *text) { struct logger *lp = loggertab + current_logger; (lp->log_text ? lp->log_text : syslog_default_logtext)(prio, text); }