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)