[gdm-list] GDM utmp support
- From: Brian Cameron <Brian Cameron Sun COM>
- To: gdm-list gnome org
- Subject: [gdm-list] GDM utmp support
- Date: Tue, 16 Oct 2007 19:04:26 -0500
Jon:
Attached please find a patch which fixes the utmp/wtmp processing quite
a bit. When you forked D-Bus, this code was still under a lot of
development and it took quite some time to get it right. The stable
GDM code has been reworked so it better supports how utmp/wtmp works
on a variety of platforms.
In summary, the following changes are in the patch:
+ configure.ac wasn't properly setting HAVE_GETUTXENT, etc. because it
was using AC_CHECK_FUNC instead of AC_CHECK_FUNCS. With this change
it works properly. Also, need to check for logwtmp for FreeBSD
support.
+ The previous code was only doing wtmp/btmp processing. This patch
adds utmp proccessing. Also, now utmpx.h is used in preference
to utmp.h if found on the system, so systems using extended utmp
are better supported.
+ This code uses #if checks to better ensure that the code compiles
across all platforms. For example, will use UT_NAME instead of
UT_USER if UT_USER isn't present on the system. Also added back
login(), logout(), and logwtmp() #ifdef's needed by FreeBSD.
+ Support ut_tv or ut_time, based on what is supported on the system.
Also support setting ut_syslen if supported on the system.
+ ut_type should be set to DEAD_PROCESS on logout. The previous code
was always setting it to USER_PROCESS.
+ ut_id is now set to x11_display_name and ut_host is now set to
hostname and x11_display_name or just x11_display_name if hostname
is not set. This matches what is in stable GDM. Unless there is
a good reason, I think we should probably try to stay consistent
with what people are currently using with GDM 2.20.
If we think we should set ut_host or ut_id differently, then we
should discuss if this should impact the GDM 2.20 code, I guess.
Brian
Index: configure.ac
===================================================================
--- configure.ac (revision 5373)
+++ configure.ac (working copy)
@@ -474,9 +474,10 @@
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)
Index: daemon/gdm-session.c
===================================================================
--- daemon/gdm-session.c (revision 5373)
+++ daemon/gdm-session.c (working copy)
@@ -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 @@
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);
+#if defined(HAVE_UT_UT_TYPE)
+ /*
+ * Set type to DEAD_PROCESS when logging out, otherwise
+ * set to USER_PROCESS.
+ */
+ 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
- /* FIXME: I have no idea what to do for ut_id.
- */
+#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
+
+#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
+
+#if defined(HAVE_UT_UT_ID)
+ /* Set ut_id to the $DISPLAY value */
strncpy (session_record.ut_id,
- session->priv->display_device +
- strlen (session->priv->display_device) -
+ session->priv->x11_display_name,
+ sizeof (session_record.ut_id));
+ g_debug ("using ut_id %.*s",
sizeof (session_record.ut_id),
- sizeof (session_record.ut_id));
+ session_record.ut_id);
+#endif
- g_debug ("using id %.*s", sizeof (session_record.ut_id), session_record.ut_id);
+#if defined(HAVE_UT_UT_HOST)
+ hostname = NULL;
- 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));
- }
-
- g_debug ("using line %.*s",
- sizeof (session_record.ut_line),
- session_record.ut_line);
-
- /* FIXME: this is a bit of a mess. Figure out how
- * wrong the logic is
+ /*
+ * Set ut_host to hostname:$DISPLAY if remote, otherwise set
+ * to $DISPLAY
*/
- hostname = NULL;
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",
+ 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);
- strncpy (session_record.ut_host,
- hostname, sizeof (session_record.ut_host));
g_free (hostname);
+
+#ifdef HAVE_UT_UT_SYSLEN
+ session_record.ut_syslen = MIN (strlen (hostname),
+ sizeof (session_record.ut_host));
+#endif
}
+#endif
- g_get_current_time (&now);
- session_record.ut_tv.tv_sec = now.tv_sec;
- session_record.ut_tv.tv_usec = now.tv_usec;
+ /*
+ * 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);
- g_debug ("using time %ld",
- (glong) session_record.ut_tv.tv_sec);
+ switch (record_type) {
+ case GDM_SESSION_RECORD_TYPE_LOGIN:
- session_record.ut_type = USER_PROCESS;
- g_debug ("using type USER_PROCESS");
+ /* 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 (session->priv->session_pid != 0) {
- session_record.ut_pid = session->priv->session_pid;
- }
+#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 ();
- g_debug ("using pid %d", (int) session_record.ut_pid);
+ /* 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
- switch (record_type) {
- case GDM_SESSION_RECORD_TYPE_LOGIN:
- g_debug ("writing session record to " GDM_NEW_SESSION_RECORDS_FILE);
- updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
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;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]