]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/wall: use logind if build without utmp support
authorThorsten Kukuk <kukuk@suse.com>
Mon, 4 Sep 2023 08:08:13 +0000 (10:08 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 6 Sep 2023 12:19:26 +0000 (13:19 +0100)
If systemd is build without utmp support, use sd_get_sessions() in
utmp_wall() to get a list of logged in users with the corresponding tty.

src/journal/journald-wall.c
src/login/logind-dbus.c
src/login/logind-wall.c [moved from src/login/logind-utmp.c with 97% similarity]
src/login/meson.build
src/shared/meson.build
src/shared/utmp-wtmp.c
src/shared/utmp-wtmp.h
src/shared/wall.c [new file with mode: 0644]
src/shared/wall.h [new file with mode: 0644]
src/tty-ask-password-agent/tty-ask-password-agent.c

index 21ec5a785bf4b5f937eec613871ec054899f08d3..c8d92c4d3e3661ced812abe2c38d28e3f961d932 100644 (file)
@@ -6,7 +6,7 @@
 #include "journald-wall.h"
 #include "process-util.h"
 #include "string-util.h"
-#include "utmp-wtmp.h"
+#include "wall.h"
 
 void server_forward_wall(
                 Server *s,
@@ -48,7 +48,7 @@ void server_forward_wall(
         } else
                 l = message;
 
-        r = utmp_wall(l, "systemd-journald", NULL, NULL, NULL);
+        r = wall(l, "systemd-journald", NULL, NULL, NULL);
         if (r < 0)
                 log_debug_errno(r, "Failed to send wall message: %m");
 }
index 2d1af602c0b81cc9af0717c2cc53e9b38680203e..dcbd195fe2d6f3d41a96959e7caa3e65676441b8 100644 (file)
@@ -57,6 +57,7 @@
 #include "user-util.h"
 #include "utmp-wtmp.h"
 #include "virt.h"
+#include "wall.h"
 
 /* As a random fun fact sysvinit had a 252 (256-(strlen(" \r\n")+1))
  * character limit for the wall message.
@@ -2342,8 +2343,8 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
                            "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_CANCELED_STR,
                            username ? "OPERATOR=%s" : NULL, username);
 
-                utmp_wall("System shutdown has been cancelled",
-                          username, tty, logind_wall_tty_filter, m);
+                (void) wall("System shutdown has been cancelled",
+                            username, tty, logind_wall_tty_filter, m);
         }
 
         reset_scheduled_shutdown(m);
similarity index 97%
rename from src/login/logind-utmp.c
rename to src/login/logind-wall.c
index 4db127a4c5212d907d5f21f473014bb384eb108a..aa7352233407dc1b45b2c44ee050a23f516d217b 100644 (file)
@@ -18,7 +18,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "user-util.h"
-#include "utmp-wtmp.h"
+#include "wall.h"
 
 static usec_t when_wall(usec_t n, usec_t elapse) {
         static const int wall_timers[] = {
@@ -94,7 +94,7 @@ static int warn_wall(Manager *m, usec_t n) {
                    username ? "OPERATOR=%s" : NULL, username);
 
         if (m->enable_wall_messages)
-                utmp_wall(l, username, m->scheduled_shutdown_tty, logind_wall_tty_filter, m);
+                (void) wall(l, username, m->scheduled_shutdown_tty, logind_wall_tty_filter, m);
 
         return 1;
 }
index 9804a36ce12b969200f3b06c0e9ef0bf3a5c8e83..276e920dfc33349ba0e25453b601ac5059591914 100644 (file)
@@ -26,7 +26,7 @@ liblogind_core_sources = files(
         'logind-session.c',
         'logind-user-dbus.c',
         'logind-user.c',
-        'logind-utmp.c',
+        'logind-wall.c',
 )
 
 liblogind_core_sources += [logind_gperf_c]
index 01e85b617f15223cff76c81b70dbefb4d2b93d9b..67f4f4517d246998f60afa9596fdf2fbae4b8e76 100644 (file)
@@ -168,6 +168,7 @@ shared_sources = files(
         'verbs.c',
         'vlan-util.c',
         'volatile-util.c',
+        'wall.c',
         'watchdog.c',
         'web-util.c',
         'wifi-util.c',
index c79764ced020a1a4f5040b33e784c51cb9148b47..c90e07d4d15c68fa37b1328d4f249d0076fd01b5 100644 (file)
@@ -280,130 +280,3 @@ int utmp_put_runlevel(int runlevel, int previous) {
 
         return write_entry_both(&store);
 }
-
-#define TIMEOUT_USEC (50 * USEC_PER_MSEC)
-
-static int write_to_terminal(const char *tty, const char *message) {
-        _cleanup_close_ int fd = -EBADF;
-        const char *p;
-        size_t left;
-        usec_t end;
-
-        assert(tty);
-        assert(message);
-
-        fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return -errno;
-        if (!isatty(fd))
-                return -ENOTTY;
-
-        p = message;
-        left = strlen(message);
-
-        end = usec_add(now(CLOCK_MONOTONIC), TIMEOUT_USEC);
-
-        while (left > 0) {
-                ssize_t n;
-                usec_t t;
-                int k;
-
-                t = now(CLOCK_MONOTONIC);
-                if (t >= end)
-                        return -ETIME;
-
-                k = fd_wait_for_event(fd, POLLOUT, end - t);
-                if (ERRNO_IS_NEG_TRANSIENT(k))
-                        continue;
-                if (k < 0)
-                        return k;
-                if (k == 0)
-                        return -ETIME;
-
-                n = write(fd, p, left);
-                if (n < 0) {
-                        if (ERRNO_IS_TRANSIENT(errno))
-                                continue;
-
-                        return -errno;
-                }
-
-                assert((size_t) n <= left);
-
-                p += n;
-                left -= n;
-        }
-
-        return 0;
-}
-
-int utmp_wall(
-        const char *message,
-        const char *username,
-        const char *origin_tty,
-        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
-        void *userdata) {
-
-        _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
-        _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
-        struct utmpx *u;
-        int r;
-
-        hn = gethostname_malloc();
-        if (!hn)
-                return -ENOMEM;
-        if (!username) {
-                un = getlogname_malloc();
-                if (!un)
-                        return -ENOMEM;
-        }
-
-        if (!origin_tty) {
-                getttyname_harder(STDIN_FILENO, &stdin_tty);
-                origin_tty = stdin_tty;
-        }
-
-        if (asprintf(&text,
-                     "\r\n"
-                     "Broadcast message from %s@%s%s%s (%s):\r\n\r\n"
-                     "%s\r\n\r\n",
-                     un ?: username, hn,
-                     origin_tty ? " on " : "", strempty(origin_tty),
-                     FORMAT_TIMESTAMP(now(CLOCK_REALTIME)),
-                     message) < 0)
-                return -ENOMEM;
-
-        utmpx = utxent_start();
-
-        r = 0;
-
-        while ((u = getutxent())) {
-                _cleanup_free_ char *buf = NULL;
-                const char *path;
-                int q;
-
-                if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
-                        continue;
-
-                /* This access is fine, because strlen("/dev/") < 32 (UT_LINESIZE) */
-                if (path_startswith(u->ut_line, "/dev/"))
-                        path = u->ut_line;
-                else {
-                        if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0)
-                                return -ENOMEM;
-                        path = buf;
-                }
-
-                /* It seems that the address field is always set for remote logins.
-                 * For local logins and other local entries, we get [0,0,0,0]. */
-                bool is_local = memeqzero(u->ut_addr_v6, sizeof(u->ut_addr_v6));
-
-                if (!match_tty || match_tty(path, is_local, userdata)) {
-                        q = write_to_terminal(path, text);
-                        if (q < 0)
-                                r = q;
-                }
-        }
-
-        return r;
-}
index 97be719abf80f52df1ce653b2772ecfc2b420fc6..ec1e27771e9b142b1b113d09e49b0849776689ee 100644 (file)
@@ -18,13 +18,6 @@ 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);
 
