mirror of
https://github.com/systemd/systemd.git
synced 2025-01-20 18:04:03 +03:00
Merge pull request #31026 from poettering/nspawn-tint
nspawn: allow tinting the background of interactive tty sessions
This commit is contained in:
commit
e944d3ab92
@ -1711,6 +1711,21 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v242"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--background=<replaceable>COLOR</replaceable></option></term>
|
||||
|
||||
<listitem><para>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 <literal>40</literal>, <literal>41</literal>, …, <literal>47</literal>, <literal>48;2;…</literal>,
|
||||
<literal>48;5;…</literal>. See <ulink
|
||||
url="https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters">ANSI
|
||||
Escape Code (Wikipedia)</ulink> for details. Assign an empty string to disable any coloring.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect2>
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user