From: Daan De Meyer Date: Wed, 7 May 2025 09:26:36 +0000 (+0200) Subject: terminal-util: Move various functions to ansi-color.c X-Git-Tag: v258-rc1~656^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7227d5bfff7a765028841a9dc353374a910a5d5b;p=thirdparty%2Fsystemd.git terminal-util: Move various functions to ansi-color.c --- diff --git a/src/basic/ansi-color.c b/src/basic/ansi-color.c new file mode 100644 index 00000000000..18e25f3bb0d --- /dev/null +++ b/src/basic/ansi-color.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "ansi-color.h" +#include "log.h" +#include "process-util.h" +#include "string-table.h" +#include "strv.h" +#include "terminal-util.h" + +static volatile int cached_color_mode = _COLOR_MODE_INVALID; +static volatile int cached_underline_enabled = -1; + +bool underline_enabled(void) { + + if (cached_underline_enabled < 0) { + + /* The Linux console doesn't support underlining, turn it off, but only there. */ + + if (colors_enabled()) + cached_underline_enabled = !streq_ptr(getenv("TERM"), "linux"); + else + cached_underline_enabled = false; + } + + return cached_underline_enabled; +} + +void reset_ansi_feature_caches(void) { + cached_color_mode = _COLOR_MODE_INVALID; + cached_underline_enabled = -1; +} + +ColorMode parse_systemd_colors(void) { + const char *e; + + e = getenv("SYSTEMD_COLORS"); + if (!e) + return _COLOR_MODE_INVALID; + + ColorMode m = color_mode_from_string(e); + if (m < 0) + return log_debug_errno(m, "Failed to parse $SYSTEMD_COLORS value '%s', ignoring: %m", e); + + return m; +} + +static ColorMode get_color_mode_impl(void) { + /* Returns the mode used to choose output colors. The possible modes are COLOR_OFF for no colors, + * COLOR_16 for only the base 16 ANSI colors, COLOR_256 for more colors, and COLOR_24BIT for + * unrestricted color output. */ + + /* First, we check $SYSTEMD_COLORS, which is the explicit way to change the mode. */ + ColorMode m = parse_systemd_colors(); + if (m >= 0) + return m; + + /* Next, check for the presence of $NO_COLOR; value is ignored. */ + if (getenv("NO_COLOR")) + return COLOR_OFF; + + /* If the above didn't work, we turn colors off unless we are on a TTY. And if we are on a TTY we + * turn it off if $TERM is set to "dumb". There's one special tweak though: if we are PID 1 then we + * do not check whether we are connected to a TTY, because we don't keep /dev/console open + * continuously due to fear of SAK, and hence things are a bit weird. */ + if (getpid_cached() == 1 ? getenv_terminal_is_dumb() : terminal_is_dumb()) + return COLOR_OFF; + + /* We failed to figure out any reason to *disable* colors. Let's see how many colors we shall use. */ + if (STRPTR_IN_SET(getenv("COLORTERM"), + "truecolor", + "24bit")) + return COLOR_24BIT; + + /* Note that the Linux console can only display 16 colors. We still enable 256 color mode + * even for PID1 output though (which typically goes to the Linux console), since the Linux + * console is able to parse the 256 color sequences and automatically map them to the closest + * color in the 16 color palette (since kernel 3.16). Doing 256 colors is nice for people who + * invoke systemd in a container or via a serial link or such, and use a true 256 color + * terminal to do so. */ + return COLOR_256; +} + +ColorMode get_color_mode(void) { + if (cached_color_mode < 0) + cached_color_mode = get_color_mode_impl(); + + return cached_color_mode; +} + + +static const char* const color_mode_table[_COLOR_MODE_MAX] = { + [COLOR_OFF] = "off", + [COLOR_16] = "16", + [COLOR_256] = "256", + [COLOR_24BIT] = "24bit", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(color_mode, ColorMode, COLOR_24BIT); diff --git a/src/basic/ansi-color.h b/src/basic/ansi-color.h index 5f1418109c8..f3e55e8165b 100644 --- a/src/basic/ansi-color.h +++ b/src/basic/ansi-color.h @@ -1,7 +1,34 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include "terminal-util.h" +#include + +#include "macro.h" + +/* Limits the use of ANSI colors to a subset. */ +typedef enum ColorMode { + COLOR_OFF, /* No colors, monochrome output. */ + COLOR_16, /* Only the base 16 colors. */ + COLOR_256, /* Only 256 colors. */ + COLOR_24BIT, /* For truecolor or 24bit color support, no restriction. */ + _COLOR_MODE_MAX, + _COLOR_MODE_INVALID = -EINVAL, +} ColorMode; + +const char* color_mode_to_string(ColorMode m) _const_; +ColorMode color_mode_from_string(const char *s) _pure_; + +ColorMode get_color_mode(void); +static inline bool colors_enabled(void) { + /* Returns true if colors are considered supported on our stdout. */ + return get_color_mode() != COLOR_OFF; +} + +ColorMode parse_systemd_colors(void); + +bool underline_enabled(void); + +void reset_ansi_feature_caches(void); /* Regular colors */ #define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */ diff --git a/src/basic/meson.build b/src/basic/meson.build index 7cc29bd0397..4588a9a6e88 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -4,6 +4,7 @@ basic_sources = files( 'MurmurHash2.c', 'af-list.c', 'alloc-util.c', + 'ansi-color.c', 'architecture.c', 'argv-util.c', 'arphrd-util.c', diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index e59c8c2efe4..acd25389524 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -60,8 +60,6 @@ static volatile unsigned cached_lines = 0; static volatile int cached_on_tty = -1; static volatile int cached_on_dev_null = -1; -static volatile int cached_color_mode = _COLOR_MODE_INVALID; -static volatile int cached_underline_enabled = -1; bool isatty_safe(int fd) { assert(fd >= 0); @@ -1433,10 +1431,10 @@ void reset_terminal_feature_caches(void) { cached_columns = 0; cached_lines = 0; - cached_color_mode = _COLOR_MODE_INVALID; - cached_underline_enabled = -1; cached_on_tty = -1; cached_on_dev_null = -1; + + reset_ansi_feature_caches(); } bool on_tty(void) { @@ -1753,72 +1751,6 @@ bool terminal_is_dumb(void) { return getenv_terminal_is_dumb(); } -static const char* const color_mode_table[_COLOR_MODE_MAX] = { - [COLOR_OFF] = "off", - [COLOR_16] = "16", - [COLOR_256] = "256", - [COLOR_24BIT] = "24bit", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(color_mode, ColorMode, COLOR_24BIT); - -static ColorMode parse_systemd_colors(void) { - const char *e; - - e = getenv("SYSTEMD_COLORS"); - if (!e) - return _COLOR_MODE_INVALID; - - ColorMode m = color_mode_from_string(e); - if (m < 0) - return log_debug_errno(m, "Failed to parse $SYSTEMD_COLORS value '%s', ignoring: %m", e); - - return m; -} - -static ColorMode get_color_mode_impl(void) { - /* Returns the mode used to choose output colors. The possible modes are COLOR_OFF for no colors, - * COLOR_16 for only the base 16 ANSI colors, COLOR_256 for more colors, and COLOR_24BIT for - * unrestricted color output. */ - - /* First, we check $SYSTEMD_COLORS, which is the explicit way to change the mode. */ - ColorMode m = parse_systemd_colors(); - if (m >= 0) - return m; - - /* Next, check for the presence of $NO_COLOR; value is ignored. */ - if (getenv("NO_COLOR")) - return COLOR_OFF; - - /* If the above didn't work, we turn colors off unless we are on a TTY. And if we are on a TTY we - * turn it off if $TERM is set to "dumb". There's one special tweak though: if we are PID 1 then we - * do not check whether we are connected to a TTY, because we don't keep /dev/console open - * continuously due to fear of SAK, and hence things are a bit weird. */ - if (getpid_cached() == 1 ? getenv_terminal_is_dumb() : terminal_is_dumb()) - return COLOR_OFF; - - /* We failed to figure out any reason to *disable* colors. Let's see how many colors we shall use. */ - if (STRPTR_IN_SET(getenv("COLORTERM"), - "truecolor", - "24bit")) - return COLOR_24BIT; - - /* Note that the Linux console can only display 16 colors. We still enable 256 color mode - * even for PID1 output though (which typically goes to the Linux console), since the Linux - * console is able to parse the 256 color sequences and automatically map them to the closest - * color in the 16 color palette (since kernel 3.16). Doing 256 colors is nice for people who - * invoke systemd in a container or via a serial link or such, and use a true 256 color - * terminal to do so. */ - return COLOR_256; -} - -ColorMode get_color_mode(void) { - if (cached_color_mode < 0) - cached_color_mode = get_color_mode_impl(); - - return cached_color_mode; -} - bool dev_console_colors_enabled(void) { _cleanup_free_ char *s = NULL; ColorMode m; @@ -1843,21 +1775,6 @@ bool dev_console_colors_enabled(void) { return !streq_ptr(s, "dumb"); } -bool underline_enabled(void) { - - if (cached_underline_enabled < 0) { - - /* The Linux console doesn't support underlining, turn it off, but only there. */ - - if (colors_enabled()) - cached_underline_enabled = !streq_ptr(getenv("TERM"), "linux"); - else - cached_underline_enabled = false; - } - - return cached_underline_enabled; -} - int vt_restore(int fd) { static const struct vt_mode mode = { diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 0faf3c87611..3f6c3767704 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -129,26 +129,6 @@ bool on_tty(void); bool getenv_terminal_is_dumb(void); bool terminal_is_dumb(void); -/* Limits the use of ANSI colors to a subset. */ -typedef enum ColorMode { - COLOR_OFF, /* No colors, monochrome output. */ - COLOR_16, /* Only the base 16 colors. */ - COLOR_256, /* Only 256 colors. */ - COLOR_24BIT, /* For truecolor or 24bit color support, no restriction. */ - _COLOR_MODE_MAX, - _COLOR_MODE_INVALID = -EINVAL, -} ColorMode; - -const char* color_mode_to_string(ColorMode m) _const_; -ColorMode color_mode_from_string(const char *s) _pure_; - -ColorMode get_color_mode(void); -static inline bool colors_enabled(void) { - /* Returns true if colors are considered supported on our stdout. */ - return get_color_mode() != COLOR_OFF; -} - -bool underline_enabled(void); bool dev_console_colors_enabled(void); int get_ctty_devnr(pid_t pid, dev_t *ret); diff --git a/src/network/networkctl-journal.c b/src/network/networkctl-journal.c index 58e67d9ebb7..ca94410aee4 100644 --- a/src/network/networkctl-journal.c +++ b/src/network/networkctl-journal.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "ansi-color.h" #include "journal-internal.h" #include "log.h" #include "logs-show.h"