diff --git a/man/org.freedesktop.hostname1.xml b/man/org.freedesktop.hostname1.xml
index 620ae83516..c70258459c 100644
--- a/man/org.freedesktop.hostname1.xml
+++ b/man/org.freedesktop.hostname1.xml
@@ -80,6 +80,8 @@ node /org/freedesktop/hostname1 {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OperatingSystemPrettyName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly s OperatingSystemFancyName = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OperatingSystemCPEName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t OperatingSystemSupportEnd = ...;
@@ -170,6 +172,8 @@ node /org/freedesktop/hostname1 {
+
+
@@ -285,9 +289,11 @@ node /org/freedesktop/hostname1 {
KernelName, KernelRelease, and
KernelVersion expose the kernel name (e.g. Linux), release
(e.g. 5.0.0-11), and version (i.e. the build number, e.g. #11) as
- reported by uname2.
- OperatingSystemPrettyName, OperatingSystemCPEName, and
- HomeURL expose the PRETTY_NAME=, CPE_NAME= and
+ reported by uname2.
+
+ OperatingSystemPrettyName, OperatingSystemFancyName,
+ OperatingSystemCPEName, and HomeURL expose the
+ PRETTY_NAME=, FANCY_NAME=, CPE_NAME= and
HOME_URL= fields from
os-release5. The
purpose of those properties is to allow remote clients to access this information over D-Bus. Local
@@ -487,6 +493,7 @@ node /org/freedesktop/hostname1 {
ChassisAssetTag, OperatingSystemImageID,
OperatingSystemImageVersion, HardwareSKU, and
HardwareVersion were added in version 258.
+ OperatingSystemFancyName was added in version 260.
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index fbe1b2fa7a..d2461981af 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -22,6 +22,7 @@
#include "device-private.h"
#include "env-file.h"
#include "env-util.h"
+#include "escape.h"
#include "extract-word.h"
#include "fileio.h"
#include "hashmap.h"
@@ -75,6 +76,7 @@ typedef enum {
PROP_OS_SUPPORT_END,
PROP_OS_IMAGE_ID,
PROP_OS_IMAGE_VERSION,
+ PROP_OS_FANCY_NAME,
_PROP_MAX,
_PROP_INVALID = -EINVAL,
} HostProperty;
@@ -192,7 +194,7 @@ static void context_read_machine_info(Context *c) {
}
static void context_read_os_release(Context *c) {
- _cleanup_free_ char *os_name = NULL, *os_pretty_name = NULL;
+ _cleanup_free_ char *os_name = NULL, *os_pretty_name = NULL, *os_fancy_name = NULL, *os_ansi_color = NULL;
struct stat current_stat = {};
int r;
@@ -209,10 +211,13 @@ static void context_read_os_release(Context *c) {
(UINT64_C(1) << PROP_OS_HOME_URL) |
(UINT64_C(1) << PROP_OS_SUPPORT_END) |
(UINT64_C(1) << PROP_OS_IMAGE_ID) |
- (UINT64_C(1) << PROP_OS_IMAGE_VERSION));
+ (UINT64_C(1) << PROP_OS_IMAGE_VERSION) |
+ (UINT64_C(1) << PROP_OS_FANCY_NAME));
r = parse_os_release(NULL,
"PRETTY_NAME", &os_pretty_name,
+ "FANCY_NAME", &os_fancy_name,
+ "ANSI_COLOR", &os_ansi_color,
"NAME", &os_name,
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
"HOME_URL", &c->data[PROP_OS_HOME_URL],
@@ -225,6 +230,31 @@ static void context_read_os_release(Context *c) {
if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
log_oom();
+ if (!isempty(os_fancy_name)) {
+ _cleanup_free_ char *unescaped = NULL;
+
+ /* We undo one level of C escapes on this */
+ ssize_t l = cunescape(os_fancy_name, /* flags= */ 0, &unescaped);
+ if (l < 0) {
+ log_warning_errno(l, "Failed to unescape fancy OS name, ignoring: %m");
+ os_fancy_name = mfree(os_fancy_name);
+ } else
+ free_and_replace(os_fancy_name, unescaped);
+ }
+
+ if (isempty(os_fancy_name)) {
+ free(os_fancy_name); /* free if empty string */
+
+ if (isempty(os_ansi_color))
+ os_fancy_name = strdup(c->data[PROP_OS_PRETTY_NAME]);
+ else
+ os_fancy_name = strjoin("\x1B[", os_ansi_color, "m", c->data[PROP_OS_PRETTY_NAME]);
+ if (!os_fancy_name)
+ log_oom();
+ }
+
+ free_and_replace(c->data[PROP_OS_FANCY_NAME], os_fancy_name);
+
c->etc_os_release_stat = current_stat;
}
@@ -1705,6 +1735,7 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
SD_JSON_BUILD_PAIR_STRING("KernelRelease", u.release),
SD_JSON_BUILD_PAIR_STRING("KernelVersion", u.version),
SD_JSON_BUILD_PAIR_STRING("OperatingSystemPrettyName", c->data[PROP_OS_PRETTY_NAME]),
+ SD_JSON_BUILD_PAIR_STRING("OperatingSystemFancyName", c->data[PROP_OS_FANCY_NAME]),
SD_JSON_BUILD_PAIR_STRING("OperatingSystemCPEName", c->data[PROP_OS_CPE_NAME]),
SD_JSON_BUILD_PAIR_STRING("OperatingSystemHomeURL", c->data[PROP_OS_HOME_URL]),
JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol),
@@ -1781,6 +1812,7 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field, offsetof(struct utsname, release), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field, offsetof(struct utsname, version), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field, offsetof(Context, data[PROP_OS_PRETTY_NAME]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("OperatingSystemFancyName", "s", property_get_os_release_field, offsetof(Context, data[PROP_OS_FANCY_NAME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field, offsetof(Context, data[PROP_OS_CPE_NAME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OperatingSystemSupportEnd", "t", property_get_os_support_end, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field, offsetof(Context, data[PROP_OS_HOME_URL]), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/shared/varlink-io.systemd.Hostname.c b/src/shared/varlink-io.systemd.Hostname.c
index fb265b7511..e10f113046 100644
--- a/src/shared/varlink-io.systemd.Hostname.c
+++ b/src/shared/varlink-io.systemd.Hostname.c
@@ -20,7 +20,10 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_DEFINE_OUTPUT(KernelName, SD_VARLINK_STRING, 0),
SD_VARLINK_DEFINE_OUTPUT(KernelRelease, SD_VARLINK_STRING, 0),
SD_VARLINK_DEFINE_OUTPUT(KernelVersion, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("'Pretty' name of the OS. This is the primary OS identifier that is suitable for presentation to the user. Typically includes a version too, but doesn't have to."),
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemPrettyName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("'Fancy' name of the OS; may contain non-ASCII Unicode chars, as well as basic ANSI sequences. This is similar to 'OperatingSystemPrettyName', but is preferably used on terminals that support ANSI sequences and full Unicode."),
+ SD_VARLINK_DEFINE_OUTPUT(OperatingSystemFancyName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemCPEName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemHomeURL, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemSupportEnd, SD_VARLINK_INT, SD_VARLINK_NULLABLE),