#include <signal.h>
#endif
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
struct BusContext
{
int refcount;
auth_mechanisms = NULL;
pidfile = NULL;
- _dbus_init_system_log ("dbus-daemon", TRUE);
+ context->syslog = bus_config_parser_get_syslog (parser);
+
+ if (context->syslog)
+ {
+#ifdef HAVE_SYSTEMD
+ /* If running under systemd, we don't want to log to both stderr and
+ * syslog, because our stderr is probably connected to journald too,
+ * so we'd duplicate all our messages. */
+ if (sd_booted () > 0)
+ _dbus_init_system_log ("dbus-daemon", DBUS_LOG_FLAGS_SYSTEM_LOG);
+ else
+#endif
+ _dbus_init_system_log ("dbus-daemon",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
+ }
+ else
+ {
+ _dbus_init_system_log ("dbus-daemon", DBUS_LOG_FLAGS_STDERR);
+ }
if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
context->systemd_activation = TRUE;
}
context->fork = bus_config_parser_get_fork (parser);
- context->syslog = bus_config_parser_get_syslog (parser);
context->keep_umask = bus_config_parser_get_keep_umask (parser);
context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser);
{
if (dbus_error_is_set (error))
{
- /* We log to syslog unconditionally here, because this is
+ /* We use both syslog and stderr here, because this is
* the configuration parser, so we don't yet know whether
- * this bus is going to want to write to syslog! (There's
- * also some layer inversion going on, if we want to use
- * the bus context.) */
+ * this bus is going to want to write to syslog! Err on
+ * the side of making sure the message gets to the sysadmin
+ * somehow. */
+ _dbus_init_system_log ("dbus-daemon",
+ DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG);
_dbus_log (DBUS_SYSTEM_LOG_INFO,
"Encountered error '%s' while parsing '%s'",
error->message,
}
static const char *syslog_tag = "dbus";
+#ifdef HAVE_SYSLOG_H
+static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
+#endif
/**
* Initialize the system log.
* the process or until _dbus_init_system_log() is called again. In practice
* it will normally be a constant.
*
+ * On platforms that do not support a system log, the
+ * #DBUS_LOG_FLAGS_SYSTEM_LOG flag is treated as equivalent to
+ * #DBUS_LOG_FLAGS_STDERR.
+ *
* @param tag the name of the executable (syslog tag)
- * @param is_daemon #TRUE if this is the dbus-daemon
+ * @param mode whether to log to stderr, the system log or both
*/
void
-_dbus_init_system_log (const char *tag,
- dbus_bool_t is_daemon)
+_dbus_init_system_log (const char *tag,
+ DBusLogFlags flags)
{
-#ifdef HAVE_SYSLOG_H
- int logopts = LOG_PID;
-
-#if HAVE_DECL_LOG_PERROR
-#ifdef HAVE_SYSTEMD
- if (!is_daemon || sd_booted () <= 0)
-#endif
- logopts |= LOG_PERROR;
-#endif
+ /* We never want to turn off logging completely */
+ _dbus_assert (
+ (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
syslog_tag = tag;
- openlog (tag, logopts, LOG_DAEMON);
+
+#ifdef HAVE_SYSLOG_H
+ log_flags = flags;
+
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ openlog (tag, LOG_PID, LOG_DAEMON);
#endif
}
/**
- * Log a message to the system log file (e.g. syslog on Unix).
+ * Log a message to the system log file (e.g. syslog on Unix) and/or stderr.
*
* @param severity a severity value
* @param msg a printf-style format string
{
va_list tmp;
#ifdef HAVE_SYSLOG_H
- int flags;
- switch (severity)
- {
- case DBUS_SYSTEM_LOG_INFO:
- flags = LOG_DAEMON | LOG_NOTICE;
- break;
- case DBUS_SYSTEM_LOG_WARNING:
- flags = LOG_DAEMON | LOG_WARNING;
- break;
- case DBUS_SYSTEM_LOG_SECURITY:
- flags = LOG_AUTH | LOG_NOTICE;
- break;
- case DBUS_SYSTEM_LOG_FATAL:
- flags = LOG_DAEMON|LOG_CRIT;
- break;
- default:
- return;
- }
-
- DBUS_VA_COPY (tmp, args);
- vsyslog (flags, msg, tmp);
- va_end (tmp);
-#endif
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ {
+ int flags;
+ switch (severity)
+ {
+ case DBUS_SYSTEM_LOG_INFO:
+ flags = LOG_DAEMON | LOG_NOTICE;
+ break;
+ case DBUS_SYSTEM_LOG_WARNING:
+ flags = LOG_DAEMON | LOG_WARNING;
+ break;
+ case DBUS_SYSTEM_LOG_SECURITY:
+ flags = LOG_AUTH | LOG_NOTICE;
+ break;
+ case DBUS_SYSTEM_LOG_FATAL:
+ flags = LOG_DAEMON|LOG_CRIT;
+ break;
+ default:
+ return;
+ }
-#if !defined(HAVE_SYSLOG_H) || !HAVE_DECL_LOG_PERROR
+ DBUS_VA_COPY (tmp, args);
+ vsyslog (flags, msg, tmp);
+ va_end (tmp);
+ }
+
+ /* If we don't have syslog.h, we always behave as though stderr was in
+ * the flags */
+ if (log_flags & DBUS_LOG_FLAGS_STDERR)
+#endif
{
- /* vsyslog() won't write to stderr, so we'd better do it */
DBUS_VA_COPY (tmp, args);
fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
vfprintf (stderr, msg, tmp);
fputc ('\n', stderr);
va_end (tmp);
}
-#endif
if (severity == DBUS_SYSTEM_LOG_FATAL)
exit (1);
_dbus_win_set_errno (saved_errno);
}
+static const char *log_tag = "dbus";
+static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
+
/**
* Initialize the system log.
*
* it will normally be a constant.
*
* @param tag the name of the executable (syslog tag)
- * @param is_daemon #TRUE if this is the dbus-daemon
+ * @param mode whether to log to stderr, the system log or both
*/
void
-_dbus_init_system_log (const char *tag,
- dbus_bool_t is_daemon)
+_dbus_init_system_log (const char *tag,
+ DBusLogFlags flags)
{
- /* OutputDebugStringA doesn't need any special initialization, do nothing */
+ /* We never want to turn off logging completely */
+ _dbus_assert (
+ (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
+
+ log_tag = tag;
+ log_flags = flags;
}
/**
va_list args)
{
char *s = "";
- char buf[1024];
- char format[1024];
+ va_list tmp;
switch(severity)
{
case DBUS_SYSTEM_LOG_FATAL: s = "fatal"; break;
}
- snprintf(format, sizeof(format), "%s%s", s ,msg);
- vsnprintf(buf, sizeof(buf), format, args);
- OutputDebugStringA(buf);
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ {
+ char buf[1024];
+ char format[1024];
+
+ DBUS_VA_COPY (tmp, args);
+ snprintf (format, sizeof (format), "%s: %s", s, msg);
+ vsnprintf(buf, sizeof(buf), format, tmp);
+ OutputDebugStringA(buf);
+ va_end (tmp);
+ }
+
+ if (log_flags & DBUS_LOG_FLAGS_STDERR)
+ {
+ DBUS_VA_COPY (tmp, args);
+ fprintf (stderr, "%s[%lu]: %s: ", log_tag, _dbus_pid_for_log (), s);
+ vfprintf (stderr, msg, tmp);
+ fprintf (stderr, "\n");
+ va_end (tmp);
+ }
if (severity == DBUS_SYSTEM_LOG_FATAL)
exit (1);
}
/**
- * Log a message to the system log file (e.g. syslog on Unix).
+ * Log a message to the system log file (e.g. syslog on Unix) and/or stderr.
*
* @param severity a severity value
* @param msg a printf-style format string
dbus_bool_t _dbus_user_at_console (const char *username,
DBusError *error);
+typedef enum {
+ DBUS_LOG_FLAGS_STDERR = (1 << 0),
+ DBUS_LOG_FLAGS_SYSTEM_LOG = (1 << 1)
+} DBusLogFlags;
+
DBUS_PRIVATE_EXPORT
-void _dbus_init_system_log (const char *tag,
- dbus_bool_t is_daemon);
+void _dbus_init_system_log (const char *tag,
+ DBusLogFlags flags);
typedef enum {
DBUS_SYSTEM_LOG_INFO,
#ifndef G_OS_WIN32
if (g_test_trap_fork (0, 0))
{
- _dbus_init_system_log ("test-syslog", FALSE);
+ _dbus_init_system_log ("test-syslog",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
_dbus_log (DBUS_SYSTEM_LOG_FATAL, MESSAGE "%d", 23);
/* should not be reached: exit 0 so the assertion in the main process
* will fail */
if (g_test_trap_fork (0, 0))
{
- _dbus_init_system_log ("test-syslog", FALSE);
+ _dbus_init_system_log ("test-syslog",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
_dbus_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
_dbus_log (DBUS_SYSTEM_LOG_WARNING, MESSAGE "%d", 45);
_dbus_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
g_test_trap_assert_stderr ("*" MESSAGE "42\n*" MESSAGE "45\n*" MESSAGE "666\n*");
#endif
/* manual test (this is the best we can do on Windows) */
- _dbus_init_system_log ("test-syslog", FALSE);
+ _dbus_init_system_log ("test-syslog",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
_dbus_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
_dbus_log (DBUS_SYSTEM_LOG_WARNING, MESSAGE "%d", 45);
_dbus_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);