mirror of
https://github.com/systemd/systemd
synced 2026-03-16 10:04:47 +01:00
Compare commits
7 Commits
e9a1271a0c
...
b61aeeb315
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b61aeeb315 | ||
|
|
0910cb9324 | ||
|
|
1dab8472e0 | ||
|
|
955446d2e4 | ||
|
|
d6749f35ae | ||
|
|
a01cd5bed3 | ||
|
|
f42dc5ea18 |
@ -80,6 +80,8 @@ node /org/freedesktop/hostname1 {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly s OperatingSystemPrettyName = '...';
|
readonly s OperatingSystemPrettyName = '...';
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly s OperatingSystemFancyName = '...';
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly s OperatingSystemCPEName = '...';
|
readonly s OperatingSystemCPEName = '...';
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t OperatingSystemSupportEnd = ...;
|
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="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="OperatingSystemCPEName"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="OperatingSystemSupportEnd"/>
|
<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
|
<para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
|
||||||
<varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
|
<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
|
(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>.
|
reported by <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
|
||||||
<varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
|
|
||||||
<varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
|
<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
|
<varname>HOME_URL=</varname> fields from
|
||||||
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
|
<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
|
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>,
|
<para><varname>ChassisAssetTag</varname>, <varname>OperatingSystemImageID</varname>,
|
||||||
<varname>OperatingSystemImageVersion</varname>, <varname>HardwareSKU</varname>, and
|
<varname>OperatingSystemImageVersion</varname>, <varname>HardwareSKU</varname>, and
|
||||||
<varname>HardwareVersion</varname> were added in version 258.</para>
|
<varname>HardwareVersion</varname> were added in version 258.</para>
|
||||||
|
<para><varname>OperatingSystemFancyName</varname> was added in version 260.</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@ -191,9 +191,34 @@
|
|||||||
|
|
||||||
<listitem><para>A pretty operating system name in a format suitable for presentation to the
|
<listitem><para>A pretty operating system name in a format suitable for presentation to the
|
||||||
user. May or may not contain a release code name or OS version of some kind, as suitable. If not
|
user. May or may not contain a release code name or OS version of some kind, as suitable. If not
|
||||||
set, a default of <literal>PRETTY_NAME="Linux"</literal> may be used</para>
|
set, a default of <literal>PRETTY_NAME="Linux"</literal> may be used.</para>
|
||||||
|
|
||||||
<para>Example: <literal>PRETTY_NAME="Fedora 17 (Beefy Miracle)"</literal>.</para></listitem>
|
<para>Example: <literal>PRETTY_NAME="Fedora 17 (Beefy Miracle)"</literal></para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>FANCY_NAME=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Similar to <varname>PRETTY_NAME=</varname>, but may contain ANSI sequences and
|
||||||
|
fancy UTF-8 characters such as emojis. If defined this shall preferably used when displaying the OS
|
||||||
|
name on modern terminal emulators. If the terminal emulator does not support emojis,
|
||||||
|
<varname>PRETTY_NAME=</varname> shall be shown instead, possibly with
|
||||||
|
<varname>ANSI_COLOR=</varname> coloring. Use <literal>\033</literal> to encode the ESC
|
||||||
|
character and <literal>\\</literal> to encode the backslash character.</para>
|
||||||
|
|
||||||
|
<!-- NB: the code actually does a full blown C style unescaping, but we are not going to mention
|
||||||
|
this here: people may add ANSI sequences, but maybe not the full expressivity of ASCII control
|
||||||
|
characters. -->
|
||||||
|
|
||||||
|
<para>Unlike <varname>PRETTY_NAME=</varname> this field must not contain information that is
|
||||||
|
present in other fields, in particular the version (already specified in
|
||||||
|
<varname>VERSION=</varname>) or the codename (already specified in
|
||||||
|
<varname>VERSION_CODENAME=</varname>).</para>
|
||||||
|
|
||||||
|
<para>Example:
|
||||||
|
<literal>FANCY_NAME="🍅 \033[31mTomato\033[0;1mOS\033[0m"</literal></para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|||||||
@ -2911,7 +2911,7 @@ endif
|
|||||||
alias_target('gensources', generated_sources)
|
alias_target('gensources', generated_sources)
|
||||||
|
|
||||||
clang_tidy = find_program('clang-tidy', required : false)
|
clang_tidy = find_program('clang-tidy', required : false)
|
||||||
if meson.version().version_compare('>=1.10.0')
|
if meson.version().version_compare('>=1.4.0')
|
||||||
uniq = {}
|
uniq = {}
|
||||||
|
|
||||||
foreach source : sources
|
foreach source : sources
|
||||||
@ -2921,7 +2921,11 @@ if meson.version().version_compare('>=1.10.0')
|
|||||||
uniq += {source.full_path(): source}
|
uniq += {source.full_path(): source}
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
sources = uniq.values()
|
# TODO: Use uniq.values() when we can rely on meson 1.10.0.
|
||||||
|
sources = []
|
||||||
|
foreach path, file : uniq
|
||||||
|
sources += [file]
|
||||||
|
endforeach
|
||||||
|
|
||||||
foreach source : sources
|
foreach source : sources
|
||||||
if systemd_headers.contains(source)
|
if systemd_headers.contains(source)
|
||||||
|
|||||||
@ -102,6 +102,7 @@
|
|||||||
#include "umask-util.h"
|
#include "umask-util.h"
|
||||||
#include "unit-name.h"
|
#include "unit-name.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
#include "utf8.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
@ -1389,14 +1390,16 @@ static int enforce_syscall_archs(Set *archs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int os_release_status(void) {
|
static int os_release_status(void) {
|
||||||
_cleanup_free_ char *pretty_name = NULL, *name = NULL, *version = NULL,
|
_cleanup_free_ char *pretty_name = NULL, *fancy_name = NULL,
|
||||||
*ansi_color = NULL, *support_end = NULL;
|
*name = NULL, *version = NULL, *ansi_color = NULL, *support_end = NULL, *codename = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = parse_os_release(NULL,
|
r = parse_os_release(NULL,
|
||||||
"PRETTY_NAME", &pretty_name,
|
"PRETTY_NAME", &pretty_name,
|
||||||
|
"FANCY_NAME", &fancy_name,
|
||||||
"NAME", &name,
|
"NAME", &name,
|
||||||
"VERSION", &version,
|
"VERSION", &version,
|
||||||
|
"VERSION_CODENAME", &codename,
|
||||||
"ANSI_COLOR", &ansi_color,
|
"ANSI_COLOR", &ansi_color,
|
||||||
"SUPPORT_END", &support_end);
|
"SUPPORT_END", &support_end);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1404,22 +1407,59 @@ static int os_release_status(void) {
|
|||||||
"Failed to read os-release file, ignoring: %m");
|
"Failed to read os-release file, ignoring: %m");
|
||||||
|
|
||||||
const char *label = os_release_pretty_name(pretty_name, name);
|
const char *label = os_release_pretty_name(pretty_name, name);
|
||||||
const char *color = empty_to_null(ansi_color) ?: "1";
|
|
||||||
|
|
||||||
if (show_status_on(arg_show_status)) {
|
if (show_status_on(arg_show_status)) {
|
||||||
|
const char *color = empty_to_null(ansi_color) ?: "1";
|
||||||
|
|
||||||
|
/* The fancy name may contain emoji characters and ANSI sequences. Don't use it if our locale
|
||||||
|
* doesn't allow that, or ANSI sequences are off, or if it is empty. */
|
||||||
|
|
||||||
|
if (!isempty(fancy_name)) {
|
||||||
|
_cleanup_free_ char *unescaped = NULL;
|
||||||
|
|
||||||
|
/* Undo one level of C-style unescaping for this one */
|
||||||
|
ssize_t l = cunescape(fancy_name, /* flags= */ 0, &unescaped);
|
||||||
|
if (l < 0) {
|
||||||
|
log_debug_errno(l, "Failed to unescape FANCY_NAME=, ignoring: %m");
|
||||||
|
fancy_name = mfree(fancy_name);
|
||||||
|
} else {
|
||||||
|
free_and_replace(fancy_name, unescaped);
|
||||||
|
|
||||||
|
/* FANCY_NAME= does not contain version/codename info (unlike PRETTY_NAME=),
|
||||||
|
* but in this context it makes sense to show them if defined, hence append
|
||||||
|
* them here. */
|
||||||
|
if (version && !strextend(&fancy_name, " ", version))
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (codename && !strextend(&fancy_name, " (", codename, ")"))
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isempty(fancy_name) ||
|
||||||
|
(!emoji_enabled() && !ascii_is_valid(fancy_name)) ||
|
||||||
|
!log_get_show_color())
|
||||||
|
fancy_name = mfree(fancy_name);
|
||||||
|
|
||||||
|
if (!fancy_name && log_get_show_color()) {
|
||||||
|
fancy_name = strjoin("\x1B[", color, "m", label);
|
||||||
|
if (!fancy_name)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
if (in_initrd()) {
|
if (in_initrd()) {
|
||||||
if (log_get_show_color())
|
if (log_get_show_color())
|
||||||
status_printf(NULL, 0,
|
status_printf(NULL, 0,
|
||||||
ANSI_HIGHLIGHT "Booting initrd of " ANSI_NORMAL "\x1B[%sm%s" ANSI_NORMAL ANSI_HIGHLIGHT "." ANSI_NORMAL,
|
ANSI_HIGHLIGHT "Booting initrd of " ANSI_NORMAL "%s" ANSI_NORMAL ANSI_HIGHLIGHT "." ANSI_NORMAL,
|
||||||
color, label);
|
fancy_name);
|
||||||
else
|
else
|
||||||
status_printf(NULL, 0,
|
status_printf(NULL, 0,
|
||||||
"Booting initrd of %s...", label);
|
"Booting initrd of %s...", label);
|
||||||
} else {
|
} else {
|
||||||
if (log_get_show_color())
|
if (log_get_show_color())
|
||||||
status_printf(NULL, 0,
|
status_printf(NULL, 0,
|
||||||
"\n" ANSI_HIGHLIGHT "Welcome to " ANSI_NORMAL "\x1B[%sm%s" ANSI_NORMAL ANSI_HIGHLIGHT "!" ANSI_NORMAL "\n",
|
"\n" ANSI_HIGHLIGHT "Welcome to " ANSI_NORMAL "%s" ANSI_NORMAL ANSI_HIGHLIGHT "!" ANSI_NORMAL "\n",
|
||||||
color, label);
|
fancy_name);
|
||||||
else
|
else
|
||||||
status_printf(NULL, 0,
|
status_printf(NULL, 0,
|
||||||
"\nWelcome to %s!\n",
|
"\nWelcome to %s!\n",
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#include "runtime-scope.h"
|
#include "runtime-scope.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
#include "utf8.h"
|
||||||
#include "verbs.h"
|
#include "verbs.h"
|
||||||
|
|
||||||
static bool arg_ask_password = true;
|
static bool arg_ask_password = true;
|
||||||
@ -51,6 +52,7 @@ typedef struct StatusInfo {
|
|||||||
const char *kernel_name;
|
const char *kernel_name;
|
||||||
const char *kernel_release;
|
const char *kernel_release;
|
||||||
const char *os_pretty_name;
|
const char *os_pretty_name;
|
||||||
|
const char *os_fancy_name;
|
||||||
const char *os_cpe_name;
|
const char *os_cpe_name;
|
||||||
usec_t os_support_end;
|
usec_t os_support_end;
|
||||||
const char *os_image_id;
|
const char *os_image_id;
|
||||||
@ -234,7 +236,14 @@ static int print_status_info(StatusInfo *i) {
|
|||||||
return table_log_add_error(r);
|
return table_log_add_error(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isempty(i->os_pretty_name)) {
|
if (!isempty(i->os_fancy_name) && (emoji_enabled() || ascii_is_valid(i->os_fancy_name)) && colors_enabled()) {
|
||||||
|
r = table_add_many(table,
|
||||||
|
TABLE_FIELD, "Operating System",
|
||||||
|
TABLE_STRING_WITH_ANSI, i->os_fancy_name,
|
||||||
|
TABLE_SET_URL, i->home_url);
|
||||||
|
if (r < 0)
|
||||||
|
return table_log_add_error(r);
|
||||||
|
} else if (!isempty(i->os_pretty_name)) {
|
||||||
r = table_add_many(table,
|
r = table_add_many(table,
|
||||||
TABLE_FIELD, "Operating System",
|
TABLE_FIELD, "Operating System",
|
||||||
TABLE_STRING, i->os_pretty_name,
|
TABLE_STRING, i->os_pretty_name,
|
||||||
@ -425,6 +434,7 @@ static int show_all_names(sd_bus *bus) {
|
|||||||
{ "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) },
|
{ "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) },
|
||||||
{ "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) },
|
{ "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) },
|
||||||
{ "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) },
|
{ "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) },
|
||||||
|
{ "OperatingSystemFancyName", "s", NULL, offsetof(StatusInfo, os_fancy_name) },
|
||||||
{ "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) },
|
{ "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) },
|
||||||
{ "OperatingSystemSupportEnd", "t", NULL, offsetof(StatusInfo, os_support_end) },
|
{ "OperatingSystemSupportEnd", "t", NULL, offsetof(StatusInfo, os_support_end) },
|
||||||
{ "OperatingSystemImageID", "s", NULL, offsetof(StatusInfo, os_image_id) },
|
{ "OperatingSystemImageID", "s", NULL, offsetof(StatusInfo, os_image_id) },
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include "device-private.h"
|
#include "device-private.h"
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
|
#include "escape.h"
|
||||||
#include "extract-word.h"
|
#include "extract-word.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
@ -75,6 +76,7 @@ typedef enum {
|
|||||||
PROP_OS_SUPPORT_END,
|
PROP_OS_SUPPORT_END,
|
||||||
PROP_OS_IMAGE_ID,
|
PROP_OS_IMAGE_ID,
|
||||||
PROP_OS_IMAGE_VERSION,
|
PROP_OS_IMAGE_VERSION,
|
||||||
|
PROP_OS_FANCY_NAME,
|
||||||
_PROP_MAX,
|
_PROP_MAX,
|
||||||
_PROP_INVALID = -EINVAL,
|
_PROP_INVALID = -EINVAL,
|
||||||
} HostProperty;
|
} HostProperty;
|
||||||
@ -192,7 +194,7 @@ static void context_read_machine_info(Context *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void context_read_os_release(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 = {};
|
struct stat current_stat = {};
|
||||||
int r;
|
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_HOME_URL) |
|
||||||
(UINT64_C(1) << PROP_OS_SUPPORT_END) |
|
(UINT64_C(1) << PROP_OS_SUPPORT_END) |
|
||||||
(UINT64_C(1) << PROP_OS_IMAGE_ID) |
|
(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,
|
r = parse_os_release(NULL,
|
||||||
"PRETTY_NAME", &os_pretty_name,
|
"PRETTY_NAME", &os_pretty_name,
|
||||||
|
"FANCY_NAME", &os_fancy_name,
|
||||||
|
"ANSI_COLOR", &os_ansi_color,
|
||||||
"NAME", &os_name,
|
"NAME", &os_name,
|
||||||
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
|
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
|
||||||
"HOME_URL", &c->data[PROP_OS_HOME_URL],
|
"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)
|
if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
|
||||||
log_oom();
|
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;
|
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("KernelRelease", u.release),
|
||||||
SD_JSON_BUILD_PAIR_STRING("KernelVersion", u.version),
|
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("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("OperatingSystemCPEName", c->data[PROP_OS_CPE_NAME]),
|
||||||
SD_JSON_BUILD_PAIR_STRING("OperatingSystemHomeURL", c->data[PROP_OS_HOME_URL]),
|
SD_JSON_BUILD_PAIR_STRING("OperatingSystemHomeURL", c->data[PROP_OS_HOME_URL]),
|
||||||
JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol),
|
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("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("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("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("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("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),
|
SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field, offsetof(Context, data[PROP_OS_HOME_URL]), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
|||||||
@ -283,6 +283,7 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TABLE_STRING:
|
case TABLE_STRING:
|
||||||
|
case TABLE_STRING_WITH_ANSI:
|
||||||
case TABLE_PATH:
|
case TABLE_PATH:
|
||||||
case TABLE_PATH_BASENAME:
|
case TABLE_PATH_BASENAME:
|
||||||
case TABLE_FIELD:
|
case TABLE_FIELD:
|
||||||
@ -529,7 +530,7 @@ int table_add_cell_stringf_full(Table *t, TableCell **ret_cell, TableDataType dt
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
assert(IN_SET(dt, TABLE_STRING, TABLE_PATH, TABLE_PATH_BASENAME, TABLE_FIELD, TABLE_HEADER, TABLE_VERSION));
|
assert(IN_SET(dt, TABLE_STRING, TABLE_STRING_WITH_ANSI, TABLE_PATH, TABLE_PATH_BASENAME, TABLE_FIELD, TABLE_HEADER, TABLE_VERSION));
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
r = vasprintf(&buffer, format, ap);
|
r = vasprintf(&buffer, format, ap);
|
||||||
@ -933,6 +934,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TABLE_STRING:
|
case TABLE_STRING:
|
||||||
|
case TABLE_STRING_WITH_ANSI:
|
||||||
case TABLE_PATH:
|
case TABLE_PATH:
|
||||||
case TABLE_PATH_BASENAME:
|
case TABLE_PATH_BASENAME:
|
||||||
case TABLE_FIELD:
|
case TABLE_FIELD:
|
||||||
@ -1393,6 +1395,7 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
|||||||
switch (a->type) {
|
switch (a->type) {
|
||||||
|
|
||||||
case TABLE_STRING:
|
case TABLE_STRING:
|
||||||
|
case TABLE_STRING_WITH_ANSI:
|
||||||
case TABLE_FIELD:
|
case TABLE_FIELD:
|
||||||
case TABLE_HEADER:
|
case TABLE_HEADER:
|
||||||
return strcmp(a->string, b->string);
|
return strcmp(a->string, b->string);
|
||||||
@ -1574,7 +1577,13 @@ static char* format_strv_width(char **strv, size_t column_width) {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercasing, size_t column_width, bool *have_soft) {
|
static const char *table_data_format(
|
||||||
|
Table *t,
|
||||||
|
TableData *d,
|
||||||
|
bool avoid_uppercasing,
|
||||||
|
size_t column_width,
|
||||||
|
bool *have_soft) {
|
||||||
|
|
||||||
assert(d);
|
assert(d);
|
||||||
|
|
||||||
if (d->formatted &&
|
if (d->formatted &&
|
||||||
@ -1587,6 +1596,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||||||
return table_ersatz_string(t);
|
return table_ersatz_string(t);
|
||||||
|
|
||||||
case TABLE_STRING:
|
case TABLE_STRING:
|
||||||
|
case TABLE_STRING_WITH_ANSI:
|
||||||
case TABLE_PATH:
|
case TABLE_PATH:
|
||||||
case TABLE_PATH_BASENAME:
|
case TABLE_PATH_BASENAME:
|
||||||
case TABLE_FIELD:
|
case TABLE_FIELD:
|
||||||
@ -2068,6 +2078,42 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
|||||||
return d->formatted;
|
return d->formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *table_data_format_strip_ansi(
|
||||||
|
Table *t,
|
||||||
|
TableData *d,
|
||||||
|
bool avoid_uppercasing,
|
||||||
|
size_t column_width,
|
||||||
|
bool *have_soft,
|
||||||
|
char **ret_buffer) {
|
||||||
|
|
||||||
|
/* Just like table_data_format() but strips ANSI sequences for ANSI fields. */
|
||||||
|
|
||||||
|
assert(ret_buffer);
|
||||||
|
|
||||||
|
const char *c;
|
||||||
|
|
||||||
|
c = table_data_format(t, d, avoid_uppercasing, column_width, have_soft);
|
||||||
|
if (!c)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (d->type != TABLE_STRING_WITH_ANSI) {
|
||||||
|
/* Shortcut: we do not consider ANSI sequences for all other column types, hence return the
|
||||||
|
* original string as-is */
|
||||||
|
*ret_buffer = NULL;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanup_free_ char *s = strdup(c);
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!strip_tab_ansi(&s, /* isz= */ NULL, /* highlight= */ NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*ret_buffer = TAKE_PTR(s);
|
||||||
|
return *ret_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
static int console_width_height(
|
static int console_width_height(
|
||||||
const char *s,
|
const char *s,
|
||||||
size_t *ret_width,
|
size_t *ret_width,
|
||||||
@ -2122,14 +2168,20 @@ static int table_data_requested_width_height(
|
|||||||
size_t *ret_height,
|
size_t *ret_height,
|
||||||
bool *have_soft) {
|
bool *have_soft) {
|
||||||
|
|
||||||
_cleanup_free_ char *truncated = NULL;
|
_cleanup_free_ char *truncated = NULL, *buffer = NULL;
|
||||||
bool truncation_applied = false;
|
bool truncation_applied = false;
|
||||||
size_t width, height;
|
size_t width, height;
|
||||||
|
bool soft = false;
|
||||||
const char *t;
|
const char *t;
|
||||||
int r;
|
int r;
|
||||||
bool soft = false;
|
|
||||||
|
|
||||||
t = table_data_format(table, d, false, available_width, &soft);
|
t = table_data_format_strip_ansi(
|
||||||
|
table,
|
||||||
|
d,
|
||||||
|
/* avoid_uppercasing= */ false,
|
||||||
|
available_width,
|
||||||
|
&soft,
|
||||||
|
&buffer);
|
||||||
if (!t)
|
if (!t)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2352,7 +2404,7 @@ int table_print(Table *t, FILE *f) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) { /* Truncated because too many lines? */
|
if (r > 0) { /* Truncated because too many lines? */
|
||||||
_cleanup_free_ char *last = NULL;
|
_cleanup_free_ char *last = NULL, *buffer = NULL;
|
||||||
const char *field;
|
const char *field;
|
||||||
|
|
||||||
/* If we are going to show only the first few lines of a cell that has
|
/* If we are going to show only the first few lines of a cell that has
|
||||||
@ -2360,9 +2412,13 @@ int table_print(Table *t, FILE *f) {
|
|||||||
* ellipsis. Hence, let's figure out the last line, and account for its
|
* ellipsis. Hence, let's figure out the last line, and account for its
|
||||||
* length plus ellipsis. */
|
* length plus ellipsis. */
|
||||||
|
|
||||||
field = table_data_format(t, d, false,
|
field = table_data_format_strip_ansi(
|
||||||
|
t,
|
||||||
|
d,
|
||||||
|
/* avoid_uppercasing= */ false,
|
||||||
width ? width[j] : SIZE_MAX,
|
width ? width[j] : SIZE_MAX,
|
||||||
&any_soft);
|
&any_soft,
|
||||||
|
&buffer);
|
||||||
if (!field)
|
if (!field)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2550,7 +2606,7 @@ int table_print(Table *t, FILE *f) {
|
|||||||
more_sublines = false;
|
more_sublines = false;
|
||||||
|
|
||||||
for (size_t j = 0; j < display_columns; j++) {
|
for (size_t j = 0; j < display_columns; j++) {
|
||||||
_cleanup_free_ char *buffer = NULL, *extracted = NULL;
|
_cleanup_free_ char *buffer = NULL, *stripped_ansi_buffer = NULL, *extracted = NULL;
|
||||||
bool lines_truncated = false;
|
bool lines_truncated = false;
|
||||||
const char *field, *color = NULL, *underline = NULL;
|
const char *field, *color = NULL, *underline = NULL;
|
||||||
TableData *d;
|
TableData *d;
|
||||||
@ -2558,7 +2614,21 @@ int table_print(Table *t, FILE *f) {
|
|||||||
|
|
||||||
assert_se(d = row[t->display_map ? t->display_map[j] : j]);
|
assert_se(d = row[t->display_map ? t->display_map[j] : j]);
|
||||||
|
|
||||||
field = table_data_format(t, d, false, width[j], NULL);
|
if (colors_enabled())
|
||||||
|
field = table_data_format(
|
||||||
|
t,
|
||||||
|
d,
|
||||||
|
/* avoid_uppercasing= */ false,
|
||||||
|
width[j],
|
||||||
|
/* have_soft= */ NULL);
|
||||||
|
else
|
||||||
|
field = table_data_format_strip_ansi(
|
||||||
|
t,
|
||||||
|
d,
|
||||||
|
/* avoid_uppercasing= */ false,
|
||||||
|
width[j],
|
||||||
|
/* have_soft= */ NULL,
|
||||||
|
&stripped_ansi_buffer);
|
||||||
if (!field)
|
if (!field)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2665,7 +2735,8 @@ int table_print(Table *t, FILE *f) {
|
|||||||
|
|
||||||
fputs(field, f);
|
fputs(field, f);
|
||||||
|
|
||||||
if (color || underline)
|
/* Reset color afterwards if colors was set or the string to output contained ANSI sequences. */
|
||||||
|
if (color || underline || (d->type == TABLE_STRING_WITH_ANSI && colors_enabled()))
|
||||||
fputs(ANSI_NORMAL, f);
|
fputs(ANSI_NORMAL, f);
|
||||||
|
|
||||||
gap_color = d->rgap_color;
|
gap_color = d->rgap_color;
|
||||||
@ -2920,6 +2991,18 @@ static int table_data_to_json(TableData *d, sd_json_variant **ret) {
|
|||||||
SD_JSON_BUILD_UNSIGNED(major(d->devnum)),
|
SD_JSON_BUILD_UNSIGNED(major(d->devnum)),
|
||||||
SD_JSON_BUILD_UNSIGNED(minor(d->devnum))));
|
SD_JSON_BUILD_UNSIGNED(minor(d->devnum))));
|
||||||
|
|
||||||
|
case TABLE_STRING_WITH_ANSI: {
|
||||||
|
_cleanup_free_ char *s = strdup(d->string);
|
||||||
|
if (!s)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* We strip the ANSI data when outputting to JSON */
|
||||||
|
if (!strip_tab_ansi(&s, /* isz= */ NULL, /* highlight= */ NULL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return sd_json_variant_new_string(ret, s);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -2963,7 +3046,7 @@ char* table_mangle_to_json_field_name(const char *str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int table_make_json_field_name(Table *t, TableData *d, char **ret) {
|
static int table_make_json_field_name(Table *t, TableData *d, char **ret) {
|
||||||
_cleanup_free_ char *mangled = NULL;
|
_cleanup_free_ char *mangled = NULL, *buffer = NULL;
|
||||||
const char *n;
|
const char *n;
|
||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
@ -2973,7 +3056,13 @@ static int table_make_json_field_name(Table *t, TableData *d, char **ret) {
|
|||||||
if (IN_SET(d->type, TABLE_HEADER, TABLE_FIELD))
|
if (IN_SET(d->type, TABLE_HEADER, TABLE_FIELD))
|
||||||
n = d->string;
|
n = d->string;
|
||||||
else {
|
else {
|
||||||
n = table_data_format(t, d, /* avoid_uppercasing= */ true, SIZE_MAX, NULL);
|
n = table_data_format_strip_ansi(
|
||||||
|
t,
|
||||||
|
d,
|
||||||
|
/* avoid_uppercasing= */ true,
|
||||||
|
/* column_width= */ SIZE_MAX,
|
||||||
|
/* have_soft= */ NULL,
|
||||||
|
&buffer);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
typedef enum TableDataType {
|
typedef enum TableDataType {
|
||||||
TABLE_EMPTY,
|
TABLE_EMPTY,
|
||||||
TABLE_STRING,
|
TABLE_STRING,
|
||||||
|
TABLE_STRING_WITH_ANSI, /* like the above, but contains ANSI sequences/TABs. They will be stripped when outputing to JSON */
|
||||||
TABLE_HEADER, /* in regular mode: the cells in the first row, that carry the column names */
|
TABLE_HEADER, /* in regular mode: the cells in the first row, that carry the column names */
|
||||||
TABLE_FIELD, /* in vertical mode: the cells in the first column, that carry the field names */
|
TABLE_FIELD, /* in vertical mode: the cells in the first column, that carry the field names */
|
||||||
TABLE_STRV,
|
TABLE_STRV,
|
||||||
|
|||||||
@ -20,7 +20,10 @@ static SD_VARLINK_DEFINE_METHOD(
|
|||||||
SD_VARLINK_DEFINE_OUTPUT(KernelName, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_OUTPUT(KernelName, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(KernelRelease, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_OUTPUT(KernelRelease, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(KernelVersion, 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_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(OperatingSystemCPEName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemHomeURL, 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),
|
SD_VARLINK_DEFINE_OUTPUT(OperatingSystemSupportEnd, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "ansi-color.h"
|
||||||
|
#include "env-util.h"
|
||||||
#include "format-table.h"
|
#include "format-table.h"
|
||||||
#include "json-util.h"
|
#include "json-util.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
@ -835,9 +837,80 @@ TEST(table_bps) {
|
|||||||
"2500000000 2.3G 2.5Gbps\n");
|
"2500000000 2.3G 2.5Gbps\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(table_ansi) {
|
||||||
|
_cleanup_(table_unrefp) Table *table = NULL;
|
||||||
|
|
||||||
|
ASSERT_NOT_NULL((table = table_new("foo", "bar", "baz", "kkk")));
|
||||||
|
|
||||||
|
ASSERT_OK(table_add_many(table,
|
||||||
|
TABLE_STRING, "hallo",
|
||||||
|
TABLE_STRING_WITH_ANSI, "knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green",
|
||||||
|
TABLE_STRING_WITH_ANSI, "noansi",
|
||||||
|
TABLE_STRING_WITH_ANSI, ANSI_GREY "thisisgrey"));
|
||||||
|
|
||||||
|
unsigned saved_columns = columns();
|
||||||
|
bool saved_color = colors_enabled();
|
||||||
|
_cleanup_free_ char *saved_term = NULL;
|
||||||
|
const char *e = getenv("TERM");
|
||||||
|
if (e)
|
||||||
|
ASSERT_NOT_NULL((saved_term = strdup(e)));
|
||||||
|
|
||||||
|
ASSERT_OK_ERRNO(setenv("COLUMNS", "200", /* overwrite= */ true));
|
||||||
|
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "1", /* overwrite= */ true));
|
||||||
|
ASSERT_OK_ERRNO(setenv("TERM", FALLBACK_TERM, /* overwrite= */ true));
|
||||||
|
reset_terminal_feature_caches();
|
||||||
|
|
||||||
|
_cleanup_free_ char *formatted = NULL;
|
||||||
|
ASSERT_OK(table_format(table, &formatted));
|
||||||
|
|
||||||
|
ASSERT_STREQ(formatted,
|
||||||
|
ANSI_ADD_UNDERLINE "FOO " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE "BAR " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE "BAZ " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||||
|
ANSI_ADD_UNDERLINE "KKK " ANSI_NORMAL "\n"
|
||||||
|
"hallo knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green" ANSI_NORMAL
|
||||||
|
" noansi" ANSI_NORMAL
|
||||||
|
" " ANSI_GREY "thisisgrey" ANSI_NORMAL "\n");
|
||||||
|
|
||||||
|
/* Validate that color is correctly stripped */
|
||||||
|
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
|
||||||
|
reset_terminal_feature_caches();
|
||||||
|
|
||||||
|
formatted = mfree(formatted);
|
||||||
|
ASSERT_OK(table_format(table, &formatted));
|
||||||
|
|
||||||
|
ASSERT_STREQ(formatted,
|
||||||
|
"FOO BAR BAZ KKK\n"
|
||||||
|
"hallo knuerzredgreen noansi thisisgrey\n");
|
||||||
|
|
||||||
|
ASSERT_OK(table_print(table, /* f= */ NULL));
|
||||||
|
|
||||||
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL, *jj = NULL;
|
||||||
|
|
||||||
|
ASSERT_OK(table_to_json(table, &j));
|
||||||
|
|
||||||
|
ASSERT_OK(sd_json_build(&jj,
|
||||||
|
SD_JSON_BUILD_ARRAY(
|
||||||
|
SD_JSON_BUILD_OBJECT(
|
||||||
|
SD_JSON_BUILD_PAIR_STRING("foo", "hallo"),
|
||||||
|
SD_JSON_BUILD_PAIR_STRING("bar", "knuerzredgreen"),
|
||||||
|
SD_JSON_BUILD_PAIR_STRING("baz", "noansi"),
|
||||||
|
SD_JSON_BUILD_PAIR_STRING("kkk", "thisisgrey")))));
|
||||||
|
ASSERT_TRUE(sd_json_variant_equal(j, jj));
|
||||||
|
|
||||||
|
ASSERT_OK(sd_json_variant_dump(j, SD_JSON_FORMAT_COLOR_AUTO|SD_JSON_FORMAT_PRETTY_AUTO, /* f= */ NULL, /* prefix= */ NULL));
|
||||||
|
|
||||||
|
ASSERT_OK(setenvf("COLUMNS", /* overwrite= */ true, "%u", saved_columns));
|
||||||
|
ASSERT_OK(setenvf("SYSTEMD_COLORS", /* overwrite= */ true, "%i", saved_color));
|
||||||
|
ASSERT_OK(set_unset_env("TERM", saved_term, /* overwrite= */ true));
|
||||||
|
}
|
||||||
|
|
||||||
static int intro(void) {
|
static int intro(void) {
|
||||||
ASSERT_OK(setenv("SYSTEMD_COLORS", "0", 1));
|
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
|
||||||
ASSERT_OK(setenv("COLUMNS", "40", 1));
|
ASSERT_OK_ERRNO(setenv("COLUMNS", "40", /* overwrite= */ true));
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user