diff options
Diffstat (limited to 'src/basic/log.c')
-rw-r--r-- | src/basic/log.c | 142 |
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"); |