From f7acd4bdab7092700a9386802a0ec86d4362e58c Mon Sep 17 00:00:00 2001 From: Vincent Becker Date: Fri, 18 Mar 2011 11:23:46 +0100 Subject: log: Add a new log target to a file descriptor This patch enables logging of text debug messages (pa_log feature) into a file or a device driver. Example : pulseaudio --log-target=file:./mylog.txt (Minor tweaks by Colin + Arun) --- src/daemon/cmdline.c | 5 +++-- src/daemon/daemon-conf.c | 21 +++++++++++++++++++++ src/pulsecore/log.c | 27 +++++++++++++++++++++++++++ src/pulsecore/log.h | 5 +++++ 4 files changed, 56 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index f6cdcdc8..4854affc 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -145,7 +145,8 @@ void pa_cmdline_help(const char *argv0) { " this time passed\n" " --log-level[=LEVEL] Increase or set verbosity level\n" " -v Increase the verbosity level\n" - " --log-target={auto,syslog,stderr} Specify the log target\n" + " --log-target={auto,syslog,stderr,file:PATH}\n" + " Specify the log target\n" " --log-meta[=BOOL] Include code location in log messages\n" " --log-time[=BOOL] Include timestamps in log messages\n" " --log-backtrace=FRAMES Include a backtrace in log messages\n" @@ -318,7 +319,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_LOG_TARGET: if (pa_daemon_conf_set_log_target(conf, optarg) < 0) { - pa_log(_("Invalid log target: use either 'syslog', 'stderr' or 'auto'.")); + pa_log(_("Invalid log target: use either 'syslog', 'stderr' or 'auto' or a valid file name 'file:'.")); goto fail; } break; diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index e38e67ad..ce93dbc6 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef HAVE_SCHED_H #include @@ -166,6 +167,9 @@ pa_daemon_conf* pa_daemon_conf_new(void) { void pa_daemon_conf_free(pa_daemon_conf *c) { pa_assert(c); + + pa_log_set_fd(-1); + pa_xfree(c->script_commands); pa_xfree(c->dl_search_path); pa_xfree(c->default_script_file); @@ -211,6 +215,23 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) { c->log_level = PA_LOG_WARN; else if (pa_startswith(string, "err")) c->log_level = PA_LOG_ERROR; + else if (pa_startswith(string, "file:")) { + char file_path[512]; + int log_fd; + + pa_strlcpy(file_path, string + 5, sizeof(file_path)); + + /* Open target file with user rights */ + if ((log_fd = open(file_path, O_RDWR|O_TRUNC|O_CREAT, S_IRWXU)) >= 0) { + c->auto_log_target = 0; + c->log_target = PA_LOG_FD; + pa_log_set_fd(log_fd); + } + else { + printf("Failed to open target file %s, error : %s\n", file_path, pa_cstrerror(errno)); + return -1; + } + } else return -1; diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 2c0e267a..b12cbf0c 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -70,6 +70,7 @@ static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_ static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0; static pa_log_flags_t flags = 0, flags_override = 0; static pa_bool_t no_rate_limit = FALSE; +static int log_fd = -1; #ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { @@ -128,6 +129,15 @@ void pa_log_set_flags(pa_log_flags_t _flags, pa_log_merge_t merge) { flags = _flags; } +void pa_log_set_fd(int fd) { + if (fd >= 0) + log_fd = fd; + else if (log_fd >= 0) { + pa_close(log_fd); + log_fd = -1; + } +} + void pa_log_set_show_backtrace(unsigned nlevels) { show_backtrace = nlevels; } @@ -399,6 +409,23 @@ void pa_log_levelv_meta( } #endif + case PA_LOG_FD: { + if (log_fd >= 0) { + char metadata[256]; + + pa_snprintf(metadata, sizeof(metadata), "\n%c %s %s", level_to_char[level], timestamp, location); + + if ((write(log_fd, metadata, strlen(metadata)) < 0) || (write(log_fd, t, strlen(t)) < 0)) { + saved_errno = errno; + pa_log_set_fd(-1); + fprintf(stderr, "%s\n", "Error writing logs to a file descriptor. Redirect log messages to console."); + fprintf(stderr, "%s %s\n", metadata, t); + pa_log_set_target(PA_LOG_STDERR); + } + } + + break; + } case PA_LOG_NULL: default: break; diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index 1fd38d44..ad04e7bd 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -36,6 +36,7 @@ typedef enum pa_log_target { PA_LOG_STDERR, /* default */ PA_LOG_SYSLOG, PA_LOG_NULL, /* to /dev/null */ + PA_LOG_FD, /* to a file descriptor, e.g. a char device */ PA_LOG_TARGET_MAX } pa_log_target_t; @@ -74,6 +75,10 @@ void pa_log_set_level(pa_log_level_t l); /* Set flags */ void pa_log_set_flags(pa_log_flags_t flags, pa_log_merge_t merge); +/* Set the file descriptor of the logging device. + Daemon conf is in charge of opening this device */ +void pa_log_set_fd(int fd); + /* Enable backtrace */ void pa_log_set_show_backtrace(unsigned nlevels); -- cgit