mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-31 22:25:33 -04:00
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:
parent
e05c12f28b
commit
b0bf132f8f
7 changed files with 205 additions and 102 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue