~ubuntu-dev/ubuntu/lucid/mpd/lucid-201002110916

« back to all changes in this revision

Viewing changes to src/log.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-10-23 12:38:20 UTC
  • mfrom: (1.1.12 upstream) (2.2.6 sid)
  • Revision ID: james.westby@ubuntu.com-20091023123820-rxt21lmekscxbkbt
Tags: 0.15.4-1ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - debian/control:
    + Don't build-depends on libmikmod2-dev (Debian bug #510675).
    + Move avahi-daemon from Suggests field to Recommends field.
  - debian/mpd.init.d:
    + Read mpd user from mpd.conf.
* Also fixes LP: #332332.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
1
/*
 
2
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 
3
 * http://www.musicpd.org
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License as published by
11
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
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
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
 */
18
19
 
19
20
#include "log.h"
20
21
#include "conf.h"
 
22
#include "utils.h"
 
23
#include "config.h"
21
24
 
22
25
#include <assert.h>
23
26
#include <sys/types.h>
30
33
#include <time.h>
31
34
#include <unistd.h>
32
35
#include <errno.h>
33
 
#include <pthread.h>
34
36
#include <glib.h>
35
37
 
 
38
#ifdef HAVE_SYSLOG
 
39
#include <syslog.h>
 
40
#endif
 
41
 
 
42
#undef G_LOG_DOMAIN
 
43
#define G_LOG_DOMAIN "log"
 
44
 
36
45
#define LOG_LEVEL_SECURE G_LOG_LEVEL_INFO
37
46
 
38
47
#define LOG_DATE_BUF_SIZE 16
39
48
#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
40
49
 
41
 
static unsigned int log_threshold = G_LOG_LEVEL_MESSAGE;
 
50
static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE;
42
51
 
43
52
static const char *log_charset;
44
53
 
45
54
static bool stdout_mode = true;
46
 
static int out_fd = -1;
47
 
static int err_fd = -1;
 
55
static int out_fd;
48
56
static const char *out_filename;
49
 
static const char *err_filename;
50
57
 
51
 
static void redirect_logs(void)
 
58
static void redirect_logs(int fd)
52
59
{
53
 
        assert(out_fd >= 0);
54
 
        assert(err_fd >= 0);
55
 
        if (dup2(out_fd, STDOUT_FILENO) < 0)
56
 
                FATAL("problems dup2 stdout : %s\n", strerror(errno));
57
 
        if (dup2(err_fd, STDERR_FILENO) < 0)
58
 
                FATAL("problems dup2 stderr : %s\n", strerror(errno));
 
60
        assert(fd >= 0);
 
61
        if (dup2(fd, STDOUT_FILENO) < 0)
 
62
                g_error("problems dup2 stdout : %s\n", strerror(errno));
 
63
        if (dup2(fd, STDERR_FILENO) < 0)
 
64
                g_error("problems dup2 stderr : %s\n", strerror(errno));
59
65
}
60
66
 
61
67
static const char *log_date(void)
82
88
}
83
89
 
84
90
static void
85
 
mpd_log_func(const gchar *log_domain,
86
 
             G_GNUC_UNUSED GLogLevelFlags log_level,
87
 
             const gchar *message, G_GNUC_UNUSED gpointer user_data)
 
91
file_log_func(const gchar *log_domain,
 
92
              GLogLevelFlags log_level,
 
93
              const gchar *message, G_GNUC_UNUSED gpointer user_data)
