/* 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);
}