]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
write: always use utmp as fallback
authorKarel Zak <kzak@redhat.com>
Wed, 13 May 2026 09:13:03 +0000 (11:13 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 13 May 2026 09:13:03 +0000 (11:13 +0200)
The systemd session list may not cover all terminals (e.g., screen,
tmux, or old-style logins). Remove the "if systemd else utmp" pattern
and always fall through to utmp when the target user or tty is not
found in systemd sessions.

Also make sd_get_sessions() and sd_session_get_username() failures
non-fatal — silently fall through to utmp instead of calling errx().

Addresses: https://redhat.atlassian.net/browse/RHEL-157244
Signed-off-by: Karel Zak <kzak@redhat.com>
term-utils/write.c

index feb6751a2e3f6431adcb48febd72e4cd3a62db41..c7c6ba4970b35e87bdcdf6f089a7ba8f01cd1e00 100644 (file)
@@ -145,17 +145,16 @@ static int check_utmp(const struct write_control *ctl)
        if (sd_booted() > 0) {
                char **sessions_list;
                int sessions = sd_get_sessions(&sessions_list);
+
                if (sessions < 0)
-                       errx(EXIT_FAILURE, _("error getting sessions: %s"),
-                               strerror(-sessions));
+                       goto utmp;
 
                for (int i = 0; i < sessions; i++) {
 
                        char *name, *tty;
-                       int r;
 
-                       if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
-                               errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));
+                       if (sd_session_get_username(sessions_list[i], &name) < 0)
+                               continue;
                        if (sd_session_get_tty(sessions_list[i], &tty) < 0) {
                                free(name);
                                continue;
@@ -174,23 +173,24 @@ static int check_utmp(const struct write_control *ctl)
                for (int i = 0; i < sessions; i++)
                        free(sessions_list[i]);
                free(sessions_list);
-       } else {
+
+               if (res == 0)
+                       return res;
+       }
+utmp:
 #endif
-               utmpxname(_PATH_UTMP);
-               setutxent();
+       utmpxname(_PATH_UTMP);
+       setutxent();
 
-               while ((u = getutxent())) {
-                       if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
-                               strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
-                               res = 0;
-                               break;
-                       }
+       while ((u = getutxent())) {
+               if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
+                       strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
+                       res = 0;
+                       break;
                }
-
-               endutxent();
-#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
        }
-#endif
+
+       endutxent();
        return res;
 }
 
@@ -216,16 +216,15 @@ static void search_utmp(struct write_control *ctl)
                char path[256];
                char **sessions_list;
                int sessions = sd_get_sessions(&sessions_list);
+
                if (sessions < 0)
-                       errx(EXIT_FAILURE, _("error getting sessions: %s"),
-                            strerror(-sessions));
+                       goto utmp;
 
                for (int i = 0; i < sessions; i++) {
                        char *name, *tty;
-                       int r;
 
-                       if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
-                               errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));
+                       if (sd_session_get_username(sessions_list[i], &name) < 0)
+                               continue;
 
                        if  (strcmp(ctl->dst_login, name) != 0) {
                                free(name);
@@ -271,7 +270,8 @@ static void search_utmp(struct write_control *ctl)
                for (int i = 0; i < sessions; i++)
                        free(sessions_list[i]);
                free(sessions_list);
-       } else
+       }
+utmp:
 #endif
        {
                char path[sizeof(u->ut_line) + 6];