88
94
{
89
 
        FILE *file = log_level <= G_LOG_LEVEL_WARNING
90
 
                ? stderr : stdout;
91
95
        char *converted;
92
96
 
93
 
        if (log_level > (int)log_threshold)
 
97
        if (log_level > log_threshold)
94
98
                return;
95
99
 
96
100
        if (log_charset != NULL) {
105
109
        if (log_domain == NULL)
106
110
                log_domain = "";
107
111
 
108
 
        fprintf(file, "%s%s%s%.*s\n",
 
112
        fprintf(stderr, "%s%s%s%.*s\n",
109
113
                stdout_mode ? "" : log_date(),
110
114
                log_domain, *log_domain == 0 ? "" : ": ",
111
115
                chomp_length(message), message);
113
117
        g_free(converted);
114
118
}
115
119
 
116
 
void initLog(bool verbose)
117
 
{
118
 
        ConfigParam *param;
 
120
static void
 
121
log_init_stdout(void)
 
122
{
 
123
        g_log_set_default_handler(file_log_func, NULL);
 
124
}
 
125
 
 
126
static int
 
127
open_log_file(void)
 
128
{
 
129
        assert(out_filename != NULL);
 
130
 
 
131
        return open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
 
132
}
 
133
 
 
134
static void
 
135
log_init_file(const char *path, unsigned line)
 
136
{
 
137
        out_filename = path;
 
138
        out_fd = open_log_file();
 
139
        if (out_fd < 0)
 
140
                g_error("problem opening log file \"%s\" (config line %u) for "
 
141
                        "writing\n", path, line);
 
142
 
 
143
        g_log_set_default_handler(file_log_func, NULL);
 
144
}
 
145
 
 
146
#ifdef HAVE_SYSLOG
 
147
 
 
148
static int
 
149
glib_to_syslog_level(GLogLevelFlags log_level)
 
150
{
 
151
        switch (log_level & G_LOG_LEVEL_MASK) {
 
152
        case G_LOG_LEVEL_ERROR:
 
153
        case G_LOG_LEVEL_CRITICAL:
 
154
                return LOG_ERR;
 
155
 
 
156
        case G_LOG_LEVEL_WARNING:
 
157
                return LOG_WARNING;
 
158
 
 
159
        case G_LOG_LEVEL_MESSAGE:
 
160
                return LOG_NOTICE;
 
161
 
 
162
        case G_LOG_LEVEL_INFO:
 
163
                return LOG_INFO;
 
164
 
 
165
        case G_LOG_LEVEL_DEBUG:
 
166
                return LOG_DEBUG;
 
167
 
 
168
        default:
 
169
                return LOG_NOTICE;
 
170
        }
 
171
}
 
172
 
 
173
static void
 
174
syslog_log_func(const gchar *log_domain,
 
175
                GLogLevelFlags log_level, const gchar *message,
 
176
                G_GNUC_UNUSED gpointer user_data)
 
177
{
 
178
        if (stdout_mode) {
 
179
                /* fall back to the file log function during
 
180
                   startup */
 
181
                file_log_func(log_domain, log_level,
 
182
                              message, user_data);
 
183
                return;
 
184
        }
 
185
 
 
186
        if (log_level > log_threshold)
 
187
                return;
 
188
 
 
189
        if (log_domain == NULL)
 
190
                log_domain = "";
 
191
 
 
192
        syslog(glib_to_syslog_level(log_level), "%s%s%.*s",
 
193
               log_domain, *log_domain == 0 ? "" : ": ",
 
194
               chomp_length(message), message);
 
195
}
 
196
 
 
197
static void
 
198
log_init_syslog(void)
 
199
{
 
200
        assert(out_filename == NULL);
 
201
 
 
202
        openlog(PACKAGE, 0, LOG_DAEMON);
 
203
        g_log_set_default_handler(syslog_log_func, NULL);
 
204
}
 
205
 
 
206
#endif
 
207
 
 
208
static inline GLogLevelFlags
 
209
parse_log_level(const char *value, unsigned line)
 
210
{
 
211
        if (0 == strcmp(value, "default"))
 
212
                return G_LOG_LEVEL_MESSAGE;
 
213
        if (0 == strcmp(value, "secure"))
 
214
                return LOG_LEVEL_SECURE;
 
215
        else if (0 == strcmp(value, "verbose"))
 
216
                return G_LOG_LEVEL_DEBUG;
 
217
        else {
 
218
                g_error("unknown log level \"%s\" at line %u\n",
 
219
                        value, line);
 
220
                return G_LOG_LEVEL_MESSAGE;
 
221
        }
 
222
}
 
223
 
 
224
void
 
225
log_early_init(bool verbose)
 
226
{
 
227
        if (verbose)
 
228
                log_threshold = G_LOG_LEVEL_DEBUG;
 
229
 
 
230
        log_init_stdout();
 
231
}
 
232
 
 
233
void log_init(bool verbose, bool use_stdout)
 
234
{
 
235
        const struct config_param *param;
119
236
 
120
237
        g_get_charset(&log_charset);
121
238
 
122
 
        g_log_set_default_handler(mpd_log_func, NULL);
123
 
 
124
 
        /* unbuffer stdout, stderr is unbuffered by default, leave it */
125
 
        setvbuf(stdout, (char *)NULL, _IONBF, 0);
126
 
 
127
 
        if (verbose) {
128
 
                log_threshold = G_LOG_LEVEL_DEBUG;
129
 
                return;
130
 
        }
131
 
        if (!(param = getConfigParam(CONF_LOG_LEVEL)))
132
 
                return;
133
 
        if (0 == strcmp(param->value, "default")) {
134
 
                log_threshold = G_LOG_LEVEL_MESSAGE;
135
 
        } else if (0 == strcmp(param->value, "secure")) {
136
 
                log_threshold = LOG_LEVEL_SECURE;
137
 
        } else if (0 == strcmp(param->value, "verbose")) {
138
 
                log_threshold = G_LOG_LEVEL_DEBUG;
 
239
        if (verbose)
 
240
                log_threshold = G_LOG_LEVEL_DEBUG;
 
241
        else if ((param = config_get_param(CONF_LOG_LEVEL)) != NULL)
 
242
                log_threshold = parse_log_level(param->value, param->line);
 
243
 
 
244
        if (use_stdout) {
 
245
                log_init_stdout();
139
246
        } else {
140
 
                FATAL("unknown log level \"%s\" at line %i\n",
141
 
                      param->value, param->line);
 
247
                param = config_get_param(CONF_LOG_FILE);
 
248
                if (param == NULL) {
 
249
#ifdef HAVE_SYSLOG
 
250
                        /* no configuration: default to syslog (if
 
251
                           available) */
 
252
                        log_init_syslog();
 
253
#else
 
254
                        g_error("config parameter \"%s\" not found\n",
 
255
                                CONF_LOG_FILE);
 
256
#endif
 
257
#ifdef HAVE_SYSLOG
 
258
                } else if (strcmp(param->value, "syslog") == 0) {
 
259
                        log_init_syslog();
 
260
#endif
 
261
                } else {
 
262
                        const char *path = config_get_path(CONF_LOG_FILE);
 
263
                        assert(path != NULL);
 
264
 
 
265
                        log_init_file(path, param->line);
 
266
                }
142
267
        }
143
268
}
144
269
 
145
 
void open_log_files(bool use_stdout)
146
 
{
147
 
        mode_t prev;
148
 
        ConfigParam *param;
149
 
 
150
 
        if (use_stdout)
151
 
                return;
152
 
 
153
 
        prev = umask(0066);
154
 
        param = parseConfigFilePath(CONF_LOG_FILE, 1);
155
 
        out_filename = param->value;
156
 
        out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
157
 
        if (out_fd < 0)
158
 
                FATAL("problem opening log file \"%s\" (config line %i) for "
159
 
                      "writing\n", param->value, param->line);
160
 
 
161
 
        param = parseConfigFilePath(CONF_ERROR_FILE, 1);
162
 
        err_filename = param->value;
163
 
        err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
164
 
        if (err_fd < 0)
165
 
                FATAL("problem opening error file \"%s\" (config line %i) for "
166
 
                      "writing\n", param->value, param->line);
167
 
 
168
 
        umask(prev);
169
 
}
170
 
 
171
270
void setup_log_output(bool use_stdout)
172
271
{
173
272
        fflush(NULL);
174
273
        if (!use_stdout) {
175
 
                redirect_logs();
 
274
                if (out_filename != NULL) {
 
275
                        redirect_logs(out_fd);
 
276
                        close(out_fd);
 
277
                }
 
278
 
176
279
                stdout_mode = false;
177
280
                log_charset = NULL;
178
281
        }
179
282
}
180
283
 
181
 
#define log_func(func,level) \
182
 
G_GNUC_PRINTF(1, 2) void func(const char *fmt, ...) \
183
 
{ \
184
 
        if (level <= (int)log_threshold) { \
185
 
                va_list args; \
186
 
                va_start(args, fmt); \
187
 
                g_logv(NULL, level, fmt, args); \
188
 
                va_end(args); \
189
 
        } \
190
 
}
191
 
 
192
 
log_func(ERROR, G_LOG_LEVEL_WARNING)
193
 
log_func(WARNING, G_LOG_LEVEL_WARNING)
194
 
log_func(LOG, G_LOG_LEVEL_MESSAGE)
195
 
log_func(SECURE, LOG_LEVEL_SECURE)
196
 
log_func(DEBUG, G_LOG_LEVEL_DEBUG)
197
 
 
198
 
#undef log_func
199
 
 
200
 
G_GNUC_PRINTF(1, 2) G_GNUC_NORETURN void FATAL(const char *fmt, ...)
201
 
{
202
 
        va_list args;
203
 
        va_start(args, fmt);
204
 
        g_logv(NULL, G_LOG_LEVEL_ERROR, fmt, args);
205
 
        va_end(args);
206
 
        exit(EXIT_FAILURE);
207
 
}
208
 
 
209
284
int cycle_log_files(void)
210
285
{
211
 
        mode_t prev;
 
286
        int fd;
212
287
 
213
 
        if (stdout_mode)
 
288
        if (stdout_mode || out_filename == NULL)
214
289
                return 0;
215
290
        assert(out_filename);
216
 
        assert(err_filename);
217
291
 
218
 
        DEBUG("Cycling log files...\n");
 
292
        g_debug("Cycling log files...\n");
219
293
        close_log_files();
220
294
 
221
 
        prev = umask(0066);
222
 
 
223
 
        out_fd = open(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
224
 
        if (out_fd < 0) {
225
 
                ERROR("error re-opening log file: %s\n", out_filename);
226
 
                return -1;
227
 
        }
228
 
 
229
 
        err_fd = open(err_filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
230
 
        if (err_fd < 0) {
231
 
                ERROR("error re-opening error file: %s\n", err_filename);
232
 
                return -1;
233
 
        }
234
 
 
235
 
        umask(prev);
236
 
 
237
 
        redirect_logs();
238
 
        DEBUG("Done cycling log files\n");
 
295
        fd = open_log_file();
 
296
        if (fd < 0) {
 
297
                g_warning("error re-opening log file: %s\n", out_filename);
 
298
                return -1;
 
299
        }
 
300
 
 
301
        redirect_logs(fd);
 
302
        g_debug("Done cycling log files\n");
239
303
        return 0;
240
304
}
241
305
 
243
307
{
244
308
        if (stdout_mode)
245
309
                return;
246
 
        assert(out_fd >= 0);
247
 
        assert(err_fd >= 0);
248
 
        close(out_fd);
249
 
        close(err_fd);
 
310
 
 
311
#ifdef HAVE_SYSLOG
 
312
        if (out_filename == NULL)
 
313
                closelog();
 
314
#endif
250
315
}
251
316