]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hostnamed: expose fancy OS name as a field
authorLennart Poettering <lennart@poettering.net>
Mon, 12 Jan 2026 12:46:47 +0000 (13:46 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 21 Jan 2026 20:32:49 +0000 (21:32 +0100)
man/org.freedesktop.hostname1.xml
src/hostname/hostnamed.c
src/shared/varlink-io.systemd.Hostname.c

index 620ae83516d7ee68d9962848647fdf943d550d90..c70258459c2464cf884caa1a928ad128743d1dea 100644 (file)
@@ -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 {
 
     <variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemPrettyName"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemFancyName"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemCPEName"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemSupportEnd"/>
@@ -285,9 +289,11 @@ node /org/freedesktop/hostname1 {
     <para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
     <varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
     (e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
-    reported by <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
-    <varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
-    <varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
+    reported by <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
+
+    <para><varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemFancyName</varname>,
+    <varname>OperatingSystemCPEName</varname>, and <varname>HomeURL</varname> expose the
+    <varname>PRETTY_NAME=</varname>, <varname>FANCY_NAME=</varname>, <varname>CPE_NAME=</varname> and
     <varname>HOME_URL=</varname> fields from
     <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. 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 {
       <para><varname>ChassisAssetTag</varname>, <varname>OperatingSystemImageID</varname>,
       <varname>OperatingSystemImageVersion</varname>, <varname>HardwareSKU</varname>, and
       <varname>HardwareVersion</varname> were added in version 258.</para>
+      <para><varname>OperatingSystemFancyName</varname> was added in version 260.</para>
     </refsect2>
   </refsect1>
 
index fbe1b2fa7a8d1faae2d8086d644d6ba10ae93b1a..d2461981af20d60c258af069e7b557393f148494 100644 (file)
@@ -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),
index fb265b75118e59b7189af6b245536b2b4f5381a2..e10f11304663968672a16cbb39c0c42dcb71320d 100644 (file)
@@ -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),