diff --git a/TODO b/TODO
index 7e23ddb2c8..916c3096aa 100644
--- a/TODO
+++ b/TODO
@@ -2268,7 +2268,7 @@ Features:
* clean up date formatting and parsing so that all absolute/relative timestamps we format can also be parsed
-* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?), get rid of systemd-update-utmp-runlevel
+* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?)
* make repeated alt-ctrl-del presses printing a dump
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 246a059fa5..1fcf30e692 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -1185,10 +1185,7 @@ manpages = [
'systemd-udevd-varlink.socket'],
''],
['systemd-update-done.service', '8', ['systemd-update-done'], ''],
- ['systemd-update-utmp.service',
- '8',
- ['systemd-update-utmp', 'systemd-update-utmp-runlevel.service'],
- 'ENABLE_UTMP'],
+ ['systemd-update-utmp.service', '8', ['systemd-update-utmp'], 'ENABLE_UTMP'],
['systemd-user-sessions.service', '8', ['systemd-user-sessions'], 'HAVE_PAM'],
['systemd-userdbd.service', '8', ['systemd-userdbd'], 'ENABLE_USERDB'],
['systemd-validatefs@.service', '8', [], 'HAVE_BLKID'],
diff --git a/man/systemd-update-utmp.service.xml b/man/systemd-update-utmp.service.xml
index 2d7dee9d3a..a3044e9739 100644
--- a/man/systemd-update-utmp.service.xml
+++ b/man/systemd-update-utmp.service.xml
@@ -17,26 +17,21 @@
systemd-update-utmp.service
- systemd-update-utmp-runlevel.service
systemd-update-utmp
- Write audit and utmp updates at bootup, runlevel
- changes and shutdown
+ Write audit and utmp updates at bootup and shutdown
systemd-update-utmp.service
- systemd-update-utmp-runlevel.service
/usr/lib/systemd/systemd-update-utmp
Description
- systemd-update-utmp-runlevel.service is
- a service that writes SysV runlevel changes to utmp and wtmp, as
- well as the audit logs, as they occur.
- systemd-update-utmp.service does the same for
- system reboots and shutdown requests.
+
+ systemd-update-utmp.service is a service that writes system reboots and shutdown
+ requests to utmp and wtmp, as well as the audit logs.
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
index 8a69e9692b..6d150e7dcf 100644
--- a/src/shared/utmp-wtmp.c
+++ b/src/shared/utmp-wtmp.c
@@ -11,44 +11,6 @@
#include "time-util.h"
#include "utmp-wtmp.h"
-int utmp_get_runlevel(int *runlevel, int *previous) {
- _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
- struct utmpx *found, lookup = { .ut_type = RUN_LVL };
- const char *e;
-
- assert(runlevel);
-
- /* If these values are set in the environment this takes
- * precedence. Presumably, sysvinit does this to work around a
- * race condition that would otherwise exist where we'd always
- * go to disk and hence might read runlevel data that might be
- * very new and not apply to the current script being executed. */
-
- e = getenv("RUNLEVEL");
- if (!isempty(e)) {
- *runlevel = e[0];
- if (previous)
- *previous = 0;
-
- return 0;
- }
-
- if (utmpxname(UTMPX_FILE) < 0)
- return -errno;
-
- utmpx = utxent_start();
-
- found = getutxid(&lookup);
- if (!found)
- return -errno;
-
- *runlevel = found->ut_pid & 0xFF;
- if (previous)
- *previous = (found->ut_pid >> 8) & 0xFF;
-
- return 0;
-}
-
static void init_timestamp(struct utmpx *store, usec_t t) {
assert(store);
@@ -237,33 +199,3 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return write_utmp_wtmp(&store, &store_wtmp);
}
-
-int utmp_put_runlevel(int runlevel, int previous) {
- struct utmpx store = {};
- int r;
-
- assert(runlevel > 0);
-
- if (previous <= 0) {
- /* Find the old runlevel automatically */
-
- r = utmp_get_runlevel(&previous, NULL);
- if (r < 0) {
- if (r != -ESRCH)
- return r;
-
- previous = 0;
- }
- }
-
- if (previous == runlevel)
- return 0;
-
- init_entry(&store, 0);
-
- store.ut_type = RUN_LVL;
- store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8);
- strncpy(store.ut_user, "runlevel", sizeof(store.ut_user));
-
- return write_entry_both(&store);
-}
diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h
index f4b543e6c0..72e8ff375b 100644
--- a/src/shared/utmp-wtmp.h
+++ b/src/shared/utmp-wtmp.h
@@ -6,11 +6,8 @@
#if ENABLE_UTMP
#include
-int utmp_get_runlevel(int *runlevel, int *previous);
-
int utmp_put_shutdown(void);
int utmp_put_reboot(usec_t timestamp);
-int utmp_put_runlevel(int runlevel, int previous);
int utmp_put_dead_process(const char *id, pid_t pid, int code, int status);
int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user);
@@ -27,18 +24,12 @@ static inline void utxent_cleanup(bool *initialized) {
#else /* ENABLE_UTMP */
-static inline int utmp_get_runlevel(int *runlevel, int *previous) {
- return -ESRCH;
-}
static inline int utmp_put_shutdown(void) {
return 0;
}
static inline int utmp_put_reboot(usec_t timestamp) {
return 0;
}
-static inline int utmp_put_runlevel(int runlevel, int previous) {
- return 0;
-}
static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return 0;
}
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index 78c693012e..4f96f3a377 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -57,81 +57,6 @@ static int get_startup_monotonic_time(Context *c, usec_t *ret) {
return 0;
}
-#define MAX_ATTEMPTS 64u
-
-static int get_current_runlevel(Context *c) {
- static const struct {
- const int runlevel;
- const char *special;
- } table[] = {
- /* The first target of this list that is active or has a job scheduled wins. We prefer
- * runlevels 5 and 3 here over the others, since these are the main runlevels used on Fedora.
- * It might make sense to change the order on some distributions. */
- { '5', SPECIAL_GRAPHICAL_TARGET },
- { '3', SPECIAL_MULTI_USER_TARGET },
- { '1', SPECIAL_RESCUE_TARGET },
- };
- int r;
-
- assert(c);
-
- for (unsigned n_attempts = 0;;) {
- if (n_attempts++ > 0) {
- /* systemd might have dropped off momentarily, let's not make this an error,
- * and wait some random time. Let's pick a random time in the range 100ms…2000ms,
- * linearly scaled by the number of failed attempts. */
- c->bus = sd_bus_flush_close_unref(c->bus);
-
- usec_t usec =
- UINT64_C(100) * USEC_PER_MSEC +
- random_u64_range(UINT64_C(1900) * USEC_PER_MSEC * n_attempts / MAX_ATTEMPTS);
- (void) usleep_safe(usec);
- }
-
- if (!c->bus) {
- r = bus_connect_system_systemd(&c->bus);
- if (r == -ECONNREFUSED && n_attempts < 64) {
- log_debug_errno(r, "Failed to %s to system bus, retrying after a slight delay: %m",
- n_attempts <= 1 ? "connect" : "reconnect");
- continue;
- }
- if (r < 0)
- return log_error_errno(r, "Failed to reconnect to system bus: %m");
- }
-
- FOREACH_ELEMENT(e, table) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *state = NULL, *path = NULL;
-
- path = unit_dbus_path_from_name(e->special);
- if (!path)
- return log_oom();
-
- r = sd_bus_get_property_string(
- c->bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "ActiveState",
- &error,
- &state);
- if ((r == -ENOTCONN || bus_error_is_connection(&error)) &&
- n_attempts < MAX_ATTEMPTS) {
- log_debug_errno(r, "Failed to get state of %s, retrying after a slight delay: %s",
- e->special, bus_error_message(&error, r));
- break;
- }
- if (r < 0)
- return log_warning_errno(r, "Failed to get state of %s: %s", e->special, bus_error_message(&error, r));
-
- if (STR_IN_SET(state, "active", "reloading"))
- return e->runlevel;
- }
- if (r >= 0)
- return 0;
- }
-}
-
static int on_reboot(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
usec_t t = 0, boottime;
@@ -182,59 +107,10 @@ static int on_shutdown(int argc, char *argv[], void *userdata) {
return q;
}
-static int on_runlevel(int argc, char *argv[], void *userdata) {
- Context *c = ASSERT_PTR(userdata);
- int r, q = 0, previous, runlevel;
-
- /* We finished changing runlevel, so let's write the utmp record and send the audit msg. */
-
- /* First, get last runlevel */
- r = utmp_get_runlevel(&previous, NULL);
- if (r < 0) {
- if (!IN_SET(r, -ESRCH, -ENOENT))
- return log_error_errno(r, "Failed to get the last runlevel from utmp: %m");
-
- previous = 0;
- }
-
- /* Secondly, get new runlevel */
- runlevel = get_current_runlevel(c);
- if (runlevel < 0)
- return runlevel;
- if (runlevel == 0) {
- log_warning("Failed to get the current runlevel, utmp update skipped.");
- return 0;
- }
-
- if (previous == runlevel)
- return 0;
-
-#if HAVE_AUDIT
- if (c->audit_fd >= 0) {
- char s[STRLEN("old-level=_ new-level=_") + 1];
-
- xsprintf(s, "old-level=%c new-level=%c",
- previous > 0 ? previous : 'N',
- runlevel);
-
- if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s,
- "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM)
- q = log_error_errno(errno, "Failed to send audit message: %m");
- }
-#endif
-
- r = utmp_put_runlevel(runlevel, previous);
- if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT))
- return log_error_errno(r, "Failed to write utmp record: %m");
-
- return q;
-}
-
static int run(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "reboot", 1, 1, 0, on_reboot },
{ "shutdown", 1, 1, 0, on_shutdown },
- { "runlevel", 1, 1, 0, on_runlevel },
{}
};
diff --git a/test/units/TEST-01-BASIC.sh b/test/units/TEST-01-BASIC.sh
index bb3ff2f1e9..780f37ee12 100755
--- a/test/units/TEST-01-BASIC.sh
+++ b/test/units/TEST-01-BASIC.sh
@@ -45,19 +45,4 @@ systemctl daemon-reload
# of systemd-analyze blame. See issue #27187.
systemd-analyze blame
-# Test for 'systemd-update-utmp runlevel' vs 'systemctl daemon-reexec'.
-# See issue #27163.
-# shellcheck disable=SC2034
-if [[ -x /usr/lib/systemd/systemd-update-utmp ]]; then
- for _ in {0..10}; do
- systemctl daemon-reexec &
- pid_reexec=$!
- # shellcheck disable=SC2034
- for _ in {0..10}; do
- SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-update-utmp runlevel
- done
- wait "$pid_reexec"
- done
-fi
-
touch /testok
diff --git a/units/meson.build b/units/meson.build
index bc67a6ee8a..34b3222f11 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -818,11 +818,6 @@ units = [
'file' : 'systemd-update-done.service.in',
'symlinks' : ['sysinit.target.wants/'],
},
- {
- 'file' : 'systemd-update-utmp-runlevel.service.in',
- 'conditions' : ['ENABLE_UTMP', 'HAVE_SYSV_COMPAT'],
- 'symlinks' : ['multi-user.target.wants/', 'graphical.target.wants/', 'rescue.target.wants/'],
- },
{
'file' : 'systemd-update-utmp.service.in',
'conditions' : ['ENABLE_UTMP'],
diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in
deleted file mode 100644
index 17772d4576..0000000000
--- a/units/systemd-update-utmp-runlevel.service.in
+++ /dev/null
@@ -1,25 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-#
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=Record Runlevel Change in UTMP
-Documentation=man:systemd-update-utmp-runlevel.service(8) man:utmp(5)
-ConditionPathExists=!/etc/initrd-release
-
-DefaultDependencies=no
-RequiresMountsFor=/var/log/wtmp
-Conflicts=shutdown.target
-Requisite=systemd-update-utmp.service
-After=systemd-update-utmp.service
-After=runlevel1.target runlevel2.target runlevel3.target runlevel4.target runlevel5.target
-Before=shutdown.target
-
-[Service]
-Type=oneshot
-ExecStart={{LIBEXECDIR}}/systemd-update-utmp runlevel