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)
44 if ((fd = open("/dev/null", O_RDONLY)) < 0)
45 FATAL("failed to open /dev/null %s\n", strerror(errno));
46 if (dup2(fd, STDIN_FILENO) < 0)
47 FATAL("dup2 stdin: %s\n", strerror(errno));
50 static void redirect_logs(void)
54 if (dup2(out_fd, STDOUT_FILENO) < 0)
55 FATAL("problems dup2 stdout : %s\n", strerror(errno));
56 if (dup2(err_fd, STDERR_FILENO) < 0)
57 FATAL("problems dup2 stderr : %s\n", strerror(errno));
60 static const char *log_date(void)
63 time_t t = time(NULL);
64 strftime(buf, 16, "%b %d %H:%M : ", localtime(&t));
68 #define BUFFER_LENGTH 4096
69 static void buffer_warning(const char *fmt, va_list args)
71 char buffer[BUFFER_LENGTH];
73 size_t len = BUFFER_LENGTH;
76 memcpy(buffer, log_date(), 15);
81 vsnprintf(tmp, len, fmt, args);
82 warningBuffer = appendToString(warningBuffer, buffer);
87 static void do_log(FILE *fp, const char *fmt, va_list args)
90 fwrite(log_date(), 15, 1, fp);
91 vfprintf(fp, fmt, args);
94 void flushWarningLog(void)
96 char *s = warningBuffer;
98 DEBUG("flushing warning messages\n");
100 if (warningBuffer != NULL)
103 char *next = strchr(s, '\n');
104 if (next == NULL) break;
107 fprintf(stderr, "%s\n", s);
111 warningBuffer = NULL;
116 DEBUG("done flushing warning messages\n");
119 void initLog(const int verbose)
123 /* unbuffer stdout, stderr is unbuffered by default, leave it */
124 setvbuf(stdout, (char *)NULL, _IONBF, 0);
127 logLevel = LOG_LEVEL_DEBUG;
130 if (!(param = getConfigParam(CONF_LOG_LEVEL)))
132 if (0 == strcmp(param->value, "default")) {
133 logLevel = LOG_LEVEL_LOW;
134 } else if (0 == strcmp(param->value, "secure")) {
135 logLevel = LOG_LEVEL_SECURE;
136 } else if (0 == strcmp(param->value, "verbose")) {
137 logLevel = LOG_LEVEL_DEBUG;
139 FATAL("unknown log level \"%s\" at line %i\n",
140 param->value, param->line);
144 void open_log_files(const int use_stdout)
155 param = parseConfigFilePath(CONF_LOG_FILE, 1);
156 out_filename = param->value;
157 out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
159 FATAL("problem opening log file \"%s\" (config line %i) for "
160 "writing\n", param->value, param->line);
162 param = parseConfigFilePath(CONF_ERROR_FILE, 1);
163 err_filename = param->value;
164 err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
166 FATAL("problem opening error file \"%s\" (config line %i) for "
167 "writing\n", param->value, param->line);
172 void setup_log_output(const int use_stdout)
183 #define log_func(func,level,fp) \
184 mpd_printf void func(const char *fmt, ...) \
186 if (logLevel >= level) { \
188 va_start(args, fmt); \
189 do_log(fp, fmt, args); \
194 log_func(ERROR, 0, stderr)
195 log_func(LOG, 0, stdout)
196 log_func(SECURE, LOG_LEVEL_SECURE, stdout)
197 log_func(DEBUG, LOG_LEVEL_DEBUG, stdout)
201 void WARNING(const char *fmt, ...)
205 if (warningFlushed) {
206 do_log(stderr, fmt, args);
208 buffer_warning(fmt, args);
212 mpd_printf mpd_noreturn void FATAL(const char *fmt, ...)
216 do_log(stderr, fmt, args);
221 int cycle_log_files(void)
227 assert(out_filename);
228 assert(err_filename);
230 DEBUG("Cycling log files...\n");
235 out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
237 ERROR("error re-opening log file: %s\n", out_filename);
241 err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
243 ERROR("error re-opening error file: %s\n", err_filename);
250 DEBUG("Done cycling log files\n");
254 void close_log_files(void)