From: Karel Zak Date: Mon, 3 Jun 2024 12:32:18 +0000 (+0200) Subject: wall: always use utmp as fallback X-Git-Tag: v2.42-start~306^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0af497c6688b53a3a176176bfbcdca821bd856ec;p=thirdparty%2Futil-linux.git wall: always use utmp as fallback Wall(1) can be compiled with systemd support to read the names of ttys from the systemd session list. However, this may not work on all systems. In case of failure, the best option is to use the traditional utmp method as a fallback. This commit uses strv (string vector) to collect tty names from both sources (systemd and utmp) and then sends a message to all ttys. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2283049 Signed-off-by: Karel Zak --- diff --git a/term-utils/wall.c b/term-utils/wall.c index 125fde438..22c3918bb 100644 --- a/term-utils/wall.c +++ b/term-utils/wall.c @@ -78,6 +78,7 @@ #include "closestream.h" #include "timeutils.h" #include "pwdutils.h" +#include "strv.h" #define TERM_WIDTH 79 #define WRITE_TIME_OUT 300 /* in seconds */ @@ -190,19 +191,30 @@ static int is_gr_member(const char *login, const struct group_workspace *buf) return 0; } +static int has_tty(char **ttys, char *name) +{ + char **str; + + STRV_FOREACH(str, ttys) { + if (strcmp(*str, name) == 0) + return 1; + } + + return 0; +} + int main(int argc, char **argv) { int ch; struct iovec iov; struct utmpx *utmpptr; - char *p; char line[sizeof(utmpptr->ut_line) + 1]; int print_banner = TRUE; struct group_workspace *group_buf = NULL; char *mbuf, *fname = NULL; size_t mbufsize; unsigned timeout = WRITE_TIME_OUT; - char **mvec = NULL; + char **mvec = NULL, **ttys = NULL, **str; int mvecsz = 0; static const struct option longopts[] = { @@ -265,30 +277,30 @@ int main(int argc, char **argv) int sessions; sessions = sd_get_sessions(&sessions_list); - if (sessions < 0) - errx(EXIT_FAILURE, _("error getting sessions: %s"), - strerror(-sessions)); + if (sessions < 0) { + warnx(_("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 (!(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); - } + if ((r = sd_session_get_username(sessions_list[i], &name)) < 0) { + warnx(_("get user name failed: %s"), strerror (-r)); + goto utmp; } + if (!(group_buf && !is_gr_member(name, group_buf)) + && sd_session_get_tty(sessions_list[i], &tty) >= 0 + && strv_consume(&ttys, tty) < 0) + err(EXIT_FAILURE, _("failed to allocate lines list")); + free(name); free(sessions_list[i]); } free(sessions_list); - } else + } +utmp: #endif { while ((utmpptr = getutxent())) { @@ -310,12 +322,21 @@ int main(int argc, char **argv) continue; mem2strcpy(line, utmpptr->ut_line, sizeof(utmpptr->ut_line), sizeof(line)); - if ((p = ttymsg(&iov, 1, line, timeout)) != NULL) - warnx("%s", p); + if (has_tty(ttys, line)) + continue; + if (strv_extend(&ttys, line) < 0) + err(EXIT_FAILURE, _("failed to allocate lines list")); } endutxent(); } + STRV_FOREACH(str, ttys) { + char *er = ttymsg(&iov, 1, *str, timeout); + if (er) + warnx("%s", er); + } + + strv_free(ttys); free(mbuf); free_group_workspace(group_buf); exit(EXIT_SUCCESS);