mhabrnal / rpms / gdm

Forked from rpms/gdm 6 years ago
Clone
Blob Blame History Raw
From 3ed96cac0c49d0687fc273d11bad51772d8233ed Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 24 Jan 2012 04:16:24 +0100
Subject: [PATCH 01/11] slave: whitespace cleanup

---
 daemon/gdm-slave.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 787ef89..c0705fd 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -541,8 +541,8 @@ gdm_slave_set_windowpath (GdmSlave *slave)
                 return;
         }
         if (XGetWindowProperty (slave->priv->server_display,
-                DefaultRootWindow (slave->priv->server_display), prop, 0, 1, 
-                False, AnyPropertyType, &actualtype, &actualformat, 
+                DefaultRootWindow (slave->priv->server_display), prop, 0, 1,
+                False, AnyPropertyType, &actualtype, &actualformat,
                 &nitems, &bytes_after, &buf)) {
                 g_debug ("no XFree86_VT property\n");
                 return;
-- 
1.7.9


From 1a5f9a0f7a65e796e044ff2f3f793e8268d31623 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 13 Jan 2012 03:53:15 +0100
Subject: [PATCH 02/11] welcome-session: get rid of register-ck-session
 property since it is unused

Nothing was using register-ck-session and it has no effect, hence let's
get rid of this dead code.
---
 daemon/Makefile.am           |    6 ------
 daemon/gdm-chooser-session.c |    1 -
 daemon/gdm-greeter-session.c |    1 -
 daemon/gdm-welcome-session.c |   25 +------------------------
 4 files changed, 1 insertions(+), 32 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 65e82b8..a153c43 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -115,8 +115,6 @@ gdm_simple_slave_SOURCES = 		\
 	simple-slave-main.c 		\
 	gdm-greeter-server.c		\
 	gdm-greeter-server.h		\
-	ck-connector.h			\
-	ck-connector.c			\
 	gdm-welcome-session.c		\
 	gdm-welcome-session.h		\
 	gdm-greeter-session.c		\
@@ -156,8 +154,6 @@ gdm_factory_slave_SOURCES = 		\
 	factory-slave-main.c 		\
 	gdm-greeter-server.c		\
 	gdm-greeter-server.h		\
-	ck-connector.h			\
-	ck-connector.c			\
 	gdm-welcome-session.c		\
 	gdm-welcome-session.h		\
 	gdm-greeter-session.c		\
@@ -232,8 +228,6 @@ gdm_xdmcp_chooser_slave_SOURCES = 		\
 	xdmcp-chooser-slave-main.c 		\
 	gdm-chooser-server.c			\
 	gdm-chooser-server.h			\
-	ck-connector.h				\
-	ck-connector.c				\
 	gdm-session.c				\
 	gdm-session.h				\
 	gdm-session-direct.c			\
diff --git a/daemon/gdm-chooser-session.c b/daemon/gdm-chooser-session.c
index da0f2ab..6aa60a6 100644
--- a/daemon/gdm-chooser-session.c
+++ b/daemon/gdm-chooser-session.c
@@ -81,7 +81,6 @@ gdm_chooser_session_new (const char *display_name,
                                "server-dbus-path", GDM_CHOOSER_SERVER_DBUS_PATH,
                                "server-dbus-interface", GDM_CHOOSER_SERVER_DBUS_INTERFACE,
                                "server-env-var-name", "GDM_CHOOSER_DBUS_ADDRESS",
-                               "register-ck-session", FALSE,
                                "x11-display-name", display_name,
                                "x11-display-device", display_device,
                                "x11-display-hostname", display_hostname,
diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c
index 8032065..44259ab 100644
--- a/daemon/gdm-greeter-session.c
+++ b/daemon/gdm-greeter-session.c
@@ -82,7 +82,6 @@ gdm_greeter_session_new (const char *display_name,
                                "server-dbus-path", GDM_GREETER_SERVER_DBUS_PATH,
                                "server-dbus-interface", GDM_GREETER_SERVER_DBUS_INTERFACE,
                                "server-env-var-name", "GDM_GREETER_DBUS_ADDRESS",
-                               "register-ck-session", TRUE,
                                "x11-display-name", display_name,
                                "x11-display-seat-id", seat_id,
                                "x11-display-device", display_device,
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index 41144a8..8721fe7 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -42,7 +42,6 @@
 #include <dbus/dbus-glib-lowlevel.h>
 
 #include "gdm-common.h"
-#include "ck-connector.h"
 
 #include "gdm-session.h"
 #include "gdm-session-direct.h"
@@ -78,7 +77,6 @@ struct GdmWelcomeSessionPrivate
         char           *server_dbus_path;
         char           *server_dbus_interface;
         char           *server_env_var_name;
-        gboolean        register_ck_session;
 
         char           *server_address;
 };
@@ -98,8 +96,7 @@ enum {
         PROP_COMMAND,
         PROP_SERVER_DBUS_PATH,
         PROP_SERVER_DBUS_INTERFACE,
-        PROP_SERVER_ENV_VAR_NAME,
-        PROP_REGISTER_CK_SESSION,
+        PROP_SERVER_ENV_VAR_NAME
 };
 
 enum {
@@ -1040,13 +1037,6 @@ _gdm_welcome_session_set_server_env_var_name (GdmWelcomeSession *welcome_session
 }
 
 static void
-_gdm_welcome_session_set_register_ck_session (GdmWelcomeSession *welcome_session,
-                                              gboolean           val)
-{
-        welcome_session->priv->register_ck_session = val;
-}
-
-static void
 gdm_welcome_session_set_property (GObject      *object,
                                   guint         prop_id,
                                   const GValue *value,
@@ -1093,9 +1083,6 @@ gdm_welcome_session_set_property (GObject      *object,
         case PROP_SERVER_DBUS_INTERFACE:
                 _gdm_welcome_session_set_server_dbus_interface (self, g_value_get_string (value));
                 break;
-        case PROP_REGISTER_CK_SESSION:
-                _gdm_welcome_session_set_register_ck_session (self, g_value_get_boolean (value));
-                break;
         case PROP_SERVER_ENV_VAR_NAME:
                 _gdm_welcome_session_set_server_env_var_name (self, g_value_get_string (value));
                 break;
@@ -1155,9 +1142,6 @@ gdm_welcome_session_get_property (GObject    *object,
         case PROP_SERVER_DBUS_INTERFACE:
                 g_value_set_string (value, self->priv->server_dbus_interface);
                 break;
-        case PROP_REGISTER_CK_SESSION:
-                g_value_set_boolean (value, self->priv->register_ck_session);
-                break;
         case PROP_SERVER_ENV_VAR_NAME:
                 g_value_set_string (value, self->priv->server_env_var_name);
                 break;
@@ -1279,13 +1263,6 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
                                                               "command",
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-        g_object_class_install_property (object_class,
-                                         PROP_REGISTER_CK_SESSION,
-                                         g_param_spec_boolean ("register-ck-session",
-                                                               NULL,
-                                                               NULL,
-                                                               FALSE,
-                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
         signals [STARTED] =
                 g_signal_new ("started",
                               G_OBJECT_CLASS_TYPE (object_class),
-- 
1.7.9


From 02697e774c2f669d1d4109fc1de975407740409b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 01:18:55 +0200
Subject: [PATCH 03/11] build-sys: add configure option --with-systemd

---
 configure.ac |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index 30397c5..dec31a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -272,6 +272,11 @@ AC_ARG_WITH(console-kit,
                            [Add ConsoleKit support @<:@default=auto@:>@]),,
             with_console_kit=auto)
 
+AC_ARG_WITH(systemd,
+            AS_HELP_STRING([--with-systemd],
+                           [Add systemd support @<:@default=auto@:>@]),,
+            with_systemd=auto)
+
 AC_ARG_WITH(at-spi-registryd-directory,
             AS_HELP_STRING([--with-at-spi-registryd-directory],
 	                   [Specify the directory of at-spi-registryd @<:@default=libexecdir@:>@])],,
@@ -927,6 +932,25 @@ AM_CONDITIONAL(WITH_CONSOLE_KIT, test x$use_console_kit = xyes)
 AC_SUBST(WITH_CONSOLE_KIT)
 
 dnl ---------------------------------------------------------------------------
+dnl - Check for systemd support
+dnl ---------------------------------------------------------------------------
+
+use_systemd=no
+if test "x$with_systemd" != "xno" ; then
+        PKG_CHECK_MODULES(SYSTEMD,
+                libsystemd-daemon
+                libsystemd-login
+        )
+        AC_SUBST(SYSTEMD_CFLAGS)
+        AC_SUBST(SYSTEMD_LIBS)
+
+	use_systemd=yes
+	AC_DEFINE(WITH_SYSTEMD, 1, [Define to enable systemd support])
+fi
+AM_CONDITIONAL(WITH_SYSTEMD, test x$use_systemd = xyes)
+AC_SUBST(WITH_SYSTEMD)
+
+dnl ---------------------------------------------------------------------------
 dnl - Check for D-Bus
 dnl ---------------------------------------------------------------------------
 
@@ -1511,6 +1535,7 @@ echo \
         XDMCP support:            ${XDMCP_SUPPORT}
         SELinux support:          ${with_selinux}
         ConsoleKit support:       ${use_console_kit}
+        systemd support:          ${use_systemd}
         UPower support:           ${have_upower}
         Build with RBAC:          ${msg_rbac_shutdown}
 "
-- 
1.7.9


From a58b27ff573109f0d9a8971fbc80e797d6cc2733 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 24 Jan 2012 04:15:26 +0100
Subject: [PATCH 04/11] slave: add native systemd implementations of
 locking/session activation

---
 daemon/Makefile.am |    5 +
 daemon/gdm-slave.c |  251 +++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 242 insertions(+), 14 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index a153c43..43d416e 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -24,6 +24,7 @@ AM_CPPFLAGS = \
 	$(XLIB_CFLAGS)					\
 	$(WARN_CFLAGS)					\
 	$(DEBUG_CFLAGS)					\
+	$(SYSTEMD_CFLAGS)				\
 	-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\"	\
 	$(NULL)
 
@@ -148,6 +149,7 @@ gdm_simple_slave_LDADD = 			\
 	$(DAEMON_LIBS)				\
 	$(EXTRA_DAEMON_LIBS)                    \
 	$(LIBXKLAVIER_LIBS)			\
+	$(SYSTEMD_LIBS) 			\
 	$(NULL)
 
 gdm_factory_slave_SOURCES = 		\
@@ -188,6 +190,7 @@ gdm_factory_slave_LDADD = 			\
 	$(top_builddir)/common/libgdmcommon.la	\
 	$(XLIB_LIBS)				\
 	$(DAEMON_LIBS)				\
+	$(SYSTEMD_LIBS) 			\
 	$(NULL)
 
 gdm_product_slave_SOURCES = 		\
@@ -222,6 +225,7 @@ gdm_product_slave_LDADD = 			\
 	$(DAEMON_LIBS)				\
 	$(EXTRA_DAEMON_LIBS)                    \
 	$(LIBXKLAVIER_LIBS)			\
+	$(SYSTEMD_LIBS) 			\
 	$(NULL)
 
 gdm_xdmcp_chooser_slave_SOURCES = 		\
@@ -254,6 +258,7 @@ gdm_xdmcp_chooser_slave_LDADD = 		\
 	$(DAEMON_LIBS)				\
 	$(EXTRA_DAEMON_LIBS)                    \
 	$(LIBXKLAVIER_LIBS)			\
+	$(SYSTEMD_LIBS) 			\
 	$(top_builddir)/common/libgdmcommon.la	\
 	$(NULL)
 
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index c0705fd..371b9bd 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -51,6 +51,11 @@
 #include <libxklavier/xklavier.h>
 #endif
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-login.h>
+#include <systemd/sd-daemon.h>
+#endif
+
 #include "gdm-common.h"
 #include "gdm-xerrors.h"
 
@@ -1198,6 +1203,8 @@ _get_uid_and_gid_for_user (const char *username,
         return TRUE;
 }
 
+#ifdef WITH_CONSOLE_KIT
+
 static gboolean
 x11_session_is_on_seat (GdmSlave        *slave,
                         const char      *session_id,
@@ -1295,9 +1302,63 @@ x11_session_is_on_seat (GdmSlave        *slave,
         return ret;
 }
 
-char *
-gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
-                                           const char *username)
+#endif
+
+#ifdef WITH_SYSTEMD
+static char*
+gdm_slave_get_primary_session_id_for_user_from_systemd (GdmSlave   *slave,
+                                                        const char *username)
+{
+        int     res, i;
+        char  **sessions;
+        uid_t   uid;
+        char   *primary_ssid;
+
+        primary_ssid = NULL;
+
+        res = sd_seat_can_multi_session (slave->priv->display_seat_id);
+        if (res < 0) {
+                g_warning ("GdmSlave: Failed to determine whether seat is multi-session capable: %s", strerror (-res));
+                return NULL;
+        } else if (res == 0) {
+                g_debug ("GdmSlave: seat is unable to activate sessions");
+                return NULL;
+        }
+
+        if (! _get_uid_and_gid_for_user (username, &uid, NULL)) {
+                g_debug ("GdmSlave: unable to determine uid for user: %s", username);
+                return NULL;
+        }
+
+        res = sd_seat_get_sessions (slave->priv->display_seat_id, &sessions, NULL, NULL);
+        if (res < 0) {
+                g_warning ("GdmSlave: Failed to get sessions on seat: %s", strerror (-res));
+                return NULL;
+        }
+
+        for (i = 0; sessions[i] != NULL; i++) {
+
+                if (primary_ssid == NULL) {
+                        uid_t other;
+
+                        res = sd_session_get_uid (sessions[i], &other);
+                        if (res > 0 && other == uid) {
+                                primary_ssid = g_strdup (sessions[i]);
+                        }
+                }
+
+                free (sessions[i]);
+        }
+
+        free (sessions);
+        return primary_ssid;
+}
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+static char *
+gdm_slave_get_primary_session_id_for_user_from_ck (GdmSlave   *slave,
+                                                   const char *username)
 {
         gboolean    res;
         gboolean    can_activate_sessions;
@@ -1309,11 +1370,6 @@ gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
         int         i;
         uid_t       uid;
 
-        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
-                g_debug ("GdmSlave: display seat ID is not set; can't switch sessions");
-                return NULL;
-        }
-
         manager_proxy = NULL;
         primary_ssid = NULL;
         sessions = NULL;
@@ -1396,11 +1452,91 @@ gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
 
         return primary_ssid;
 }
+#endif
+
+char *
+gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
+                                           const char *username)
+{
+
+        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
+                g_debug ("GdmSlave: display seat ID is not set; can't switch sessions");
+                return NULL;
+        }
 
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return gdm_slave_get_primary_session_id_for_user_from_systemd (slave, username);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return gdm_slave_get_primary_session_id_for_user_from_ck (slave, username);
+#else
+        return NULL;
+#endif
+}
+
+#ifdef WITH_SYSTEMD
 static gboolean
-activate_session_id (GdmSlave   *slave,
-                     const char *seat_id,
-                     const char *session_id)
+activate_session_id_for_systemd (GdmSlave   *slave,
+                                 const char *seat_id,
+                                 const char *session_id)
+{
+        DBusError    local_error;
+        DBusMessage *message;
+        DBusMessage *reply;
+        gboolean     ret;
+
+        ret = FALSE;
+        reply = NULL;
+
+        dbus_error_init (&local_error);
+
+        message = dbus_message_new_method_call ("org.freedesktop.login1",
+                                                "/org/freedesktop/login1",
+                                                "org.freedesktop.login1.Manager",
+                                                "ActivateSessionOnSeat");
+        if (message == NULL) {
+                goto out;
+        }
+
+        if (! dbus_message_append_args (message,
+                                        DBUS_TYPE_STRING, &session_id,
+                                        DBUS_TYPE_STRING, &seat_id,
+                                        DBUS_TYPE_INVALID)) {
+                goto out;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
+                                                           message,
+                                                           -1,
+                                                           &local_error);
+        if (dbus_error_is_set (&local_error)) {
+                g_warning ("GdmSlave: Unable to activate session: %s", local_error.message);
+                dbus_error_free (&local_error);
+                goto out;
+        }
+
+        ret = TRUE;
+
+ out:
+        if (message != NULL) {
+                dbus_message_unref (message);
+        }
+        if (reply != NULL) {
+                dbus_message_unref (reply);
+        }
+
+        return ret;
+}
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+static gboolean
+activate_session_id_for_ck (GdmSlave   *slave,
+                            const char *seat_id,
+                            const char *session_id)
 {
         DBusError    local_error;
         DBusMessage *message;
@@ -1448,16 +1584,82 @@ activate_session_id (GdmSlave   *slave,
 
         return ret;
 }
+#endif
+
+static gboolean
+activate_session_id (GdmSlave   *slave,
+                     const char *seat_id,
+                     const char *session_id)
+{
+
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return activate_session_id_for_systemd (slave, seat_id, session_id);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return activate_session_id_for_ck (slave, seat_id, session_id);
+#else
+        return FALSE;
+#endif
+}
 
+#ifdef WITH_SYSTEMD
 static gboolean
-session_unlock (GdmSlave   *slave,
-                const char *ssid)
+session_unlock_for_systemd (GdmSlave   *slave,
+                            const char *ssid)
+{
+        DBusError       error;
+        DBusMessage    *message;
+        DBusMessage    *reply;
+
+        dbus_error_init (&error);
+
+        message = dbus_message_new_method_call ("org.freedesktop.login",
+                                                "/org/freedesktop/login1",
+                                                "org.freedesktop.login1.Manager",
+                                                "UnlockSession");
+
+        if (message == NULL) {
+                g_debug ("GdmSlave: couldn't allocate the D-Bus message");
+                return FALSE;
+        }
+
+        if (! dbus_message_append_args (message,
+                                        DBUS_TYPE_STRING, &ssid,
+                                        DBUS_TYPE_INVALID)) {
+                g_debug ("GdmSlave: couldn't attach the D-Bus message data");
+                return FALSE;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
+                                                           message,
+                                                           -1, &error);
+        dbus_message_unref(message);
+        if (reply != NULL) {
+                dbus_message_unref(reply);
+        }
+
+        if (dbus_error_is_set (&error)) {
+                g_warning ("GdmSlave: Unable to unlock session: %s", error.message);
+                dbus_error_free (&error);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+static gboolean
+session_unlock_for_ck (GdmSlave   *slave,
+                       const char *ssid)
 {
         DBusError       error;
         DBusMessage    *message;
         DBusMessage    *reply;
 
-        g_debug ("ConsoleKit: Unlocking session %s", ssid);
         message = dbus_message_new_method_call (CK_NAME,
                                                 ssid,
                                                 CK_SESSION_INTERFACE,
@@ -1485,6 +1687,27 @@ session_unlock (GdmSlave   *slave,
 
         return TRUE;
 }
+#endif
+
+static gboolean
+session_unlock (GdmSlave   *slave,
+                const char *ssid)
+{
+
+        g_debug ("ConsoleKit: Unlocking session %s", ssid);
+
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return session_unlock_for_systemd (slave, ssid);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return session_unlock_for_ck (slave, ssid);
+#else
+        return TRUE;
+#endif
+}
 
 gboolean
 gdm_slave_switch_to_user_session (GdmSlave   *slave,
-- 
1.7.9


From c77c03e6ca67ea670de89babbbfd9648b2fec9bd Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 01:27:22 +0200
Subject: [PATCH 05/11] build-sys: make CK support optional

---
 daemon/Makefile.am |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 43d416e..b228fea 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -264,8 +264,6 @@ gdm_xdmcp_chooser_slave_LDADD = 		\
 
 gdm_session_worker_SOURCES = 			\
 	session-worker-main.c 			\
-	ck-connector.h				\
-	ck-connector.c				\
 	gdm-session-settings.h			\
 	gdm-session-settings.c			\
 	gdm-session-auditor.h			\
@@ -274,6 +272,12 @@ gdm_session_worker_SOURCES = 			\
 	gdm-session-worker.c			\
 	$(NULL)
 
+if WITH_CONSOLE_KIT
+gdm_session_worker_SOURCES += 			\
+	ck-connector.h				\
+	ck-connector.c
+endif
+
 if HAVE_LIBAUDIT
 gdm_session_worker_SOURCES += gdm-session-linux-auditor.h       \
 	                      gdm-session-linux-auditor.c
-- 
1.7.9


From 54abef19f0b338d7c57c4629f6ca2cf441bcb553 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 01:30:09 +0200
Subject: [PATCH 06/11] slave: pass seat id from product/simple slave to
 worker, via the direct session
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass seat id from product and simple slave to the direct sessions
created by it (along with the other display meta data we pass already).

Pass seat id from session to worker (via D-Bus) along with the other
display meta data.

We need the seat information for the PAM conversation (later patch)
hence we need to pass it from the slaves down to the workers.

(Note that the seat ID has always been passed from the display to the
slave, we just need to pass it on the worker now, so that the chain is
complete: display → slave → session → worker)
---
 daemon/gdm-product-slave.c   |    3 ++
 daemon/gdm-session-direct.c  |   60 ++++++++++++++++++++++++++++++++++++++++++
 daemon/gdm-session-direct.h  |    2 +
 daemon/gdm-session-worker.c  |   12 +++++++-
 daemon/gdm-simple-slave.c    |    3 ++
 daemon/gdm-welcome-session.c |    1 +
 daemon/test-session.c        |    1 +
 7 files changed, 81 insertions(+), 1 deletions(-)

diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
index d56a74b..629c6e7 100644
--- a/daemon/gdm-product-slave.c
+++ b/daemon/gdm-product-slave.c
@@ -998,6 +998,7 @@ create_new_session (GdmProductSlave *slave)
         char          *display_name;
         char          *display_hostname;
         char          *display_device;
+        char          *display_seat_id;
         char          *display_x11_authority_file;
 
         g_debug ("GdmProductSlave: Creating new session");
@@ -1008,6 +1009,7 @@ create_new_session (GdmProductSlave *slave)
                       "display-hostname", &display_hostname,
                       "display-is-local", &display_is_local,
                       "display-x11-authority-file", &display_x11_authority_file,
+                      "display-seat-id", &display_seat_id,
                       NULL);
 
         /* FIXME: we don't yet have a display device! */
@@ -1017,6 +1019,7 @@ create_new_session (GdmProductSlave *slave)
                                                        display_name,
                                                        display_hostname,
                                                        display_device,
+                                                       display_seat_id,
                                                        display_x11_authority_file,
                                                        display_is_local);
         g_free (display_id);
diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c
index bb2bff8..9f750f2 100644
--- a/daemon/gdm-session-direct.c
+++ b/daemon/gdm-session-direct.c
@@ -103,6 +103,7 @@ struct _GdmSessionDirectPrivate
         char                *display_name;
         char                *display_hostname;
         char                *display_device;
+        char                *display_seat_id;
         char                *display_x11_authority_file;
         gboolean             display_is_local;
 
@@ -121,6 +122,7 @@ enum {
         PROP_DISPLAY_HOSTNAME,
         PROP_DISPLAY_IS_LOCAL,
         PROP_DISPLAY_DEVICE,
+        PROP_DISPLAY_SEAT_ID,
         PROP_DISPLAY_X11_AUTHORITY_FILE,
         PROP_USER_X11_AUTHORITY_FILE,
 };
@@ -1389,6 +1391,7 @@ do_introspect (DBusConnection *connection,
                                "      <arg name=\"service_name\" type=\"s\"/>\n"
                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
                                "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
                                "      <arg name=\"hostname\" type=\"s\"/>\n"
                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                                "    </signal>\n"
@@ -1396,6 +1399,7 @@ do_introspect (DBusConnection *connection,
                                "      <arg name=\"service_name\" type=\"s\"/>\n"
                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
                                "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
                                "      <arg name=\"hostname\" type=\"s\"/>\n"
                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                                "      <arg name=\"username\" type=\"s\"/>\n"
@@ -1404,6 +1408,7 @@ do_introspect (DBusConnection *connection,
                                "      <arg name=\"service_name\" type=\"s\"/>\n"
                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
                                "      <arg name=\"display_device\" type=\"s\"/>\n"
+                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
                                "      <arg name=\"hostname\" type=\"s\"/>\n"
                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                                "      <arg name=\"log_file\" type=\"s\"/>\n"
@@ -1975,6 +1980,7 @@ send_setup (GdmSessionDirect *session,
         DBusMessageIter iter;
         const char     *display_name;
         const char     *display_device;
+        const char     *display_seat_id;
         const char     *display_hostname;
         const char     *display_x11_authority_file;
         GdmSessionConversation *conversation;
@@ -1996,6 +2002,11 @@ send_setup (GdmSessionDirect *session,
         } else {
                 display_device = "";
         }
+        if (session->priv->display_seat_id != NULL) {
+                display_seat_id = session->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
         if (session->priv->display_x11_authority_file != NULL) {
                 display_x11_authority_file = session->priv->display_x11_authority_file;
         } else {
@@ -2012,6 +2023,7 @@ send_setup (GdmSessionDirect *session,
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
 
@@ -2031,6 +2043,7 @@ send_setup_for_user (GdmSessionDirect *session,
         DBusMessageIter iter;
         const char     *display_name;
         const char     *display_device;
+        const char     *display_seat_id;
         const char     *display_hostname;
         const char     *display_x11_authority_file;
         const char     *selected_user;
@@ -2053,6 +2066,11 @@ send_setup_for_user (GdmSessionDirect *session,
         } else {
                 display_device = "";
         }
+        if (session->priv->display_seat_id != NULL) {
+                display_seat_id = session->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
         if (session->priv->display_x11_authority_file != NULL) {
                 display_x11_authority_file = session->priv->display_x11_authority_file;
         } else {
@@ -2074,6 +2092,7 @@ send_setup_for_user (GdmSessionDirect *session,
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user);
@@ -2095,6 +2114,7 @@ send_setup_for_program (GdmSessionDirect *session,
         DBusMessageIter iter;
         const char     *display_name;
         const char     *display_device;
+        const char     *display_seat_id;
         const char     *display_hostname;
         const char     *display_x11_authority_file;
         GdmSessionConversation *conversation;
@@ -2116,6 +2136,11 @@ send_setup_for_program (GdmSessionDirect *session,
         } else {
                 display_device = "";
         }
+        if (session->priv->display_seat_id != NULL) {
+                display_seat_id = session->priv->display_seat_id;
+        } else {
+                display_seat_id = "";
+        }
         if (session->priv->display_x11_authority_file != NULL) {
                 display_x11_authority_file = session->priv->display_x11_authority_file;
         } else {
@@ -2132,6 +2157,7 @@ send_setup_for_program (GdmSessionDirect *session,
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &log_file);
@@ -2587,6 +2613,14 @@ gdm_session_direct_get_display_device (GdmSessionDirect *session)
         return g_strdup (session->priv->display_device);
 }
 
+char *
+gdm_session_direct_get_display_seat_id (GdmSessionDirect *session)
+{
+        g_return_val_if_fail (session != NULL, NULL);
+
+        return g_strdup (session->priv->display_seat_id);
+}
+
 gboolean
 gdm_session_direct_bypasses_xsession (GdmSessionDirect *session_direct)
 {
@@ -2754,6 +2788,14 @@ _gdm_session_direct_set_display_device (GdmSessionDirect *session,
 }
 
 static void
+_gdm_session_direct_set_display_seat_id (GdmSessionDirect *session,
+                                         const char       *name)
+{
+        g_free (session->priv->display_seat_id);
+        session->priv->display_seat_id = g_strdup (name);
+}
+
+static void
 _gdm_session_direct_set_user_x11_authority_file (GdmSessionDirect *session,
                                                  const char       *name)
 {
@@ -2799,6 +2841,9 @@ gdm_session_direct_set_property (GObject      *object,
         case PROP_DISPLAY_DEVICE:
                 _gdm_session_direct_set_display_device (self, g_value_get_string (value));
                 break;
+        case PROP_DISPLAY_SEAT_ID:
+                _gdm_session_direct_set_display_seat_id (self, g_value_get_string (value));
+                break;
         case PROP_USER_X11_AUTHORITY_FILE:
                 _gdm_session_direct_set_user_x11_authority_file (self, g_value_get_string (value));
                 break;
@@ -2837,6 +2882,9 @@ gdm_session_direct_get_property (GObject    *object,
         case PROP_DISPLAY_DEVICE:
                 g_value_set_string (value, self->priv->display_device);
                 break;
+        case PROP_DISPLAY_SEAT_ID:
+                g_value_set_string (value, self->priv->display_seat_id);
+                break;
         case PROP_USER_X11_AUTHORITY_FILE:
                 g_value_set_string (value, self->priv->user_x11_authority_file);
                 break;
@@ -2875,6 +2923,9 @@ gdm_session_direct_dispose (GObject *object)
         g_free (session->priv->display_device);
         session->priv->display_device = NULL;
 
+        g_free (session->priv->display_seat_id);
+        session->priv->display_seat_id = NULL;
+
         g_free (session->priv->display_x11_authority_file);
         session->priv->display_x11_authority_file = NULL;
 
@@ -3063,6 +3114,13 @@ gdm_session_direct_class_init (GdmSessionDirectClass *session_class)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_SEAT_ID,
+                                         g_param_spec_string ("display-seat-id",
+                                                              "display seat id",
+                                                              "display seat id",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
         dbus_g_object_type_install_info (GDM_TYPE_SESSION_DIRECT, &dbus_glib_gdm_session_direct_object_info);
 }
@@ -3072,6 +3130,7 @@ gdm_session_direct_new (const char *display_id,
                         const char *display_name,
                         const char *display_hostname,
                         const char *display_device,
+                        const char *display_seat_id,
                         const char *display_x11_authority_file,
                         gboolean    display_is_local)
 {
@@ -3082,6 +3141,7 @@ gdm_session_direct_new (const char *display_id,
                                 "display-name", display_name,
                                 "display-hostname", display_hostname,
                                 "display-device", display_device,
+                                "display-seat-id", display_seat_id,
                                 "display-x11-authority-file", display_x11_authority_file,
                                 "display-is-local", display_is_local,
                                 NULL);
diff --git a/daemon/gdm-session-direct.h b/daemon/gdm-session-direct.h
index 8023bf9..e35fa35 100644
--- a/daemon/gdm-session-direct.h
+++ b/daemon/gdm-session-direct.h
@@ -52,11 +52,13 @@ GdmSessionDirect * gdm_session_direct_new                      (const char *disp
                                                                 const char *display_name,
                                                                 const char *display_hostname,
                                                                 const char *display_device,
+                                                                const char *display_seat_id,
                                                                 const char *display_x11_authority_file,
                                                                 gboolean    display_is_local) G_GNUC_MALLOC;
 
 char             * gdm_session_direct_get_username             (GdmSessionDirect     *session_direct);
 char             * gdm_session_direct_get_display_device       (GdmSessionDirect     *session_direct);
+char             * gdm_session_direct_get_display_seat_id      (GdmSessionDirect     *session_direct);
 gboolean           gdm_session_direct_bypasses_xsession        (GdmSessionDirect     *session_direct);
 
 /* Exported methods */
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index c402e6c..1fe0aaf 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -118,6 +118,7 @@ struct GdmSessionWorkerPrivate
         char             *x11_display_name;
         char             *x11_authority_file;
         char             *display_device;
+        char             *display_seat_id;
         char             *hostname;
         char             *username;
         char             *log_file;
@@ -2494,6 +2495,7 @@ on_setup (GdmSessionWorker *worker,
         const char *x11_display_name;
         const char *x11_authority_file;
         const char *console;
+        const char *seat_id;
         const char *hostname;
         dbus_bool_t res;
 
@@ -2508,6 +2510,7 @@ on_setup (GdmSessionWorker *worker,
                                      DBUS_TYPE_STRING, &service,
                                      DBUS_TYPE_STRING, &x11_display_name,
                                      DBUS_TYPE_STRING, &console,
+                                     DBUS_TYPE_STRING, &seat_id,
                                      DBUS_TYPE_STRING, &hostname,
                                      DBUS_TYPE_STRING, &x11_authority_file,
                                      DBUS_TYPE_INVALID);
@@ -2516,6 +2519,7 @@ on_setup (GdmSessionWorker *worker,
                 worker->priv->x11_display_name = g_strdup (x11_display_name);
                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
                 worker->priv->display_device = g_strdup (console);
+                worker->priv->display_seat_id = g_strdup (seat_id);
                 worker->priv->hostname = g_strdup (hostname);
                 worker->priv->username = NULL;
 
@@ -2536,6 +2540,7 @@ on_setup_for_user (GdmSessionWorker *worker,
         const char *x11_display_name;
         const char *x11_authority_file;
         const char *console;
+        const char *seat_id;
         const char *hostname;
         const char *username;
         dbus_bool_t res;
@@ -2551,6 +2556,7 @@ on_setup_for_user (GdmSessionWorker *worker,
                                      DBUS_TYPE_STRING, &service,
                                      DBUS_TYPE_STRING, &x11_display_name,
                                      DBUS_TYPE_STRING, &console,
+                                     DBUS_TYPE_STRING, &seat_id,
                                      DBUS_TYPE_STRING, &hostname,
                                      DBUS_TYPE_STRING, &x11_authority_file,
                                      DBUS_TYPE_STRING, &username,
@@ -2560,6 +2566,7 @@ on_setup_for_user (GdmSessionWorker *worker,
                 worker->priv->x11_display_name = g_strdup (x11_display_name);
                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
                 worker->priv->display_device = g_strdup (console);
+                worker->priv->display_seat_id = g_strdup (seat_id);
                 worker->priv->hostname = g_strdup (hostname);
                 worker->priv->username = g_strdup (username);
 
@@ -2598,6 +2605,7 @@ on_setup_for_program (GdmSessionWorker *worker,
         char *service;
         char *x11_display_name;
         char *console;
+        char *seat_id;
         char *hostname;
         char *x11_authority_file;
         char *log_file;
@@ -2614,6 +2622,7 @@ on_setup_for_program (GdmSessionWorker *worker,
                                      DBUS_TYPE_STRING, &service,
                                      DBUS_TYPE_STRING, &x11_display_name,
                                      DBUS_TYPE_STRING, &console,
+                                     DBUS_TYPE_STRING, &seat_id,
                                      DBUS_TYPE_STRING, &hostname,
                                      DBUS_TYPE_STRING, &x11_authority_file,
                                      DBUS_TYPE_STRING, &log_file,
@@ -2627,6 +2636,7 @@ on_setup_for_program (GdmSessionWorker *worker,
                 worker->priv->x11_display_name = g_strdup (x11_display_name);
                 worker->priv->hostname = g_strdup (hostname);
                 worker->priv->display_device = g_strdup (console);
+                worker->priv->display_seat_id = g_strdup (seat_id);
                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
                 worker->priv->log_file = g_strdup (log_file);
                 worker->priv->is_program_session = TRUE;
@@ -2945,6 +2955,7 @@ gdm_session_worker_finalize (GObject *object)
         g_free (worker->priv->x11_display_name);
         g_free (worker->priv->x11_authority_file);
         g_free (worker->priv->display_device);
+        g_free (worker->priv->display_seat_id);
         g_free (worker->priv->hostname);
         g_free (worker->priv->username);
         g_free (worker->priv->server_address);
@@ -2964,4 +2975,3 @@ gdm_session_worker_new (const char *address)
 
         return GDM_SESSION_WORKER (object);
 }
-
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index b9165fd..873b7f9 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -750,6 +750,7 @@ create_new_session (GdmSimpleSlave *slave)
         char          *display_name;
         char          *display_hostname;
         char          *display_device;
+        char          *display_seat_id;
         char          *display_x11_authority_file;
 
         g_debug ("GdmSimpleSlave: Creating new session");
@@ -760,6 +761,7 @@ create_new_session (GdmSimpleSlave *slave)
                       "display-hostname", &display_hostname,
                       "display-is-local", &display_is_local,
                       "display-x11-authority-file", &display_x11_authority_file,
+                      "display-seat-id", &display_seat_id,
                       NULL);
 
         display_device = NULL;
@@ -771,6 +773,7 @@ create_new_session (GdmSimpleSlave *slave)
                                                        display_name,
                                                        display_hostname,
                                                        display_device,
+                                                       display_seat_id,
                                                        display_x11_authority_file,
                                                        display_is_local);
         g_free (display_id);
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index 8721fe7..26af552 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -849,6 +849,7 @@ gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
                                                                               welcome_session->priv->x11_display_name,
                                                                               welcome_session->priv->x11_display_hostname,
                                                                               welcome_session->priv->x11_display_device,
+                                                                              welcome_session->priv->x11_display_seat_id,
                                                                               welcome_session->priv->x11_authority_file,
                                                                               welcome_session->priv->x11_display_is_local));
 
diff --git a/daemon/test-session.c b/daemon/test-session.c
index fe78230..f75d5ed 100644
--- a/daemon/test-session.c
+++ b/daemon/test-session.c
@@ -268,6 +268,7 @@ main (int   argc,
                                                   ":0",
                                                   g_get_host_name (),
                                                   ttyname (STDIN_FILENO),
+                                                  "",
                                                   getenv("XAUTHORITY"),
                                                   TRUE);
                 g_debug ("GdmSessionDirect object created successfully");
-- 
1.7.9


From 69a8b09c993669e324c785be463136313be2cdb4 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 01:31:16 +0200
Subject: [PATCH 07/11] pam: pass XDG_SEAT env var into PAM to inform PAM
 modules about seat id

This optionally replaces the current CK session registration logic with
support for passing seat information to pam_systemd (and hence rely on
pam_systemd's session registration).

With this patch applied we can register sessions in systemd and in CK
with the same binary.
---
 daemon/Makefile.am          |    1 +
 daemon/gdm-session-worker.c |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index b228fea..8f8eedf 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -296,6 +296,7 @@ gdm_session_worker_LDFLAGS =			\
 gdm_session_worker_LDADD = 			\
 	$(top_builddir)/common/libgdmcommon.la	\
 	$(DAEMON_LIBS)				\
+	$(SYSTEMD_LIBS) 			\
 	$(NULL)
 
 sbin_PROGRAMS = 			\
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 1fe0aaf..acf820c 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -46,7 +46,13 @@
 
 #include <X11/Xauth.h>
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
+#ifdef WITH_CONSOLE_KIT
 #include "ck-connector.h"
+#endif
 
 #include "gdm-common.h"
 #include "gdm-log.h"
@@ -107,7 +113,9 @@ struct GdmSessionWorkerPrivate
 
         int               exit_code;
 
+#ifdef WITH_CONSOLE_KIT
         CkConnector      *ckc;
+#endif
         pam_handle_t     *pam_handle;
 
         GPid              child_pid;
@@ -151,8 +159,13 @@ static void     gdm_session_worker_class_init   (GdmSessionWorkerClass *klass);
 static void     gdm_session_worker_init         (GdmSessionWorker      *session_worker);
 static void     gdm_session_worker_finalize     (GObject               *object);
 
+static void     gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
+                                                             const char       *key,
+                                                             const char       *value);
+
 static void     queue_state_change              (GdmSessionWorker      *worker);
 
+
 typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int,
                                                     const struct pam_message **,
                                                     struct pam_response **,
@@ -171,6 +184,7 @@ gdm_session_worker_error_quark (void)
         return error_quark;
 }
 
+#ifdef WITH_CONSOLE_KIT
 static gboolean
 open_ck_session (GdmSessionWorker  *worker)
 {
@@ -257,6 +271,7 @@ open_ck_session (GdmSessionWorker  *worker)
  out:
         return ret;
 }
+#endif
 
 /* adapted from glib script_execute */
 static void
@@ -1057,6 +1072,7 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                                    const char       *x11_display_name,
                                    const char       *x11_authority_file,
                                    const char       *display_device,
+                                   const char       *seat_id,
                                    GError          **error)
 {
         struct pam_conv        pam_conversation;
@@ -1138,6 +1154,13 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                 goto out;
         }
 
+#ifdef WITH_SYSTEMD
+        /* set seat ID */
+        if (seat_id != NULL && seat_id[0] != '\0' && sd_booted() > 0) {
+                gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
+        }
+#endif
+
 #ifdef PAM_XDISPLAY
         /* set XDISPLAY */
         error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
@@ -1571,6 +1594,13 @@ register_ck_session (GdmSessionWorker *worker)
         const char *session_cookie;
         gboolean    res;
 
+#ifdef WITH_SYSTEMD
+        if (sd_booted() > 0) {
+                return;
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
         session_cookie = NULL;
         res = open_ck_session (worker);
         if (res) {
@@ -1581,6 +1611,7 @@ register_ck_session (GdmSessionWorker *worker)
                                                              "XDG_SESSION_COOKIE",
                                                              session_cookie);
         }
+#endif
 }
 
 static void
@@ -1611,11 +1642,13 @@ session_worker_child_watch (GPid              pid,
                                       num);
         }
 
+#ifdef WITH_CONSOLE_KIT
         if (worker->priv->ckc != NULL) {
                 ck_connector_close_session (worker->priv->ckc, NULL);
                 ck_connector_unref (worker->priv->ckc);
                 worker->priv->ckc = NULL;
         }
+#endif
 
         gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
 
@@ -2140,6 +2173,7 @@ do_setup (GdmSessionWorker *worker)
                                                  worker->priv->x11_display_name,
                                                  worker->priv->x11_authority_file,
                                                  worker->priv->display_device,
+                                                 worker->priv->display_seat_id,
                                                  &error);
         if (! res) {
                 if (g_error_matches (error,
-- 
1.7.9


From 6e9fb3fb4df7d05c803cc01fe638eb9cf88c4beb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 01:32:54 +0200
Subject: [PATCH 08/11] local-display-factory: subscribe to new seats being
 created and removed

logind will notify us when ever a new seat becomes available in the
system, or an existing seat is removed. We simply create a new display
for each seat showing up and remove a display when a seat goes away.
---
 daemon/Makefile.am                 |    1 +
 daemon/gdm-local-display-factory.c |  239 +++++++++++++++++++++++++++++++++---
 2 files changed, 224 insertions(+), 16 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 8f8eedf..ffbaf9b 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -363,6 +363,7 @@ gdm_binary_LDADD = \
 	$(DAEMON_LIBS)				\
 	$(XDMCP_LIBS)                           \
 	$(LIBWRAP_LIBS)                         \
+	$(SYSTEMD_LIBS)				\
 	$(NULL)
 
 if WITH_CONSOLE_KIT
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 349c7b2..988b2ff 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -27,6 +27,13 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include "gdm-display-factory.h"
 #include "gdm-local-display-factory.h"
 #include "gdm-local-display-factory-glue.h"
@@ -64,7 +71,8 @@ static void     gdm_local_display_factory_class_init    (GdmLocalDisplayFactoryC
 static void     gdm_local_display_factory_init          (GdmLocalDisplayFactory      *factory);
 static void     gdm_local_display_factory_finalize      (GObject                     *object);
 
-static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory);
+static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory,
+                                                         const char                  *seat_id);
 
 static gpointer local_display_factory_object = NULL;
 
@@ -282,6 +290,7 @@ on_static_display_status_changed (GdmDisplay             *display,
         int              status;
         GdmDisplayStore *store;
         int              num;
+        char            *seat_id = NULL;
 
         num = -1;
         gdm_display_get_x11_display_number (display, &num, NULL);
@@ -289,6 +298,8 @@ on_static_display_status_changed (GdmDisplay             *display,
 
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
+        g_object_get (display, "seat-id", &seat_id, NULL);
+
         status = gdm_display_get_status (display);
 
         g_debug ("GdmLocalDisplayFactory: static display status changed: %d", status);
@@ -300,7 +311,7 @@ on_static_display_status_changed (GdmDisplay             *display,
                 gdm_display_store_remove (store, display);
                 /* reset num failures */
                 factory->priv->num_failures = 0;
-                create_display (factory);
+                create_display (factory, seat_id);
                 break;
         case GDM_DISPLAY_FAILED:
                 /* leave the display number in factory->priv->displays
@@ -313,7 +324,7 @@ on_static_display_status_changed (GdmDisplay             *display,
                         /* FIXME: should monitor hardware changes to
                            try again when seats change */
                 } else {
-                        create_display (factory);
+                        create_display (factory, seat_id);
                 }
                 break;
         case GDM_DISPLAY_UNMANAGED:
@@ -326,13 +337,44 @@ on_static_display_status_changed (GdmDisplay             *display,
                 g_assert_not_reached ();
                 break;
         }
+
+        g_free (seat_id);
+}
+
+static gboolean
+lookup_by_seat_id (const char *id,
+                   GdmDisplay *display,
+                   gpointer    user_data)
+{
+        const char *looking_for = user_data;
+        char *current;
+        gboolean res;
+
+        g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
+
+        res = g_strcmp0 (current, looking_for) == 0;
+
+        g_free(current);
+
+        return res;
 }
 
 static GdmDisplay *
-create_display (GdmLocalDisplayFactory *factory)
+create_display (GdmLocalDisplayFactory *factory,
+                const char             *seat_id)
 {
-        GdmDisplay *display;
-        guint32     num;
+        GdmDisplayStore *store;
+        GdmDisplay      *display;
+        guint32          num;
+
+        /* Ensure we don't create the same display more than once */
+        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+        display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+        if (display != NULL) {
+                return NULL;
+        }
+
+        g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
 
         num = take_next_display_number (factory);
 
@@ -342,8 +384,7 @@ create_display (GdmLocalDisplayFactory *factory)
         display = gdm_static_display_new (num);
 #endif
 
-        /* FIXME: don't hardcode seat1? */
-        g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL);
+        g_object_set (display, "seat-id", seat_id, NULL);
 
         g_signal_connect (display,
                           "notify::status",
@@ -362,24 +403,182 @@ create_display (GdmLocalDisplayFactory *factory)
         return display;
 }
 
+#ifdef WITH_SYSTEMD
+
+static void
+delete_display (GdmLocalDisplayFactory *factory,
+                const char             *seat_id) {
+
+        GdmDisplayStore *store;
+
+        g_debug ("GdmLocalDisplayFactory: Removing displays on seat %s", seat_id);
+
+        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+        gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id);
+}
+
+static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
+{
+        DBusError error;
+        DBusMessage *message, *reply;
+        DBusMessageIter iter, sub, sub2;
+
+        dbus_error_init (&error);
+
+        message = dbus_message_new_method_call (
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "ListSeats");
+        if (message == NULL) {
+                g_warning ("GdmLocalDisplayFactory: Failed to allocate message");
+                return FALSE;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (factory->priv->connection), message, -1, &error);
+        dbus_message_unref (message);
+
+        if (reply == NULL) {
+                g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error.message);
+                dbus_error_free (&error);
+                return FALSE;
+        }
+
+        if (!dbus_message_iter_init (reply, &iter) ||
+            dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY ||
+            dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRUCT)  {
+                g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
+                dbus_message_unref (reply);
+                return FALSE;
+        }
+
+        dbus_message_iter_recurse (&iter, &sub);
+
+        while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) {
+                const char *seat;
+
+                if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_STRUCT) {
+                        g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
+                        dbus_message_unref (reply);
+                        return FALSE;
+                }
+
+                dbus_message_iter_recurse (&sub, &sub2);
+
+                if (dbus_message_iter_get_arg_type (&sub2) != DBUS_TYPE_STRING) {
+                        g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
+                        dbus_message_unref (reply);
+                        return FALSE;
+                }
+
+                dbus_message_iter_get_basic (&sub2, &seat);
+                create_display (factory, seat);
+
+                dbus_message_iter_next (&sub);
+        }
+
+        dbus_message_unref (reply);
+        return TRUE;
+}
+
+static DBusHandlerResult
+on_seat_signal (DBusConnection *connection,
+                DBusMessage    *message,
+                void           *user_data)
+{
+        GdmLocalDisplayFactory *factory = user_data;
+        DBusError error;
+
+        dbus_error_init (&error);
+
+        if (dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatNew") ||
+            dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatRemoved")) {
+                const char *seat;
+
+                dbus_message_get_args (message,
+                                       &error,
+                                       DBUS_TYPE_STRING, &seat,
+                                       DBUS_TYPE_INVALID);
+
+                if (dbus_error_is_set (&error)) {
+                        g_warning ("GdmLocalDisplayFactory: Failed to decode seat message: %s", error.message);
+                        dbus_error_free (&error);
+                } else {
+
+                        if (strcmp (dbus_message_get_member (message), "SeatNew") == 0) {
+                                create_display (factory, seat);
+                        } else {
+                                delete_display (factory, seat);
+                        }
+                }
+        }
+
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
+{
+        DBusError error;
+
+        dbus_error_init (&error);
+
+        dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection),
+                            "type='signal',"
+                            "sender='org.freedesktop.login1',"
+                            "path='/org/freedesktop/login1',"
+                            "interface='org.freedesktop.login1.Manager',"
+                            "member='SeatNew'",
+                            &error);
+
+        if (dbus_error_is_set (&error)) {
+                g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message);
+                dbus_error_free (&error);
+        }
+
+        dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection),
+                            "type='signal',"
+                            "sender='org.freedesktop.login1',"
+                            "path='/org/freedesktop/login1',"
+                            "interface='org.freedesktop.login1.Manager',"
+                            "member='SeatRemoved'",
+                            &error);
+
+        if (dbus_error_is_set (&error)) {
+                g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message);
+                dbus_error_free (&error);
+        }
+
+        dbus_connection_add_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory, NULL);
+}
+
+static void
+gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
+{
+        dbus_connection_remove_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory);
+}
+
+#endif
+
 static gboolean
 gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
 {
-        gboolean                ret;
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
         GdmDisplay             *display;
 
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
 
-        ret = TRUE;
-
-        /* FIXME: use seat configuration */
-        display = create_display (factory);
-        if (display == NULL) {
-                ret = FALSE;
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                gdm_local_display_factory_start_monitor (factory);
+                return gdm_local_display_factory_sync_seats (factory);
         }
+#endif
 
-        return ret;
+        /* On ConsoleKit just create Seat1, and that's it. */
+        display = create_display (factory, CK_SEAT1_PATH);
+
+        return display != NULL;
 }
 
 static gboolean
@@ -389,6 +588,10 @@ gdm_local_display_factory_stop (GdmDisplayFactory *base_factory)
 
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
 
+#ifdef WITH_SYSTEMD
+        gdm_local_display_factory_stop_monitor (factory);
+#endif
+
         return TRUE;
 }
 
@@ -499,6 +702,10 @@ gdm_local_display_factory_finalize (GObject *object)
 
         g_hash_table_destroy (factory->priv->displays);
 
+#ifdef WITH_SYSTEMD
+        gdm_local_display_factory_stop_monitor (factory);
+#endif
+
         G_OBJECT_CLASS (gdm_local_display_factory_parent_class)->finalize (object);
 }
 
-- 
1.7.9


From 51a27a199e36fcb5e90e8332c1f025e8a282fbd5 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 27 Jul 2011 04:06:10 +0200
Subject: [PATCH 09/11] server: pass seat id to server

When we spawn a new X server, let's pass the seat id to it via the
"-seat" parameter, which has been available since a while in upstream
Xorg.

-seat causes the X server to only make use of hardware that is assigned
to the seat specified, and leave all other hardware untouched.
---
 daemon/gdm-factory-slave.c |    4 +++-
 daemon/gdm-product-slave.c |    4 +++-
 daemon/gdm-server.c        |   37 ++++++++++++++++++++++++++++++++++++-
 daemon/gdm-server.h        |    1 +
 daemon/gdm-simple-slave.c  |    4 +++-
 5 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c
index 6154cd3..3538627 100644
--- a/daemon/gdm-factory-slave.c
+++ b/daemon/gdm-factory-slave.c
@@ -674,12 +674,14 @@ static gboolean
 gdm_factory_slave_run (GdmFactorySlave *slave)
 {
         char    *display_name;
+        char    *seat_id;
         char    *auth_file;
         gboolean display_is_local;
 
         g_object_get (slave,
                       "display-is-local", &display_is_local,
                       "display-name", &display_name,
+                      "display-seat-id", &seat_id,
                       "display-x11-authority-file", &auth_file,
                       NULL);
 
@@ -688,7 +690,7 @@ gdm_factory_slave_run (GdmFactorySlave *slave)
         if (display_is_local) {
                 gboolean res;
 
-                slave->priv->server = gdm_server_new (display_name, auth_file);
+                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
                 g_signal_connect (slave->priv->server,
                                   "exited",
                                   G_CALLBACK (on_server_exited),
diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
index 629c6e7..844af48 100644
--- a/daemon/gdm-product-slave.c
+++ b/daemon/gdm-product-slave.c
@@ -479,11 +479,13 @@ gdm_product_slave_create_server (GdmProductSlave *slave)
 {
         char    *display_name;
         char    *auth_file;
+        char    *seat_id;
         gboolean display_is_local;
 
         g_object_get (slave,
                       "display-is-local", &display_is_local,
                       "display-name", &display_name,
+                      "display-seat-id", &seat_id,
                       "display-x11-authority-file", &auth_file,
                       NULL);
 
@@ -492,7 +494,7 @@ gdm_product_slave_create_server (GdmProductSlave *slave)
         if (display_is_local) {
                 gboolean res;
 
-                slave->priv->server = gdm_server_new (display_name, auth_file);
+                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
                 g_signal_connect (slave->priv->server,
                                   "exited",
                                   G_CALLBACK (on_server_exited),
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 62ffca1..9a11ba0 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -38,6 +38,10 @@
 #include <sys/prctl.h>
 #endif
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
@@ -77,6 +81,7 @@ struct GdmServerPrivate
         char    *log_dir;
         char    *display_name;
         char    *display_device;
+        char    *display_seat_id;
         char    *auth_file;
 
         gboolean is_parented;
@@ -90,6 +95,7 @@ struct GdmServerPrivate
 enum {
         PROP_0,
         PROP_DISPLAY_NAME,
+        PROP_DISPLAY_SEAT_ID,
         PROP_DISPLAY_DEVICE,
         PROP_AUTH_FILE,
         PROP_IS_PARENTED,
@@ -284,7 +290,7 @@ gdm_server_resolve_command_line (GdmServer  *server,
                         query_in_arglist = TRUE;
         }
 
-        argv = g_renew (char *, argv, len + 10);
+        argv = g_renew (char *, argv, len + 12);
         /* shift args down one */
         for (i = len - 1; i >= 1; i--) {
                 argv[i+1] = argv[i];
@@ -299,6 +305,11 @@ gdm_server_resolve_command_line (GdmServer  *server,
                 argv[len++] = g_strdup (server->priv->auth_file);
         }
 
+        if (sd_booted () > 0 && server->priv->display_seat_id != NULL) {
+                argv[len++] = g_strdup ("-seat");
+                argv[len++] = g_strdup (server->priv->display_seat_id);
+        }
+
         if (server->priv->chosen_hostname) {
                 /* run just one session */
                 argv[len++] = g_strdup ("-terminate");
@@ -753,6 +764,14 @@ _gdm_server_set_display_name (GdmServer  *server,
 }
 
 static void
+_gdm_server_set_display_seat_id (GdmServer  *server,
+                                 const char *name)
+{
+        g_free (server->priv->display_seat_id);
+        server->priv->display_seat_id = g_strdup (name);
+}
+
+static void
 _gdm_server_set_auth_file (GdmServer  *server,
                            const char *auth_file)
 {
@@ -789,6 +808,9 @@ gdm_server_set_property (GObject      *object,
         case PROP_DISPLAY_NAME:
                 _gdm_server_set_display_name (self, g_value_get_string (value));
                 break;
+        case PROP_DISPLAY_SEAT_ID:
+                _gdm_server_set_display_seat_id (self, g_value_get_string (value));
+                break;
         case PROP_AUTH_FILE:
                 _gdm_server_set_auth_file (self, g_value_get_string (value));
                 break;
@@ -818,6 +840,9 @@ gdm_server_get_property (GObject    *object,
         case PROP_DISPLAY_NAME:
                 g_value_set_string (value, self->priv->display_name);
                 break;
+        case PROP_DISPLAY_SEAT_ID:
+                g_value_set_string (value, self->priv->display_seat_id);
+                break;
         case PROP_DISPLAY_DEVICE:
                 g_value_take_string (value,
                                      gdm_server_get_display_device (self));
@@ -889,6 +914,13 @@ gdm_server_class_init (GdmServerClass *klass)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
         g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_SEAT_ID,
+                                         g_param_spec_string ("display-seat-id",
+                                                              "Seat ID",
+                                                              "ID of the seat this display is running on",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
                                          PROP_DISPLAY_DEVICE,
                                          g_param_spec_string ("display-device",
                                                               "Display Device",
@@ -954,6 +986,7 @@ gdm_server_finalize (GObject *object)
         g_free (server->priv->session_args);
         g_free (server->priv->log_dir);
         g_free (server->priv->display_name);
+        g_free (server->priv->display_seat_id);
         g_free (server->priv->display_device);
         g_free (server->priv->auth_file);
         g_free (server->priv->parent_display_name);
@@ -965,12 +998,14 @@ gdm_server_finalize (GObject *object)
 
 GdmServer *
 gdm_server_new (const char *display_name,
+                const char *seat_id,
                 const char *auth_file)
 {
         GObject *object;
 
         object = g_object_new (GDM_TYPE_SERVER,
                                "display-name", display_name,
+                               "display-seat-id", seat_id,
                                "auth-file", auth_file,
                                NULL);
 
diff --git a/daemon/gdm-server.h b/daemon/gdm-server.h
index 535a69a..b53d68e 100644
--- a/daemon/gdm-server.h
+++ b/daemon/gdm-server.h
@@ -54,6 +54,7 @@ typedef struct
 
 GType               gdm_server_get_type  (void);
 GdmServer *         gdm_server_new       (const char *display_id,
+                                          const char *seat_id,
                                           const char *auth_file);
 gboolean            gdm_server_start     (GdmServer   *server);
 gboolean            gdm_server_stop      (GdmServer   *server);
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 873b7f9..9d1347a 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -1437,11 +1437,13 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
 {
         char    *display_name;
         char    *auth_file;
+        char    *seat_id;
         gboolean display_is_local;
 
         g_object_get (slave,
                       "display-is-local", &display_is_local,
                       "display-name", &display_name,
+                      "display-seat-id", &seat_id,
                       "display-x11-authority-file", &auth_file,
                       NULL);
 
@@ -1451,7 +1453,7 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
                 gboolean res;
                 gboolean disable_tcp;
 
-                slave->priv->server = gdm_server_new (display_name, auth_file);
+                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
 
                 disable_tcp = TRUE;
                 if (gdm_settings_client_get_boolean (GDM_KEY_DISALLOW_TCP,
-- 
1.7.9


From 2b24451c3816ecea30fdbfff2c249a6ac527e1b6 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 24 Jan 2012 00:03:10 +0100
Subject: [PATCH 10/11] server: invoke X with the systemd multi seat X wrapper
 if necessary

systemd 39 and newer provide a small wrapper for X which works around
the fact that XOrg upstream currently support multi-seat hotplug for
displays. Let's make use of this as a stop-gap until this feature is
added to XOrg upstream.

This code tries to be as defensive as possible and makes use of the
wrapper only if the system as actually booted with systemd, the wrapper
is available and we actually use a seat != "seat0".
---
 configure.ac        |    6 +++++-
 daemon/gdm-server.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index dec31a9..855948d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -939,7 +939,7 @@ use_systemd=no
 if test "x$with_systemd" != "xno" ; then
         PKG_CHECK_MODULES(SYSTEMD,
                 libsystemd-daemon
-                libsystemd-login
+                libsystemd-login >= 39
         )
         AC_SUBST(SYSTEMD_CFLAGS)
         AC_SUBST(SYSTEMD_LIBS)
@@ -950,6 +950,10 @@ fi
 AM_CONDITIONAL(WITH_SYSTEMD, test x$use_systemd = xyes)
 AC_SUBST(WITH_SYSTEMD)
 
+AC_PATH_PROG(SYSTEMD_X_SERVER, systemd-multi-seat-x, [/lib/systemd/systemd-multi-seat-x], [/lib/systemd:/usr/lib/systemd:$PATH])
+AC_SUBST(SYSTEMD_X_SERVER)
+AC_DEFINE_UNQUOTED(SYSTEMD_X_SERVER,"$SYSTEMD_X_SERVER",[Path to systemd X server wrapper])
+
 dnl ---------------------------------------------------------------------------
 dnl - Check for D-Bus
 dnl ---------------------------------------------------------------------------
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 9a11ba0..54bf8b3 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -260,6 +260,52 @@ connect_to_parent (GdmServer *server)
 }
 #endif
 
+static void
+gdm_server_init_command (GdmServer *server)
+{
+
+        if (server->priv->command != NULL) {
+                return;
+        }
+
+#ifdef WITH_SYSTEMD
+
+        /* This is a temporary hack to work around the fact that XOrg
+         * currently lacks support for multi-seat hotplugging for
+         * display devices. This bit should be removed as soon as XOrg
+         * gains native support for automatically enumerating usb
+         * based graphics adapters at start-up via udev. */
+
+        /* systemd ships an X server wrapper tool which simply invokes
+         * the usual X but ensures it only uses the display devices of
+         * the seat. */
+
+        /* We do not rely on this wrapper server if, a) the machine
+         * wasn't booted using systemd, or b) the wrapper tool is
+         * missing, or c) we are running for the main seat 'seat0'. */
+
+        if (sd_booted () <= 0) {
+                goto fallback;
+        }
+
+        if (g_access (SYSTEMD_X_SERVER, X_OK) < 0) {
+                goto fallback;
+        }
+
+        if (server->priv->display_seat_id == NULL ||
+            strcmp (server->priv->display_seat_id, "seat0") == 0) {
+                goto fallback;
+        }
+
+        server->priv->command = g_strdup (SYSTEMD_X_SERVER " -br -verbose -logverbose 7");
+        return;
+
+fallback:
+#endif
+
+        server->priv->command = g_strdup (X_SERVER " -br -verbose -logverbose 7");
+}
+
 static gboolean
 gdm_server_resolve_command_line (GdmServer  *server,
                                  const char *vtarg,
@@ -273,6 +319,8 @@ gdm_server_resolve_command_line (GdmServer  *server,
         gboolean gotvtarg = FALSE;
         gboolean query_in_arglist = FALSE;
 
+        gdm_server_init_command (server);
+
         g_shell_parse_argv (server->priv->command, &argc, &argv, NULL);
 
         for (len = 0; argv != NULL && argv[len] != NULL; len++) {
@@ -959,7 +1007,7 @@ gdm_server_init (GdmServer *server)
         server->priv = GDM_SERVER_GET_PRIVATE (server);
 
         server->priv->pid = -1;
-        server->priv->command = g_strdup (X_SERVER " -br -verbose -logverbose 7");
+
         server->priv->log_dir = g_strdup (LOGDIR);
 
         add_ready_handler (server);
-- 
1.7.9


From 28c7f9e6d875076bfe0c79cdee98fc6aefc29874 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 7 Feb 2012 22:48:40 +0100
Subject: [PATCH 11/11] gdmflexiserver: port gdmflexiserver to
 libsystemd-logind

Port over gdmflexiserver to use native systemd calls with a fallback on
CK.
---
 utils/Makefile.am      |    3 +-
 utils/gdmflexiserver.c |  256 ++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 239 insertions(+), 20 deletions(-)

diff --git a/utils/Makefile.am b/utils/Makefile.am
index 379c3d5..1cda413 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
 	$(CANBERRA_GTK_CFLAGS)				\
 	$(GTK_CFLAGS)					\
 	$(XLIB_CFLAGS)					\
+	$(SYSTEMD_CFLAGS)				\
 	$(COMMON_CFLAGS)				\
 	$(NULL)
 
@@ -31,6 +32,7 @@ gdmflexiserver_SOURCES =	\
 gdmflexiserver_LDADD =		\
 	$(GTK_LIBS)		\
 	$(COMMON_LIBS)		\
+	$(SYSTEMD_LIBS)         \
 	$(NULL)
 
 gdm_screenshot_SOURCES =	\
@@ -49,4 +51,3 @@ CLEANFILES = 			\
 
 DISTCLEANFILES = 		\
 	$(NULL)
-
diff --git a/utils/gdmflexiserver.c b/utils/gdmflexiserver.c
index f7fac33..59bccd1 100644
--- a/utils/gdmflexiserver.c
+++ b/utils/gdmflexiserver.c
@@ -29,6 +29,11 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+#endif
+
 #define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
@@ -37,6 +42,7 @@
 #define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH      "/org/gnome/DisplayManager/LocalDisplayFactory"
 #define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
 
+#ifdef WITH_CONSOLE_KIT
 #define CK_NAME      "org.freedesktop.ConsoleKit"
 #define CK_PATH      "/org/freedesktop/ConsoleKit"
 #define CK_INTERFACE "org.freedesktop.ConsoleKit"
@@ -45,6 +51,7 @@
 #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
 #define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
 #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+#endif
 
 static const char *send_command     = NULL;
 static gboolean    use_xnest        = FALSE;
@@ -206,6 +213,8 @@ create_transient_display (DBusConnection *connection,
         return ret;
 }
 
+#ifdef WITH_CONSOLE_KIT
+
 static gboolean
 get_current_session_id (DBusConnection *connection,
                         char          **session_id)
@@ -335,9 +344,9 @@ get_current_seat_id (DBusConnection *connection)
 }
 
 static gboolean
-activate_session_id (DBusConnection *connection,
-                     const char     *seat_id,
-                     const char     *session_id)
+activate_session_id_for_ck (DBusConnection *connection,
+                            const char     *seat_id,
+                            const char     *session_id)
 {
         DBusError    local_error;
         DBusMessage *message;
@@ -609,9 +618,9 @@ seat_get_sessions (DBusConnection *connection,
 }
 
 static gboolean
-get_login_window_session_id (DBusConnection  *connection,
-                             const char      *seat_id,
-                             char           **session_id)
+get_login_window_session_id_for_ck (DBusConnection  *connection,
+                                    const char      *seat_id,
+                                    char           **session_id)
 {
         gboolean    can_activate_sessions;
         char      **sessions;
@@ -645,46 +654,225 @@ get_login_window_session_id (DBusConnection  *connection,
 }
 
 static gboolean
-goto_login_session (GError **error)
+goto_login_session_for_ck (DBusConnection  *connection,
+                           GError         **error)
 {
         gboolean        ret;
         gboolean        res;
         char           *session_id;
         char           *seat_id;
-        DBusError       local_error;
-        DBusConnection *connection;
 
         ret = FALSE;
 
+        /* First look for any existing LoginWindow sessions on the seat.
+           If none are found, create a new one. */
+
+        seat_id = get_current_seat_id (connection);
+        if (seat_id == NULL || seat_id[0] == '\0') {
+                g_debug ("seat id is not set; can't switch sessions");
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current session."));
+
+                return FALSE;
+        }
+
+        res = get_login_window_session_id_for_ck (connection, seat_id, &session_id);
+        if (! res) {
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to switch sessions."));
+                return FALSE;
+        }
+
+        if (session_id != NULL) {
+                res = activate_session_id_for_ck (connection, seat_id, session_id);
+                if (res) {
+                        ret = TRUE;
+                }
+        }
+
+        if (! ret) {
+                res = create_transient_display (connection, error);
+                if (res) {
+                        ret = TRUE;
+                }
+        }
+
+        return ret;
+}
+#endif
+
+#ifdef WITH_SYSTEMD
+
+static gboolean
+activate_session_id_for_systemd (DBusConnection *connection,
+                                 const char     *seat_id,
+                                 const char     *session_id)
+{
+        DBusError    local_error;
+        DBusMessage *message;
+        DBusMessage *reply;
+        gboolean     ret;
+
+        ret = FALSE;
+        reply = NULL;
+
+        g_debug ("Switching to session %s", session_id);
+
+        message = dbus_message_new_method_call ("org.freedesktop.login1",
+                                                "/org/freedesktop/login1",
+                                                "org.freedesktop.login1.Manager",
+                                                "ActivateSessionOnSeat");
+        if (message == NULL) {
+                goto out;
+        }
+
+        if (! dbus_message_append_args (message,
+                                        DBUS_TYPE_STRING, &session_id,
+                                        DBUS_TYPE_STRING, &seat_id,
+                                        DBUS_TYPE_INVALID)) {
+                goto out;
+        }
+
         dbus_error_init (&local_error);
-        connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
-        if (connection == NULL) {
-                g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
-                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
+        reply = dbus_connection_send_with_reply_and_block (connection,
+                                                           message,
+                                                           -1,
+                                                           &local_error);
+        if (dbus_error_is_set (&local_error)) {
+                g_warning ("Unable to activate session: %s", local_error.message);
                 dbus_error_free (&local_error);
+                goto out;
+        }
+
+        ret = TRUE;
+out:
+        if (message != NULL) {
+                dbus_message_unref (message);
+        }
+        if (reply != NULL) {
+                dbus_message_unref (reply);
+        }
+
+        return ret;
+}
+
+static gboolean
+get_login_window_session_id_for_systemd (const char  *seat_id,
+                                         char       **session_id)
+{
+        gboolean   ret;
+        int        res, i;
+        char     **sessions;
+        char      *service_id;
+
+        res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
+        if (res < 0) {
+                g_debug ("Failed to determine sessions: %s", strerror (-res));
                 return FALSE;
         }
 
+        if (sessions == NULL || sessions[0] == NULL) {
+                *session_id = NULL;
+                ret = TRUE;
+                goto out;
+        }
+
+        for (i = 0; sessions[i]; i ++) {
+
+                res = sd_session_get_service (sessions[i], &service_id);
+                if (res < 0) {
+                        g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
+                        ret = FALSE;
+                        goto out;
+                }
+
+                if (strcmp (service_id, "gdm-welcome") == 0) {
+                        *session_id = g_strdup (sessions[i]);
+                        ret = TRUE;
+
+                        free (service_id);
+                        goto out;
+                }
+
+                free (service_id);
+        }
+
+        *session_id = NULL;
+        ret = TRUE;
+
+out:
+        for (i = 0; sessions[i]; i ++) {
+                free (sessions[i]);
+        }
+
+        free (sessions);
+
+        return ret;
+}
+
+static gboolean
+goto_login_session_for_systemd (DBusConnection  *connection,
+                                GError         **error)
+{
+        gboolean        ret;
+        int             res;
+        char           *our_session;
+        char           *session_id;
+        char           *seat_id;
+
+        ret = FALSE;
+
         /* First look for any existing LoginWindow sessions on the seat.
            If none are found, create a new one. */
 
-        seat_id = get_current_seat_id (connection);
-        if (seat_id == NULL || seat_id[0] == '\0') {
-                g_debug ("seat id is not set; can't switch sessions");
+        /* Note that we mostly use free () here, instead of g_free ()
+         * since the data allocated is from libsystemd-logind, which
+         * does not use GLib's g_malloc (). */
+
+        res = sd_pid_get_session (0, &our_session);
+        if (res < 0) {
+                g_debug ("failed to determine own session: %s", strerror (-res));
                 g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current session."));
 
                 return FALSE;
         }
 
-        res = get_login_window_session_id (connection, seat_id, &session_id);
+        res = sd_session_get_seat (our_session, &seat_id);
+        free (our_session);
+        if (res < 0) {
+                g_debug ("failed to determine own seat: %s", strerror (-res));
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current seat."));
+
+                return FALSE;
+        }
+
+        res = sd_seat_can_multi_session (seat_id);
+        if (res < 0) {
+                free (seat_id);
+
+                g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify multi session property."));
+
+                return FALSE;
+        }
+
+        if (res == 0) {
+                free (seat_id);
 
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Seat can't do multi session"));
+
+                return FALSE;
+        }
+
+        res = get_login_window_session_id_for_systemd (seat_id, &session_id);
         if (! res) {
-                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to switch sessions."));
+                free (seat_id);
+
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to determine login session."));
                 return FALSE;
         }
 
         if (session_id != NULL) {
-                res = activate_session_id (connection, seat_id, session_id);
+                res = activate_session_id_for_systemd (connection, seat_id, session_id);
+
                 if (res) {
                         ret = TRUE;
                 }
@@ -697,8 +885,38 @@ goto_login_session (GError **error)
                 }
         }
 
+        free (seat_id);
+        g_free (session_id);
+
         return ret;
 }
+#endif
+
+static gboolean
+goto_login_session (GError **error)
+{
+        DBusError       local_error;
+        DBusConnection *connection;
+
+        dbus_error_init (&local_error);
+        connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
+        if (connection == NULL) {
+                g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
+                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
+                dbus_error_free (&local_error);
+                return FALSE;
+        }
+
+#ifdef WITH_SYSTEMD
+        if (sd_booted () > 0) {
+                return goto_login_session_for_systemd (connection, error);
+        }
+#endif
+
+#ifdef WITH_CONSOLE_KIT
+        return goto_login_session_for_ck (connection, error);
+#endif
+}
 
 int
 main (int argc, char *argv[])
-- 
1.7.9

From 4c80969a0f8667d9a17ae44281cacb939e9f1a21 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 9 Feb 2012 13:27:11 -0500
Subject: [PATCH] slave: fix crasher in systemd integration

sd_seat_get_sessions returns NULL instead of a one
element array in the case there are no sessions
associated with a seat.

This commit guards against that problem.
---
 daemon/gdm-slave.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 371b9bd..d864a3d 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -1336,6 +1336,11 @@ gdm_slave_get_primary_session_id_for_user_from_systemd (GdmSlave   *slave,
                 return NULL;
         }
 
+        if (sessions == NULL) {
+                g_debug ("GdmSlave: seat has no active sessions");
+                return NULL;
+        }
+
         for (i = 0; sessions[i] != NULL; i++) {
 
                 if (primary_ssid == NULL) {
-- 
1.7.9