commit
b2c0c506e8
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@ -110,10 +110,11 @@ jobs:
|
||||
# define the standard environment variable used in the rest of the steps.
|
||||
CONF_FLAGS_amd64_min: "--disable-ipv6 --disable-jpeg --disable-fuse --disable-mp3lame
|
||||
--disable-fdkaac --disable-opus --disable-rfxcodec --disable-painter
|
||||
--disable-pixman"
|
||||
--disable-pixman --disable-utmp"
|
||||
CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
|
||||
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
|
||||
--enable-pixman --with-imlib2 --with-freetype2 --enable-tests"
|
||||
--enable-pixman --enable-utmp
|
||||
--with-imlib2 --with-freetype2 --enable-tests"
|
||||
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-mp3lame
|
||||
--enable-opus --enable-rfxcodec --enable-painter
|
||||
--disable-pixman --with-imlib2 --with-freetype2
|
||||
|
@ -3302,10 +3302,10 @@ g_set_allusercontext(int uid)
|
||||
/*****************************************************************************/
|
||||
/* does not work in win32
|
||||
returns pid of process that exits or zero if signal occurred
|
||||
an exit_status struct can optionally be passed in to get the
|
||||
a proc_exit_status struct can optionally be passed in to get the
|
||||
exit status of the child */
|
||||
int
|
||||
g_waitchild(struct exit_status *e)
|
||||
g_waitchild(struct proc_exit_status *e)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 0;
|
||||
@ -3313,14 +3313,14 @@ g_waitchild(struct exit_status *e)
|
||||
int wstat;
|
||||
int rv;
|
||||
|
||||
struct exit_status dummy;
|
||||
struct proc_exit_status dummy;
|
||||
|
||||
if (e == NULL)
|
||||
{
|
||||
e = &dummy; // Set this, then throw it away
|
||||
}
|
||||
|
||||
e->reason = E_XR_UNEXPECTED;
|
||||
e->reason = E_PXR_UNEXPECTED;
|
||||
e->val = 0;
|
||||
|
||||
rv = waitpid(-1, &wstat, WNOHANG);
|
||||
@ -3335,12 +3335,12 @@ g_waitchild(struct exit_status *e)
|
||||
}
|
||||
else if (WIFEXITED(wstat))
|
||||
{
|
||||
e->reason = E_XR_STATUS_CODE;
|
||||
e->reason = E_PXR_STATUS_CODE;
|
||||
e->val = WEXITSTATUS(wstat);
|
||||
}
|
||||
else if (WIFSIGNALED(wstat))
|
||||
{
|
||||
e->reason = E_XR_SIGNAL;
|
||||
e->reason = E_PXR_SIGNAL;
|
||||
e->val = WTERMSIG(wstat);
|
||||
}
|
||||
|
||||
@ -3381,10 +3381,14 @@ g_waitpid(int pid)
|
||||
|
||||
Note that signal handlers are established with BSD-style semantics,
|
||||
so this call is NOT interrupted by a signal */
|
||||
struct exit_status
|
||||
struct proc_exit_status
|
||||
g_waitpid_status(int pid)
|
||||
{
|
||||
struct exit_status exit_status = {.reason = E_XR_UNEXPECTED, .val = 0};
|
||||
struct proc_exit_status exit_status =
|
||||
{
|
||||
.reason = E_PXR_UNEXPECTED,
|
||||
.val = 0
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
if (pid > 0)
|
||||
@ -3399,12 +3403,12 @@ g_waitpid_status(int pid)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
exit_status.reason = E_XR_STATUS_CODE;
|
||||
exit_status.reason = E_PXR_STATUS_CODE;
|
||||
exit_status.val = WEXITSTATUS(status);
|
||||
}
|
||||
if (WIFSIGNALED(status))
|
||||
{
|
||||
exit_status.reason = E_XR_SIGNAL;
|
||||
exit_status.reason = E_PXR_SIGNAL;
|
||||
exit_status.val = WTERMSIG(status);
|
||||
}
|
||||
}
|
||||
|
@ -23,16 +23,16 @@
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
enum exit_reason
|
||||
enum proc_exit_reason
|
||||
{
|
||||
E_XR_STATUS_CODE = 0, ///< 'val' contains exit status
|
||||
E_XR_SIGNAL, ///< 'val' contains a signal number
|
||||
E_XR_UNEXPECTED
|
||||
E_PXR_STATUS_CODE = 0, ///< 'val' contains exit status
|
||||
E_PXR_SIGNAL, ///< 'val' contains a signal number
|
||||
E_PXR_UNEXPECTED
|
||||
};
|
||||
|
||||
struct exit_status
|
||||
struct proc_exit_status
|
||||
{
|
||||
enum exit_reason reason;
|
||||
enum proc_exit_reason reason;
|
||||
int val;
|
||||
};
|
||||
|
||||
@ -352,9 +352,9 @@ int g_setlogin(const char *name);
|
||||
*/
|
||||
int g_set_allusercontext(int uid);
|
||||
#endif
|
||||
int g_waitchild(struct exit_status *e);
|
||||
int g_waitchild(struct proc_exit_status *e);
|
||||
int g_waitpid(int pid);
|
||||
struct exit_status g_waitpid_status(int pid);
|
||||
struct proc_exit_status g_waitpid_status(int pid);
|
||||
/*
|
||||
* Sets the process group ID of the indicated process to the specified value.
|
||||
* (POSIX.1)
|
||||
|
21
configure.ac
21
configure.ac
@ -6,6 +6,7 @@ AC_DEFINE([VERSION_YEAR], 2024, [Copyright year])
|
||||
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
|
||||
AM_INIT_AUTOMAKE([1.7.2 foreign])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_C_CONST
|
||||
@ -183,6 +184,11 @@ AC_ARG_ENABLE(rdpsndaudin, AS_HELP_STRING([--enable-rdpsndaudin],
|
||||
[], [enable_rdpsndaudin=no])
|
||||
AM_CONDITIONAL(XRDP_RDPSNDAUDIN, [test x$enable_rdpsndaudin = xyes])
|
||||
|
||||
AC_ARG_ENABLE(utmp, AS_HELP_STRING([--enable-utmp],
|
||||
[Update utmp (default: no)]),
|
||||
[], [enable_utmp=no])
|
||||
AM_CONDITIONAL(XRDP_UTMP, [test x$enable_utmp = xyes])
|
||||
|
||||
AC_ARG_WITH(imlib2, AS_HELP_STRING([--with-imlib2=ARG], [imlib2 library to use for non-BMP backgrounds (ARG=yes/no/<abs-path>)]),,)
|
||||
|
||||
AC_ARG_WITH(freetype2, AS_HELP_STRING([--with-freetype2=ARG], [freetype2 library to use for rendering fonts (ARG=yes/no/<abs-path>)]),,)
|
||||
@ -515,6 +521,15 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [],
|
||||
[AC_MSG_ERROR([please install libxrandr-dev or libXrandr-devel])],
|
||||
[#include <X11/Xlib.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"
|
||||
|
||||
# perform unit tests if libcheck and libmocka found
|
||||
@ -632,6 +647,12 @@ echo " ipv6only $enable_ipv6only"
|
||||
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"
|
||||
|
@ -1,4 +1,3 @@
|
||||
#%PAM-1.0
|
||||
auth include system-remote-login
|
||||
-auth optional pam_gnome_keyring.so
|
||||
-auth optional pam_kwallet5.so
|
||||
@ -8,5 +7,8 @@ account include system-remote-login
|
||||
password include system-remote-login
|
||||
|
||||
session include system-remote-login
|
||||
# For wtmp/lastlog support uncomment one of the following lines:-
|
||||
#session optional pam_lastlog.so quiet
|
||||
#session optional pam_lastlog2.so silent
|
||||
-session optional pam_gnome_keyring.so auto_start
|
||||
-session optional pam_kwallet5.so auto_start
|
||||
|
@ -9,6 +9,10 @@ auth required pam_env.so readenv=1 envfile=/etc/default/locale
|
||||
|
||||
@include common-password
|
||||
|
||||
# Set the loginuid process attribute.
|
||||
session required pam_loginuid.so
|
||||
# Update wtmp/lastlog
|
||||
session optional pam_lastlog.so quiet
|
||||
@include common-session
|
||||
-session optional pam_gnome_keyring.so auto_start
|
||||
-session optional pam_kwallet5.so auto_start
|
||||
|
@ -1,5 +1,11 @@
|
||||
#%PAM-1.0
|
||||
auth include password-auth
|
||||
account include password-auth
|
||||
|
||||
# Set the loginuid process attribute.
|
||||
session required pam_loginuid.so
|
||||
# Update wtmp/lastlog
|
||||
session optional pam_lastlog.so quiet
|
||||
|
||||
session include password-auth
|
||||
password include password-auth
|
||||
|
@ -1,5 +1,11 @@
|
||||
#%PAM-1.0
|
||||
auth include common-auth
|
||||
account include common-account
|
||||
|
||||
# Set the loginuid process attribute.
|
||||
session required pam_loginuid.so
|
||||
# Update lastlog database
|
||||
session optional pam_lastlog2.so silent
|
||||
|
||||
session include common-session
|
||||
password include common-password
|
||||
|
@ -2,4 +2,8 @@
|
||||
auth include system-auth
|
||||
account include system-auth
|
||||
password include system-auth
|
||||
|
||||
# For wtmp/lastlog support uncomment one of the following lines:-
|
||||
#session optional pam_lastlog.so quiet
|
||||
#session optional pam_lastlog2.so silent
|
||||
session include system-auth
|
||||
|
43
m4/axrdp.m4
Normal file
43
m4/axrdp.m4
Normal file
@ -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 <utmpx.h>
|
||||
# include <stddef.h>
|
||||
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])
|
||||
])
|
||||
|
||||
|
@ -9,6 +9,10 @@ AM_CPPFLAGS = \
|
||||
|
||||
SESEXEC_EXTRA_LIBS =
|
||||
|
||||
if XRDP_UTMP
|
||||
AM_CPPFLAGS += -DUSE_UTMP
|
||||
endif
|
||||
|
||||
pkglibexec_PROGRAMS = \
|
||||
xrdp-sesexec
|
||||
|
||||
@ -25,6 +29,8 @@ xrdp_sesexec_SOURCES = \
|
||||
env.h \
|
||||
login_info.c \
|
||||
login_info.h \
|
||||
sessionrecord.c \
|
||||
sessionrecord.h \
|
||||
xauth.c \
|
||||
xauth.h \
|
||||
xwait.c \
|
||||
|
@ -241,7 +241,7 @@ sesexec_terminate_main_loop(int status)
|
||||
static void
|
||||
process_sigchld_event(void)
|
||||
{
|
||||
struct exit_status e;
|
||||
struct proc_exit_status e;
|
||||
int pid;
|
||||
|
||||
// Check for any finished children
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "login_info.h"
|
||||
#include "os_calls.h"
|
||||
#include "sesexec.h"
|
||||
#include "sessionrecord.h"
|
||||
#include "string_calls.h"
|
||||
#include "xauth.h"
|
||||
#include "xwait.h"
|
||||
@ -656,6 +657,7 @@ session_start_wrapped(struct login_info *login_info,
|
||||
}
|
||||
else
|
||||
{
|
||||
utmp_login(window_manager_pid, s->display, login_info);
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting the xrdp channel server for display :%d",
|
||||
s->display);
|
||||
@ -807,11 +809,11 @@ cleanup_sockets(int uid, int display)
|
||||
|
||||
/******************************************************************************/
|
||||
static void
|
||||
exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
|
||||
exit_status_to_str(const struct proc_exit_status *e, char buff[], int bufflen)
|
||||
{
|
||||
switch (e->reason)
|
||||
{
|
||||
case E_XR_STATUS_CODE:
|
||||
case E_PXR_STATUS_CODE:
|
||||
if (e->val == 0)
|
||||
{
|
||||
g_snprintf(buff, bufflen, "exit code zero");
|
||||
@ -822,7 +824,7 @@ exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
|
||||
}
|
||||
break;
|
||||
|
||||
case E_XR_SIGNAL:
|
||||
case E_PXR_SIGNAL:
|
||||
{
|
||||
char sigstr[MAXSTRSIGLEN];
|
||||
g_snprintf(buff, bufflen, "signal %s",
|
||||
@ -840,7 +842,7 @@ exit_status_to_str(const struct exit_status *e, char buff[], int bufflen)
|
||||
void
|
||||
session_process_child_exit(struct session_data *sd,
|
||||
int pid,
|
||||
const struct exit_status *e)
|
||||
const struct proc_exit_status *e)
|
||||
{
|
||||
if (pid == sd->x_server)
|
||||
{
|
||||
@ -860,7 +862,7 @@ session_process_child_exit(struct session_data *sd,
|
||||
{
|
||||
int wm_wait_time = g_time1() - sd->start_time;
|
||||
|
||||
if (e->reason == E_XR_STATUS_CODE && e->val == 0)
|
||||
if (e->reason == E_PXR_STATUS_CODE && e->val == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Window manager (pid %d, display %d) "
|
||||
@ -886,6 +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, e);
|
||||
sd->win_mgr = -1;
|
||||
|
||||
if (sd->x_server > 0)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "xrdp_constants.h"
|
||||
|
||||
struct login_info;
|
||||
struct exit_status;
|
||||
struct proc_exit_status;
|
||||
|
||||
/**
|
||||
* Information used to start a session
|
||||
@ -89,7 +89,7 @@ session_start(struct login_info *login_info,
|
||||
void
|
||||
session_process_child_exit(struct session_data *sd,
|
||||
int pid,
|
||||
const struct exit_status *e);
|
||||
const struct proc_exit_status *e);
|
||||
|
||||
/**
|
||||
* Returns a count of active processes in the session
|
||||
|
200
sesman/sesexec/sessionrecord.c
Normal file
200
sesman/sesexec/sessionrecord.c
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Emmanuel Blindauer 2017
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* str2memcpy() is taken from util-linux/include/strutils.h v2.39 which
|
||||
* has the following header:-
|
||||
*
|
||||
* No copyright is claimed. This code is in the public domain; do with
|
||||
* it what you wish.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file sessionrecord.c
|
||||
* @brief utmp handling code
|
||||
*
|
||||
* wtmp/lastlog/btmp is handled by PAM or (on FreeBSD) UTX
|
||||
*
|
||||
* Idea: Only implement actual utmp, i.e. utmpx for 99%.
|
||||
* See http://80386.nl/unix/utmpx/
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "sessionrecord.h"
|
||||
#include "login_info.h"
|
||||
#include "log.h"
|
||||
|
||||
// Operational mode of add_xtmp_entry()
|
||||
//
|
||||
// We can't use USER_PROCESS/DEAD_PROCESS directly, as they
|
||||
// won't be available for platforms without USE_UTMP
|
||||
enum add_xtmp_mode
|
||||
{
|
||||
MODE_LOGIN,
|
||||
MODE_LOGOUT
|
||||
};
|
||||
|
||||
#ifdef USE_UTMP
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_UTMPX_H
|
||||
#include <utmpx.h>
|
||||
typedef struct utmpx _utmp;
|
||||
#else
|
||||
#include <utmp.h>
|
||||
typedef struct utmp _utmp;
|
||||
#endif
|
||||
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#define XRDP_LINE_FORMAT "xrdp:%d"
|
||||
// ut_id is a very small field on some platforms, so use the display
|
||||
// number in hex
|
||||
#define XRDP_ID_FORMAT ":%x"
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* utmp-specific strncpy() replacement
|
||||
*
|
||||
* @param dest Destination pointer
|
||||
* @param src Source pointer
|
||||
* @param n bytes to copy
|
||||
*
|
||||
* This is like strncpy(), but based on memcpy(), so compilers and static
|
||||
* analyzers do not complain when sizeof(destination) is the same as 'n' and
|
||||
* result is not terminated by zero.
|
||||
*
|
||||
* ONLY use this function to copy string to logs with fixed sizes
|
||||
* (wtmp/utmp. ...) where string terminator is optional.
|
||||
*/
|
||||
static inline void *__attribute__((nonnull (1)))
|
||||
str2memcpy(void *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t bytes = strlen(src) + 1;
|
||||
|
||||
if (bytes > n)
|
||||
{
|
||||
bytes = n;
|
||||
}
|
||||
|
||||
memcpy(dest, src, bytes);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Prepare the utmp struct and write it.
|
||||
*
|
||||
* @param pid PID of session manager
|
||||
* @param display Display number of session
|
||||
* @param login_info Login info (NULL for MODE_LOGOUT)
|
||||
* @param mode see enum add_xtmp_mode
|
||||
* @param e Exit status (NULL unless MODE_LOGOUT)
|
||||
*/
|
||||
|
||||
static void
|
||||
add_xtmp_entry(int pid, int display, const struct login_info *login_info,
|
||||
enum add_xtmp_mode mode, const struct proc_exit_status *e)
|
||||
{
|
||||
char idbuff[16];
|
||||
char str_display[16];
|
||||
|
||||
_utmp ut;
|
||||
struct timeval tv;
|
||||
|
||||
g_memset(&ut, 0, sizeof(ut));
|
||||
g_snprintf(str_display, sizeof(str_display), XRDP_LINE_FORMAT, display);
|
||||
g_snprintf(idbuff, sizeof(idbuff), XRDP_ID_FORMAT, display);
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
ut.ut_type = (mode == MODE_LOGIN) ? USER_PROCESS : DEAD_PROCESS;
|
||||
ut.ut_pid = pid;
|
||||
str2memcpy(ut.ut_id, idbuff, sizeof(ut.ut_id));
|
||||
|
||||
// Linux utmp(5) suggests ut_line, ut_time, ut_user, and ut_host
|
||||
// are not set for a DEAD_PROCESS
|
||||
if (ut.ut_type != DEAD_PROCESS)
|
||||
{
|
||||
ut.ut_tv.tv_sec = tv.tv_sec;
|
||||
ut.ut_tv.tv_usec = tv.tv_usec;
|
||||
str2memcpy(ut.ut_line, str_display, sizeof(ut.ut_line));
|
||||
if (login_info != NULL)
|
||||
{
|
||||
str2memcpy(ut.ut_user, login_info->username, sizeof(ut.ut_user));
|
||||
#ifdef HAVE_UTMPX_UT_HOST
|
||||
str2memcpy(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 */
|
||||
setutxent();
|
||||
/* add the computed entry */
|
||||
pututxline(&ut);
|
||||
/* closes utmp */
|
||||
endutxent();
|
||||
|
||||
}
|
||||
#else // USE_UTMP
|
||||
static void
|
||||
add_xtmp_entry(int pid, int display, const struct login_info *login_info,
|
||||
short state, const struct proc_exit_status *e)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
utmp_login(int pid, int display, const struct login_info *login_info)
|
||||
{
|
||||
log_message(LOG_LEVEL_DEBUG,
|
||||
"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, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
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, exit_status);
|
||||
}
|
52
sesman/sesexec/sessionrecord.h
Normal file
52
sesman/sesexec/sessionrecord.h
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Emmanuel Blindauer 2017
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file sessionrecord.h
|
||||
* @brief utmp handling code
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SESSIONRECORD_H
|
||||
#define SESSIONRECORD_H
|
||||
|
||||
struct login_info;
|
||||
struct proc_exit_status;
|
||||
|
||||
/**
|
||||
* @brief Record login in utmp
|
||||
*
|
||||
* @param pid PID of window manager
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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, const struct proc_exit_status *exit_status);
|
||||
|
||||
#endif
|
@ -142,7 +142,7 @@ wait_for_xserver(uid_t uid,
|
||||
}
|
||||
else
|
||||
{
|
||||
struct exit_status e;
|
||||
struct proc_exit_status e;
|
||||
|
||||
fd[0] = -1; // File descriptor closed by fclose()
|
||||
log_waitforx_messages(dp);
|
||||
@ -150,11 +150,11 @@ wait_for_xserver(uid_t uid,
|
||||
e = g_waitpid_status(pid);
|
||||
switch (e.reason)
|
||||
{
|
||||
case E_XR_STATUS_CODE:
|
||||
case E_PXR_STATUS_CODE:
|
||||
rv = (enum xwait_status)e.val;
|
||||
break;
|
||||
|
||||
case E_XR_SIGNAL:
|
||||
case E_PXR_SIGNAL:
|
||||
{
|
||||
char sigstr[MAXSTRSIGLEN];
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
|
@ -79,7 +79,7 @@ END_TEST
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_child_stop_1)
|
||||
{
|
||||
struct exit_status e;
|
||||
struct proc_exit_status e;
|
||||
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
@ -98,7 +98,7 @@ START_TEST(test_g_signal_child_stop_1)
|
||||
|
||||
e = g_waitpid_status(pid);
|
||||
|
||||
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.reason, E_PXR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.val, 45);
|
||||
|
||||
// Try another one to make sure the signal handler is still in place.
|
||||
@ -116,7 +116,7 @@ START_TEST(test_g_signal_child_stop_1)
|
||||
|
||||
e = g_waitpid_status(pid);
|
||||
|
||||
ck_assert_int_eq(e.reason, E_XR_SIGNAL);
|
||||
ck_assert_int_eq(e.reason, E_PXR_SIGNAL);
|
||||
ck_assert_int_eq(e.val, SIGSEGV);
|
||||
|
||||
// Clean up
|
||||
@ -133,7 +133,7 @@ START_TEST(test_g_signal_child_stop_2)
|
||||
int pids[CHILD_COUNT];
|
||||
unsigned int i;
|
||||
|
||||
struct exit_status e;
|
||||
struct proc_exit_status e;
|
||||
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
@ -157,7 +157,7 @@ START_TEST(test_g_signal_child_stop_2)
|
||||
for (i = 0 ; i < CHILD_COUNT; ++i)
|
||||
{
|
||||
e = g_waitpid_status(pids[i]);
|
||||
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.reason, E_PXR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.val, (i + 1));
|
||||
}
|
||||
|
||||
@ -246,12 +246,12 @@ START_TEST(test_waitpid_not_interrupted_by_sig)
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
g_set_alarm(set_wobj1, 1);
|
||||
|
||||
struct exit_status e = g_waitpid_status(child_pid);
|
||||
struct proc_exit_status e = g_waitpid_status(child_pid);
|
||||
// We should have had the alarm...
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
// ..and got the status of the child
|
||||
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.reason, E_PXR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.val, 42);
|
||||
|
||||
// Clean up
|
||||
|
@ -856,12 +856,12 @@ xrdp_listen_conn_in(struct trans *self, struct trans *new_self)
|
||||
static void
|
||||
process_pending_sigchld_events(void)
|
||||
{
|
||||
struct exit_status e;
|
||||
struct proc_exit_status e;
|
||||
int pid;
|
||||
|
||||
while ((pid = g_waitchild(&e)) > 0)
|
||||
{
|
||||
if (e.reason == E_XR_SIGNAL)
|
||||
if (e.reason == E_PXR_SIGNAL)
|
||||
{
|
||||
char sigstr[MAXSTRSIGLEN];
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
|
Loading…
Reference in New Issue
Block a user