? gdmsetup
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/gdm2/configure.ac,v
retrieving revision 1.70
diff -p -u -r1.70 configure.ac
--- configure.ac	30 Oct 2006 22:10:10 -0000	1.70
+++ configure.ac	31 Oct 2006 19:36:28 -0000
@@ -10,6 +10,7 @@ IT_PROG_INTLTOOL([0.35.0])
 
 GNOME_DOC_INIT
 
+DBUS_REQUIRED=0.30
 GLIB_REQUIRED=2.8.0
 GTK_REQUIRED=2.6.0
 PANGO_REQUIRED=1.3.0
@@ -71,6 +72,10 @@ AC_ARG_WITH(dmx,
 
 AC_ARG_WITH(selinux, [  --with-selinux  Add SELinux support])
 
+AC_ARG_WITH(console-kit,
+  [  --with-console-kit=[auto/yes/no]  Add ConsoleKit support [default=auto]],,
+  with_console_kit=auto)
+
 # On Solaris, Xnest is only shipped in /usr/openwin/, but your
 # should use "--with-post-path=/usr/openwin/bin" for full
 # Xserver support (such as access to Xnest and other X executables
@@ -156,7 +161,7 @@ PKG_CHECK_MODULES(VICIOUS, gtk+-2.0 >= $
 AC_SUBST(VICIOUS_CFLAGS)
 AC_SUBST(VICIOUS_LIBS)
 
-PKG_CHECK_MODULES(DAEMON, gtk+-2.0 >= $GTK_REQUIRED)
+PKG_CHECK_MODULES(DAEMON, gtk+-2.0 >= $GTK_REQUIRED dbus-glib-1 >= $DBUS_REQUIRED)
 AC_SUBST(DAEMON_CFLAGS)
 AC_SUBST(DAEMON_LIBS)
 
@@ -777,6 +782,17 @@ if test "x$with_selinux" = "xyes" ; then
 fi
 
 #
+# ConsoleKit support
+#
+use_console_kit=no
+if test "x$with_console_kit" != "xno" ; then
+	use_console_kit=yes
+	AC_DEFINE(WITH_CONSOLE_KIT, 1, [Define to enable ConsoleKit support])
+fi
+AM_CONDITIONAL(WITH_CONSOLE_KIT, test x$use_console_kit = xyes)
+AC_SUBST(WITH_CONSOLE_KIT)
+
+#
 # Subst the extra libs
 #
 AC_SUBST(EXTRA_DAEMON_LIBS)
@@ -1213,6 +1229,13 @@ if test "x$found_tsol" = "xyes" ; then
 	echo "Solaris Trusted Extensions support    : YES"
 else
 	echo "Solaris Trusted Extensions support    : NO"
+fi
+
+dnl <= ConsoleKit support =>
+if test "x$use_console_kit" = "xyes" ; then
+	echo "ConsoleKit support                    : YES"
+else
+	echo "ConsoleKit support                    : NO"
 fi
 
 dnl <= Authentication scheme =>
Index: daemon/Makefile.am
===================================================================
RCS file: /cvs/gnome/gdm2/daemon/Makefile.am,v
retrieving revision 1.37
diff -p -u -r1.37 Makefile.am
--- daemon/Makefile.am	28 Mar 2006 23:43:21 -0000	1.37
+++ daemon/Makefile.am	31 Oct 2006 19:36:28 -0000
@@ -48,6 +48,8 @@ gdm_binary_SOURCES = \
 	fstype.c \
 	slave.c \
 	slave.h \
+	gdmconsolekit.c \
+	gdmconsolekit.h \
 	server.c \
 	server.h \
 	misc.c \
Index: daemon/gdm.c
===================================================================
RCS file: /cvs/gnome/gdm2/daemon/gdm.c,v
retrieving revision 1.265
diff -p -u -r1.265 gdm.c
--- daemon/gdm.c	30 Oct 2006 18:14:46 -0000	1.265
+++ daemon/gdm.c	31 Oct 2006 19:36:28 -0000
@@ -46,6 +46,7 @@
 
 #include <X11/Xauth.h>
 #include <glib/gi18n.h>
+#include <glib-object.h>
 
 /* Needed for signal handling */
 #include <vicious.h>
@@ -1533,6 +1534,8 @@ main (int argc, char *argv[])
 
     /* Initialize runtime environment */
     umask (022);
+
+    g_type_init ();
 
     ctx = g_option_context_new (_("- The GNOME login manager"));
     g_option_context_add_main_entries (ctx, options, _("main options"));
Index: daemon/gdmconsolekit.c
===================================================================
RCS file: daemon/gdmconsolekit.c
diff -N daemon/gdmconsolekit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ daemon/gdmconsolekit.c	31 Oct 2006 19:36:28 -0000
@@ -0,0 +1,330 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <pwd.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "misc.h" /* for gdm_debug */
+#include "gdmconsolekit.h"
+
+
+#define CK_NAME              "org.freedesktop.ConsoleKit"
+#define CK_PATH              "/org/freedesktop/ConsoleKit"
+#define CK_INTERFACE         "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \
+							  G_TYPE_STRING, \
+							  G_TYPE_VALUE, \
+							  G_TYPE_INVALID))
+#define CK_TYPE_PARAMETER_LIST (dbus_g_type_get_collection ("GPtrArray", \
+							    CK_TYPE_PARAMETER_STRUCT))
+static void
+add_param_int (GPtrArray       *parameters,
+	       const char      *key,
+	       int              value)
+{
+	GValue val = { 0, };
+	GValue param_val = { 0, };
+
+	g_value_init (&val, G_TYPE_INT);
+	g_value_set_int (&val, value);
+	g_value_init (&param_val, CK_TYPE_PARAMETER_STRUCT);
+	g_value_take_boxed (&param_val,
+			    dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT));
+	dbus_g_type_struct_set (&param_val,
+				0, key,
+				1, &val,
+				G_MAXUINT);
+	g_ptr_array_add (parameters, g_value_get_boxed (&param_val));
+}
+
+static void
+add_param_boolean (GPtrArray       *parameters,
+		   const char      *key,
+		   gboolean         value)
+{
+	GValue val = { 0, };
+	GValue param_val = { 0, };
+
+	g_value_init (&val, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&val, value);
+	g_value_init (&param_val, CK_TYPE_PARAMETER_STRUCT);
+	g_value_take_boxed (&param_val,
+			    dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT));
+	dbus_g_type_struct_set (&param_val,
+				0, key,
+				1, &val,
+				G_MAXUINT);
+	g_ptr_array_add (parameters, g_value_get_boxed (&param_val));
+}
+
+static void
+add_param_string (GPtrArray       *parameters,
+		  const char      *key,
+		  const char      *value)
+{
+	GValue val = { 0, };
+	GValue param_val = { 0, };
+
+	g_value_init (&val, G_TYPE_STRING);
+	g_value_set_string (&val, value);
+
+	g_value_init (&param_val, CK_TYPE_PARAMETER_STRUCT);
+	g_value_take_boxed (&param_val,
+			    dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT));
+
+	dbus_g_type_struct_set (&param_val,
+				0, key,
+				1, &val,
+				G_MAXUINT);
+	g_ptr_array_add (parameters, g_value_get_boxed (&param_val));
+}
+
+static gboolean
+get_string (DBusGProxy *proxy,
+	    const char *method,
+	    char      **str)
+{
+	GError	*error;
+	gboolean res;
+
+	error = NULL;
+	res = dbus_g_proxy_call (proxy,
+				 method,
+				 &error,
+				 G_TYPE_INVALID,
+				 G_TYPE_STRING, str,
+				 G_TYPE_INVALID);
+	if (! res) {
+		g_warning ("%s failed: %s", method, error->message);
+		g_error_free (error);
+	}
+
+	return res;
+}
+
+void
+unlock_ck_session (const char *user,
+		   const char *x11_display)
+{
+	DBusGConnection *connection;
+	DBusGProxy	*proxy;
+	GError		*error;
+	gboolean	 res;
+	struct passwd	*pwent;
+	GPtrArray	*sessions;
+	int		 i;
+
+	gdm_debug ("Unlocking ConsoleKit session for %s on %s", user, x11_display);
+
+	error = NULL;
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+	if (connection == NULL) {
+		g_message ("Failed to connect to the D-Bus daemon: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+					   CK_NAME,
+					   CK_MANAGER_PATH,
+					   CK_MANAGER_INTERFACE);
+	if (proxy == NULL) {
+		return;
+	}
+
+	pwent = getpwnam (user);
+
+	error = NULL;
+	res = dbus_g_proxy_call (proxy,
+				 "GetSessionsForUser",
+				 &error,
+				 G_TYPE_UINT,
+				 pwent->pw_uid,
+				 G_TYPE_INVALID,
+				 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+				 &sessions,
+				 G_TYPE_INVALID);
+	if (! res) {
+		g_warning ("Failed to get list of sessions: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	for (i = 0; i < sessions->len; i++) {
+		char	   *ssid;
+		DBusGProxy *session_proxy;
+
+		ssid = g_ptr_array_index (sessions, i);
+
+		session_proxy = dbus_g_proxy_new_for_name (connection,
+							   CK_NAME,
+							   ssid,
+							   CK_SESSION_INTERFACE);
+		if (session_proxy != NULL) {
+			char *xdisplay;
+
+			get_string (session_proxy, "GetX11Display", &xdisplay);
+			if (xdisplay != NULL
+			    && x11_display != NULL
+			    && strcmp (xdisplay, x11_display) == 0) {
+				res = dbus_g_proxy_call (session_proxy,
+							 "Unlock",
+							 &error,
+							 G_TYPE_INVALID,
+							 G_TYPE_INVALID);
+				if (! res) {
+					g_warning ("Unable to unlock %s: %s", ssid, error->message);
+					g_error_free (error);
+				}
+			}
+		}
+
+		g_object_unref (session_proxy);
+		g_free (ssid);
+	}
+
+	g_ptr_array_free (sessions, TRUE);
+
+ out:
+	g_object_unref (proxy);
+}
+
+char *
+open_ck_session (struct passwd *pwent,
+		 GdmDisplay    *d,
+		 const char    *session)
+{
+	DBusGConnection *connection;
+	DBusGProxy	*proxy;
+	GError		*error;
+	gboolean	 res;
+	char		*cookie;
+	GPtrArray	*parameters;
+
+	cookie = NULL;
+
+	gdm_debug ("Opening ConsoleKit session for %s", pwent->pw_name);
+
+	error = NULL;
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+	if (connection == NULL) {
+		g_message ("Failed to connect to the D-Bus daemon: %s", error->message);
+		g_error_free (error);
+		return NULL;
+	}
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+					   CK_NAME,
+					   CK_MANAGER_PATH,
+					   CK_MANAGER_INTERFACE);
+	if (proxy == NULL) {
+		return NULL;
+	}
+
+	parameters = g_ptr_array_sized_new (10);
+
+	add_param_int (parameters, "user", pwent->pw_uid);
+	add_param_string (parameters, "x11-display", d->name);
+	add_param_string (parameters, "host-name", d->hostname);
+	add_param_boolean (parameters, "is-local", d->attached);
+
+	/* FIXME: this isn't really a reliable value to use */
+	add_param_string (parameters, "session-type", session);
+
+	if (d->vt > 0) {
+		char *device;
+
+		/* FIXME: how does xorg construct this */
+		device = g_strdup_printf ("/dev/tty%d", d->vt);
+		add_param_string (parameters, "display-device", device);
+		g_free (device);
+	}
+
+	error = NULL;
+	res = dbus_g_proxy_call (proxy,
+				 "OpenSessionWithParameters",
+				 &error,
+				 CK_TYPE_PARAMETER_LIST,
+				 parameters,
+				 G_TYPE_INVALID,
+				 G_TYPE_STRING,
+				 &cookie,
+				 G_TYPE_INVALID);
+	if (! res) {
+		g_warning ("OpenSession failed: %s", error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (proxy);
+
+	g_ptr_array_free (parameters, TRUE);
+
+	return cookie;
+}
+
+void
+close_ck_session (const char *cookie)
+{
+	DBusGConnection *connection;
+	DBusGProxy	*proxy;
+	GError		*error;
+	gboolean	 res;
+
+	error = NULL;
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+	if (connection == NULL) {
+		g_message ("Failed to connect to the D-Bus daemon: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	proxy = dbus_g_proxy_new_for_name (connection,
+					   CK_NAME,
+					   CK_MANAGER_PATH,
+					   CK_MANAGER_INTERFACE);
+	if (proxy == NULL) {
+		return;
+	}
+
+	error = NULL;
+	res = dbus_g_proxy_call (proxy,
+				 "CloseSession",
+				 &error,
+				 G_TYPE_STRING,
+				 &cookie,
+				 G_TYPE_INVALID,
+				 G_TYPE_INVALID);
+	if (! res) {
+		g_warning ("CloseSession failed: %s", error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (proxy);
+}
Index: daemon/gdmconsolekit.h
===================================================================
RCS file: daemon/gdmconsolekit.h
diff -N daemon/gdmconsolekit.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ daemon/gdmconsolekit.h	31 Oct 2006 19:36:28 -0000
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __GDM_CONSOLE_KIT_H
+#define __GDM_CONSOLE_KIT_H
+
+G_BEGIN_DECLS
+
+char *      open_ck_session       (struct passwd *pwent,
+                                   GdmDisplay    *display,
+                                   const char    *session);
+void        close_ck_session      (const char    *cookie);
+void        unlock_ck_session     (const char    *user,
+                                   const char    *x11_display);
+
+G_END_DECLS
+
+#endif /* __GDM_CONSOLE_KIT_H */
Index: daemon/slave.c
===================================================================
RCS file: /cvs/gnome/gdm2/daemon/slave.c,v
retrieving revision 1.333
diff -p -u -r1.333 slave.c
--- daemon/slave.c	29 Oct 2006 02:38:51 -0000	1.333
+++ daemon/slave.c	31 Oct 2006 19:36:29 -0000
@@ -90,6 +90,10 @@
 #include "cookie.h"
 #include "gdmconfig.h"
 
+#ifdef WITH_CONSOLE_KIT
+#include "gdmconsolekit.h"
+#endif
+
 /* Some per slave globals */
 static GdmDisplay *d = 0;
 static gchar *login = NULL;
@@ -1234,6 +1238,10 @@ gdm_slave_check_user_wants_to_log_in (co
 			 */
 			gdm_sleep_no_signal (1);
 
+#ifdef WITH_CONSOLE_KIT
+			unlock_ck_session (user, migrate_to);
+#endif
+
 			gdm_slave_send_string (GDM_SOP_MIGRATE, migrate_to);
 			g_free (migrate_to);
 
@@ -3344,6 +3352,9 @@ session_child_run (struct passwd *pwent,
 		   gboolean failsafe,
 		   const char *home_dir,
 		   gboolean home_dir_ok,
+#ifdef WITH_CONSOLE_KIT
+		   const char *ck_session_cookie,
+#endif
 		   const char *session,
 		   const char *save_session,
 		   const char *language,
@@ -3434,6 +3445,9 @@ session_child_run (struct passwd *pwent,
 	g_setenv ("USER", pwent->pw_name, TRUE);
 	g_setenv ("USERNAME", pwent->pw_name, TRUE);
 	g_setenv ("HOME", home_dir, TRUE);
+#ifdef WITH_CONSOLE_KIT
+	g_setenv ("XDG_SESSION_COOKIE", ck_session_cookie, TRUE);
+#endif
 	g_setenv ("GDMSESSION", session, TRUE);
 	g_setenv ("DESKTOP_SESSION", session, TRUE);
 	g_setenv ("SHELL", pwent->pw_shell, TRUE);
@@ -3580,7 +3594,7 @@ session_child_run (struct passwd *pwent,
 	gdm_close_all_descriptors (3 /* from */, -1 /* except */, -1 /* except2 */);
 
 	openlog ("gdm", LOG_PID, LOG_DAEMON);
-	
+
 	argv[0] = NULL;
 	argv[1] = NULL;
 	argv[2] = NULL;
@@ -3930,6 +3944,9 @@ gdm_slave_session_start (void)
     const char *home_dir = NULL;
     char *save_session = NULL, *session = NULL, *language = NULL, *usrsess, *usrlang;
     char *gnome_session = NULL;
+#ifdef WITH_CONSOLE_KIT
+    char *ck_session_cookie;
+#endif
     char *tmp;
     gboolean savesess = FALSE, savelang = FALSE;
     gboolean usrcfgok = FALSE, authok = FALSE;
@@ -4242,6 +4259,10 @@ gdm_slave_session_start (void)
      * could reset time or do other crazy things */
     session_start_time = time (NULL);
 
+#ifdef WITH_CONSOLE_KIT
+    ck_session_cookie = open_ck_session (pwent, d, session);
+#endif
+
     /* Start user process */
     gdm_sigchld_block_push ();
     gdm_sigterm_block_push ();
@@ -4266,6 +4287,9 @@ gdm_slave_session_start (void)
 			   failsafe,
 			   home_dir,
 			   home_dir_ok,
+#ifdef WITH_CONSOLE_KIT
+			   ck_session_cookie,
+#endif
 			   session,
 			   save_session,
 			   language,
@@ -4353,6 +4377,11 @@ gdm_slave_session_start (void)
 			    FALSE /* no_shutdown_check */);
 
     gdm_debug ("gdm_slave_session_start: Session ended OK (now all finished)");
+
+#ifdef WITH_CONSOLE_KIT
+    close_ck_session (ck_session_cookie);
+    g_free (ck_session_cookie);
+#endif
 }
 
 
Index: docs/C/gdm.xml
===================================================================
RCS file: /cvs/gnome/gdm2/docs/C/gdm.xml,v
retrieving revision 1.144
diff -p -u -r1.144 gdm.xml
--- docs/C/gdm.xml	30 Oct 2006 22:24:48 -0000	1.144
+++ docs/C/gdm.xml	31 Oct 2006 19:36:29 -0000
@@ -1005,6 +1005,41 @@ gdm: .your.domain
     </sect2>
   </sect1>
 
+  <sect1 id="consolekit">
+    <title>Support for ConsoleKit</title>
+
+    <para>
+      GDM includes support for publishing user login information with the user and login
+      session accounting framework known as ConsoleKit.  ConsoleKit is able to keep track
+      of all the users currently logged in.  In this respect, it can be used as a replacement
+      for the utmp or utmpx files that are available on most Unix-like operating systems.
+    </para>
+
+    <para>
+      When GDM is about to create a new login process for a user it will call a privileged
+      method of ConsoleKit in order to open a new session for this user.  At this time
+      GDM also provides ConsoleKit with information about this user session such as: the user ID,
+      the X11 Display name that will be associated with the session, the host-name from which the
+      session originates (useful in the case of an XDMCP session), whether or not this session
+      is local, etc.  As the entity that initiates the user process, GDM is in a unique position
+      know and to be trusted to provide these bits of information about the user session.  The use
+      of this privileged method is restricted by the use of D-Bus system message bus security policy.
+    </para>
+
+    <para>
+      In the case where a user with an existing session and has authenticated at GDM and requests to
+      resume that existing session GDM calls a privileged method of ConsoleKit to unlock that
+      session.  The exact details of what happens when the session receives this unlock signal is
+      undefined and session-specific.  However, most sessions will unlock a screensaver in response.
+    </para>
+
+    <para>
+      When the user chooses to log out, or if GDM or the session quit unexpectedly the user session
+      will be unregistered from ConsoleKit.
+    </para>
+
+  </sect1>
+
   <sect1 id="gdmsetupusage">
     <title>Using gdmsetup To Configure GDM</title>
 
