? gdmsetup
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/gdm2/configure.ac,v
retrieving revision 1.69
diff -p -u -r1.69 configure.ac
--- configure.ac	16 Oct 2006 17:50:43 -0000	1.69
+++ configure.ac	26 Oct 2006 18:17:33 -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
@@ -156,7 +157,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)
 
Index: daemon/gdm.c
===================================================================
RCS file: /cvs/gnome/gdm2/daemon/gdm.c,v
retrieving revision 1.263
diff -p -u -r1.263 gdm.c
--- daemon/gdm.c	16 Oct 2006 17:35:46 -0000	1.263
+++ daemon/gdm.c	26 Oct 2006 18:17:33 -0000
@@ -46,6 +46,7 @@
 
 #include <X11/Xauth.h>
 #include <glib/gi18n.h>
+#include <glib-object.h>
 
 /* Needed for signal handling */
 #include <vicious.h>
@@ -1439,6 +1440,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/slave.c
===================================================================
RCS file: /cvs/gnome/gdm2/daemon/slave.c,v
retrieving revision 1.332
diff -p -u -r1.332 slave.c
--- daemon/slave.c	16 Oct 2006 17:35:46 -0000	1.332
+++ daemon/slave.c	26 Oct 2006 18:17:34 -0000
@@ -77,6 +77,11 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
 #include "gdm.h"
 #include "slave.h"
 #include "misc.h"
@@ -1160,6 +1165,303 @@ ask_migrate (const char *migrate_to)
 	return r;
 }
 
+#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;
+}
+
+static 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);
+}
+
+static char *
+open_ck_session (struct passwd *pwent,
+		 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;
+}
+
+static 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);
+}
+
 gboolean
 gdm_slave_check_user_wants_to_log_in (const char *user)
 {
@@ -1234,6 +1536,8 @@ gdm_slave_check_user_wants_to_log_in (co
 			 */
 			gdm_sleep_no_signal (1);
 
+			unlock_ck_session (user, migrate_to);
+
 			gdm_slave_send_string (GDM_SOP_MIGRATE, migrate_to);
 			g_free (migrate_to);
 
@@ -3344,6 +3648,7 @@ session_child_run (struct passwd *pwent,
 		   gboolean failsafe,
 		   const char *home_dir,
 		   gboolean home_dir_ok,
+		   const char *ck_session_cookie,
 		   const char *session,
 		   const char *save_session,
 		   const char *language,
@@ -3434,6 +3739,7 @@ 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);
+	g_setenv ("XDG_SESSION_COOKIE", ck_session_cookie, TRUE);
 	g_setenv ("GDMSESSION", session, TRUE);
 	g_setenv ("DESKTOP_SESSION", session, TRUE);
 	g_setenv ("SHELL", pwent->pw_shell, TRUE);
@@ -3580,7 +3886,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 +4236,7 @@ gdm_slave_session_start (void)
     const char *home_dir = NULL;
     char *save_session = NULL, *session = NULL, *language = NULL, *usrsess, *usrlang;
     char *gnome_session = NULL;
+    char *ck_session_cookie;
     char *tmp;
     gboolean savesess = FALSE, savelang = FALSE;
     gboolean usrcfgok = FALSE, authok = FALSE;
@@ -4242,6 +4549,8 @@ gdm_slave_session_start (void)
      * could reset time or do other crazy things */
     session_start_time = time (NULL);
 
+    ck_session_cookie = open_ck_session (pwent, session);
+
     /* Start user process */
     gdm_sigchld_block_push ();
     gdm_sigterm_block_push ();
@@ -4266,6 +4575,7 @@ gdm_slave_session_start (void)
 			   failsafe,
 			   home_dir,
 			   home_dir_ok,
+			   ck_session_cookie,
 			   session,
 			   save_session,
 			   language,
@@ -4353,6 +4663,9 @@ gdm_slave_session_start (void)
 			    FALSE /* no_shutdown_check */);
 
     gdm_debug ("gdm_slave_session_start: Session ended OK (now all finished)");
+
+    close_ck_session (ck_session_cookie);
+    g_free (ck_session_cookie);
 }
 
 
