summaryrefslogtreecommitdiffstats
path: root/src/basic/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/log.c')
-rw-r--r--src/basic/log.c142
1 files changed, 118 insertions, 24 deletions
diff --git a/src/basic/log.c b/src/basic/log.c
index 7a44300..13ad19a 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -49,6 +49,12 @@ static void *log_syntax_callback_userdata = NULL;
static LogTarget log_target = LOG_TARGET_CONSOLE;
static int log_max_level = LOG_INFO;
+static int log_target_max_level[] = {
+ [LOG_TARGET_CONSOLE] = INT_MAX,
+ [LOG_TARGET_KMSG] = INT_MAX,
+ [LOG_TARGET_SYSLOG] = INT_MAX,
+ [LOG_TARGET_JOURNAL] = INT_MAX,
+};
static int log_facility = LOG_DAEMON;
static bool ratelimit_kmsg = true;
@@ -69,6 +75,7 @@ static bool upgrade_syslog_to_journal = false;
static bool always_reopen_console = false;
static bool open_when_needed = false;
static bool prohibit_ipc = false;
+static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
/* Akin to glibc's __abort_msg; which is private and we hence cannot
* use here. */
@@ -249,7 +256,7 @@ fail:
return r;
}
-static bool stderr_is_journal(void) {
+bool stderr_is_journal(void) {
_cleanup_free_ char *w = NULL;
const char *e;
uint64_t dev, ino;
@@ -389,7 +396,7 @@ void log_forget_fds(void) {
}
void log_set_max_level(int level) {
- assert(level == LOG_NULL || (level & LOG_PRIMASK) == level);
+ assert(level == LOG_NULL || LOG_PRI(level) == level);
log_max_level = level;
@@ -414,7 +421,7 @@ static bool check_console_fd_is_tty(void) {
return false;
if (console_fd_is_tty < 0)
- console_fd_is_tty = isatty(console_fd) > 0;
+ console_fd_is_tty = isatty_safe(console_fd);
return console_fd_is_tty;
}
@@ -443,6 +450,9 @@ static int write_to_console(
if (dumb < 0)
dumb = getenv_terminal_is_dumb();
+ if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_CONSOLE])
+ return 0;
+
if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
xsprintf(prefix, "<%i>", level);
iovec[n++] = IOVEC_MAKE_STRING(prefix);
@@ -528,6 +538,9 @@ static int write_to_syslog(
if (syslog_fd < 0)
return 0;
+ if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_SYSLOG])
+ return 0;
+
xsprintf(header_priority, "<%i>", level);
t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
@@ -597,6 +610,9 @@ static int write_to_kmsg(
if (kmsg_fd < 0)
return 0;
+ if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_KMSG])
+ return 0;
+
if (ratelimit_kmsg && !ratelimit_below(&ratelimit)) {
if (ratelimit_num_dropped(&ratelimit) > 1)
return 0;
@@ -724,6 +740,9 @@ static int write_to_journal(
if (journal_fd < 0)
return 0;
+ if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_JOURNAL])
+ return 0;
+
iovec_len = MIN(6 + _log_context_num_fields * 2, IOVEC_MAX);
iovec = newa(struct iovec, iovec_len);
@@ -769,7 +788,7 @@ int log_dispatch_internal(
return -ERRNO_VALUE(error);
/* Patch in LOG_DAEMON facility if necessary */
- if ((level & LOG_FACMASK) == 0)
+ if (LOG_FAC(level) == 0)
level |= log_facility;
if (open_when_needed)
@@ -987,9 +1006,13 @@ void log_assert_failed_return(
const char *file,
int line,
const char *func) {
+
+ if (assert_return_is_critical)
+ log_assert_failed(text, file, line, func);
+
PROTECT_ERRNO;
log_assert(LOG_DEBUG, text, file, line, func,
- "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
+ "Assertion '%s' failed at %s:%u, function %s(), ignoring.");
}
int log_oom_internal(int level, const char *file, int line, const char *func) {
@@ -1054,7 +1077,7 @@ int log_struct_internal(
log_target == LOG_TARGET_NULL)
return -ERRNO_VALUE(error);
- if ((level & LOG_FACMASK) == 0)
+ if (LOG_FAC(level) == 0)
level |= log_facility;
if (IN_SET(log_target,
@@ -1157,7 +1180,7 @@ int log_struct_iovec_internal(
log_target == LOG_TARGET_NULL)
return -ERRNO_VALUE(error);
- if ((level & LOG_FACMASK) == 0)
+ if (LOG_FAC(level) == 0)
level |= log_facility;
if (IN_SET(log_target, LOG_TARGET_AUTO,
@@ -1219,11 +1242,74 @@ int log_set_target_from_string(const char *e) {
int log_set_max_level_from_string(const char *e) {
int r;
- r = log_level_from_string(e);
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *prefix = NULL;
+ LogTarget target;
+ const char *colon;
+
+ r = extract_first_word(&e, &word, ",", 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ colon = strchr(word, ':');
+ if (!colon) {
+ r = log_level_from_string(word);
+ if (r < 0)
+ return r;
+
+ log_set_max_level(r);
+ continue;
+ }
+
+ prefix = strndup(word, colon - word);
+ if (!prefix)
+ return -ENOMEM;
+
+ target = log_target_from_string(prefix);
+ if (target < 0)
+ return target;
+
+ if (target >= _LOG_TARGET_SINGLE_MAX)
+ return -EINVAL;
+
+ r = log_level_from_string(colon + 1);
+ if (r < 0)
+ return r;
+
+ log_target_max_level[target] = r;
+ }
+
+ return 0;
+}
+
+int log_max_levels_to_string(int level, char **ret) {
+ _cleanup_free_ char *s = NULL;
+ int r;
+
+ assert(ret);
+
+ r = log_level_to_string_alloc(level, &s);
if (r < 0)
return r;
- log_set_max_level(r);
+ for (LogTarget target = 0; target < _LOG_TARGET_SINGLE_MAX; target++) {
+ _cleanup_free_ char *l = NULL;
+
+ if (log_target_max_level[target] == INT_MAX)
+ continue;
+
+ r = log_level_to_string_alloc(log_target_max_level[target], &l);
+ if (r < 0)
+ return r;
+
+ r = strextendf_with_separator(&s, ",", "%s:%s", log_target_to_string(target), l);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -1238,6 +1324,14 @@ static int log_set_ratelimit_kmsg_from_string(const char *e) {
return 0;
}
+void log_set_assert_return_is_critical(bool b) {
+ assert_return_is_critical = b;
+}
+
+bool log_get_assert_return_is_critical(void) {
+ return assert_return_is_critical;
+}
+
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
/*
@@ -1258,7 +1352,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
if (log_set_target_from_string(value) < 0)
- log_warning("Failed to parse log target '%s'. Ignoring.", value);
+ log_warning("Failed to parse log target '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
@@ -1266,32 +1360,32 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
if (log_set_max_level_from_string(value) < 0)
- log_warning("Failed to parse log level '%s'. Ignoring.", value);
+ log_warning("Failed to parse log level setting '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
if (log_show_color_from_string(value ?: "1") < 0)
- log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
+ log_warning("Failed to parse log color setting '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
if (log_show_location_from_string(value ?: "1") < 0)
- log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
+ log_warning("Failed to parse log location setting '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_tid")) {
if (log_show_tid_from_string(value ?: "1") < 0)
- log_warning("Failed to parse log tid setting '%s'. Ignoring.", value);
+ log_warning("Failed to parse log tid setting '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_time")) {
if (log_show_time_from_string(value ?: "1") < 0)
- log_warning("Failed to parse log time setting '%s'. Ignoring.", value);
+ log_warning("Failed to parse log time setting '%s', ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.log_ratelimit_kmsg")) {
if (log_set_ratelimit_kmsg_from_string(value ?: "1") < 0)
- log_warning("Failed to parse log ratelimit kmsg boolean '%s'. Ignoring.", value);
+ log_warning("Failed to parse log ratelimit kmsg boolean '%s', ignoring.", value);
}
return 0;
@@ -1311,31 +1405,31 @@ void log_parse_environment_variables(void) {
e = getenv("SYSTEMD_LOG_TARGET");
if (e && log_set_target_from_string(e) < 0)
- log_warning("Failed to parse log target '%s'. Ignoring.", e);
+ log_warning("Failed to parse log target '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_LEVEL");
if (e && log_set_max_level_from_string(e) < 0)
- log_warning("Failed to parse log level '%s'. Ignoring.", e);
+ log_warning("Failed to parse log level '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_COLOR");
if (e && log_show_color_from_string(e) < 0)
- log_warning("Failed to parse log color '%s'. Ignoring.", e);
+ log_warning("Failed to parse log color '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_LOCATION");
if (e && log_show_location_from_string(e) < 0)
- log_warning("Failed to parse log location '%s'. Ignoring.", e);
+ log_warning("Failed to parse log location '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_TIME");
if (e && log_show_time_from_string(e) < 0)
- log_warning("Failed to parse log time '%s'. Ignoring.", e);
+ log_warning("Failed to parse log time '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_TID");
if (e && log_show_tid_from_string(e) < 0)
- log_warning("Failed to parse log tid '%s'. Ignoring.", e);
+ log_warning("Failed to parse log tid '%s', ignoring.", e);
e = getenv("SYSTEMD_LOG_RATELIMIT_KMSG");
if (e && log_set_ratelimit_kmsg_from_string(e) < 0)
- log_warning("Failed to parse log ratelimit kmsg boolean '%s'. Ignoring.", e);
+ log_warning("Failed to parse log ratelimit kmsg boolean '%s', ignoring.", e);
}
void log_parse_environment(void) {
@@ -1667,7 +1761,7 @@ bool log_context_enabled(void) {
if (saved_log_context_enabled >= 0)
return saved_log_context_enabled;
- r = getenv_bool_secure("SYSTEMD_ENABLE_LOG_CONTEXT");
+ r = secure_getenv_bool("SYSTEMD_ENABLE_LOG_CONTEXT");
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_ENABLE_LOG_CONTEXT, ignoring: %m");