LogBackend.cxx 3.48 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * http://www.musicpd.org
 *
 * 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 2 of the License, 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, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"
21
#include "LogBackend.hxx"
22 23
#include "Log.hxx"
#include "util/Domain.hxx"
24
#include "util/CharUtil.hxx"
25

26
#ifdef HAVE_GLIB
27
#include <glib.h>
28
#endif
29 30

#include <assert.h>
31 32
#include <stdio.h>
#include <string.h>
33
#include <time.h>
34

35 36 37 38 39
#ifdef HAVE_SYSLOG
#include <syslog.h>
#endif

static LogLevel log_threshold = LogLevel::INFO;
40 41

#ifdef HAVE_GLIB
42
static const char *log_charset;
43
#endif
44 45 46 47 48 49 50 51 52 53 54 55 56

static bool enable_timestamp;

#ifdef HAVE_SYSLOG
static bool enable_syslog;
#endif

void
SetLogThreshold(LogLevel _threshold)
{
	log_threshold = _threshold;
}

57 58
#ifdef HAVE_GLIB

59 60 61 62 63 64
void
SetLogCharset(const char *_charset)
{
	log_charset = _charset;
}

65 66
#endif

67 68
void
EnableLogTimestamp()
69
{
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
#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) {
108
	case LogLevel::DEBUG:
109
		return LOG_DEBUG;
110 111

	case LogLevel::INFO:
112
		return LOG_INFO;
113 114

	case LogLevel::DEFAULT:
115
		return LOG_NOTICE;
116 117

	case LogLevel::WARNING:
118 119
		return LOG_WARNING;

120
	case LogLevel::ERROR:
121
		return LOG_ERR;
122 123 124 125 126 127
	}

	assert(false);
	gcc_unreachable();
}

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
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)
{
155
#ifdef HAVE_GLIB
156 157 158 159 160 161 162 163 164 165 166
	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;
167
#endif
168 169 170 171 172 173

	fprintf(stderr, "%s%s: %.*s\n",
		enable_timestamp ? log_date() : "",
		domain.GetName(),
		chomp_length(message), message);

174
#ifdef HAVE_GLIB
175
	g_free(converted);
176
#endif
177 178
}

179 180 181
void
Log(const Domain &domain, LogLevel level, const char *msg)
{
182 183 184 185 186 187 188 189 190 191 192
	if (level < log_threshold)
		return;

#ifdef HAVE_SYSLOG
	if (enable_syslog) {
		SysLog(domain, level, msg);
		return;
	}
#endif

	FileLog(domain, msg);
193
}