-int utmp_wall(
-        const char *message,
-        const char *username,
-        const char *origin_tty,
-        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
-        void *userdata);
-
 static inline bool utxent_start(void) {
         setutxent();
         return true;
@@ -54,13 +47,5 @@ static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int
 static inline int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) {
         return 0;
 }
-static inline int utmp_wall(
-                const char *message,
-                const char *username,
-                const char *origin_tty,
-                bool (*match_tty)(const char *tty, bool is_local, void *userdata),
-                void *userdata) {
-        return 0;
-}
 
 #endif /* ENABLE_UTMP */
diff --git a/src/shared/wall.c b/src/shared/wall.c
new file mode 100644 (file)
index 0000000..e99fd90
--- /dev/null
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <errno.h>
+#include <poll.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sd-login.h"
+
+#include "errno-util.h"
+#include "fd-util.h"
+#include "hostname-util.h"
+#include "io-util.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "user-util.h"
+#include "utmp-wtmp.h"
+#include "wall.h"
+
+#define TIMEOUT_USEC (50 * USEC_PER_MSEC)
+
+static int write_to_terminal(const char *tty, const char *message) {
+        _cleanup_close_ int fd = -EBADF;
+        const char *p;
+        size_t left;
+        usec_t end;
+
+        assert(tty);
+        assert(message);
+
+        fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return -errno;
+        if (!isatty(fd))
+                return -ENOTTY;
+
+        p = message;
+        left = strlen(message);
+
+        end = usec_add(now(CLOCK_MONOTONIC), TIMEOUT_USEC);
+
+        while (left > 0) {
+                ssize_t n;
+                usec_t t;
+                int k;
+
+                t = now(CLOCK_MONOTONIC);
+                if (t >= end)
+                        return -ETIME;
+
+                k = fd_wait_for_event(fd, POLLOUT, end - t);
+                if (ERRNO_IS_NEG_TRANSIENT(k))
+                        continue;
+                if (k < 0)
+                        return k;
+                if (k == 0)
+                        return -ETIME;
+
+                n = write(fd, p, left);
+                if (n < 0) {
+                        if (ERRNO_IS_TRANSIENT(errno))
+                                continue;
+
+                        return -errno;
+                }
+
+                assert((size_t) n <= left);
+
+                p += n;
+                left -= n;
+        }
+
+        return 0;
+}
+
+#if ENABLE_UTMP
+static int do_wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
+        void *userdata) {
+
+        _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
+        struct utmpx *u;
+        int r;
+
+        utmpx = utxent_start();
+
+        r = 0;
+
+        while ((u = getutxent())) {
+                _cleanup_free_ char *buf = NULL;
+                const char *path;
+                int q;
+
+                if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
+                        continue;
+
+                /* This access is fine, because strlen("/dev/") < 32 (UT_LINESIZE) */
+                if (path_startswith(u->ut_line, "/dev/"))
+                        path = u->ut_line;
+                else {
+                        if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0)
+                                return -ENOMEM;
+                        path = buf;
+                }
+
+                /* It seems that the address field is always set for remote logins.
+                 * For local logins and other local entries, we get [0,0,0,0]. */
+                bool is_local = memeqzero(u->ut_addr_v6, sizeof(u->ut_addr_v6));
+
+                if (!match_tty || match_tty(path, is_local, userdata)) {
+                        q = write_to_terminal(path, message);
+                        if (q < 0)
+                                r = q;
+                }
+        }
+
+        return r;
+}
+
+#else
+
+static int do_wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
+        void *userdata) {
+
+        int r;
+        _cleanup_strv_free_ char **sessions = NULL;
+
+        r = sd_get_sessions(&sessions);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(s, sessions) {
+                _cleanup_free_ char *path = NULL, *tty = NULL, *rhost = NULL;
+                int q;
+
+                q = sd_session_get_tty(*s, &tty);
+                if (q < 0) {
+                        if (q != -ENXIO && q != -ENODATA)
+                                r = q;
+                        continue;
+                }
+
+                path = strjoin("/dev/", tty);
+                if (!path)
+                        return -ENOMEM;
+
+                (void) sd_session_get_remote_host(*s, &rhost);
+                bool is_local = !rhost;
+
+                if (!match_tty || match_tty(path, is_local, userdata)) {
+                        q = write_to_terminal(path, message);
+                        if (q < 0)
+                                r = q;
+                }
+        }
+        return r;
+}
+
+#endif
+
+int wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
+        void *userdata) {
+
+        _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
+
+        hn = gethostname_malloc();
+        if (!hn)
+                return -ENOMEM;
+        if (!username) {
+                un = getlogname_malloc();
+                if (!un)
+                        return -ENOMEM;
+        }
+
+        if (!origin_tty) {
+                (void) getttyname_harder(STDIN_FILENO, &stdin_tty);
+                origin_tty = stdin_tty;
+        }
+
+        if (asprintf(&text,
+                     "\r\n"
+                     "Broadcast message from %s@%s%s%s (%s):\r\n\r\n"
+                     "%s\r\n\r\n",
+                     un ?: username, hn,
+                     origin_tty ? " on " : "", strempty(origin_tty),
+                     FORMAT_TIMESTAMP(now(CLOCK_REALTIME)),
+                     message) < 0)
+                return -ENOMEM;
+
+        return do_wall(text, username, origin_tty, match_tty, userdata);
+}
diff --git a/src/shared/wall.h b/src/shared/wall.h
new file mode 100644 (file)
index 0000000..4423c39
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdbool.h>
+
+int wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, bool is_local, void *userdata),
+        void *userdata);
index 46d2307ad315407eaab14e345e032035abc5c199..87c610bc73be7e8bb206a3217fc2d9b31d0b96f4 100644 (file)
@@ -41,7 +41,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "terminal-util.h"
-#include "utmp-wtmp.h"
+#include "wall.h"
 
 static enum {
         ACTION_LIST,
@@ -216,16 +216,16 @@ static int process_one_password_file(const char *filename) {
                 return 0;
 
         case ACTION_WALL: {
-                 _cleanup_free_ char *wall = NULL;
+                 _cleanup_free_ char *msg = NULL;
 
-                 if (asprintf(&wall,
+                 if (asprintf(&msg,
                               "Password entry required for \'%s\' (PID " PID_FMT ").\r\n"
                               "Please enter password with the systemd-tty-ask-password-agent tool.",
                               strna(message),
                               pid) < 0)
                          return log_oom();
 
-                 (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL);
+                 (void) wall(msg, NULL, NULL, wall_tty_match, NULL);
                  return 0;
         }
         case ACTION_QUERY: