From: Thorsten Kukuk Date: 2023-08-17 08:03:09+0000 References: https://github.com/util-linux/util-linux/pull/2100 diff --git a/configure.ac b/configure.ac index d631b062d2..17d3ab703b 100644 --- a/configure.ac +++ b/configure.ac @@ -2491,6 +2491,7 @@ AS_IF([test "x$with_systemd" != xno], [ [*:yes], AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define if libsystemd is available]) AC_DEFINE([USE_SYSTEMD], [1], [Define if systemd support is wanted ]) + AC_CHECK_DECLS([sd_session_get_username], [], [], [#include ]) ) ]) AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$have_systemd" = xyes]) diff --git a/term-utils/Makemodule.am b/term-utils/Makemodule.am index 07004d43ca..1542320422 100644 --- a/term-utils/Makemodule.am +++ b/term-utils/Makemodule.am @@ -98,6 +98,10 @@ dist_noinst_DATA += term-utils/wall.1.adoc wall_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) wall_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) wall_LDADD = $(LDADD) libcommon.la +if HAVE_SYSTEMD +wall_LDADD += $(SYSTEMD_LIBS) +wall_CFLAGS += $(SYSTEMD_CFLAGS) +endif if USE_TTY_GROUP if MAKEINSTALL_DO_CHOWN install-exec-hook-wall:: diff --git a/term-utils/wall.c b/term-utils/wall.c index c601d3e5b7..313b1bdee5 100644 --- a/term-utils/wall.c +++ b/term-utils/wall.c @@ -61,6 +61,11 @@ #include #include +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 +# include +# include +#endif + #include "nls.h" #include "xalloc.h" #include "strutils.h" @@ -246,6 +251,37 @@ int main(int argc, char **argv) iov.iov_base = mbuf; iov.iov_len = mbufsize; +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + if (sd_booted() > 0) { + char **sessions_list; + int sessions; + + sessions = sd_get_sessions(&sessions_list); + if (sessions < 0) + errx(EXIT_FAILURE, _("error getting sessions: %s"), + strerror(-sessions)); + + 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 (!(group_buf && !is_gr_member(name, group_buf))) { + if (sd_session_get_tty(sessions_list[i], &tty) >= 0) { + if ((p = ttymsg(&iov, 1, tty, timeout)) != NULL) + warnx("%s", p); + + free(tty); + } + } + free(name); + free(sessions_list[i]); + } + free(sessions_list); + } else { +#endif while((utmpptr = getutxent())) { if (!utmpptr->ut_user[0]) continue; @@ -269,6 +305,9 @@ int main(int argc, char **argv) warnx("%s", p); } endutxent(); +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + } +#endif free(mbuf); free_group_workspace(group_buf); exit(EXIT_SUCCESS); From e915e6baeba3cbce154336a4f1f24a8be93e85ae Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 31 May 2023 08:57:01 +0200 Subject: [PATCH 2/3] agetty: use sd_get_sessions() for number of users (#2088) --- term-utils/Makemodule.am | 4 ++++ term-utils/agetty.c | 28 ++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/term-utils/Makemodule.am b/term-utils/Makemodule.am index 1542320422..b7037fb116 100644 --- a/term-utils/Makemodule.am +++ b/term-utils/Makemodule.am @@ -58,6 +58,10 @@ endif if HAVE_ECONF agetty_LDADD += -leconf endif +if HAVE_SYSTEMD +agetty_LDADD += $(SYSTEMD_LIBS) +agetty_CFLAGS = $(SYSTEMD_CFLAGS) +endif endif # BUILD_AGETTY diff --git a/term-utils/agetty.c b/term-utils/agetty.c index cf8725537b..6bc3e5b5a8 100644 --- a/term-utils/agetty.c +++ b/term-utils/agetty.c @@ -73,6 +73,11 @@ # endif #endif +#ifdef USE_SYSTEMD +# include +# include +#endif + #ifdef __linux__ # include # define USE_SYSLOG @@ -2864,12 +2869,23 @@ static void output_special_char(struct issue *ie, case 'U': { int users = 0; - struct utmpx *ut; - setutxent(); - while ((ut = getutxent())) - if (ut->ut_type == USER_PROCESS) - users++; - endutxent(); +#ifdef USE_SYSTEMD + if (sd_booted() > 0) { + users = sd_get_sessions(NULL); + if (users < 0) + users = 0; + } else { +#endif + users = 0; + struct utmpx *ut; + setutxent(); + while ((ut = getutxent())) + if (ut->ut_type == USER_PROCESS) + users++; + endutxent(); +#ifdef USE_SYSTEMD + } +#endif if (c == 'U') fprintf(ie->output, P_("%d user", "%d users", users), users); else From 5c62c27001467f3ef0baaa66ae4e3bb80a0298a6 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 31 May 2023 09:00:09 +0200 Subject: [PATCH 3/3] write: query logind for list of users with tty (#2088) --- term-utils/Makemodule.am | 4 ++ term-utils/write.c | 130 +++++++++++++++++++++++++++++++++++---- 2 files changed, 123 insertions(+), 11 deletions(-) diff --git a/term-utils/Makemodule.am b/term-utils/Makemodule.am index b7037fb116..1efe1c57e3 100644 --- a/term-utils/Makemodule.am +++ b/term-utils/Makemodule.am @@ -126,6 +126,10 @@ write_SOURCES = term-utils/write.c write_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) write_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) write_LDADD = $(LDADD) libcommon.la +if HAVE_SYSTEMD +write_LDADD += $(SYSTEMD_LIBS) +write_CFLAGS += $(SYSTEMD_CFLAGS) +endif if USE_TTY_GROUP if MAKEINSTALL_DO_CHOWN diff --git a/term-utils/write.c b/term-utils/write.c index 8b86e9a9d5..8aa450d563 100644 --- a/term-utils/write.c +++ b/term-utils/write.c @@ -59,6 +59,11 @@ #include #include +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 +# include +# include +#endif + #include "c.h" #include "carefulputc.h" #include "closestream.h" @@ -131,19 +136,56 @@ static int check_utmp(const struct write_control *ctl) { struct utmpx *u; int res = 1; - - 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; +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + 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)); + + 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_tty(sessions_list[i], &tty) < 0) { + free(name); + continue; + } + + if (strcmp(ctl->dst_login, name) == 0 && + strcmp(ctl->dst_tty_name, tty) == 0) { + free(name); + free(tty); + res = 0; + break; + } + free(name); + free(tty); + } + for (int i = 0; i < sessions; i++) + free(sessions_list[i]); + free(sessions_list); + } else { +#endif + 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; + } } - } - endutxent(); + endutxent(); +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + } +#endif return res; } @@ -163,6 +205,69 @@ static void search_utmp(struct write_control *ctl) struct utmpx *u; time_t best_atime = 0, tty_atime; int num_ttys = 0, valid_ttys = 0, tty_writeable = 0, user_is_me = 0; + +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + if (sd_booted() > 0) { + 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)); + + 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 (strcmp(ctl->dst_login, name) != 0) { + free(name); + continue; + } + + if (sd_session_get_tty(sessions_list[i], &tty) < 0) { + free(name); + continue; + } + + num_ttys++; + snprintf(path, sizeof(path), "/dev/%s", tty); + if (check_tty(path, &tty_writeable, &tty_atime, 0)) { + /* bad term? skip */ + free(name); + free(tty); + continue; + } + if (ctl->src_uid && !tty_writeable) { + /* skip ttys with msgs off */ + free(name); + free(tty); + continue; + } + if (strcmp(tty, ctl->src_tty_name) == 0) { + user_is_me = 1; + free(name); + free(tty); + /* don't write to yourself */ + continue; + } + valid_ttys++; + if (best_atime < tty_atime) { + best_atime = tty_atime; + free(ctl->dst_tty_path); + ctl->dst_tty_path = xstrdup(path); + ctl->dst_tty_name = ctl->dst_tty_path + 5; + } + free(name); + free(tty); + } + for (int i = 0; i < sessions; i++) + free(sessions_list[i]); + free(sessions_list); + } else { +#endif char path[sizeof(u->ut_line) + 6]; utmpxname(_PATH_UTMP); @@ -197,6 +302,9 @@ static void search_utmp(struct write_control *ctl) } endutxent(); +#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1 + } +#endif if (num_ttys == 0) errx(EXIT_FAILURE, _("%s is not logged in"), ctl->dst_login); if (valid_ttys == 0) {