Re: [PATCHv3] w using logind instead of utmp
"Thorsten Kukuk" <[email protected]> ("kukuk") Tue, 25 Jul 2023 09:02:04 +0000
| Newsgroups | gmane.linux.procps.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi,
On Sun, Jun 25, Thorsten Kukuk wrote:
> This patch contains two fixes to compile again without systemd support.
Any updates or comments for this patch?
Thanks,
Thorsten
>
> Thorsten
> --
> Thorsten Kukuk, Distinguished Engineer, Senior Architect, Future Technologies
> SUSE Software Solutions Germany GmbH, Frankenstraße 146, 90461 Nuernberg, Germany
> Managing Director: Ivo Totev, Andrew Myers, Andrew McDonald, Martje Boudien Moerman
> (HRB 36809, AG Nürnberg)
> From ba3f9b85040858b5120c5ef523bf1e97758d9cc9 Mon Sep 17 00:00:00 2001
> From: Thorsten Kukuk <[email protected]>
> Date: Fri, 23 Jun 2023 11:06:32 +0200
> Subject: [PATCH 1/1] w: Prefer logind over utmp
>
> The utmp format of glibc is not Y2038 safe, not even on 64bit systems.
> Query logind/elogind for all required informations instead.
>
> Signed-off-by: Thorsten Kukuk <[email protected]>
> ---
> configure.ac | 7 ++
> src/w.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 177 insertions(+), 16 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index e20a2c55..04e92757 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -280,6 +280,13 @@ AS_IF([test "x$with_systemd" != "xno"], [
> [PKG_CHECK_MODULES([SYSTEMD], [libsystemd-login])]
> )
> AC_DEFINE(WITH_SYSTEMD, 1, [enable systemd support])
> +
> + # The functions needed to replace utmp with logind are only available
> + # with systemd v254 or later.
> + old_LIBS="$LIBS"
> + LIBS="$LIBS $SYSTEMD_LIBS"
> + AC_CHECK_FUNCS([sd_session_get_leader])
> + LIBS="$old_LIBS"
> ])
> AM_CONDITIONAL([WITH_SYSTEMD], [test x$with_systemd != xno])
>
> diff --git a/src/w.c b/src/w.c
> index 093cfbc7..3f855e0d 100644
> --- a/src/w.c
> +++ b/src/w.c
> @@ -53,6 +53,14 @@
> # include <utmp.h>
> #endif
> #include <arpa/inet.h>
> +#ifdef WITH_SYSTEMD
> +# include <systemd/sd-login.h>
> +# include <systemd/sd-daemon.h>
> +#endif
> +#ifdef WITH_ELOGIND
> +# include <elogind/sd-login.h>
> +# include <elogind/sd-daemon.h>
> +#endif
>
> #include "c.h"
> #include "fileutils.h"
> @@ -196,7 +204,25 @@ static void print_display_or_interface(const char *restrict host, int len, int r
>
>
> /* This routine prints either the hostname or the IP address of the remote */
> -static void print_from(const utmp_t *restrict const u, const int ip_addresses, const int fromlen) {
> +static void print_from(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + const char *session,
> +#endif
> + const utmp_t *restrict const u, const int ip_addresses, const int fromlen) {
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (session) {
> + char *host = NULL;
> + int r;
> +
> + r = sd_session_get_remote_host(session, &host);
> + if (r < 0 || host == NULL)
> + print_host("", 0, fromlen);
> + else {
> + print_host(host, strlen(host), fromlen);
> + free(host);
> + }
> + } else {
> +#endif
> char buf[fromlen + 1];
> char buf_ipv6[INET6_ADDRSTRLEN];
> int len;
> @@ -241,6 +267,9 @@ static void print_from(const utmp_t *restrict const u, const int ip_addresses, c
> #else
> print_host(u->ut_host, UT_HOSTSIZE, fromlen);
> #endif
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + }
> +#endif
> }
>
>
> @@ -343,7 +372,7 @@ static int get_tty_device(const char *restrict const name)
>
> for (i=0; dev_paths[i] != NULL; i++) {
> snprintf(buf, 32, dev_paths[i], name);
> - if (stat(buf, &st) == 0)
> + if (stat(buf, &st) == 0 && (st.st_mode & S_IFMT) == S_IFCHR)
> return st.st_rdev;
> }
> return -1;
> @@ -357,6 +386,9 @@ static int get_tty_device(const char *restrict const name)
> * essential core of 'w'.
> */
> static int find_best_proc(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + const char *session,
> +#endif
> const utmp_t * restrict const u,
> const char *restrict const tty,
> unsigned long long *restrict const jcpu,
> @@ -369,6 +401,7 @@ static int find_best_proc(
> #define PIDS_GETULL(e) PIDS_VAL(EU_ ## e, ull_int, reap->stacks[i], info)
> #define PIDS_GETSTR(e) PIDS_VAL(EU_ ## e, str, reap->stacks[i], info)
> unsigned uid = ~0U;
> + pid_t ut_pid = -1;
> int found_utpid = 0;
> int i, total_procs, line;
> unsigned long long best_time = 0;
> @@ -394,6 +427,12 @@ static int find_best_proc(
> *jcpu = 0;
> *pcpu = 0;
> if (!ignoreuser) {
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (session) {
> + if (sd_session_get_uid(session, &uid) < 0)
> + return 0;
> + } else {
> +#endif
> char buf[UT_NAMESIZE + 1];
> struct passwd *passwd_data;
> strncpy(buf, u->ut_user, UT_NAMESIZE);
> @@ -402,6 +441,9 @@ static int find_best_proc(
> return 0;
> uid = passwd_data->pw_uid;
> /* OK to have passwd_data go out of scope here */
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + }
> +#endif
> }
>
> line = get_tty_device(tty);
> @@ -414,9 +456,16 @@ static int find_best_proc(
> _("Unable to load process information"));
> total_procs = reap->counts->total;
>
> + if (u)
> + ut_pid = u->ut_pid;
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + else
> + sd_session_get_leader(session, &ut_pid);
> +#endif
> +
> for (i=0; i < total_procs; i++) {
> /* is this the login process? */
> - if (PIDS_GETINT(TGID) == u->ut_pid) {
> + if (PIDS_GETINT(TGID) == ut_pid) {
> found_utpid = 1;
> if (!best_time) {
> best_time = PIDS_GETULL(START);
> @@ -458,6 +507,9 @@ static int find_best_proc(
> }
>
> static void showinfo(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + const char *session, const char *name,
> +#endif
> utmp_t * u, int formtype, int maxcmd, int from,
> const int userlen, const int fromlen, const int ip_addresses,
> const int pids)
> @@ -473,14 +525,37 @@ static void showinfo(
> strcpy(cmdline, "-");
>
> hertz = procps_hertz_get();
> +
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (session) {
> + char *sd_tty;
> +
> + if (sd_session_get_tty(session, &sd_tty) >= 0) {
> + for (i = 0; i < strlen (sd_tty); i++)
> + /* clean up tty if garbled */
> + if (isalnum(sd_tty[i]) || (sd_tty[i] == '/'))
> + tty[i + 5] = sd_tty[i];
> + else
> + tty[i + 5] = '\0';
> + free(sd_tty);
> + }
> + } else {
> +#endif
> for (i = 0; i < UT_LINESIZE; i++)
> /* clean up tty if garbled */
> if (isalnum(u->ut_line[i]) || (u->ut_line[i] == '/'))
> tty[i + 5] = u->ut_line[i];
> else
> tty[i + 5] = '\0';
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + }
> +#endif
>
> - if (find_best_proc(u, tty + 5, &jcpu, &pcpu, cmdline, &best_pid) == 0)
> + if (find_best_proc(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + session,
> +#endif
> + u, tty + 5, &jcpu, &pcpu, cmdline, &best_pid) == 0)
> /*
> * just skip if stale utmp entry (i.e. login proc doesn't
> * exist). If there is a desire a cmdline flag could be
> @@ -489,20 +564,44 @@ static void showinfo(
> */
> return;
>
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (name)
> + strncpy(uname, name, UT_NAMESIZE);
> + else
> +#endif
> + strncpy(uname, u->ut_user, UT_NAMESIZE);
> /* force NUL term for printf */
> - strncpy(uname, u->ut_user, UT_NAMESIZE);
> uname[UT_NAMESIZE] = '\0';
>
> if (formtype) {
> printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, tty + 5);
> - if (from)
> - print_from(u, ip_addresses, fromlen);
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (session) {
> + uint64_t ltime;
> +
> + if (from)
> + print_from(session, NULL, ip_addresses, fromlen);
> +
> + sd_session_get_start_time(session, <ime);
> + print_logintime(ltime/((uint64_t) 1000000ULL), stdout);
> + } else {
> +#endif
> + if (from)
> + print_from(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + NULL,
> +#endif
> + u, ip_addresses, fromlen);
> +
> #ifdef HAVE_UTMPX_H
> - print_logintime(u->ut_tv.tv_sec, stdout);
> + print_logintime(u->ut_tv.tv_sec, stdout);
> #else
> - print_logintime(u->ut_time, stdout);
> + print_logintime(u->ut_time, stdout);
> +#endif
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + }
> #endif
> - if (*u->ut_line == ':')
> + if (u && *u->ut_line == ':')
> /* idle unknown for xdm logins */
> printf(" ?xdm? ");
> else
> @@ -518,15 +617,26 @@ static void showinfo(
> } else {
> printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, tty + 5);
> if (from)
> - print_from(u, ip_addresses, fromlen);
> - if (*u->ut_line == ':')
> + print_from(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + NULL,
> +#endif
> + u, ip_addresses, fromlen);
> + if (u && *u->ut_line == ':')
> /* idle unknown for xdm logins */
> printf(" ?xdm? ");
> else
> print_time_ival7(idletime(tty), 0, stdout);
> }
> if (pids) {
> - pids_length = printf(" %d/%d", u->ut_pid, best_pid);
> + pid_t ut_pid = -1;
> + if (u)
> + ut_pid = u->ut_pid;
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + else
> + sd_session_get_leader(session, &ut_pid);
> +#endif
> + pids_length = printf(" %d/%d", ut_pid, best_pid);
> if (pids_length > maxcmd) {
> maxcmd = 0;
> } else if (pids_length > 0) {
> @@ -692,7 +802,40 @@ int main(int argc, char **argv)
> else
> printf(_(" IDLE WHAT\n"));
> }
> -
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + if (sd_booted() > 0) {
> + char **sessions_list;
> + int sessions;
> + int i;
> +
> + sessions = sd_get_sessions (&sessions_list);
> + if (sessions < 0 && sessions != -ENOENT)
> + error(EXIT_FAILURE, -sessions, _("error getting sessions"));
> +
> + if (sessions >= 0) {
> + for (int i = 0; i < sessions; i++) {
> + char *name;
> + int r;
> +
> + if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
> + error(EXIT_FAILURE, -r, _("get user name failed"));
> +
> + if (user) {
> + if (!strcmp(name, user))
> + showinfo(sessions_list[i], name, NULL, longform,
> + maxcmd, from, userlen, fromlen,
> + ip_addresses, pids);
> + } else {
> + showinfo(sessions_list[i], name, NULL, longform, maxcmd,
> + from, userlen, fromlen, ip_addresses, pids);
> + }
> + free(name);
> + free(sessions_list[i]);
> + }
> + free(sessions_list);
> + }
> + } else {
> +#endif
> #ifdef HAVE_UTMPX_H
> setutxent();
> #else
> @@ -711,7 +854,11 @@ int main(int argc, char **argv)
> if (u->ut_type != USER_PROCESS)
> continue;
> if (!strncmp(u->ut_user, user, UT_NAMESIZE))
> - showinfo(u, longform, maxcmd, from, userlen,
> + showinfo(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + NULL, NULL,
> +#endif
> + u, longform, maxcmd, from, userlen,
> fromlen, ip_addresses, pids);
> }
> } else {
> @@ -726,7 +873,11 @@ int main(int argc, char **argv)
> if (u->ut_type != USER_PROCESS)
> continue;
> if (*u->ut_user)
> - showinfo(u, longform, maxcmd, from, userlen,
> + showinfo(
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + NULL, NULL,
> +#endif
> + u, longform, maxcmd, from, userlen,
> fromlen, ip_addresses, pids);
> }
> }
> @@ -735,6 +886,9 @@ int main(int argc, char **argv)
> #else
> endutent();
> #endif
> +#if (defined(WITH_SYSTEMD) || defined(WITH_ELOGIND)) && defined(HAVE_SD_SESSION_GET_LEADER)
> + }
> +#endif
>
> return EXIT_SUCCESS;
> }
> --
> 2.41.0
>
--
Thorsten Kukuk, Distinguished Engineer, Senior Architect, Future Technologies
SUSE Software Solutions Germany GmbH, Frankenstraße 146, 90461 Nuernberg, Germany
Managing Director: Ivo Totev, Andrew Myers, Andrew McDonald, Martje Boudien Moerman
(HRB 36809, AG Nürnberg)