diff options
Diffstat (limited to '')
-rw-r--r-- | src/LogBackend.cxx | 141 |
1 files changed, 133 insertions, 8 deletions
diff --git a/src/LogBackend.cxx b/src/LogBackend.cxx index a06a41573..a5c0a691f 100644 --- a/src/LogBackend.cxx +++ b/src/LogBackend.cxx @@ -18,37 +18,162 @@ */ #include "config.h" +#include "LogBackend.hxx" #include "Log.hxx" #include "util/Domain.hxx" +#include "util/CharUtil.hxx" #include <glib.h> #include <assert.h> +#include <stdio.h> +#include <string.h> -static GLogLevelFlags -ToGLib(LogLevel level) +#ifdef HAVE_SYSLOG +#include <syslog.h> +#endif + +static LogLevel log_threshold = LogLevel::INFO; +static const char *log_charset; + +static bool enable_timestamp; + +#ifdef HAVE_SYSLOG +static bool enable_syslog; +#endif + +void +SetLogThreshold(LogLevel _threshold) +{ + log_threshold = _threshold; +} + +void +SetLogCharset(const char *_charset) +{ + log_charset = _charset; +} + +void +EnableLogTimestamp() { - switch (level) { +#ifdef HAVE_SYSLOG + assert(!enable_syslog); +#endif + assert(!enable_timestamp); + + enable_timestamp = true; +} + +static const char *log_date(void) +{ + static constexpr size_t LOG_DATE_BUF_SIZE = 16; + static char buf[LOG_DATE_BUF_SIZE]; + time_t t = time(nullptr); + strftime(buf, LOG_DATE_BUF_SIZE, "%b %d %H:%M : ", localtime(&t)); + return buf; +} + +/** + * Determines the length of the string excluding trailing whitespace + * characters. + */ +static int +chomp_length(const char *p) +{ + size_t length = strlen(p); + + while (length > 0 && IsWhitespaceOrNull(p[length - 1])) + --length; + + return (int)length; +} + +#ifdef HAVE_SYSLOG + +static int +ToSysLogLevel(LogLevel log_level) +{ + switch (log_level) { case LogLevel::DEBUG: - return G_LOG_LEVEL_DEBUG; + return LOG_DEBUG; case LogLevel::INFO: - return G_LOG_LEVEL_INFO; + return LOG_INFO; case LogLevel::DEFAULT: - return G_LOG_LEVEL_MESSAGE; + return LOG_NOTICE; case LogLevel::WARNING: + return LOG_WARNING; + case LogLevel::ERROR: - return G_LOG_LEVEL_WARNING; + return LOG_ERR; } assert(false); gcc_unreachable(); } +static void +SysLog(const Domain &domain, LogLevel log_level, const char *message) +{ + syslog(ToSysLogLevel(log_level), "%s: %.*s", + domain.GetName(), + chomp_length(message), message); +} + +void +LogInitSysLog() +{ + openlog(PACKAGE, 0, LOG_DAEMON); + enable_syslog = true; +} + +void +LogFinishSysLog() +{ + if (enable_syslog) + closelog(); +} + +#endif + +static void +FileLog(const Domain &domain, const char *message) +{ + char *converted; + + if (log_charset != nullptr) { + converted = g_convert_with_fallback(message, -1, + log_charset, "utf-8", + nullptr, nullptr, + nullptr, nullptr); + if (converted != nullptr) + message = converted; + } else + converted = nullptr; + + fprintf(stderr, "%s%s: %.*s\n", + enable_timestamp ? log_date() : "", + domain.GetName(), + chomp_length(message), message); + + g_free(converted); +} + void Log(const Domain &domain, LogLevel level, const char *msg) { - g_log(domain.GetName(), ToGLib(level), "%s", msg); + if (level < log_threshold) + return; + +#ifdef HAVE_SYSLOG + if (enable_syslog) { + SysLog(domain, level, msg); + return; + } +#endif + + FileLog(domain, msg); } |