cli, log: Improve the set-log-target functionality

Add a new log target 'newfile:PATH', and refactoring 'pa_log_target_type'.

Signed-off-by: Shuai Fan <shuai900217@126.com>
This commit is contained in:
Shuai Fan 2013-06-19 11:59:08 +08:00 committed by Tanu Kaskinen
parent e05c12f28b
commit b0bf132f8f
7 changed files with 205 additions and 102 deletions

View file

@ -263,7 +263,7 @@ USA.
<option> <option>
<p><opt>set-log-target</opt> <arg>target</arg></p> <p><opt>set-log-target</opt> <arg>target</arg></p>
<optdesc><p>Change the log target (null, auto, syslog, stderr, file:PATH).</p></optdesc> <optdesc><p>Change the log target (null, auto, syslog, stderr, file:PATH, newfile:PATH).</p></optdesc>
</option> </option>
<option> <option>

View file

@ -73,12 +73,11 @@ static const pa_daemon_conf default_conf = {
.flat_volumes = TRUE, .flat_volumes = TRUE,
.exit_idle_time = 20, .exit_idle_time = 20,
.scache_idle_time = 20, .scache_idle_time = 20,
.auto_log_target = 1,
.script_commands = NULL, .script_commands = NULL,
.dl_search_path = NULL, .dl_search_path = NULL,
.load_default_script_file = TRUE, .load_default_script_file = TRUE,
.default_script_file = NULL, .default_script_file = NULL,
.log_target = PA_LOG_SYSLOG, .log_target = NULL,
.log_level = PA_LOG_NOTICE, .log_level = PA_LOG_NOTICE,
.log_backtrace = 0, .log_backtrace = 0,
.log_meta = FALSE, .log_meta = FALSE,
@ -167,77 +166,31 @@ pa_daemon_conf *pa_daemon_conf_new(void) {
void pa_daemon_conf_free(pa_daemon_conf *c) { void pa_daemon_conf_free(pa_daemon_conf *c) {
pa_assert(c); pa_assert(c);
pa_log_set_fd(-1);
pa_xfree(c->script_commands); pa_xfree(c->script_commands);
pa_xfree(c->dl_search_path); pa_xfree(c->dl_search_path);
pa_xfree(c->default_script_file); pa_xfree(c->default_script_file);
if (c->log_target)
pa_log_target_free(c->log_target);
pa_xfree(c->config_file); pa_xfree(c->config_file);
pa_xfree(c); pa_xfree(c);
} }
#define PA_LOG_MAX_SUFFIX_NUMBER 100
int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) { int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
pa_log_target *log_target = NULL;
pa_assert(c); pa_assert(c);
pa_assert(string); pa_assert(string);
if (pa_streq(string, "auto")) if (!pa_streq(string, "auto")) {
c->auto_log_target = 1; log_target = pa_log_parse_target(string);
else if (pa_streq(string, "syslog")) {
c->auto_log_target = 0;
c->log_target = PA_LOG_SYSLOG;
} else if (pa_streq(string, "stderr")) {
c->auto_log_target = 0;
c->log_target = PA_LOG_STDERR;
} else if (pa_startswith(string, "file:")) {
char file_path[512];
int log_fd;
pa_strlcpy(file_path, string + 5, sizeof(file_path)); if (!log_target)
/* Open target file with user rights */
if ((log_fd = open(file_path, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR | S_IWUSR)) >= 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; return -1;
} }
} else if (pa_startswith(string, "newfile:")) {
char file_path[512];
int log_fd;
int version = 0;
int left_size;
char *p;
pa_strlcpy(file_path, string + 8, sizeof(file_path)); c->log_target = log_target;
left_size = sizeof(file_path) - strlen(file_path);
p = file_path + strlen(file_path);
do {
memset(p, 0, left_size);
if (version > 0)
pa_snprintf(p, left_size, ".%d", version);
} while (++version <= PA_LOG_MAX_SUFFIX_NUMBER &&
(log_fd = open(file_path, O_RDWR|O_TRUNC|O_CREAT|O_EXCL, S_IRUSR | S_IWUSR)) < 0);
if (version > PA_LOG_MAX_SUFFIX_NUMBER) {
memset(p, 0, left_size);
printf("Tried to open target files '%s', '%s.1', '%s.2' ... '%s.%d', but all failed.\n",
file_path, file_path, file_path, file_path, PA_LOG_MAX_SUFFIX_NUMBER - 1);
return -1;
} else {
printf("Opened target file %s\n", file_path);
c->auto_log_target = 0;
c->log_target = PA_LOG_FD;
pa_log_set_fd(log_fd);
}
} else
return -1;
return 0; return 0;
} }
@ -755,6 +708,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
pa_strbuf *s; pa_strbuf *s;
char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
char *log_target = NULL;
pa_assert(c); pa_assert(c);
@ -765,6 +719,9 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
pa_assert(c->log_level < PA_LOG_LEVEL_MAX); pa_assert(c->log_level < PA_LOG_LEVEL_MAX);
if (c->log_target)
log_target = pa_log_target_to_string(c->log_target);
pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize)); pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail)); pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority)); pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
@ -787,7 +744,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path)); pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c))); pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file)); pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing)); pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
@ -846,5 +803,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
#endif #endif
#endif #endif
pa_xfree(log_target);
return pa_strbuf_tostring_free(s); return pa_strbuf_tostring_free(s);
} }

View file

@ -80,12 +80,11 @@ typedef struct pa_daemon_conf {
pa_server_type_t local_server_type; pa_server_type_t local_server_type;
int exit_idle_time, int exit_idle_time,
scache_idle_time, scache_idle_time,
auto_log_target,
realtime_priority, realtime_priority,
nice_level, nice_level,
resample_method; resample_method;
char *script_commands, *dl_search_path, *default_script_file; char *script_commands, *dl_search_path, *default_script_file;
pa_log_target_t log_target; pa_log_target *log_target;
pa_log_level_t log_level; pa_log_level_t log_level;
unsigned log_backtrace; unsigned log_backtrace;
char *config_file; char *config_file;

View file

@ -499,8 +499,14 @@ int main(int argc, char *argv[]) {
goto finish; goto finish;
} }
if (conf->log_target)
pa_log_set_target(conf->log_target);
else {
pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL };
pa_log_set_target(&target);
}
pa_log_set_level(conf->log_level); pa_log_set_level(conf->log_level);
pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
if (conf->log_meta) if (conf->log_meta)
pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET); pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
if (conf->log_time) if (conf->log_time)
@ -810,8 +816,10 @@ int main(int argc, char *argv[]) {
daemon_pipe[0] = -1; daemon_pipe[0] = -1;
#endif #endif
if (conf->auto_log_target) if (!conf->log_target) {
pa_log_set_target(PA_LOG_SYSLOG); pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
pa_log_set_target(&target);
}
#ifdef HAVE_SETSID #ifdef HAVE_SETSID
if (setsid() < 0) { if (setsid() < 0) {
@ -1042,7 +1050,7 @@ int main(int argc, char *argv[]) {
c->cpu_info.cpu_type = PA_CPU_X86; c->cpu_info.cpu_type = PA_CPU_X86;
if (pa_cpu_init_arm(&(c->cpu_info.flags.arm))) if (pa_cpu_init_arm(&(c->cpu_info.flags.arm)))
c->cpu_info.cpu_type = PA_CPU_ARM; c->cpu_info.cpu_type = PA_CPU_ARM;
pa_cpu_init_orc(c->cpu_info); pa_cpu_init_orc(c->cpu_info);
} }
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);

View file

@ -188,7 +188,7 @@ static const struct command commands[] = {
{ "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
{ "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
{ "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
{ "set-log-target", pa_cli_command_log_target, "Change the log target (args: null,auto,syslog,stderr,file:PATH)", 2}, { "set-log-target", pa_cli_command_log_target, "Change the log target (args: null|auto|syslog|stderr|file:PATH|newfile:PATH)", 2},
{ "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2}, { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
{ "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2}, { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
{ "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2}, { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
@ -1501,6 +1501,7 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, p
static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
const char *m; const char *m;
pa_log_target *log_target = NULL;
pa_core_assert_ref(c); pa_core_assert_ref(c);
pa_assert(t); pa_assert(t);
@ -1508,34 +1509,30 @@ static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf
pa_assert(fail); pa_assert(fail);
if (!(m = pa_tokenizer_get(t, 1))) { if (!(m = pa_tokenizer_get(t, 1))) {
pa_strbuf_puts(buf, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n"); pa_strbuf_puts(buf, "You need to specify a log target (null|auto|syslog|stderr|file:PATH|newfile:PATH).\n");
return -1; return -1;
} }
if (pa_streq(m, "null")) /* 'auto' is actually the effect with 'stderr' */
pa_log_set_target(PA_LOG_NULL); if (pa_streq(m, "auto"))
else if (pa_streq(m, "syslog")) log_target = pa_log_target_new(PA_LOG_STDERR, NULL);
pa_log_set_target(PA_LOG_SYSLOG); else {
else if (pa_streq(m, "stderr") || pa_streq(m, "auto")) { log_target = pa_log_parse_target(m);
/* 'auto' is actually the effect with 'stderr' */
pa_log_set_target(PA_LOG_STDERR);
} else if (pa_startswith(m, "file:")) {
const char *file_path = m + 5;
int log_fd;
/* Open target file with user rights */ if (!log_target) {
if ((log_fd = open(file_path, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR | S_IWUSR)) >= 0) { pa_strbuf_puts(buf, "Invalid log target.\n");
pa_log_set_target(PA_LOG_FD);
pa_log_set_fd(log_fd);
} else {
pa_strbuf_printf(buf, "Failed to open target file %s, error : %s\n", file_path, pa_cstrerror(errno));
return -1; return -1;
} }
} else { }
pa_strbuf_puts(buf, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n");
if (pa_log_set_target(log_target) < 0) {
pa_strbuf_puts(buf, "Failed to set log target.\n");
pa_log_target_free(log_target);
return -1; return -1;
} }
pa_log_target_free(log_target);
return 0; return 0;
} }

View file

@ -29,6 +29,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#ifdef HAVE_EXECINFO_H #ifdef HAVE_EXECINFO_H
#include <execinfo.h> #include <execinfo.h>
@ -47,9 +48,11 @@
#include <pulsecore/macro.h> #include <pulsecore/macro.h>
#include <pulsecore/core-util.h> #include <pulsecore/core-util.h>
#include <pulsecore/core-error.h>
#include <pulsecore/once.h> #include <pulsecore/once.h>
#include <pulsecore/ratelimit.h> #include <pulsecore/ratelimit.h>
#include <pulsecore/thread.h> #include <pulsecore/thread.h>
#include <pulsecore/i18n.h>
#include "log.h" #include "log.h"
@ -63,9 +66,11 @@
#define ENV_LOG_BACKTRACE "PULSE_LOG_BACKTRACE" #define ENV_LOG_BACKTRACE "PULSE_LOG_BACKTRACE"
#define ENV_LOG_BACKTRACE_SKIP "PULSE_LOG_BACKTRACE_SKIP" #define ENV_LOG_BACKTRACE_SKIP "PULSE_LOG_BACKTRACE_SKIP"
#define ENV_LOG_NO_RATELIMIT "PULSE_LOG_NO_RATE_LIMIT" #define ENV_LOG_NO_RATELIMIT "PULSE_LOG_NO_RATE_LIMIT"
#define LOG_MAX_SUFFIX_NUMBER 99
static char *ident = NULL; /* in local charset format */ static char *ident = NULL; /* in local charset format */
static pa_log_target_t target = PA_LOG_STDERR, target_override; static pa_log_target target = { PA_LOG_STDERR, NULL };
static pa_log_target_type_t target_override;
static pa_bool_t target_override_set = FALSE; static pa_bool_t target_override_set = FALSE;
static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_LOG_ERROR; static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_LOG_ERROR;
static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0; static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0;
@ -113,10 +118,65 @@ void pa_log_set_level(pa_log_level_t l) {
maximum_level = l; maximum_level = l;
} }
void pa_log_set_target(pa_log_target_t t) { int pa_log_set_target(pa_log_target *t) {
pa_assert(t < PA_LOG_TARGET_MAX); int fd = -1;
int old_fd;
target = t; pa_assert(t);
switch (t->type) {
case PA_LOG_STDERR:
case PA_LOG_SYSLOG:
case PA_LOG_NULL:
break;
case PA_LOG_FILE:
if ((fd = pa_open_cloexec(t->file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
pa_log(_("Failed to open target file '%s'."), t->file);
return -1;
}
break;
case PA_LOG_NEWFILE: {
char *file_path;
char *p;
unsigned version;
file_path = pa_sprintf_malloc("%s.xx", t->file);
p = file_path + strlen(t->file);
for (version = 0; version <= LOG_MAX_SUFFIX_NUMBER; version++) {
memset(p, 0, 3); /* Overwrite the ".xx" part in file_path with zero bytes. */
if (version > 0)
pa_snprintf(p, 4, ".%u", version); /* Why 4? ".xx" + termitating zero byte. */
if ((fd = pa_open_cloexec(file_path, O_WRONLY | O_TRUNC | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) >= 0)
break;
}
if (version > LOG_MAX_SUFFIX_NUMBER) {
pa_log(_("Tried to open target file '%s', '%s.1', '%s.2' ... '%s.%d', but all failed."),
file_path, file_path, file_path, file_path, LOG_MAX_SUFFIX_NUMBER);
pa_xfree(file_path);
return -1;
} else
pa_log_debug("Opened target file %s\n", file_path);
pa_xfree(file_path);
break;
}
}
target.type = t->type;
pa_xfree(target.file);
target.file = pa_xstrdup(t->file);
old_fd = log_fd;
log_fd = fd;
if (old_fd >= 0)
pa_close(old_fd);
return 0;
} }
void pa_log_set_flags(pa_log_flags_t _flags, pa_log_merge_t merge) { void pa_log_set_flags(pa_log_flags_t _flags, pa_log_merge_t merge) {
@ -276,7 +336,7 @@ void pa_log_levelv_meta(
char *t, *n; char *t, *n;
int saved_errno = errno; int saved_errno = errno;
char *bt = NULL; char *bt = NULL;
pa_log_target_t _target; pa_log_target_type_t _target;
pa_log_level_t _maximum_level; pa_log_level_t _maximum_level;
unsigned _show_backtrace; unsigned _show_backtrace;
pa_log_flags_t _flags; pa_log_flags_t _flags;
@ -290,7 +350,7 @@ void pa_log_levelv_meta(
init_defaults(); init_defaults();
_target = target_override_set ? target_override : target; _target = target_override_set ? target_override : target.type;
_maximum_level = PA_MAX(maximum_level, maximum_level_override); _maximum_level = PA_MAX(maximum_level, maximum_level_override);
_show_backtrace = PA_MAX(show_backtrace, show_backtrace_override); _show_backtrace = PA_MAX(show_backtrace, show_backtrace_override);
_flags = flags | flags_override; _flags = flags | flags_override;
@ -410,18 +470,20 @@ void pa_log_levelv_meta(
} }
#endif #endif
case PA_LOG_FD: { case PA_LOG_FILE:
case PA_LOG_NEWFILE: {
if (log_fd >= 0) { if (log_fd >= 0) {
char metadata[256]; char metadata[256];
pa_snprintf(metadata, sizeof(metadata), "\n%c %s %s", level_to_char[level], timestamp, location); 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)) { if ((write(log_fd, metadata, strlen(metadata)) < 0) || (write(log_fd, t, strlen(t)) < 0)) {
pa_log_target new_target = { .type = PA_LOG_STDERR, .file = NULL };
saved_errno = errno; saved_errno = errno;
pa_log_set_fd(-1); pa_log_set_fd(-1);
fprintf(stderr, "%s\n", "Error writing logs to a file descriptor. Redirect log messages to console."); fprintf(stderr, "%s\n", "Error writing logs to a file descriptor. Redirect log messages to console.");
fprintf(stderr, "%s %s\n", metadata, t); fprintf(stderr, "%s %s\n", metadata, t);
pa_log_set_target(PA_LOG_STDERR); pa_log_set_target(&new_target);
} }
} }
@ -473,3 +535,68 @@ pa_bool_t pa_log_ratelimit(pa_log_level_t level) {
return pa_ratelimit_test(&ratelimit, level); return pa_ratelimit_test(&ratelimit, level);
} }
pa_log_target *pa_log_target_new(pa_log_target_type_t type, const char *file) {
pa_log_target *t = NULL;
t = pa_xnew(pa_log_target, 1);
t->type = type;
t->file = pa_xstrdup(file);
return t;
}
void pa_log_target_free(pa_log_target *t) {
pa_assert(t);
pa_xfree(t->file);
pa_xfree(t);
}
pa_log_target *pa_log_parse_target(const char *string) {
pa_log_target *t = NULL;
pa_assert(string);
if (pa_streq(string, "stderr"))
t = pa_log_target_new(PA_LOG_STDERR, NULL);
else if (pa_streq(string, "syslog"))
t = pa_log_target_new(PA_LOG_SYSLOG, NULL);
else if (pa_streq(string, "null"))
t = pa_log_target_new(PA_LOG_NULL, NULL);
else if (pa_startswith(string, "file:"))
t = pa_log_target_new(PA_LOG_FILE, string + 5);
else if (pa_startswith(string, "newfile:"))
t = pa_log_target_new(PA_LOG_NEWFILE, string + 8);
else
pa_log(_("Invalid log target."));
return t;
}
char *pa_log_target_to_string(const pa_log_target *t) {
char *string = NULL;
pa_assert(t);
switch (t->type) {
case PA_LOG_STDERR:
string = pa_xstrdup("stderr");
break;
case PA_LOG_SYSLOG:
string = pa_xstrdup("syslog");
break;
case PA_LOG_NULL:
string = pa_xstrdup("null");
break;
case PA_LOG_FILE:
string = pa_sprintf_malloc("file:%s", t->file);
break;
case PA_LOG_NEWFILE:
string = pa_sprintf_malloc("newfile:%s", t->file);
break;
}
return string;
}

View file

@ -32,13 +32,13 @@
/* A simple logging subsystem */ /* A simple logging subsystem */
/* Where to log to */ /* Where to log to */
typedef enum pa_log_target { typedef enum pa_log_target_type {
PA_LOG_STDERR, /* default */ PA_LOG_STDERR, /* default */
PA_LOG_SYSLOG, PA_LOG_SYSLOG,
PA_LOG_NULL, /* to /dev/null */ PA_LOG_NULL, /* to /dev/null */
PA_LOG_FD, /* to a file descriptor, e.g. a char device */ PA_LOG_FILE, /* to a user specified file */
PA_LOG_TARGET_MAX PA_LOG_NEWFILE, /* with an automatic suffix to avoid overwriting anything */
} pa_log_target_t; } pa_log_target_type_t;
typedef enum pa_log_level { typedef enum pa_log_level {
PA_LOG_ERROR = 0, /* Error messages */ PA_LOG_ERROR = 0, /* Error messages */
@ -63,11 +63,16 @@ typedef enum pa_log_merge {
PA_LOG_RESET PA_LOG_RESET
} pa_log_merge_t; } pa_log_merge_t;
typedef struct {
pa_log_target_type_t type;
char *file;
} pa_log_target;
/* Set an identification for the current daemon. Used when logging to syslog. */ /* Set an identification for the current daemon. Used when logging to syslog. */
void pa_log_set_ident(const char *p); void pa_log_set_ident(const char *p);
/* Set a log target. */ /* Set a log target. */
void pa_log_set_target(pa_log_target_t t); int pa_log_set_target(pa_log_target *t);
/* Maximal log level */ /* Maximal log level */
void pa_log_set_level(pa_log_level_t l); void pa_log_set_level(pa_log_level_t l);
@ -109,6 +114,14 @@ void pa_log_levelv(
const char *format, const char *format,
va_list ap); va_list ap);
pa_log_target *pa_log_target_new(pa_log_target_type_t type, const char *file);
void pa_log_target_free(pa_log_target *t);
pa_log_target *pa_log_parse_target(const char *string);
char *pa_log_target_to_string(const pa_log_target *t);
#if __STDC_VERSION__ >= 199901L #if __STDC_VERSION__ >= 199901L
/* ISO varargs available */ /* ISO varargs available */