From b53c683edff1af897a351a09f950eed845d6a25e Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:27:06 +0100 Subject: [PATCH] Allow some utmpx fields to be optional POSIX.1 doesn't define ut_host in struct utmpx. Also, Linux has support for an exit status value in ut_exit. This commit adds conditional code for both ut_host and ut_exit to maximise portability. --- configure.ac | 9 +++++++ m4/axrdp.m4 | 43 ++++++++++++++++++++++++++++++++++ sesman/sesexec/session.c | 2 +- sesman/sesexec/sessionrecord.c | 27 ++++++++++++++------- sesman/sesexec/sessionrecord.h | 8 +++++-- 5 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 m4/axrdp.m4 diff --git a/configure.ac b/configure.ac index 819557cf2a..0862809d59 100644 --- a/configure.ac +++ b/configure.ac @@ -523,6 +523,10 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [], if test "x$enable_utmp" = "xyes" then AC_CHECK_HEADERS(utmp.h utmpx.h) + + # Test for non-standard extensions in struct utmpx + AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_host], [HAVE_UTMPX_UT_HOST]) + AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_exit], [HAVE_UTMPX_UT_EXIT]) fi CFLAGS="$save_CFLAGS" @@ -643,6 +647,11 @@ echo " vsock $enable_vsock" echo " auth mechanism $auth_mech" echo " rdpsndaudin $enable_rdpsndaudin" echo " utmp support $enable_utmp" +if test x$enable_utmp = xyes; then + echo " utmpx.ut_host $ac_cv_utmpx_has_ut_host" + echo " utmpx.ut_exit $ac_cv_utmpx_has_ut_exit" +fi + echo echo " with imlib2 $use_imlib2" echo " with freetype2 $use_freetype2" diff --git a/m4/axrdp.m4 b/m4/axrdp.m4 new file mode 100644 index 0000000000..4ba87e5d42 --- /dev/null +++ b/m4/axrdp.m4 @@ -0,0 +1,43 @@ +# SYNOPSIS +# +# AXRDP_CHECK_UTMPX_MEMBER_EXISTS(MEMBER, COMPILE-DEFINE) +# +# EXAMPLE +# +# AXRDP_CHECK_UTMPX_MEMBER_EXISTS([ut_exit], [HAVE_UTMPX_UT_EXIT]) +# +# DESCRIPTION +# +# If the member MEMBER exists in the utmpx struct, the COMPILE-DEFINE +# is set for the C compiler. +# +# The shell variable 'ac_cv_utmpx_has_$MEMBER' is set to 'yes' or 'no' +# and cached +# +AC_DEFUN([AXRDP_CHECK_UTMPX_MEMBER_EXISTS], +[ + AS_VAR_PUSHDEF([x_var], [ac_cv_utmpx_has_$1]) + AS_VAR_PUSHDEF([x_define], [$2]) + AC_CACHE_CHECK( + [for $1 in struct utmpx], + [x_var], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[ +# include +# include + int main() + { + return offsetof(struct utmpx,$1); + }]])], + [AS_VAR_SET([x_var], [yes])], + [AS_VAR_SET([x_var], [no])])] + ) + AS_VAR_IF( + [x_var], + [yes], + [AC_DEFINE([x_define], [1], [Define if '$1' is in struct utmpx.])]) + AS_VAR_POPDEF([x_var]) + AS_VAR_POPDEF([x_define]) +]) + + diff --git a/sesman/sesexec/session.c b/sesman/sesexec/session.c index f8f7af864e..f9c408205b 100644 --- a/sesman/sesexec/session.c +++ b/sesman/sesexec/session.c @@ -888,7 +888,7 @@ session_process_child_exit(struct session_data *sd, sd->win_mgr, sd->params.display, wm_wait_time); } - utmp_logout(sd->win_mgr, sd->params.display); + utmp_logout(sd->win_mgr, sd->params.display, e); sd->win_mgr = -1; if (sd->x_server > 0) diff --git a/sesman/sesexec/sessionrecord.c b/sesman/sesexec/sessionrecord.c index d1aa6c9a91..e642876df1 100644 --- a/sesman/sesexec/sessionrecord.c +++ b/sesman/sesexec/sessionrecord.c @@ -48,10 +48,6 @@ enum add_xtmp_mode #ifdef USE_UTMP -#include -#include -#include -#include #include #include @@ -80,7 +76,7 @@ typedef struct utmp _utmp; static void add_xtmp_entry(int pid, int display, const struct login_info *login_info, - enum add_xtmp_mode mode) + enum add_xtmp_mode mode, const struct proc_exit_status *e) { #if USE_UTMP char idbuff[16]; @@ -102,9 +98,22 @@ add_xtmp_entry(int pid, int display, const struct login_info *login_info, g_strncpy(ut.ut_id, idbuff, sizeof(ut.ut_id)); if (login_info != NULL) { - g_strncpy(ut.ut_user, login_info->username , sizeof(ut.ut_user)); + g_strncpy(ut.ut_user, login_info->username, sizeof(ut.ut_user)); +#ifdef HAVE_UTMPX_UT_HOST g_strncpy(ut.ut_host, login_info->ip_addr, sizeof(ut.ut_host)); +#endif + } + +#ifdef HAVE_UTMPX_UT_EXIT + if (e != NULL && e->reason == E_PXR_STATUS_CODE) + { + ut.ut_exit.e_exit = e->val; } + else if (e != NULL && e->reason == E_PXR_SIGNAL) + { + ut.ut_exit.e_termination = e->val; + } +#endif /* update the utmp file */ /* open utmp */ @@ -124,15 +133,15 @@ utmp_login(int pid, int display, const struct login_info *login_info) "adding login info for utmp: %d - %d - %s - %s", pid, display, login_info->username, login_info->ip_addr); - add_xtmp_entry(pid, display, login_info, MODE_LOGIN); + add_xtmp_entry(pid, display, login_info, MODE_LOGIN, NULL); } void -utmp_logout(int pid, int display) +utmp_logout(int pid, int display, const struct proc_exit_status *exit_status) { log_message(LOG_LEVEL_DEBUG, "adding logout info for utmp: %d - %d", pid, display); - add_xtmp_entry(pid, display, NULL, MODE_LOGOUT); + add_xtmp_entry(pid, display, NULL, MODE_LOGOUT, exit_status); } diff --git a/sesman/sesexec/sessionrecord.h b/sesman/sesexec/sessionrecord.h index 28a26b49c9..d547877182 100644 --- a/sesman/sesexec/sessionrecord.h +++ b/sesman/sesexec/sessionrecord.h @@ -27,6 +27,7 @@ #define SESSIONRECORD_H struct login_info; +struct proc_exit_status; /** * @brief Record login in utmp @@ -35,14 +36,17 @@ struct login_info; * @param display Display number * @param login_info Information about logged in user */ -void utmp_login(int pid, int display, const struct login_info *login_info); +void +utmp_login(int pid, int display, const struct login_info *login_info); /** * @brief Record logout in utmp * * @param pid PID of window manager * @param display Display number + * @param exit_status Exit status of process */ -void utmp_logout(int pid, int display); +void +utmp_logout(int pid, int display, const struct proc_exit_status *exit_status); #endif