]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: split utmp related code into logind-utmp.[ch]
authorLennart Poettering <lennart@poettering.net>
Wed, 2 Apr 2025 14:42:40 +0000 (16:42 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 2 Apr 2025 15:12:42 +0000 (17:12 +0200)
No real changes, just moving of code around.

src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-utmp.c [new file with mode: 0644]
src/login/logind-utmp.h [new file with mode: 0644]
src/login/logind.c
src/login/logind.h
src/login/meson.build

index f3102c3199495610a5e7093c0abac9b79dd992a9..1619276520638731bac1720e017e957c0cf344f5 100644 (file)
@@ -20,6 +20,7 @@
 #include "fd-util.h"
 #include "limits-util.h"
 #include "logind.h"
+#include "logind-utmp.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
@@ -29,7 +30,6 @@
 #include "udev-util.h"
 #include "user-util.h"
 #include "userdb.h"
-#include "utmp-wtmp.h"
 
 void manager_reset_config(Manager *m) {
         assert(m);
@@ -711,137 +711,6 @@ bool manager_all_buttons_ignored(Manager *m) {
         return true;
 }
 
-int manager_read_utmp(Manager *m) {
-#if ENABLE_UTMP
-        int r;
-        _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
-
-        assert(m);
-
-        if (utmpxname(UTMPX_FILE) < 0)
-                return log_error_errno(errno, "Failed to set utmp path to " UTMPX_FILE ": %m");
-
-        utmpx = utxent_start();
-
-        for (;;) {
-                _cleanup_free_ char *t = NULL;
-                struct utmpx *u;
-                const char *c;
-                Session *s;
-
-                errno = 0;
-                u = getutxent();
-                if (!u) {
-                        if (errno == ENOENT)
-                                log_debug_errno(errno, UTMPX_FILE " does not exist, ignoring.");
-                        else if (errno != 0)
-                                log_warning_errno(errno, "Failed to read " UTMPX_FILE ", ignoring: %m");
-                        return 0;
-                }
-
-                if (u->ut_type != USER_PROCESS)
-                        continue;
-
-                if (!pid_is_valid(u->ut_pid))
-                        continue;
-
-                t = strndup(u->ut_line, sizeof(u->ut_line));
-                if (!t)
-                        return log_oom();
-
-                c = path_startswith(t, "/dev/");
-                if (c) {
-                        r = free_and_strdup(&t, c);
-                        if (r < 0)
-                                return log_oom();
-                }
-
-                if (isempty(t))
-                        continue;
-
-                if (manager_get_session_by_pidref(m, &PIDREF_MAKE_FROM_PID(u->ut_pid), &s) <= 0)
-                        continue;
-
-                if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
-                        /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
-                         * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
-                         * information and never acquire it again. */
-
-                        s->tty = mfree(s->tty);
-                        s->tty_validity = TTY_UTMP_INCONSISTENT;
-                        log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
-                        continue;
-                }
-
-                /* Never override what we figured out once */
-                if (s->tty || s->tty_validity >= 0)
-                        continue;
-
-                s->tty = TAKE_PTR(t);
-                s->tty_validity = TTY_FROM_UTMP;
-                log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
-        }
-
-#else
-        return 0;
-#endif
-}
-
-#if ENABLE_UTMP
-static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
-        Manager *m = ASSERT_PTR(userdata);
-
-        /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
-         * reestablish the watch on whatever there's now. */
-        if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
-                manager_connect_utmp(m);
-
-        (void) manager_read_utmp(m);
-        return 0;
-}
-#endif
-
-void manager_connect_utmp(Manager *m) {
-#if ENABLE_UTMP
-        sd_event_source *s = NULL;
-        int r;
-
-        assert(m);
-
-        /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
-         * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
-         * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
-         * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
-         *
-         * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
-         * detection (which, for tty sessions, relies on the TTY used) */
-
-        r = sd_event_add_inotify(m->event, &s, UTMPX_FILE, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
-        if (r < 0)
-                log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " UTMPX_FILE ", ignoring: %m");
-        else {
-                r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
-                if (r < 0)
-                        log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
-
-                (void) sd_event_source_set_description(s, "utmp");
-        }
-
-        sd_event_source_unref(m->utmp_event_source);
-        m->utmp_event_source = s;
-#endif
-}
-
-void manager_reconnect_utmp(Manager *m) {
-#if ENABLE_UTMP
-        assert(m);
-
-        if (m->utmp_event_source)
-                return;
-
-        manager_connect_utmp(m);
-#endif
-}
 
 int manager_read_efi_boot_loader_entries(Manager *m) {
 #if ENABLE_EFI
index ed0db4a2ffc89dd73c63cfbbd7094036eae939fe..404bee5a858e6aed68642b113f95ae53a8daa16a 100644 (file)
 #include "fileio.h"
 #include "format-util.h"
 #include "fs-util.h"
+#include "logind.h"
 #include "logind-action.h"
 #include "logind-dbus.h"
 #include "logind-polkit.h"
 #include "logind-seat-dbus.h"
 #include "logind-session-dbus.h"
 #include "logind-user-dbus.h"
-#include "logind.h"
+#include "logind-utmp.h"
 #include "mkdir-label.h"
 #include "parse-util.h"
 #include "path-util.h"
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
new file mode 100644 (file)
index 0000000..d2a1331
--- /dev/null
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "logind-utmp.h"
+#include "path-util.h"
+#include "utmp-wtmp.h"
+
+int manager_read_utmp(Manager *m) {
+#if ENABLE_UTMP
+        int r;
+        _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
+
+        assert(m);
+
+        if (utmpxname(UTMPX_FILE) < 0)
+                return log_error_errno(errno, "Failed to set utmp path to " UTMPX_FILE ": %m");
+
+        utmpx = utxent_start();
+
+        for (;;) {
+                _cleanup_free_ char *t = NULL;
+                struct utmpx *u;
+                const char *c;
+                Session *s;
+
+                errno = 0;
+                u = getutxent();
+                if (!u) {
+                        if (errno == ENOENT)
+                                log_debug_errno(errno, UTMPX_FILE " does not exist, ignoring.");
+                        else if (errno != 0)
+                                log_warning_errno(errno, "Failed to read " UTMPX_FILE ", ignoring: %m");
+                        return 0;
+                }
+
+                if (u->ut_type != USER_PROCESS)
+                        continue;
+
+                if (!pid_is_valid(u->ut_pid))
+                        continue;
+
+                t = strndup(u->ut_line, sizeof(u->ut_line));
+                if (!t)
+                        return log_oom();
+
+                c = path_startswith(t, "/dev/");
+                if (c) {
+                        r = free_and_strdup(&t, c);
+                        if (r < 0)
+                                return log_oom();
+                }
+
+                if (isempty(t))
+                        continue;
+
+                if (manager_get_session_by_pidref(m, &PIDREF_MAKE_FROM_PID(u->ut_pid), &s) <= 0)
+                        continue;
+
+                if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
+                        /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
+                         * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
+                         * information and never acquire it again. */
+
+                        s->tty = mfree(s->tty);
+                        s->tty_validity = TTY_UTMP_INCONSISTENT;
+                        log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
+                        continue;
+                }
+
+                /* Never override what we figured out once */
+                if (s->tty || s->tty_validity >= 0)
+                        continue;
+
+                s->tty = TAKE_PTR(t);
+                s->tty_validity = TTY_FROM_UTMP;
+                log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
+        }
+
+#else
+        return 0;
+#endif
+}
+
+#if ENABLE_UTMP
+static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
+        Manager *m = ASSERT_PTR(userdata);
+
+        /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
+         * reestablish the watch on whatever there's now. */
+        if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
+                manager_connect_utmp(m);
+
+        (void) manager_read_utmp(m);
+        return 0;
+}
+#endif
+
+void manager_connect_utmp(Manager *m) {
+#if ENABLE_UTMP
+        sd_event_source *s = NULL;
+        int r;
+
+        assert(m);
+
+        /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
+         * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
+         * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
+         * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
+         *
+         * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
+         * detection (which, for tty sessions, relies on the TTY used) */
+
+        r = sd_event_add_inotify(m->event, &s, UTMPX_FILE, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
+        if (r < 0)
+                log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " UTMPX_FILE ", ignoring: %m");
+        else {
+                r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
+
+                (void) sd_event_source_set_description(s, "utmp");
+        }
+
+        sd_event_source_unref(m->utmp_event_source);
+        m->utmp_event_source = s;
+#endif
+}
+
+void manager_reconnect_utmp(Manager *m) {
+#if ENABLE_UTMP
+        assert(m);
+
+        if (m->utmp_event_source)
+                return;
+
+        manager_connect_utmp(m);
+#endif
+}
diff --git a/src/login/logind-utmp.h b/src/login/logind-utmp.h
new file mode 100644 (file)
index 0000000..1358e27
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "logind.h"
+
+int manager_read_utmp(Manager *m);
+void manager_connect_utmp(Manager *m);
+void manager_reconnect_utmp(Manager *m);
index ef1952b0cca833ecd32169856c87465748d9b875..f1e2ea3c46165154c5baf334165f12212e7180e3 100644 (file)
@@ -29,6 +29,7 @@
 #include "logind-seat-dbus.h"
 #include "logind-session-dbus.h"
 #include "logind-user-dbus.h"
+#include "logind-utmp.h"
 #include "logind-varlink.h"
 #include "main-func.h"
 #include "mkdir-label.h"
index b19fbb7f3e05009fa284ce6bfc2c831484f13c10..35d4e9c257c8b44b5e8dd7037eb98f3fe96d4e8c 100644 (file)
@@ -181,10 +181,6 @@ bool manager_is_docked_or_external_displays(Manager *m);
 bool manager_is_on_external_power(void);
 bool manager_all_buttons_ignored(Manager *m);
 
-int manager_read_utmp(Manager *m);
-void manager_connect_utmp(Manager *m);
-void manager_reconnect_utmp(Manager *m);
-
 /* gperf lookup function */
 const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
 
index b74484393361daac230e179b36bfd0e90298a618..2983819c56bd7f5d567a8f83cef7b7affae6ad80 100644 (file)
@@ -26,6 +26,7 @@ liblogind_core_sources = files(
         'logind-session.c',
         'logind-user-dbus.c',
         'logind-user.c',
+        'logind-utmp.c',
         'logind-varlink.c',
         'logind-wall.c',
 )