1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "myfprintf.h"
31 static unsigned int logLevel = LOG_LEVEL_LOW;
32 static int warningFlushed;
33 static int stdout_mode = 1;
34 static char *warningBuffer;
35 static int out_fd = -1;
36 static int err_fd = -1;
37 static const char *out_filename;
38 static const char *err_filename;
40 /* redirect stdin to /dev/null to work around a libao bug */
41 static void redirect_stdin(void)
46 if ((st = fstat(STDIN_FILENO, &ss)) < 0 || /* If STDIN is already closed (e.g. mpd launched in a non-interactive shell) */
47 ! isatty(STDIN_FILENO)) { /* ... or FD 0 does not correspond to a tty device */
48 return; /* ... do nothing and return. */
50 if ((fd = open("/dev/null", O_RDONLY)) < 0)
51 FATAL("failed to open /dev/null %s\n", strerror(errno));
52 if (dup2(fd, STDIN_FILENO) < 0)
53 FATAL("dup2 stdin: %s\n", strerror(errno));
56 static void redirect_logs(void)
60 if (dup2(out_fd, STDOUT_FILENO) < 0)
61 FATAL("problems dup2 stdout : %s\n", strerror(errno));
62 if (dup2(err_fd, STDERR_FILENO) < 0)
63 FATAL("problems dup2 stderr : %s\n", strerror(errno));
66 static const char *log_date(void)
69 time_t t = time(NULL);
70 strftime(buf, 16, "%b %d %H:%M : ", localtime(&t));
74 #define BUFFER_LENGTH 4096
75 static void buffer_warning(const char *fmt, va_list args)
77 char buffer[BUFFER_LENGTH];
79 size_t len = BUFFER_LENGTH;
82 memcpy(buffer, log_date(), 15);
87 vsnprintf(tmp, len, fmt, args);
88 warningBuffer = appendToString(warningBuffer, buffer);
93 static void do_log(FILE *fp, const char *fmt, va_list args)
96 fwrite(log_date(), 15, 1, fp);
97 vfprintf(fp, fmt, args);
100 void flushWarningLog(void)
102 char *s = warningBuffer;
104 DEBUG("flushing warning messages\n");
106 if (warningBuffer != NULL)
109 char *next = strchr(s, '\n');
110 if (next == NULL) break;
113 fprintf(stderr, "%s\n", s);
117 warningBuffer = NULL;
122 DEBUG("done flushing warning messages\n");
125 void initLog(const int verbose)
129 /* unbuffer stdout, stderr is unbuffered by default, leave it */
130 setvbuf(stdout, (char *)NULL, _IONBF, 0);
133 logLevel = LOG_LEVEL_DEBUG;
136 if (!(param = getConfigParam(CONF_LOG_LEVEL)))
138 if (0 == strcmp(param->value, "default")) {
139 logLevel = LOG_LEVEL_LOW;
140 } else if (0 == strcmp(param->value, "secure")) {
141 logLevel = LOG_LEVEL_SECURE;
142 } else if (0 == strcmp(param->value, "verbose")) {
143 logLevel = LOG_LEVEL_DEBUG;
145 FATAL("unknown log level \"%s\" at line %i\n",
146 param->value, param->line);
150 void open_log_files(const int use_stdout)
161 param = parseConfigFilePath(CONF_LOG_FILE, 1);
162 out_filename = param->value;
163 out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
165 FATAL("problem opening log file \"%s\" (config line %i) for "
166 "writing\n", param->value, param->line);
168 param = parseConfigFilePath(CONF_ERROR_FILE, 1);
169 err_filename = param->value;
170 err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
172 FATAL("problem opening error file \"%s\" (config line %i) for "
173 "writing\n", param->value, param->line);
178 void setup_log_output(const int use_stdout)
189 #define log_func(func,level,fp) \
190 mpd_printf void func(const char *fmt, ...) \
192 if (logLevel >= level) { \
194 va_start(args, fmt); \
195 do_log(fp, fmt, args); \
200 log_func(ERROR, 0, stderr)
201 log_func(LOG, 0, stdout)
202 log_func(SECURE, LOG_LEVEL_SECURE, stdout)
203 log_func(DEBUG, LOG_LEVEL_DEBUG, stdout)
207 void WARNING(const char *fmt, ...)
211 if (warningFlushed) {
212 do_log(stderr, fmt, args);
214 buffer_warning(fmt, args);
218 mpd_printf mpd_noreturn void FATAL(const char *fmt, ...)
222 do_log(stderr, fmt, args);
227 int cycle_log_files(void)
233 assert(out_filename);
234 assert(err_filename);
236 DEBUG("Cycling log files...\n");
241 out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
243 ERROR("error re-opening log file: %s\n", out_filename);
247 err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
249 ERROR("error re-opening error file: %s\n", err_filename);
256 DEBUG("Done cycling log files\n");
260 void close_log_files(void)