Commit dfb8ae48 authored by William Jon McCann's avatar William Jon McCann Committed by William Jon McCann

Merge changes from 2.20 branch to fix utmp/wtmp handling. Patch from Brian

2007-10-18  William Jon McCann  <mccann@jhu.edu>

	* configure.ac:
	* daemon/gdm-session.c: (gdm_session_write_record):
	Merge changes from 2.20 branch to fix utmp/wtmp handling.
	Patch from Brian Cameron <brian.cameron@sun.com>


svn path=/trunk/; revision=5377
parent 2135595d
2007-10-18 William Jon McCann <mccann@jhu.edu>
* configure.ac:
* daemon/gdm-session.c: (gdm_session_write_record):
Merge changes from 2.20 branch to fix utmp/wtmp handling.
Patch from Brian Cameron <brian.cameron@sun.com>
2007-10-18 William Jon McCann <mccann@jhu.edu>
* HACKING: Futz with the order.
......
......@@ -474,9 +474,10 @@ dnl - Check for utmp stuff
dnl ---------------------------------------------------------------------------
AC_CHECK_HEADERS(utmp.h utmpx.h libutil.h sys/param.h)
AC_CHECK_FUNC(getutmpx updwtmpx)
AC_CHECK_FUNCS([getutxent updwtmpx updwtmp])
AC_CHECK_LIB(util,login)
AC_CHECK_LIB(util,logout)
AC_CHECK_LIB(util,logwtmp)
GDM_CHECK_UTMP
AC_MSG_CHECKING(if utmpx structure has ut_syslen field)
......
......@@ -40,7 +40,12 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if defined(HAVE_UTMPX_H)
#include <utmpx.h>
#elif defined(HAVE_UTMP_H)
#include <utmp.h>
#endif
#include <glib.h>
#include <glib/gi18n.h>
......@@ -179,110 +184,243 @@ static void
gdm_session_write_record (GdmSession *session,
GdmSessionRecordType record_type)
{
#if defined(HAVE_UTMPX_H)
struct utmpx session_record = { 0 };
struct utmpx *u = NULL;
#elif defined(HAVE_UTMP_H)
struct utmp session_record = { 0 };
#endif
GTimeVal now = { 0 };
char *hostname;
char *hostname, *username;
g_debug ("writing %s record",
record_type == GDM_SESSION_RECORD_TYPE_LOGIN? "session" :
record_type == GDM_SESSION_RECORD_TYPE_LOGOUT? "logout" :
g_debug ("Writing %s utmp/wtmp record",
record_type == GDM_SESSION_RECORD_TYPE_LOGIN ? "session" :
record_type == GDM_SESSION_RECORD_TYPE_LOGOUT ? "logout" :
"failed session attempt");
if (record_type != GDM_SESSION_RECORD_TYPE_LOGOUT) {
/* it's possible that PAM failed before it mapped the user input
* into a valid username, so we fallback to try using "(unknown)"
/*
* It is possible that PAM failed before it mapped the user
* input into a valid username, so we fallback to try using
* "(unknown)"
*/
if (session->priv->username != NULL)
strncpy (session_record.ut_user, session->priv->username,
sizeof (session_record.ut_user));
username = session->priv->username;
else
strncpy (session_record.ut_user, "(unknown)",
sizeof (session_record.ut_user));
username = "(unknown)";
#if defined(HAVE_UT_UT_USER)
strncpy (session_record.ut_user,
username,
sizeof (session_record.ut_user));
g_debug ("using ut_user %.*s",
sizeof (session_record.ut_user),
session_record.ut_user);
#elif defined(HAVE_UT_UT_NAME)
strncpy (session_record.ut_name,
username
sizeof (session_record.ut_name));
g_debug ("using ut_name %.*s",
sizeof (session_record.ut_name),
session_record.ut_name);
#endif
}
g_debug ("using username %.*s",
sizeof (session_record.ut_user),
session_record.ut_user);
/* FIXME: I have no idea what to do for ut_id.
#if defined(HAVE_UT_UT_TYPE)
/*
* Set type to DEAD_PROCESS when logging out, otherwise
* set to USER_PROCESS.
*/
strncpy (session_record.ut_id,
session->priv->display_device +
strlen (session->priv->display_device) -
sizeof (session_record.ut_id),
sizeof (session_record.ut_id));
g_debug ("using id %.*s", sizeof (session_record.ut_id), session_record.ut_id);
if (record_type == GDM_SESSION_RECORD_TYPE_LOGOUT) {
session_record.ut_type = DEAD_PROCESS;
g_debug ("using ut_type DEAD_PROCESS");
} else {
session_record.ut_type = USER_PROCESS;
g_debug ("using ut_type USER_PROCESS");
}
#endif
if (g_str_has_prefix (session->priv->display_device, "/dev/")) {
strncpy (session_record.ut_line,
session->priv->display_device + strlen ("/dev/"),
sizeof (session_record.ut_line));
} else if (g_str_has_prefix (session->priv->display_device, ":")) {
strncpy (session_record.ut_line,
session->priv->display_device,
sizeof (session_record.ut_line));
#if defined(HAVE_UT_UT_PID)
/* Set pid */
if (session->priv->session_pid != 0) {
session_record.ut_pid = session->priv->session_pid;
}
g_debug ("using ut_pid %d", (int) session_record.ut_pid);
#endif
g_debug ("using line %.*s",
sizeof (session_record.ut_line),
session_record.ut_line);
#if defined(HAVE_UT_UT_TV)
/* Set time in TV format */
g_get_current_time (&now);
session_record.ut_tv.tv_sec = now.tv_sec;
session_record.ut_tv.tv_usec = now.tv_usec;
g_debug ("using ut_tv time %ld",
(glong) session_record.ut_tv.tv_sec);
#elif defined(HAVE_UT_UT_TIME)
/* Set time in time format */
time (&session_record.ut_time);
g_debug ("using ut_time %ld",
(glong) session_record.ut_time);
#endif
/* FIXME: this is a bit of a mess. Figure out how
* wrong the logic is
*/
#if defined(HAVE_UT_UT_ID)
/* Set ut_id to the $DISPLAY value */
strncpy (session_record.ut_id,
session->priv->x11_display_name,
sizeof (session_record.ut_id));
g_debug ("using ut_id %.*s",
sizeof (session_record.ut_id),
session_record.ut_id);
#endif
#if defined(HAVE_UT_UT_HOST)
hostname = NULL;
/*
* Set ut_host to hostname:$DISPLAY if remote, otherwise set
* to $DISPLAY
*/
if ((session->priv->hostname != NULL) &&
g_str_has_prefix (session->priv->display_device, ":"))
g_str_has_prefix (session->priv->x11_display_name, ":"))
hostname = g_strdup_printf ("%s%s", session->priv->hostname,
session->priv->display_device);
else if ((session->priv->hostname != NULL) &&
!strstr (session->priv->display_device, ":"))
hostname = g_strdup (session->priv->hostname);
else if (!g_str_has_prefix (session->priv->display_device, ":") &&
strstr (session->priv->display_device, ":"))
hostname = g_strdup (session->priv->display_device);
session->priv->x11_display_name);
else
hostname = g_strdup (session->priv->x11_display_name);
if (hostname) {
g_debug ("using hostname %.*s",
sizeof (session_record.ut_host),
session_record.ut_host);
strncpy (session_record.ut_host,
hostname, sizeof (session_record.ut_host));
g_debug ("using ut_host %.*s",
sizeof (session_record.ut_host),
session_record.ut_host);
g_free (hostname);
}
g_get_current_time (&now);
session_record.ut_tv.tv_sec = now.tv_sec;
session_record.ut_tv.tv_usec = now.tv_usec;
g_debug ("using time %ld",
(glong) session_record.ut_tv.tv_sec);
session_record.ut_type = USER_PROCESS;
g_debug ("using type USER_PROCESS");
if (session->priv->session_pid != 0) {
session_record.ut_pid = session->priv->session_pid;
#ifdef HAVE_UT_UT_SYSLEN
session_record.ut_syslen = MIN (strlen (hostname),
sizeof (session_record.ut_host));
#endif
}
#endif
g_debug ("using pid %d", (int) session_record.ut_pid);
/*
* Set ut_line to the device name associated with this display
* but remove the "/dev/" prefix. If no device, then use the
* $DISPLAY value.
*/
if (g_str_has_prefix (session->priv->display_device, "/dev/")) {
strncpy (session_record.ut_line,
session->priv->display_device + strlen ("/dev/"),
sizeof (session_record.ut_line));
} else if (g_str_has_prefix (session->priv->x11_display_name, ":")) {
strncpy (session_record.ut_line,
session->priv->x11_display_name,
sizeof (session_record.ut_line));
}
g_debug ("using ut_line %.*s",
sizeof (session_record.ut_line),
session_record.ut_line);
switch (record_type) {
case GDM_SESSION_RECORD_TYPE_LOGIN:
g_debug ("writing session record to " GDM_NEW_SESSION_RECORDS_FILE);
/* Handle wtmp */
g_debug ("Writing wtmp session record to " GDM_NEW_SESSION_RECORDS_FILE);
#if defined(HAVE_UPDWTMPX)
updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
#elif defined(HAVE_UPDWTMP)
updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
#elif defined(HAVE_LOGWTMP) && defined(HAVE_UT_UT_HOST) && !defined(HAVE_LOGIN)
#if defined(HAVE_UT_UT_USER)
logwtmp (record.ut_line, record.ut_user, record.ut_host);
#elif defined(HAVE_UT_UT_NAME)
logwtmp (record.ut_line, record.ut_name, record.ut_host);
#endif
#endif
#if defined(HAVE_GETUTXENT)
/*
* Handle utmp
* Update if entry already exists
*/
while ((u = getutxent ()) != NULL) {
if (u->ut_type == USER_PROCESS &&
(session_record.ut_line != NULL &&
(strncmp (u->ut_line, session_record.ut_line,
sizeof (u->ut_line)) == 0 ||
u->ut_pid == session_record.ut_pid))) {
g_debug ("Updating existing utmp record");
pututxline (&session_record);
break;
}
}
endutxent ();
/* Add new entry if update did not work */
if (u == (struct utmpx *)NULL) {
g_debug ("Adding new utmp record");
pututxline (&session_record);
}
#elif defined(HAVE_LOGIN)
login (&session_record);
#endif
break;
case GDM_SESSION_RECORD_TYPE_LOGOUT:
g_debug ("writing logout record to " GDM_NEW_SESSION_RECORDS_FILE);
/* Handle wtmp */
g_debug ("Writing wtmp logout record to " GDM_NEW_SESSION_RECORDS_FILE);
#if defined(HAVE_UPDWTMPX)
updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
#elif defined (HAVE_UPDWTMP)
updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
#elif defined(HAVE_LOGWTMP)
logwtmp (record.ut_line, "", "");
#endif
/* Hande utmp */
#if defined(HAVE_GETUTXENT)
setutxent ();
while ((u = getutxent ()) != NULL &&
(u = getutxid (&session_record)) != NULL) {
g_debug ("Removing utmp record");
if (u->ut_pid == session->priv->session_pid &&
u->ut_type == DEAD_PROCESS) {
/* Already done */
break;
}
u->ut_type = DEAD_PROCESS;
#if defined(HAVE_UT_UT_TV)
u->ut_tv.tv_sec = session_record.ut_tv.tv_sec;
#elif defined(HAVE_UT_UT_TIME)
u->ut_time = session_record.ut_time;
#endif
u->ut_exit.e_termination = 0;
u->ut_exit.e_exit = 0;
pututxline (u);
break;
}
endutxent ();
#elif defined(HAVE_LOGOUT)
logout (session_record.ut_line);
#endif
break;
case GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT:
g_debug ("writing failed session attempt record to "
/* Handle btmp */
g_debug ("Writing btmp failed session attempt record to "
GDM_BAD_SESSION_RECORDS_FILE);
#if defined(HAVE_UPDWTMPX)
updwtmpx (GDM_BAD_SESSION_RECORDS_FILE, &session_record);
#elif defined(HAVE_UPDWTMP)
updwtmp (GDM_BAD_SESSION_RECORDS_FILE, &session_record);
#endif
break;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment