Skip to content

Commit

Permalink
write: query logind for list of users with tty (#2088)
Browse files Browse the repository at this point in the history
  • Loading branch information
thkukuk committed May 31, 2023
1 parent 010c443 commit 289653b
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 11 deletions.
4 changes: 4 additions & 0 deletions term-utils/Makemodule.am
Expand Up @@ -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
Expand Down
130 changes: 119 additions & 11 deletions term-utils/write.c
Expand Up @@ -59,6 +59,11 @@
#include <unistd.h>
#include <utmpx.h>

#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
# include <systemd/sd-login.h>
# include <systemd/sd-daemon.h>
#endif

#include "c.h"
#include "carefulputc.h"
#include "closestream.h"
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 289653b

Please sign in to comment.