diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 1a9fb09aae..59b2c1a2d0 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -1711,6 +1711,21 @@ After=sys-subsystem-net-devices-ens1.device
+
+
+
+
+ Change the terminal background color to the specified ANSI color as long as the
+ container runs. The color specified should be an ANSI X3.64 SGR background color, i.e. strings such
+ as 40, 41, …, 47, 48;2;…,
+ 48;5;…. See ANSI
+ Escape Code (Wikipedia) for details. Assign an empty string to disable any coloring.
+
+
+
+
+
diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn
index cc3d2f6598..b12711be80 100644
--- a/shell-completion/bash/systemd-nspawn
+++ b/shell-completion/bash/systemd-nspawn
@@ -73,7 +73,7 @@ _systemd_nspawn() {
--pivot-root --property --private-users --private-users-ownership --network-namespace-path
--network-ipvlan --network-veth-extra --network-zone -p --port --system-call-filter --overlay
--overlay-ro --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity
- --resolv-conf --timezone --root-hash-sig'
+ --resolv-conf --timezone --root-hash-sig --background'
)
_init_completion || return
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 89ef0e4daa..50bb0565ca 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -236,6 +236,7 @@ static bool arg_suppress_sync = false;
static char *arg_settings_filename = NULL;
static Architecture arg_architecture = _ARCHITECTURE_INVALID;
static ImagePolicy *arg_image_policy = NULL;
+static char *arg_background = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_template, freep);
@@ -272,6 +273,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
static int handle_arg_console(const char *arg) {
if (streq(arg, "help")) {
@@ -450,6 +452,7 @@ static int help(void) {
" --console=MODE Select how stdin/stdout/stderr and /dev/console are\n"
" set up for the container.\n"
" -P --pipe Equivalent to --console=pipe\n\n"
+ " --background=COLOR Set ANSI color for background\n"
"%3$sCredentials:%4$s\n"
" --set-credential=ID:VALUE\n"
" Pass a credential with literal value to container.\n"
@@ -745,6 +748,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_BIND_USER,
ARG_SUPPRESS_SYNC,
ARG_IMAGE_POLICY,
+ ARG_BACKGROUND,
};
static const struct option options[] = {
@@ -819,6 +823,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "bind-user", required_argument, NULL, ARG_BIND_USER },
{ "suppress-sync", required_argument, NULL, ARG_SUPPRESS_SYNC },
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
+ { "background", required_argument, NULL, ARG_BACKGROUND },
{}
};
@@ -1608,6 +1613,12 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
+ case ARG_BACKGROUND:
+ r = free_and_strdup_warn(&arg_background, optarg);
+ if (r < 0)
+ return r;
+ break;
+
case '?':
return -EINVAL;
@@ -5339,9 +5350,22 @@ static int run_container(
return log_error_errno(r, "Failed to create PTY forwarder: %m");
if (arg_console_width != UINT_MAX || arg_console_height != UINT_MAX)
- (void) pty_forward_set_width_height(forward,
- arg_console_width,
- arg_console_height);
+ (void) pty_forward_set_width_height(
+ forward,
+ arg_console_width,
+ arg_console_height);
+
+ if (!arg_background) {
+ _cleanup_free_ char *bg = NULL;
+
+ r = terminal_tint_color(220 /* blue */, &bg);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine terminal background color, not tinting.");
+ else
+ (void) pty_forward_set_background_color(forward, bg);
+ } else if (!isempty(arg_background))
+ (void) pty_forward_set_background_color(forward, arg_background);
+
break;
default:
diff --git a/src/run/run.c b/src/run/run.c
index c3313c6c52..a695fea0f0 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -17,7 +17,6 @@
#include "bus-unit-util.h"
#include "bus-wait-for-jobs.h"
#include "calendarspec.h"
-#include "color-util.h"
#include "env-util.h"
#include "escape.h"
#include "exit-status.h"
@@ -940,34 +939,16 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
return log_oom();
if (!arg_background && arg_stdio == ARG_STDIO_PTY) {
- double red, green, blue;
+ double hue;
- r = get_default_background_color(&red, &green, &blue);
+ if (!arg_exec_user || STR_IN_SET(arg_exec_user, "root", "0"))
+ hue = 0; /* red */
+ else
+ hue = 60 /* yellow */;
+
+ r = terminal_tint_color(hue, &arg_background);
if (r < 0)
log_debug_errno(r, "Unable to get terminal background color, not tinting background: %m");
- else {
- double h, s, v;
-
- rgb_to_hsv(red, green, blue, &h, &s, &v);
-
- if (!arg_exec_user || STR_IN_SET(arg_exec_user, "root", "0"))
- h = 0; /* red */
- else
- h = 60 /* yellow */;
-
- if (v > 50) /* If the background is bright, then pull down saturation */
- s = 25;
- else /* otherwise pump it up */
- s = 75;
-
- v = MAX(30, v); /* Make sure we don't hide the color in black */
-
- uint8_t r8, g8, b8;
- hsv_to_rgb(h, s, v, &r8, &g8, &b8);
-
- if (asprintf(&arg_background, "48;2;%u;%u;%u", r8, g8, b8) < 0)
- return log_oom();
- }
}
return 1;
diff --git a/src/shared/color-util.c b/src/shared/color-util.c
index 776445ecfc..9d714c0fff 100644
--- a/src/shared/color-util.c
+++ b/src/shared/color-util.c
@@ -11,35 +11,38 @@ void rgb_to_hsv(double r, double g, double b,
assert(r >= 0 && r <= 1);
assert(g >= 0 && g <= 1);
assert(b >= 0 && b <= 1);
- assert(ret_h);
- assert(ret_s);
- assert(ret_v);
double max_color = fmax(r, fmax(g, b));
double min_color = fmin(r, fmin(g, b));
double delta = max_color - min_color;
- *ret_v = max_color * 100.0;
+ if (ret_v)
+ *ret_v = max_color * 100.0;
- if (max_color > 0)
- *ret_s = delta / max_color * 100.0;
- else {
- *ret_s = 0;
- *ret_h = NAN;
+ if (max_color <= 0) {
+ if (ret_s)
+ *ret_s = 0;
+ if (ret_h)
+ *ret_h = NAN;
return;
}
- if (delta > 0) {
- if (r >= max_color)
- *ret_h = 60 * fmod((g - b) / delta, 6);
- else if (g >= max_color)
- *ret_h = 60 * (((b - r) / delta) + 2);
- else if (b >= max_color)
- *ret_h = 60 * (((r - g) / delta) + 4);
+ if (ret_s)
+ *ret_s = delta / max_color * 100.0;
- *ret_h = fmod(*ret_h, 360);
- } else
- *ret_h = NAN;
+ if (ret_h) {
+ if (delta > 0) {
+ if (r >= max_color)
+ *ret_h = 60 * fmod((g - b) / delta, 6);
+ else if (g >= max_color)
+ *ret_h = 60 * (((b - r) / delta) + 2);
+ else if (b >= max_color)
+ *ret_h = 60 * (((r - g) / delta) + 4);
+
+ *ret_h = fmod(*ret_h, 360);
+ } else
+ *ret_h = NAN;
+ }
}
void hsv_to_rgb(double h, double s, double v,
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c
index cb1ac2bb76..7dd31a099f 100644
--- a/src/shared/pretty-print.c
+++ b/src/shared/pretty-print.c
@@ -5,6 +5,7 @@
#include
#include "alloc-util.h"
+#include "color-util.h"
#include "conf-files.h"
#include "constants.h"
#include "env-util.h"
@@ -441,3 +442,32 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) {
return cat_files(path, files, flags);
}
+
+int terminal_tint_color(double hue, char **ret) {
+ double red, green, blue;
+ int r;
+
+ assert(ret);
+
+ r = get_default_background_color(&red, &green, &blue);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to get terminal background color: %m");
+
+ double s, v;
+ rgb_to_hsv(red, green, blue, /* h= */ NULL, &s, &v);
+
+ if (v > 50) /* If the background is bright, then pull down saturation */
+ s = 25;
+ else /* otherwise pump it up */
+ s = 75;
+
+ v = MAX(30, v); /* Make sure we don't hide the color in black */
+
+ uint8_t r8, g8, b8;
+ hsv_to_rgb(hue, s, v, &r8, &g8, &b8);
+
+ if (asprintf(ret, "48;2;%u;%u;%u", r8, g8, b8) < 0)
+ return -ENOMEM;
+
+ return 0;
+}
diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h
index c17e976580..6069318be7 100644
--- a/src/shared/pretty-print.h
+++ b/src/shared/pretty-print.h
@@ -47,3 +47,5 @@ static inline const char *green_check_mark_internal(char buffer[static GREEN_CHE
#define GREEN_CHECK_MARK() green_check_mark_internal((char[GREEN_CHECK_MARK_MAX]) {})
#define COLOR_MARK_BOOL(b) ((b) ? GREEN_CHECK_MARK() : RED_CROSS_MARK())
+
+int terminal_tint_color(double hue, char **ret);