manager: add taint flag "support-ended"

In the welcome line, use NAME= as the fallback for PRETTY_NAME=.
PRETTY_NAME= doesn't have to be set, but NAME= should.

Example output:
---
Welcome to Fedora Linux 37 (Rawhide Prerelease)!

[  !!  ] This OS version (Fedora Linux 37 (Rawhide Prerelease)) is past its end-of-support date (1999-01-01)
Queued start job for default target graphical.target.
[  OK  ] Created slice system-getty.slice.
---
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2022-07-09 18:00:33 +02:00
parent 8bf9eb7e6b
commit 4bd035153b
6 changed files with 100 additions and 19 deletions

View file

@ -1544,6 +1544,15 @@ node /org/freedesktop/systemd1 {
UTC.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>support-ended</literal></term>
<listitem><para>The system is running past the end of support declared by the vendor. See the
description of <varname>SUPPORT_END=</varname> in
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>old-kernel</literal></term>

View file

@ -317,3 +317,38 @@ int load_extension_release_pairs(const char *root, const char *extension, char *
return load_env_file_pairs(f, p, ret);
}
int os_release_support_ended(const char *support_end, bool quiet) {
_cleanup_free_ char *_support_end_alloc = NULL;
int r;
if (!support_end) {
/* If the caller has the variably handy, they can pass it in. If not, we'll read it
* ourselves. */
r = parse_os_release(NULL,
"SUPPORT_END", &_support_end_alloc);
if (r < 0)
return log_full_errno((r == -ENOENT || quiet) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
if (!_support_end_alloc)
return false; /* no end date defined */
support_end = _support_end_alloc;
}
struct tm tm = {};
const char *k = strptime(support_end, "%Y-%m-%d", &tm);
if (!k || *k)
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
"Failed to parse SUPPORT_END= in os-release file, ignoring: %m");
time_t eol = mktime(&tm);
if (eol == (time_t) -1)
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
"Failed to convert SUPPORT_END= in os-release file, ignoring: %m");
usec_t ts = now(CLOCK_REALTIME);
return DIV_ROUND_UP(ts, USEC_PER_SEC) > (usec_t) eol;
}

View file

@ -31,3 +31,5 @@ int _parse_os_release(const char *root, ...) _sentinel_;
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
int os_release_support_ended(const char *support_end, bool quiet);

View file

@ -1312,29 +1312,46 @@ static int enforce_syscall_archs(Set *archs) {
return 0;
}
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
static int os_release_status(void) {
_cleanup_free_ char *pretty_name = NULL, *name = NULL, *version = NULL,
*ansi_color = NULL, *support_end = NULL;
int r;
if (!show_status_on(arg_show_status))
return 0;
r = parse_os_release(NULL,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color);
"NAME", &name,
"VERSION", &version,
"ANSI_COLOR", &ansi_color,
"SUPPORT_END", &support_end);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
if (log_get_show_color())
return status_printf(NULL, 0,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
isempty(ansi_color) ? "1" : ansi_color,
isempty(pretty_name) ? "Linux" : pretty_name);
else
return status_printf(NULL, 0,
"\nWelcome to %s!\n",
isempty(pretty_name) ? "Linux" : pretty_name);
const char *label = empty_to_null(pretty_name) ?: empty_to_null(name) ?: "Linux";
if (show_status_on(arg_show_status)) {
if (log_get_show_color())
status_printf(NULL, 0,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
empty_to_null(ansi_color) ?: "1",
label);
else
status_printf(NULL, 0,
"\nWelcome to %s!\n",
label);
}
if (support_end && os_release_support_ended(support_end, false) > 0)
/* pretty_name may include the version already, so we'll print the version only if we
* have it and we're not using pretty_name. */
status_printf(ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, 0,
"This OS version (%s%s%s) is past its end-of-support date (%s)",
label,
(pretty_name || !version) ? "" : " version ",
(pretty_name || !version) ? "" : version,
support_end);
return 0;
}
static int write_container_id(void) {
@ -2100,7 +2117,7 @@ static int initialize_runtime(
return r;
}
status_welcome();
(void) os_release_status();
(void) hostname_setup(true);
/* Force transient machine-id on first boot. */
machine_id_setup(NULL, first_boot, arg_machine_id, NULL);

View file

@ -61,6 +61,7 @@
#include "manager-serialize.h"
#include "memory-util.h"
#include "mkdir-label.h"
#include "os-util.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
@ -4475,7 +4476,7 @@ char* manager_taint_string(const Manager *m) {
assert(m);
const char* stage[12] = {};
const char* stage[13] = {};
size_t n = 0;
if (m->taint_usr)
@ -4494,6 +4495,9 @@ char* manager_taint_string(const Manager *m) {
if (clock_is_localtime(NULL) > 0)
stage[n++] = "local-hwclock";
if (os_release_support_ended(NULL, true) > 0)
stage[n++] = "support-ended";
_cleanup_free_ char *destination = NULL;
if (readlink_malloc("/var/run", &destination) < 0 ||
!PATH_IN_SET(destination, "../run", "/run"))

View file

@ -72,4 +72,18 @@ TEST(load_os_release_pairs) {
assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0);
}
TEST(os_release_support_ended) {
int r;
assert_se(os_release_support_ended("1999-01-01", false) == true);
assert_se(os_release_support_ended("2037-12-31", false) == false);
assert_se(os_release_support_ended("-1-1-1", true) == -EINVAL);
r = os_release_support_ended(NULL, false);
if (r < 0)
log_info_errno(r, "Failed to check host: %m");
else
log_info_errno(r, "Host is supported: %s", yes_no(!r));
}
DEFINE_TEST_MAIN(LOG_DEBUG);