if (m >= 0 && m < _COLOR_MODE_FIXED_MAX)
return m;
- /* Next, check for the presence of $NO_COLOR; value is ignored. */
- if (m != COLOR_TRUE && 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;
+ /* If SYSTEMD_COLORS=true was set explicitly, skip the environment checks below — the user
+ * explicitly requested colors, so honor it even when stdout is piped or $NO_COLOR is set. */
+ if (m != COLOR_TRUE) {
+ /* Check for the presence of $NO_COLOR; value is ignored. */
+ if (getenv("NO_COLOR"))
+ return COLOR_OFF;
+
+ /* 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 (m == COLOR_AUTO_16)
test_get_color_mode_with_env("SYSTEMD_COLORS", "auto-256", terminal_is_dumb() ? COLOR_OFF : COLOR_256);
test_get_color_mode_with_env("SYSTEMD_COLORS", "auto-24bit", terminal_is_dumb() ? COLOR_OFF : COLOR_24BIT);
ASSERT_OK_ERRNO(setenv("COLORTERM", "truecolor", true));
- test_get_color_mode_with_env("SYSTEMD_COLORS", "1", terminal_is_dumb() ? COLOR_OFF : COLOR_24BIT);
- test_get_color_mode_with_env("SYSTEMD_COLORS", "yes", terminal_is_dumb() ? COLOR_OFF : COLOR_24BIT);
+ /* SYSTEMD_COLORS=1/yes/true all map to COLOR_TRUE and must force colors on
+ * even when stdout is not a TTY (piped). With COLORTERM=truecolor, we get 24bit. */
+ test_get_color_mode_with_env("SYSTEMD_COLORS", "1", COLOR_24BIT);
+ test_get_color_mode_with_env("SYSTEMD_COLORS", "yes", COLOR_24BIT);
ASSERT_OK_ERRNO(unsetenv("COLORTERM"));
- test_get_color_mode_with_env("SYSTEMD_COLORS", "true", terminal_is_dumb() ? COLOR_OFF : COLOR_256);
+ /* Without COLORTERM, COLOR_TRUE still bypasses the TTY check but autodetects depth. */
+ test_get_color_mode_with_env("SYSTEMD_COLORS", "true", COLOR_256);
ASSERT_OK_ERRNO(setenv("NO_COLOR", "1", true));
- test_get_color_mode_with_env("SYSTEMD_COLORS", "true", terminal_is_dumb() ? COLOR_OFF : COLOR_256);
+ /* COLOR_TRUE also bypasses NO_COLOR. */
+ test_get_color_mode_with_env("SYSTEMD_COLORS", "true", COLOR_256);
test_get_color_mode_with_env("SYSTEMD_COLORS", "auto-16", COLOR_OFF);
test_get_color_mode_with_env("SYSTEMD_COLORS", "auto-256", COLOR_OFF);
test_get_color_mode_with_env("SYSTEMD_COLORS", "auto-24bit", COLOR_OFF);