aboutsummaryrefslogtreecommitdiffstats
path: root/testing/gdm
diff options
context:
space:
mode:
authorWilliam Pitcock <nenolod@dereferenced.org>2017-06-06 00:45:41 +0000
committerWilliam Pitcock <nenolod@dereferenced.org>2017-06-06 00:45:41 +0000
commitf25f0efdfce3e8ca39ba2d3f3f1a7e83bee5cc81 (patch)
tree501d1092724aae4600deecdd80bcab04446e0d1b /testing/gdm
parent847eca8ecc25283df946914ec189aa2d737e62cf (diff)
downloadaports-f25f0efdfce3e8ca39ba2d3f3f1a7e83bee5cc81.tar.bz2
aports-f25f0efdfce3e8ca39ba2d3f3f1a7e83bee5cc81.tar.xz
testing/gdm: new aport
Diffstat (limited to 'testing/gdm')
-rw-r--r--testing/gdm/0001-gdm-session-record-alpine-does-not-have-utmp.patch151
-rw-r--r--testing/gdm/0002-configure-Alpine-does-not-use-PAM.patch42
-rw-r--r--testing/gdm/0003-reintroduce-ConsoleKit-support.patch2816
-rw-r--r--testing/gdm/APKBUILD50
4 files changed, 3059 insertions, 0 deletions
diff --git a/testing/gdm/0001-gdm-session-record-alpine-does-not-have-utmp.patch b/testing/gdm/0001-gdm-session-record-alpine-does-not-have-utmp.patch
new file mode 100644
index 0000000000..57990ea047
--- /dev/null
+++ b/testing/gdm/0001-gdm-session-record-alpine-does-not-have-utmp.patch
@@ -0,0 +1,151 @@
+From 4d25e3bbd9e22a4db5dfb3c9267f0336761ea904 Mon Sep 17 00:00:00 2001
+From: William Pitcock <nenolod@dereferenced.org>
+Date: Tue, 6 Jun 2017 00:23:34 +0000
+Subject: [PATCH 1/3] gdm-session-record: alpine does not have utmp
+
+---
+ daemon/gdm-session-record.c | 100 ++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 96 insertions(+), 4 deletions(-)
+
+diff --git a/daemon/gdm-session-record.c b/daemon/gdm-session-record.c
+index 32933ef0..3154df2e 100644
+--- a/daemon/gdm-session-record.c
++++ b/daemon/gdm-session-record.c
+@@ -33,6 +33,16 @@
+ #include <utmp.h>
+ #endif
+
++#if defined(HAVE_UTIL_H)
++#include <util.h>
++#endif
++
++#if defined(HAVE_GETTTYENT)
++#include <fcntl.h> /* open(2) */
++#include <ttyent.h>
++static int fd = -1;
++#endif
++
+ #include <glib.h>
+ #include <glib/gi18n.h>
+ #include <glib/gstdio.h>
+@@ -43,6 +53,9 @@
+ #define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp"
+ #endif
+
++static void write_utmp_login_manually (struct utmp *ut);
++static void write_utmp_logout_manually (char *);
++
+ #if !defined(GDM_NEW_SESSION_RECORDS_FILE)
+ # if defined(WTMPX_FILE)
+ # define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILE
+@@ -183,6 +196,84 @@ record_set_line (UTMP *u,
+ g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line);
+ }
+
++static void
++write_utmp_login_manually (struct utmp *ut)
++{
++#if defined(HAVE_GETTTYENT) && defined(HAVE_UTMP_H)
++ UTMP ubuf;
++ int topslot = -1;
++
++ g_debug ("Adding new utmp record");
++
++ /*
++ * First, loop through /etc/ttys, if needed, to initialize the
++ * top of the tty slots, since gdm has no tty.
++ */
++ if (topslot < 0) {
++ topslot = 0;
++ while (getttyent () != (struct ttyent *) NULL)
++ topslot++;
++ }
++ if ((topslot < 0) || ((fd < 0) &&
++ (fd = open (_PATH_UTMP, O_RDWR|O_CREAT, 0644)) < 0))
++ return;
++
++ /*
++ * Now find a slot that's not in use...
++ */
++ (void) lseek (fd, (off_t) (topslot * sizeof (struct utmp)), SEEK_SET);
++
++ while (1) {
++ if (read (fd, &ubuf, sizeof (struct utmp)) ==
++ sizeof (struct utmp)) {
++ if (!ubuf.ut_name[0]) {
++ (void) lseek (fd, -(off_t) sizeof (struct utmp),
++ SEEK_CUR);
++ break;
++ }
++ topslot++;
++ } else {
++ (void) lseek (fd, (off_t) (topslot *
++ sizeof (struct utmp)), SEEK_SET);
++ break;
++ }
++ }
++
++ (void) write (fd, ut, sizeof (struct utmp));
++#endif
++}
++
++static void
++write_utmp_logout_manually (char *line)
++{
++#if defined(HAVE_GETTTYENT) && defined(HAVE_UTMP_H)
++ int rval = 1;
++ struct timeval tv;
++ UTMP ut;
++
++ g_debug ("Removing utmp record");
++
++ if (fd >= 0) {
++ (void) lseek (fd, 0, SEEK_SET);
++ while (read (fd, &ut, sizeof (struct utmp)) == sizeof (struct utmp)) {
++ if (!ut.ut_name[0] ||
++ strncmp (ut.ut_line, line, UT_LINESIZE))
++ continue;
++ bzero (ut.ut_name, UT_NAMESIZE);
++ bzero (ut.ut_host, UT_HOSTSIZE);
++ gettimeofday (&tv, NULL);
++ ut.ut_time = tv.tv_sec;
++ (void) lseek (fd, -(off_t) sizeof (struct utmp), SEEK_CUR);
++ (void) write (fd, &ut, sizeof (struct utmp));
++ rval = 0;
++ }
++ }
++
++ if (rval != 0)
++ g_debug ("Failed to remove utmp record");
++#endif
++}
++
+ void
+ gdm_session_record_login (GPid session_pid,
+ const char *user_name,
+@@ -227,8 +318,9 @@ gdm_session_record_login (GPid session_pid,
+ #if defined(HAVE_GETUTXENT)
+ g_debug ("Adding or updating utmp record for login");
+ pututxline (&session_record);
+-#elif defined(HAVE_LOGIN)
+- login (&session_record);
++#else
++ if (strcmp (session_record.ut_name, "(unknown)") != 0)
++ write_utmp_login_manually (&session_record);
+ #endif
+ }
+
+@@ -270,8 +362,8 @@ gdm_session_record_logout (GPid session_pid,
+ #if defined(HAVE_GETUTXENT)
+ g_debug ("Adding or updating utmp record for logout");
+ pututxline (&session_record);
+-#elif defined(HAVE_LOGOUT)
+- logout (session_record.ut_line);
++#else
++ write_utmp_logout_manually (session_record.ut_line);
+ #endif
+ }
+
+--
+2.13.0
+
diff --git a/testing/gdm/0002-configure-Alpine-does-not-use-PAM.patch b/testing/gdm/0002-configure-Alpine-does-not-use-PAM.patch
new file mode 100644
index 0000000000..c66b1e23f6
--- /dev/null
+++ b/testing/gdm/0002-configure-Alpine-does-not-use-PAM.patch
@@ -0,0 +1,42 @@
+From 7500e98c4794413f3e78c712147f5f35962d6c6d Mon Sep 17 00:00:00 2001
+From: William Pitcock <nenolod@dereferenced.org>
+Date: Tue, 6 Jun 2017 00:27:22 +0000
+Subject: [PATCH 2/3] configure: Alpine does not use PAM.
+
+---
+ Makefile.am | 1 -
+ configure.ac | 6 ------
+ 2 files changed, 7 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index d3c46c8f..aa527219 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -6,7 +6,6 @@ SUBDIRS = \
+ daemon \
+ libgdm \
+ utils \
+- pam_gdm \
+ po \
+ tests \
+ $(NULL)
+diff --git a/configure.ac b/configure.ac
+index e8434d78..602969bd 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -232,12 +232,6 @@ AM_CONDITIONAL(ENABLE_EXHERBO_PAM_CONFIG, test x$with_default_pam_config = xexhe
+ AM_CONDITIONAL(ENABLE_LFS_PAM_CONFIG, test x$with_default_pam_config = xlfs)
+ AM_CONDITIONAL(ENABLE_ARCH_PAM_CONFIG, test x$with_default_pam_config = xarch)
+
+-AC_CHECK_HEADERS([security/pam_modules.h security/pam_modutil.h security/pam_ext.h],
+- [have_pam=yes],
+- [if test "x$have_pam" = xyes ; then
+- AC_MSG_ERROR([PAM development files not found.])
+- fi])
+-
+ AC_ARG_ENABLE(console-helper,
+ AS_HELP_STRING([--enable-console-helper],
+ [Enable PAM console helper @<:@default=auto@:>@]),,
+--
+2.13.0
+
diff --git a/testing/gdm/0003-reintroduce-ConsoleKit-support.patch b/testing/gdm/0003-reintroduce-ConsoleKit-support.patch
new file mode 100644
index 0000000000..c110517ac0
--- /dev/null
+++ b/testing/gdm/0003-reintroduce-ConsoleKit-support.patch
@@ -0,0 +1,2816 @@
+From f4a1a8c560796804e0ec763ab50f5e56e2ff05c4 Mon Sep 17 00:00:00 2001
+From: William Pitcock <nenolod@dereferenced.org>
+Date: Tue, 6 Jun 2017 00:29:44 +0000
+Subject: [PATCH 3/3] reintroduce ConsoleKit support
+
+---
+ common/gdm-common.c | 335 +++++++++++++++++-
+ common/gdm-common.h | 3 +
+ common/gdm-log.c | 22 ++
+ configure.ac | 64 +++-
+ daemon/Makefile.am | 10 +
+ daemon/gdm-launch-environment.c | 7 +-
+ daemon/gdm-local-display-factory.c | 35 +-
+ daemon/gdm-manager.c | 679 +++++++++++++++++++++++++++----------
+ daemon/gdm-server.c | 69 +++-
+ daemon/gdm-session-worker-job.c | 2 +
+ daemon/gdm-session-worker.c | 314 +++++++++++++++--
+ daemon/gdm-session-worker.xml | 3 +
+ daemon/gdm-session.c | 25 ++
+ daemon/gdm-session.h | 2 +
+ libgdm/gdm-user-switching.c | 349 ++++++++++++++++++-
+ 15 files changed, 1653 insertions(+), 266 deletions(-)
+
+diff --git a/common/gdm-common.c b/common/gdm-common.c
+index 31fc810a..2ad134a6 100644
+--- a/common/gdm-common.c
++++ b/common/gdm-common.c
+@@ -39,12 +39,25 @@
+ #include "mkdtemp.h"
+ #endif
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-login.h>
++#endif
+
+ #define GDM_DBUS_NAME "org.gnome.DisplayManager"
+ #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"
++
++#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
++#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
++
+ G_DEFINE_QUARK (gdm-common-error, gdm_common_error);
+
+ const char *
+@@ -343,10 +356,301 @@ create_transient_display (GDBusConnection *connection,
+ return TRUE;
+ }
+
++#ifdef WITH_CONSOLE_KIT
++
++static gboolean
++get_current_session_id (GDBusConnection *connection,
++ char **session_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ CK_MANAGER_PATH,
++ CK_MANAGER_INTERFACE,
++ "GetCurrentSession",
++ NULL, /* parameters */
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine session: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(o)", session_id);
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static gboolean
++get_seat_id_for_session (GDBusConnection *connection,
++ const char *session_id,
++ char **seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ session_id,
++ CK_SESSION_INTERFACE,
++ "GetSeatId",
++ NULL, /* parameters */
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine seat: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(o)", seat_id);
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static char *
++get_current_seat_id (GDBusConnection *connection)
++{
++ gboolean res;
++ char *session_id;
++ char *seat_id;
++
++ session_id = NULL;
++ seat_id = NULL;
++
++ res = get_current_session_id (connection, &session_id);
++ if (res) {
++ res = get_seat_id_for_session (connection, session_id, &seat_id);
++ }
++ g_free (session_id);
++
++ return seat_id;
++}
++
++static gboolean
++activate_session_id_for_ck (GDBusConnection *connection,
++ const char *seat_id,
++ const char *session_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "ActivateSession",
++ g_variant_new ("(o)", session_id),
++ NULL,
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to activate session: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static gboolean
++session_is_login_window (GDBusConnection *connection,
++ const char *session_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ const char *value;
++ gboolean ret;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ session_id,
++ CK_SESSION_INTERFACE,
++ "GetSessionType",
++ NULL,
++ G_VARIANT_TYPE ("(s)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine session type: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(&s)", &value);
++
++ if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
++ ret = FALSE;
++ } else {
++ ret = TRUE;
++ }
++
++ g_variant_unref (reply);
++
++ return ret;
++}
++
++static gboolean
++seat_can_activate_sessions (GDBusConnection *connection,
++ const char *seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ gboolean ret;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "CanActivateSessions",
++ NULL,
++ G_VARIANT_TYPE ("(b)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine if can activate sessions: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(b)", &ret);
++ g_variant_unref (reply);
++
++ return ret;
++}
++
++static const char **
++seat_get_sessions (GDBusConnection *connection,
++ const char *seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ const char **value;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "GetSessions",
++ NULL,
++ G_VARIANT_TYPE ("(ao)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to list sessions: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(^ao)", &value);
++ g_variant_unref (reply);
++
++ return value;
++}
++
++static gboolean
++get_login_window_session_id_for_ck (GDBusConnection *connection,
++ const char *seat_id,
++ char **session_id)
++{
++ gboolean can_activate_sessions;
++ const char **sessions;
++ int i;
++
++ *session_id = NULL;
++ sessions = NULL;
++
++ g_debug ("checking if seat can activate sessions");
++
++ can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
++ if (! can_activate_sessions) {
++ g_debug ("seat is unable to activate sessions");
++ return FALSE;
++ }
++
++ sessions = seat_get_sessions (connection, seat_id);
++ for (i = 0; sessions [i] != NULL; i++) {
++ const char *ssid;
++
++ ssid = sessions [i];
++
++ if (session_is_login_window (connection, ssid)) {
++ *session_id = g_strdup (ssid);
++ break;
++ }
++ }
++ g_free (sessions);
++
++ return TRUE;
++}
++
++static gboolean
++goto_login_session_for_ck (GDBusConnection *connection,
++ GError **error)
++{
++ gboolean ret;
++ gboolean res;
++ 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");
++ g_set_error (error, GDM_COMMON_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_COMMON_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 && g_strcmp0 (seat_id, "/org/freedesktop/ConsoleKit/Seat1") == 0) {
++ res = create_transient_display (connection, error);
++ if (res) {
++ ret = TRUE;
++ }
++ }
++
++ return ret;
++}
++#endif
++
++#ifdef WITH_SYSTEMD
++
+ static gboolean
+-activate_session_id (GDBusConnection *connection,
+- const char *seat_id,
+- const char *session_id)
++activate_session_id_for_systemd (GDBusConnection *connection,
++ const char *seat_id,
++ const char *session_id)
+ {
+ GError *local_error = NULL;
+ GVariant *reply;
+@@ -373,8 +677,8 @@ activate_session_id (GDBusConnection *connection,
+ }
+
+ static gboolean
+-get_login_window_session_id (const char *seat_id,
+- char **session_id)
++get_login_window_session_id_for_systemd (const char *seat_id,
++ char **session_id)
+ {
+ gboolean ret;
+ int res, i;
+@@ -442,8 +746,8 @@ out:
+ }
+
+ static gboolean
+-goto_login_session (GDBusConnection *connection,
+- GError **error)
++goto_login_session_for_systemd (GDBusConnection *connection,
++ GError **error)
+ {
+ gboolean ret;
+ int res;
+@@ -497,9 +801,9 @@ goto_login_session (GDBusConnection *connection,
+ return FALSE;
+ }
+
+- res = get_login_window_session_id (seat_id, &session_id);
++ res = get_login_window_session_id_for_systemd (seat_id, &session_id);
+ if (res && 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;
+@@ -518,6 +822,7 @@ goto_login_session (GDBusConnection *connection,
+
+ return ret;
+ }
++#endif
+
+ gboolean
+ gdm_goto_login_session (GError **error)
+@@ -533,7 +838,17 @@ gdm_goto_login_session (GError **error)
+ return FALSE;
+ }
+
+- return goto_login_session (connection, error);
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return goto_login_session_for_systemd (connection, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return goto_login_session_for_ck (connection, error);
++#else
++ return FALSE;
++#endif
+ }
+
+ static void
+diff --git a/common/gdm-common.h b/common/gdm-common.h
+index 8d83a124..4ffb9a25 100644
+--- a/common/gdm-common.h
++++ b/common/gdm-common.h
+@@ -31,6 +31,9 @@
+ expr; \
+ } while G_UNLIKELY (errno == EINTR);
+
++/* check if logind is running */
++#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0)
++
+ GQuark gdm_common_error_quark (void);
+ #define GDM_COMMON_ERROR gdm_common_error_quark()
+
+diff --git a/common/gdm-log.c b/common/gdm-log.c
+index 8a2d0154..22d8c7d6 100644
+--- a/common/gdm-log.c
++++ b/common/gdm-log.c
+@@ -30,7 +30,9 @@
+ #include <unistd.h>
+
+ #include <syslog.h>
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-daemon.h>
++#endif
+
+ #include <glib.h>
+ #include <glib/gstdio.h>
+@@ -133,7 +135,27 @@ gdm_log_init (void)
+
+ initialized = TRUE;
+
++#ifdef WITH_SYSTEMD
++ is_sd_booted = sd_booted () > 0;
++#endif
++
+ g_log_set_default_handler (gdm_log_default_handler, NULL);
++
++ /* Only set up syslog if !systemd, otherwise with systemd
++ * enabled, we keep the default GLib log handler which goes to
++ * stderr, which is routed to the appropriate place in the
++ * systemd service file.
++ */
++ if (!is_sd_booted) {
++ prg_name = g_get_prgname ();
++
++ options = LOG_PID;
++#ifdef LOG_PERROR
++ options |= LOG_PERROR;
++#endif
++
++ openlog (prg_name, options, LOG_DAEMON);
++ }
+ }
+
+ void
+diff --git a/configure.ac b/configure.ac
+index 602969bd..07a56ce4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -257,7 +257,15 @@ AC_ARG_WITH(tcp-wrappers,
+ [Use TCP Wrappers @<:@default=auto@:>@]),,
+ with_tcp_wrappers=auto)
+
+-
++AC_ARG_WITH(console-kit,
++ AS_HELP_STRING([--with-console-kit],
++ [Add ConsoleKit support @<:@default=auto@:>@]),,
++ with_console_kit=no)
++
++AC_ARG_WITH(systemd,
++ AS_HELP_STRING([--with-systemd],
++ [Add systemd support @<:@default=auto@:>@]),
++ [with_systemd=$withval], [with_systemd=auto])
+ AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
+ [Directory for systemd service files]),
+@@ -640,14 +648,8 @@ dnl ---------------------------------------------------------------------------
+ dnl - Check for utmp stuff
+ dnl ---------------------------------------------------------------------------
+
+-AC_CHECK_HEADERS(utmp.h utmpx.h libutil.h sys/param.h)
+-AC_CHECK_FUNCS([getutxent updwtmpx updwtmp])
+-AC_CHECK_LIB(util, login, [
+- AC_DEFINE(HAVE_LOGIN, 1, [Define if have login])
+- EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -lutil" ])
+-AC_CHECK_LIB(util, logout, [
+- AC_DEFINE(HAVE_LOGOUT, 1, [Define if have logout])
+- EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -lutil" ])
++AC_CHECK_HEADERS(utmp.h utmpx.h util.h sys/param.h)
++AC_CHECK_FUNCS([getutxent getttyent updwtmpx updwtmp])
+ AC_CHECK_LIB(util, logwtmp, [
+ AC_DEFINE(HAVE_LOGWTMP, 1, [Define if have logwtmp])
+ EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -lutil" ])
+@@ -896,12 +898,42 @@ AC_SUBST(XINERAMA_LIBS)
+ CPPFLAGS="$xinerama_save_cppflags"
+
+ dnl ---------------------------------------------------------------------------
++dnl - Check for ConsoleKit support
++dnl ---------------------------------------------------------------------------
++
++use_console_kit=no
++if test "x$with_console_kit" != "xno" ; then
++ use_console_kit=yes
++ AC_DEFINE(WITH_CONSOLE_KIT, 1, [Define to enable ConsoleKit support])
++fi
++AM_CONDITIONAL(WITH_CONSOLE_KIT, test x$use_console_kit = xyes)
++AC_SUBST(WITH_CONSOLE_KIT)
++
++dnl ---------------------------------------------------------------------------
+ dnl - Check for systemd support
+ dnl ---------------------------------------------------------------------------
+
+ PKG_CHECK_MODULES(SYSTEMD,
+- [libsystemd])
++ [libsystemd-login >= 186 libsystemd-daemon],
++ [have_systemd=yes], [have_systemd=no])
+
++if test "x$with_systemd" = "xauto" ; then
++ if test x$have_systemd = xno ; then
++ use_systemd=no
++ else
++ use_systemd=yes
++ fi
++else
++ use_systemd="$with_systemd"
++fi
++
++if test "x$use_systemd" != "xno" ; then
++ if test "x$have_systemd" = "xno"; then
++ AC_MSG_ERROR([Systemd support explicitly required, but systemd not found])
++ fi
++
++ AC_DEFINE(WITH_SYSTEMD, 1, [Define to enable systemd support])
++fi
+ AC_SUBST(SYSTEMD_CFLAGS)
+ AC_SUBST(SYSTEMD_LIBS)
+
+@@ -1094,6 +1126,14 @@ fi
+ AC_SUBST(GDM_CUSTOM_CONF)
+ AC_SUBST(GDM_OLD_CONF, '${gdmconfdir}/gdm.conf')
+
++AC_ARG_WITH(consolekit-directory,
++ [AC_HELP_STRING([--with-consolekit-directory],
++ [Specify the directory of ck-get-x11-display-device @<:@default=libexecdir@:>@])],,
++ [with_consolekit_directory="\${libexecdir}"])
++
++CONSOLEKIT_DIR=$with_consolekit_directory
++AC_SUBST(CONSOLEKIT_DIR)
++
+ AC_ARG_WITH(gnome-settings-daemon-directory,
+ [AC_HELP_STRING([--with-gnome-settings-daemon-directory],
+ [Specify the directory of gnome-settings-daemon used by the chooser @<:@default=libexecdir@:>@])],,
+@@ -1582,6 +1622,7 @@ echo "
+ dmconfdir: ${dmconfdir}
+ localstatedir: ${localstatedir}
+ datadir: ${datadir}
++ consolekit location: ${with_consolekit_directory}
+ gnome-settings-daemon location: ${with_gnome_settings_daemon_directory}
+ gnome-session-check-accel location: ${with_check_accelerated_directory}
+ source code location: ${srcdir}
+@@ -1612,6 +1653,8 @@ echo \
+ " Xinerama support: ${XINERAMA_SUPPORT}
+ XDMCP support: ${XDMCP_SUPPORT}
+ SELinux support: ${use_selinux}
++ ConsoleKit support: ${use_console_kit}
++ systemd support: ${use_systemd}
+ systemd unit dir: ${with_systemdsystemunitdir}
+ plymouth support: ${use_plymouth}
+ wayland support: ${enable_wayland_support}
+@@ -1620,3 +1663,4 @@ echo \
+ Enable documentation: ${enable_documentation}
+ Install GDM's Xsession: ${enable_gdm_xsession}
+ "
++
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index ab5dda06..e3cf73a6 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -20,6 +20,7 @@ AM_CPPFLAGS = \
+ -DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
+ -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
+ -DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
++ -DCONSOLEKIT_DIR=\"$(CONSOLEKIT_DIR)\" \
+ $(DISABLE_DEPRECATED_CFLAGS) \
+ $(DAEMON_CFLAGS) \
+ $(XLIB_CFLAGS) \
+@@ -264,6 +265,11 @@ EXTRA_gdm_SOURCES = \
+ $(XDMCP_SOURCES) \
+ $(NULL)
+
++CONSOLE_KIT_SOURCES = \
++ $(NULL)
++
++EXTRA_gdm_SOURCES += $(CONSOLE_KIT_SOURCES)
++
+ gdm_LDADD = \
+ $(top_builddir)/common/libgdmcommon.la \
+ $(XLIB_LIBS) \
+@@ -275,6 +281,10 @@ gdm_LDADD = \
+ $(EXTRA_DAEMON_LIBS) \
+ $(NULL)
+
++if WITH_CONSOLE_KIT
++gdm_SOURCES += $(CONSOLE_KIT_SOURCES)
++endif
++
+ CLEANFILES = \
+ gdm-display-glue.c \
+ gdm-local-display-factory-glue.c \
+diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c
+index 5fd346ff..88183265 100644
+--- a/daemon/gdm-launch-environment.c
++++ b/daemon/gdm-launch-environment.c
+@@ -50,7 +50,7 @@
+ #include "gdm-settings-direct.h"
+ #include "gdm-settings-keys.h"
+
+-#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
++#define INITIAL_SETUP_USERNAME "_gnome-initial-setup"
+ #define GDM_SESSION_MODE "gdm"
+ #define INITIAL_SETUP_SESSION_MODE "initial-setup"
+ #define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
+@@ -197,6 +197,9 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
+ char *seat_id;
+
+ seat_id = launch_environment->priv->x11_display_seat_id;
++ if (g_str_has_prefix (seat_id, "/org/freedesktop/ConsoleKit/")) {
++ seat_id += strlen ("/org/freedesktop/ConsoleKit/");
++ }
+
+ g_hash_table_insert (hash, g_strdup ("GDM_SEAT_ID"), g_strdup (seat_id));
+ }
+@@ -224,6 +227,8 @@ on_session_setup_complete (GdmSession *session,
+ gdm_session_set_environment_variable (launch_environment->priv->session, key, value);
+ }
+ g_hash_table_destroy (hash);
++
++ gdm_session_select_session_type (launch_environment->priv->session, "LoginWindow");
+ }
+
+ static void
+diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
+index 7a4643d0..b31310c7 100644
+--- a/daemon/gdm-local-display-factory.c
++++ b/daemon/gdm-local-display-factory.c
+@@ -42,6 +42,8 @@
+
+ #define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
+
++#define CK_SEAT1_PATH "/org/freedesktop/ConsoleKit/Seat1"
++
+ #define GDM_DBUS_PATH "/org/gnome/DisplayManager"
+ #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
+ #define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
+@@ -57,8 +59,10 @@ struct GdmLocalDisplayFactoryPrivate
+ /* FIXME: this needs to be per seat? */
+ guint num_failures;
+
++#ifdef WITH_SYSTEMD
+ guint seat_new_id;
+ guint seat_removed_id;
++#endif
+ };
+
+ enum {
+@@ -206,8 +210,10 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
+
+ g_debug ("GdmLocalDisplayFactory: Creating transient display");
+
+-#ifdef ENABLE_USER_DISPLAY_SERVER
+- display = gdm_local_display_new ();
++#if defined ENABLE_USER_DISPLAY_SERVER && defined WITH_SYSTEMD
++ if (LOGIND_RUNNING() > 0) {
++ display = gdm_local_display_new ();
++ }
+ #else
+ if (display == NULL) {
+ guint32 num;
+@@ -289,7 +295,7 @@ on_display_status_changed (GdmDisplay *display,
+ /* reset num failures */
+ factory->priv->num_failures = 0;
+
+- gdm_local_display_factory_sync_seats (factory);
++ create_display (factory, seat_id, session_type, is_initial);
+ }
+ break;
+ case GDM_DISPLAY_FAILED:
+@@ -368,7 +374,7 @@ create_display (GdmLocalDisplayFactory *factory,
+
+ g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
+
+-#ifdef ENABLE_USER_DISPLAY_SERVER
++#if defined ENABLE_USER_DISPLAY_SERVER && defined WITH_SYSTEMD
+ if (g_strcmp0 (seat_id, "seat0") == 0) {
+ display = gdm_local_display_new ();
+ if (session_type != NULL) {
+@@ -400,6 +406,8 @@ create_display (GdmLocalDisplayFactory *factory,
+ return display;
+ }
+
++#ifdef WITH_SYSTEMD
++
+ static void
+ delete_display (GdmLocalDisplayFactory *factory,
+ const char *seat_id) {
+@@ -536,6 +544,7 @@ gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
+ factory->priv->seat_removed_id = 0;
+ }
+ }
++#endif
+
+ static void
+ on_display_added (GdmDisplayStore *display_store,
+@@ -576,6 +585,7 @@ static gboolean
+ gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
+ {
+ GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
++ GdmDisplay *display;
+ GdmDisplayStore *store;
+
+ g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+@@ -594,8 +604,17 @@ gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
+ factory,
+ 0);
+
+- gdm_local_display_factory_start_monitor (factory);
+- return gdm_local_display_factory_sync_seats (factory);
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ gdm_local_display_factory_start_monitor (factory);
++ return gdm_local_display_factory_sync_seats (factory);
++ }
++#endif
++
++ /* On ConsoleKit just create Seat1, and that's it. */
++ display = create_display (factory, CK_SEAT1_PATH, NULL, TRUE);
++
++ return display != NULL;
+ }
+
+ static gboolean
+@@ -606,7 +625,9 @@ 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
+
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+
+@@ -762,7 +783,9 @@ gdm_local_display_factory_finalize (GObject *object)
+
+ g_hash_table_destroy (factory->priv->used_display_numbers);
+
++#ifdef WITH_SYSTEMD
+ gdm_local_display_factory_stop_monitor (factory);
++#endif
+
+ G_OBJECT_CLASS (gdm_local_display_factory_parent_class)->finalize (object);
+ }
+diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
+index d080b308..f5439855 100644
+--- a/daemon/gdm-manager.c
++++ b/daemon/gdm-manager.c
+@@ -36,7 +36,9 @@
+
+ #include <act/act-user-manager.h>
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-login.h>
++#endif
+
+ #include "gdm-common.h"
+
+@@ -61,7 +63,16 @@
+ #define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager"
+ #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
+
+-#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
++#define INITIAL_SETUP_USERNAME "_gnome-initial-setup"
++
++#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_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
++#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+ typedef struct
+ {
+@@ -206,9 +217,10 @@ plymouth_quit_without_transition (void)
+ }
+ #endif
+
++#ifdef WITH_SYSTEMD
+ static char *
+-get_session_id_for_pid (pid_t pid,
+- GError **error)
++get_session_id_for_pid_systemd (pid_t pid,
++ GError **error)
+ {
+ char *session, *gsession;
+ int ret;
+@@ -233,11 +245,61 @@ get_session_id_for_pid (pid_t pid,
+ return NULL;
+ }
+ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static char *
++get_session_id_for_pid_consolekit (GDBusConnection *connection,
++ pid_t pid,
++ GError **error)
++{
++ GVariant *reply;
++ char *retval;
++
++ reply = g_dbus_connection_call_sync (connection,
++ "org.freedesktop.ConsoleKit",
++ "/org/freedesktop/ConsoleKit/Manager",
++ "org.freedesktop.ConsoleKit.Manager",
++ "GetSessionForUnixProcess",
++ g_variant_new ("(u)", pid),
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, error);
++ if (reply == NULL) {
++ return NULL;
++ }
++
++ g_variant_get (reply, "(o)", &retval);
++ g_variant_unref (reply);
++
++ return retval;
++}
++#endif
++
++static char *
++get_session_id_for_pid (GDBusConnection *connection,
++ pid_t pid,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return get_session_id_for_pid_systemd (pid, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return get_session_id_for_pid_consolekit (connection, pid, error);
++#endif
++
++ return NULL;
++}
+
++#ifdef WITH_SYSTEMD
+ static gboolean
+-get_uid_for_session_id (const char *session_id,
+- uid_t *uid,
+- GError **error)
++get_uid_for_systemd_session_id (const char *session_id,
++ uid_t *uid,
++ GError **error)
+ {
+ int ret;
+
+@@ -254,6 +316,60 @@ get_uid_for_session_id (const char *session_id,
+
+ return TRUE;
+ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++get_uid_for_consolekit_session_id (GDBusConnection *connection,
++ const char *session_id,
++ uid_t *out_uid,
++ GError **error)
++{
++ GVariant *reply;
++ guint32 uid;
++
++ reply = g_dbus_connection_call_sync (connection,
++ "org.freedesktop.ConsoleKit",
++ session_id,
++ "org.freedesktop.ConsoleKit.Session",
++ "GetUnixUser",
++ NULL,
++ G_VARIANT_TYPE ("(u)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ error);
++ if (reply == NULL) {
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(u)", &uid);
++ g_variant_unref (reply);
++
++ *out_uid = (uid_t) uid;
++
++ return TRUE;
++}
++#endif
++
++static gboolean
++get_uid_for_session_id (GDBusConnection *connection,
++ const char *session_id,
++ uid_t *uid,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return get_uid_for_systemd_session_id (session_id, uid, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return get_uid_for_consolekit_session_id (connection, session_id, uid, error);
++#endif
++
++ return FALSE;
++}
+
+ static gboolean
+ lookup_by_session_id (const char *id,
+@@ -267,10 +383,50 @@ lookup_by_session_id (const char *id,
+ return g_strcmp0 (current, looking_for) == 0;
+ }
+
++#ifdef WITH_CONSOLE_KIT
+ static gboolean
+-is_login_session (GdmManager *self,
+- const char *session_id,
+- GError **error)
++is_consolekit_login_session (GdmManager *self,
++ GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++ GVariant *reply;
++ char *session_type = NULL;
++
++ reply = g_dbus_connection_call_sync (connection,
++ "org.freedesktop.ConsoleKit",
++ session_id,
++ "org.freedesktop.ConsoleKit.Session",
++ "GetSessionType",
++ NULL,
++ G_VARIANT_TYPE ("(s)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ error);
++ if (reply == NULL) {
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(s)", &session_type);
++ g_variant_unref (reply);
++
++ if (g_strcmp0 (session_type, "LoginWindow") != 0) {
++ g_free (session_type);
++
++ return FALSE;
++ }
++
++ g_free (session_type);
++ return TRUE;
++}
++#endif
++
++#ifdef WITH_SYSTEMD
++static gboolean
++is_systemd_login_session (GdmManager *self,
++ const char *session_id,
++ GError **error)
+ {
+ char *session_class = NULL;
+ int ret;
+@@ -295,11 +451,32 @@ is_login_session (GdmManager *self,
+ g_free (session_class);
+ return TRUE;
+ }
++#endif
+
+ static gboolean
+-activate_session_id (GdmManager *manager,
+- const char *seat_id,
+- const char *session_id)
++is_login_session (GdmManager *self,
++ GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return is_systemd_login_session (self, session_id, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return is_consolekit_login_session (self, connection, session_id, error);
++#endif
++
++ return FALSE;
++}
++
++#ifdef WITH_SYSTEMD
++static gboolean
++activate_session_id_for_systemd (GdmManager *manager,
++ const char *seat_id,
++ const char *session_id)
+ {
+ GError *error = NULL;
+ GVariant *reply;
+@@ -326,15 +503,74 @@ activate_session_id (GdmManager *manager,
+
+ return TRUE;
+ }
++#endif
+
++#ifdef WITH_CONSOLE_KIT
+ static gboolean
+-session_unlock (GdmManager *manager,
+- const char *ssid)
++activate_session_id_for_ck (GdmManager *manager,
++ const char *seat_id,
++ const char *session_id)
+ {
+ GError *error = NULL;
+ GVariant *reply;
+
+- g_debug ("Unlocking session %s", ssid);
++ reply = g_dbus_connection_call_sync (manager->priv->connection,
++ CK_NAME,
++ seat_id,
++ "org.freedesktop.ConsoleKit.Seat",
++ "ActivateSession",
++ g_variant_new ("(o)", session_id),
++ NULL, /* expected reply */
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++ if (reply == NULL) {
++ g_debug ("GdmManager: ConsoleKit %s raised:\n %s\n\n",
++ g_dbus_error_get_remote_error (error), error->message);
++ g_error_free (error);
++
++ /* It is very likely that the "error" just reported is
++ * that the session is already active. Unfortunately,
++ * ConsoleKit doesn't use proper error codes and it
++ * translates the error message, so we have no real way
++ * to detect this case...
++ */
++ return TRUE;
++ }
++
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++#endif
++
++static gboolean
++activate_session_id (GdmManager *manager,
++ const char *seat_id,
++ const char *session_id)
++{
++
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return activate_session_id_for_systemd (manager, seat_id, session_id);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return activate_session_id_for_ck (manager, seat_id, session_id);
++#else
++ return FALSE;
++#endif
++}
++
++#ifdef WITH_SYSTEMD
++static gboolean
++session_unlock_for_systemd (GdmManager *manager,
++ const char *ssid)
++{
++ GError *error = NULL;
++ GVariant *reply;
+
+ reply = g_dbus_connection_call_sync (manager->priv->connection,
+ "org.freedesktop.login1",
+@@ -358,6 +594,59 @@ session_unlock (GdmManager *manager,
+
+ return TRUE;
+ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++session_unlock_for_ck (GdmManager *manager,
++ const char *ssid)
++{
++ GError *error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (manager->priv->connection,
++ CK_NAME,
++ ssid,
++ CK_SESSION_INTERFACE,
++ "Unlock",
++ NULL, /* parameters */
++ NULL, /* expected reply */
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++ if (reply == NULL) {
++ g_debug ("GdmManager: ConsoleKit %s raised:\n %s\n\n",
++ g_dbus_error_get_remote_error (error), error->message);
++ g_error_free (error);
++ return FALSE;
++ }
++
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++#endif
++
++static gboolean
++session_unlock (GdmManager *manager,
++ const char *ssid)
++{
++
++ g_debug ("Unlocking session %s", ssid);
++
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return session_unlock_for_systemd (manager, ssid);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return session_unlock_for_ck (manager, ssid);
++#else
++ return TRUE;
++#endif
++}
+
+ static GdmSession *
+ find_session_for_user_on_seat (GdmManager *manager,
+@@ -389,10 +678,43 @@ find_session_for_user_on_seat (GdmManager *manager,
+ return NULL;
+ }
+
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++is_consolekit_remote_session (GdmManager *self,
++ GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++ GVariant *reply;
++ gboolean is_remote;
++
++ reply = g_dbus_connection_call_sync (connection,
++ "org.freedesktop.ConsoleKit",
++ session_id,
++ "org.freedesktop.ConsoleKit.Session",
++ "IsLocal",
++ NULL,
++ G_VARIANT_TYPE ("(b)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ error);
++ if (reply == NULL) {
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(b)", &is_remote);
++ g_variant_unref (reply);
++
++ return is_remote;
++}
++#endif
++
++#ifdef WITH_SYSTEMD
+ static gboolean
+-is_remote_session (GdmManager *self,
+- const char *session_id,
+- GError **error)
++is_systemd_remote_session (GdmManager *self,
++ const char *session_id,
++ GError **error)
+ {
+ char *seat;
+ int ret;
+@@ -418,10 +740,31 @@ is_remote_session (GdmManager *self,
+
+ return is_remote;
+ }
++#endif
++
++static gboolean
++is_remote_session (GdmManager *self,
++ GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return is_systemd_remote_session (self, session_id, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return is_consolekit_remote_session (self, connection, session_id, error);
++#endif
++
++ return FALSE;
++}
+
++#ifdef WITH_SYSTEMD
+ static char *
+-get_seat_id_for_session_id (const char *session_id,
+- GError **error)
++get_seat_id_for_systemd_session_id (const char *session_id,
++ GError **error)
+ {
+ int ret;
+ char *seat, *out_seat;
+@@ -446,10 +789,61 @@ get_seat_id_for_session_id (const char *session_id,
+
+ return out_seat;
+ }
++#endif
+
++#ifdef WITH_CONSOLE_KIT
+ static char *
+-get_tty_for_session_id (const char *session_id,
+- GError **error)
++get_seat_id_for_consolekit_session_id (GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++ GVariant *reply;
++ char *retval;
++
++ reply = g_dbus_connection_call_sync (connection,
++ "org.freedesktop.ConsoleKit",
++ session_id,
++ "org.freedesktop.ConsoleKit.Session",
++ "GetSeatId",
++ NULL,
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ error);
++ if (reply == NULL) {
++ return NULL;
++ }
++
++ g_variant_get (reply, "(o)", &retval);
++ g_variant_unref (reply);
++
++ return retval;
++}
++#endif
++
++static char *
++get_seat_id_for_session_id (GDBusConnection *connection,
++ const char *session_id,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return get_seat_id_for_systemd_session_id (session_id, error);
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ return get_seat_id_for_consolekit_session_id (connection, session_id, error);
++#endif
++
++ return NULL;
++}
++
++#ifdef WITH_SYSTEMD
++static char *
++get_tty_for_systemd_session_id (const char *session_id,
++ GError **error)
+ {
+ int ret;
+ char *tty, *out_tty;
+@@ -473,6 +867,20 @@ get_tty_for_session_id (const char *session_id,
+
+ return out_tty;
+ }
++#endif
++
++static char *
++get_tty_for_session_id (const char *session_id,
++ GError **error)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return get_tty_for_systemd_session_id (session_id, error);
++ }
++#endif
++
++ return NULL;
++}
+
+ static void
+ get_display_and_details_for_bus_sender (GdmManager *self,
+@@ -516,7 +924,7 @@ get_display_and_details_for_bus_sender (GdmManager *self,
+ goto out;
+ }
+
+- session_id = get_session_id_for_pid (pid, &error);
++ session_id = get_session_id_for_pid (connection, pid, &error);
+
+ if (session_id == NULL) {
+ g_debug ("GdmManager: Error while retrieving session id for sender: %s",
+@@ -530,7 +938,7 @@ get_display_and_details_for_bus_sender (GdmManager *self,
+ }
+
+ if (out_is_login_screen != NULL) {
+- *out_is_login_screen = is_login_session (self, session_id, &error);
++ *out_is_login_screen = is_login_session (self, connection, session_id, &error);
+
+ if (error != NULL) {
+ g_debug ("GdmManager: Error while checking if sender is login screen: %s",
+@@ -540,7 +948,7 @@ get_display_and_details_for_bus_sender (GdmManager *self,
+ }
+ }
+
+- if (!get_uid_for_session_id (session_id, &session_uid, &error)) {
++ if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) {
+ g_debug ("GdmManager: Error while retrieving uid for session: %s",
+ error->message);
+ g_error_free (error);
+@@ -557,7 +965,7 @@ get_display_and_details_for_bus_sender (GdmManager *self,
+ }
+
+ if (out_seat_id != NULL) {
+- *out_seat_id = get_seat_id_for_session_id (session_id, &error);
++ *out_seat_id = get_seat_id_for_session_id (connection, session_id, &error);
+
+ if (error != NULL) {
+ g_debug ("GdmManager: Error while retrieving seat id for session: %s",
+@@ -567,7 +975,7 @@ get_display_and_details_for_bus_sender (GdmManager *self,
+ }
+
+ if (out_is_remote != NULL) {
+- *out_is_remote = is_remote_session (self, session_id, &error);
++ *out_is_remote = is_remote_session (self, connection, session_id, &error);
+
+ if (error != NULL) {
+ g_debug ("GdmManager: Error while retrieving remoteness for session: %s",
+@@ -956,7 +1364,8 @@ on_reauthentication_client_rejected (GdmSession *session,
+ * same audit session, ignore it since it doesn't "own" the
+ * reauthentication session
+ */
+- client_session_id = get_session_id_for_pid (pid_of_client,
++ client_session_id = get_session_id_for_pid (self->priv->connection,
++ pid_of_client,
+ NULL);
+ session_id = g_object_get_data (G_OBJECT (session), "caller-session-id");
+
+@@ -1168,16 +1577,20 @@ static gboolean
+ display_is_on_seat0 (GdmDisplay *display)
+ {
+ gboolean is_on_seat0 = TRUE;
+- char *seat_id = NULL;
+
+- g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ char *seat_id = NULL;
+
+- if (g_strcmp0 (seat_id, "seat0") != 0) {
+- is_on_seat0 = FALSE;
+- }
++ g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
+
+- g_free (seat_id);
++ if (g_strcmp0 (seat_id, "seat0") != 0) {
++ is_on_seat0 = FALSE;
++ }
+
++ g_free (seat_id);
++ }
++#endif
+ return is_on_seat0;
+ }
+
+@@ -1315,133 +1728,6 @@ maybe_start_pending_initial_login (GdmManager *manager,
+ g_free (user_session_seat_id);
+ }
+
+-static gboolean
+-get_login_window_session_id (const char *seat_id,
+- char **session_id)
+-{
+- gboolean ret;
+- int res, i;
+- char **sessions;
+- char *service_id;
+- char *service_class;
+- char *state;
+-
+- 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_class (sessions[i], &service_class);
+- if (res < 0) {
+- g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
+- ret = FALSE;
+- goto out;
+- }
+-
+- if (strcmp (service_class, "greeter") != 0) {
+- free (service_class);
+- continue;
+- }
+-
+- free (service_class);
+-
+- ret = sd_session_get_state (sessions[i], &state);
+- if (ret < 0) {
+- g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
+- ret = FALSE;
+- goto out;
+- }
+-
+- if (g_strcmp0 (state, "closing") == 0) {
+- free (state);
+- continue;
+- }
+- free (state);
+-
+- 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-launch-environment") == 0) {
+- *session_id = g_strdup (sessions[i]);
+- ret = TRUE;
+-
+- free (service_id);
+- goto out;
+- }
+-
+- free (service_id);
+- }
+-
+- *session_id = NULL;
+- ret = TRUE;
+-
+-out:
+- if (sessions) {
+- for (i = 0; sessions[i]; i ++) {
+- free (sessions[i]);
+- }
+-
+- free (sessions);
+- }
+-
+- return ret;
+-}
+-
+-static void
+-activate_login_window_session_on_seat (GdmManager *self,
+- const char *seat_id)
+-{
+- char *session_id;
+-
+- if (!get_login_window_session_id (seat_id, &session_id)) {
+- return;
+- }
+-
+- activate_session_id (self, seat_id, session_id);
+-}
+-
+-static void
+-maybe_activate_other_session (GdmManager *self,
+- GdmDisplay *old_display)
+-{
+- char *seat_id = NULL;
+- char *session_id;
+- int ret;
+-
+- g_object_get (G_OBJECT (old_display),
+- "seat-id", &seat_id,
+- NULL);
+-
+- ret = sd_seat_get_active (seat_id, &session_id, NULL);
+-
+- if (ret == 0) {
+- GdmDisplay *display;
+-
+- display = gdm_display_store_find (self->priv->display_store,
+- lookup_by_session_id,
+- (gpointer) session_id);
+-
+- if (display == NULL) {
+- activate_login_window_session_on_seat (self, seat_id);
+- }
+- }
+-
+- g_free (seat_id);
+-}
+-
+ static const char *
+ get_username_for_greeter_display (GdmManager *manager,
+ GdmDisplay *display)
+@@ -1684,7 +1970,6 @@ on_display_status_changed (GdmDisplay *display,
+ manager->priv->ran_once = TRUE;
+ }
+ maybe_start_pending_initial_login (manager, display);
+- maybe_activate_other_session (manager, display);
+ break;
+ default:
+ break;
+@@ -2014,11 +2299,57 @@ on_user_session_died (GdmSession *session,
+ }
+
+ static char *
++query_ck_for_display_device (GdmManager *manager,
++ GdmDisplay *display)
++{
++ char *out;
++ char *command;
++ char *display_name = NULL;
++ int status;
++ gboolean res;
++ GError *error;
++
++ g_object_get (G_OBJECT (display),
++ "x11-display-name", &display_name,
++ NULL);
++
++ error = NULL;
++ command = g_strdup_printf (CONSOLEKIT_DIR "/ck-get-x11-display-device --display %s",
++ display_name);
++ g_free (display_name);
++
++ g_debug ("GdmManager: Running helper %s", command);
++ out = NULL;
++ res = g_spawn_command_line_sync (command,
++ &out,
++ NULL,
++ &status,
++ &error);
++ if (! res) {
++ g_warning ("GdmManager: Could not run helper %s: %s", command, error->message);
++ g_error_free (error);
++ } else {
++ out = g_strstrip (out);
++ g_debug ("GdmManager: Got tty: '%s'", out);
++ }
++
++ g_free (command);
++
++ return out;
++}
++
++static char *
+ get_display_device (GdmManager *manager,
+ GdmDisplay *display)
+ {
+- /* systemd finds the display device out on its own based on the display */
+- return NULL;
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ /* systemd finds the display device out on its own based on the display */
++ return NULL;
++ }
++#endif
++
++ return query_ck_for_display_device (manager, display);
+ }
+
+ static void
+@@ -2027,26 +2358,6 @@ on_session_reauthenticated (GdmSession *session,
+ GdmManager *manager)
+ {
+ gboolean fail_if_already_switched = FALSE;
+-
+- if (gdm_session_get_display_mode (session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
+- const char *seat_id;
+- char *session_id;
+-
+- seat_id = gdm_session_get_display_seat_id (session);
+- if (get_login_window_session_id (seat_id, &session_id)) {
+- GdmDisplay *display = gdm_display_store_find (manager->priv->display_store,
+- lookup_by_session_id,
+- (gpointer) session_id);
+-
+- if (display != NULL) {
+- gdm_display_stop_greeter_session (display);
+- gdm_display_unmanage (display);
+- gdm_display_finish (display);
+- }
+- }
+- g_free (session_id);
+- }
+-
+ /* There should already be a session running, so jump to its
+ * VT. In the event we're already on the right VT, (i.e. user
+ * used an unlock screen instead of a user switched login screen),
+diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
+index 6357d344..6ecd0f70 100644
+--- a/daemon/gdm-server.c
++++ b/daemon/gdm-server.c
+@@ -43,7 +43,9 @@
+ #include <linux/vt.h>
+ #endif
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-daemon.h>
++#endif
+
+ #ifdef ENABLE_SYSTEMD_JOURNAL
+ #include <systemd/sd-journal.h>
+@@ -122,11 +124,59 @@ static void gdm_server_finalize (GObject *object);
+
+ G_DEFINE_TYPE (GdmServer, gdm_server, G_TYPE_OBJECT)
+
++static char *
++_gdm_server_query_ck_for_display_device (GdmServer *server)
++{
++ char *out;
++ char *command;
++ int status;
++ gboolean res;
++ GError *error;
++
++ g_return_val_if_fail (GDM_IS_SERVER (server), NULL);
++
++ error = NULL;
++ command = g_strdup_printf (CONSOLEKIT_DIR "/ck-get-x11-display-device --display %s",
++ server->priv->display_name);
++
++ g_debug ("GdmServer: Running helper %s", command);
++ out = NULL;
++ res = g_spawn_command_line_sync (command,
++ &out,
++ NULL,
++ &status,
++ &error);
++ if (! res) {
++ g_warning ("Could not run helper: %s", error->message);
++ g_error_free (error);
++ } else {
++ out = g_strstrip (out);
++ g_debug ("GdmServer: Got tty: '%s'", out);
++ }
++
++ g_free (command);
++
++ return out;
++}
++
+ char *
+ gdm_server_get_display_device (GdmServer *server)
+ {
+- /* systemd finds the display device out on its own based on the display */
+- return NULL;
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ /* systemd finds the display device out on its own based on the display */
++ return NULL;
++ }
++#endif
++
++ if (server->priv->display_device == NULL) {
++ server->priv->display_device =
++ _gdm_server_query_ck_for_display_device (server);
++
++ g_object_notify (G_OBJECT (server), "display-device");
++ }
++
++ return g_strdup (server->priv->display_device);
+ }
+
+ static void
+@@ -226,7 +276,9 @@ gdm_server_init_command (GdmServer *server)
+ debug_options = "";
+ }
+
+-#define X_SERVER_ARG_FORMAT " -background none -noreset -verbose %s%s"
++ #define X_SERVER_ARG_FORMAT " -background none -noreset -verbose %s%s"
++
++#ifdef WITH_SYSTEMD
+
+ /* This is a temporary hack to work around the fact that XOrg
+ * currently lacks support for multi-seat hotplugging for
+@@ -242,6 +294,10 @@ gdm_server_init_command (GdmServer *server)
+ * wasn't booted using systemd, or b) the wrapper tool is
+ * missing, or c) we are running for the main seat 'seat0'. */
+
++ if (!LOGIND_RUNNING()) {
++ goto fallback;
++ }
++
+ #ifdef ENABLE_SYSTEMD_JOURNAL
+ /* For systemd, we don't have a log file but instead log to stdout,
+ so set it to the xserver's built-in default verbosity */
+@@ -264,8 +320,9 @@ gdm_server_init_command (GdmServer *server)
+ return;
+
+ fallback:
+- server->priv->command = g_strdup_printf (X_SERVER X_SERVER_ARG_FORMAT, verbosity, debug_options);
++#endif
+
++ server->priv->command = g_strdup_printf (X_SERVER X_SERVER_ARG_FORMAT, verbosity, debug_options);
+ }
+
+ static gboolean
+@@ -315,10 +372,12 @@ gdm_server_resolve_command_line (GdmServer *server,
+ argv[len++] = g_strdup (server->priv->auth_file);
+ }
+
+- if (server->priv->display_seat_id != NULL) {
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING() && server->priv->display_seat_id != NULL) {
+ argv[len++] = g_strdup ("-seat");
+ argv[len++] = g_strdup (server->priv->display_seat_id);
+ }
++#endif
+
+ /* If we were compiled with Xserver >= 1.17 we need to specify
+ * '-listen tcp' as the X server dosen't listen on tcp sockets
+diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c
+index 69dca2e5..c117f709 100644
+--- a/daemon/gdm-session-worker-job.c
++++ b/daemon/gdm-session-worker-job.c
+@@ -36,7 +36,9 @@
+ #include <sys/prctl.h>
+ #endif
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-daemon.h>
++#endif
+
+ #ifdef ENABLE_SYSTEMD_JOURNAL
+ #include <systemd/sd-journal.h>
+diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
+index d97b02b5..a6354163 100644
+--- a/daemon/gdm-session-worker.c
++++ b/daemon/gdm-session-worker.c
+@@ -28,9 +28,11 @@
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
++#ifdef WITH_SYSTEMD
+ #include <sys/ioctl.h>
+ #include <sys/vt.h>
+ #include <sys/kd.h>
++#endif
+ #include <errno.h>
+ #include <grp.h>
+ #include <pwd.h>
+@@ -49,7 +51,9 @@
+
+ #include <X11/Xauth.h>
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-daemon.h>
++#endif
+
+ #ifdef ENABLE_SYSTEMD_JOURNAL
+ #include <systemd/sd-journal.h>
+@@ -131,6 +135,10 @@ struct GdmSessionWorkerPrivate
+
+ int exit_code;
+
++#ifdef WITH_CONSOLE_KIT
++ char *session_cookie;
++#endif
++
+ pam_handle_t *pam_handle;
+
+ GPid child_pid;
+@@ -145,6 +153,7 @@ struct GdmSessionWorkerPrivate
+ char *hostname;
+ char *username;
+ char *log_file;
++ char *session_type;
+ char *session_id;
+ uid_t uid;
+ gid_t gid;
+@@ -207,6 +216,204 @@ G_DEFINE_TYPE_WITH_CODE (GdmSessionWorker,
+ G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_WORKER,
+ worker_interface_init))
+
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++open_ck_session (GdmSessionWorker *worker)
++{
++ GDBusConnection *system_bus;
++ GVariantBuilder builder;
++ GVariant *parameters;
++ GVariant *in_args;
++ struct passwd *pwent;
++ GVariant *reply;
++ GError *error = NULL;
++ const char *display_name;
++ const char *display_device;
++ const char *display_hostname;
++ const char *session_type;
++ gint32 uid;
++
++ g_assert (worker->priv->session_cookie == NULL);
++
++ if (worker->priv->x11_display_name != NULL) {
++ display_name = worker->priv->x11_display_name;
++ } else {
++ display_name = "";
++ }
++ if (worker->priv->hostname != NULL) {
++ display_hostname = worker->priv->hostname;
++ } else {
++ display_hostname = "";
++ }
++ if (worker->priv->display_device != NULL) {
++ display_device = worker->priv->display_device;
++ } else {
++ display_device = "";
++ }
++
++ if (worker->priv->session_type != NULL) {
++ session_type = worker->priv->session_type;
++ } else {
++ session_type = "";
++ }
++
++ g_assert (worker->priv->username != NULL);
++
++ gdm_get_pwent_for_name (worker->priv->username, &pwent);
++ if (pwent == NULL) {
++ goto out;
++ }
++
++ uid = (gint32) pwent->pw_uid;
++
++ error = NULL;
++ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
++
++ if (system_bus == NULL) {
++ g_warning ("Couldn't create connection to system bus: %s",
++ error->message);
++
++ g_error_free (error);
++ goto out;
++ }
++
++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sv)"));
++ g_variant_builder_add_parsed (&builder, "('unix-user', <%i>)", uid);
++ g_variant_builder_add_parsed (&builder, "('x11-display-device', <%s>)", display_device);
++ g_variant_builder_add_parsed (&builder, "('x11-display', <%s>)", display_name);
++ g_variant_builder_add_parsed (&builder, "('remote-host-name', <%s>)", display_hostname);
++ g_variant_builder_add_parsed (&builder, "('is-local', <%b>)", worker->priv->display_is_local);
++ g_variant_builder_add_parsed (&builder, "('session-type', <%s>)", session_type);
++
++ parameters = g_variant_builder_end (&builder);
++ in_args = g_variant_new_tuple (&parameters, 1);
++
++ reply = g_dbus_connection_call_sync (system_bus,
++ "org.freedesktop.ConsoleKit",
++ "/org/freedesktop/ConsoleKit/Manager",
++ "org.freedesktop.ConsoleKit.Manager",
++ "OpenSessionWithParameters",
++ in_args,
++ G_VARIANT_TYPE ("(s)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++
++ if (! reply) {
++ g_warning ("%s\n", error->message);
++ g_clear_error (&error);
++ goto out;
++ }
++
++ g_variant_get (reply, "(s)", &worker->priv->session_cookie);
++
++ g_variant_unref (reply);
++
++out:
++ return worker->priv->session_cookie != NULL;
++}
++
++static void
++close_ck_session (GdmSessionWorker *worker)
++{
++ GDBusConnection *system_bus;
++ GVariant *reply;
++ GError *error = NULL;
++ gboolean was_closed;
++
++ if (worker->priv->session_cookie == NULL) {
++ return;
++ }
++
++ error = NULL;
++ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
++
++ if (system_bus == NULL) {
++ g_warning ("Couldn't create connection to system bus: %s",
++ error->message);
++
++ g_error_free (error);
++ goto out;
++ }
++
++ reply = g_dbus_connection_call_sync (system_bus,
++ "org.freedesktop.ConsoleKit",
++ "/org/freedesktop/ConsoleKit/Manager",
++ "org.freedesktop.ConsoleKit.Manager",
++ "CloseSession",
++ g_variant_new ("(s)", worker->priv->session_cookie),
++ G_VARIANT_TYPE ("(b)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++
++ if (! reply) {
++ g_warning ("%s", error->message);
++ g_clear_error (&error);
++ goto out;
++ }
++
++ g_variant_get (reply, "(b)", &was_closed);
++
++ if (!was_closed) {
++ g_warning ("Unable to close ConsoleKit session");
++ }
++
++ g_variant_unref (reply);
++
++out:
++ g_clear_pointer (&worker->priv->session_cookie,
++ (GDestroyNotify) g_free);
++}
++
++static char *
++get_ck_session_id (GdmSessionWorker *worker)
++{
++ GDBusConnection *system_bus;
++ GVariant *reply;
++ GError *error = NULL;
++ char *session_id = NULL;
++
++ error = NULL;
++ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
++
++ if (system_bus == NULL) {
++ g_warning ("Couldn't create connection to system bus: %s",
++ error->message);
++
++ g_error_free (error);
++ goto out;
++ }
++
++ reply = g_dbus_connection_call_sync (system_bus,
++ "org.freedesktop.ConsoleKit",
++ "/org/freedesktop/ConsoleKit/Manager",
++ "org.freedesktop.ConsoleKit.Manager",
++ "GetSessionForCookie",
++ g_variant_new ("(s)", worker->priv->session_cookie),
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL,
++ &error);
++
++ if (reply == NULL) {
++ g_warning ("%s", error->message);
++ g_clear_error (&error);
++ goto out;
++ }
++
++ g_variant_get (reply, "(o)", &session_id);
++
++ g_variant_unref (reply);
++
++out:
++ return session_id;
++}
++#endif
++
+ /* adapted from glib script_execute */
+ static void
+ script_execute (const gchar *file,
+@@ -754,6 +961,7 @@ gdm_session_worker_stop_auditor (GdmSessionWorker *worker)
+ worker->priv->auditor = NULL;
+ }
+
++#ifdef WITH_SYSTEMD
+ static void
+ on_release_display (int signal)
+ {
+@@ -879,6 +1087,7 @@ jump_to_vt (GdmSessionWorker *worker,
+
+ close (active_vt_tty_fd);
+ }
++#endif
+
+ static void
+ gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
+@@ -909,9 +1118,11 @@ gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
+
+ gdm_session_worker_stop_auditor (worker);
+
++#ifdef WITH_SYSTEMD
+ if (worker->priv->login_vt != worker->priv->session_vt) {
+ jump_to_vt (worker, worker->priv->login_vt);
+ }
++#endif
+
+ worker->priv->login_vt = 0;
+ worker->priv->session_vt = 0;
+@@ -963,32 +1174,6 @@ _get_xauth_for_pam (const char *x11_authority_file)
+ #endif
+
+ static gboolean
+-ensure_login_vt (GdmSessionWorker *worker)
+-{
+- int fd;
+- struct vt_stat vt_state = { 0 };
+- gboolean got_login_vt = FALSE;
+-
+- fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
+-
+- if (fd < 0) {
+- g_debug ("GdmSessionWorker: couldn't open VT master: %m");
+- return FALSE;
+- }
+-
+- if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
+- g_debug ("GdmSessionWorker: couldn't get current VT: %m");
+- goto out;
+- }
+-
+- worker->priv->login_vt = vt_state.v_active;
+- got_login_vt = TRUE;
+-out:
+- close (fd);
+- return got_login_vt;
+-}
+-
+-static gboolean
+ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+ const char *service,
+ const char *username,
+@@ -1002,7 +1187,6 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+ {
+ struct pam_conv pam_conversation;
+ int error_code;
+- char tty_string[256];
+
+ g_assert (worker->priv->pam_handle == NULL);
+
+@@ -1063,10 +1247,12 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+ }
+ }
+
++#ifdef WITH_SYSTEMD
+ /* set seat ID */
+- if (seat_id != NULL && seat_id[0] != '\0') {
++ if (seat_id != NULL && seat_id[0] != '\0' && LOGIND_RUNNING()) {
+ gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
+ }
++#endif
+
+ if (strcmp (service, "gdm-launch-environment") == 0) {
+ gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
+@@ -1075,14 +1261,6 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+ g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
+ worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;
+
+- /* Temporarily set PAM_TTY with the currently active VT (login screen)
+- PAM_TTY will be reset with the users VT right before the user session is opened */
+- ensure_login_vt (worker);
+- g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt);
+- pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
+- if (!display_is_local)
+- worker->priv->password_is_required = TRUE;
+-
+ out:
+ if (error_code != PAM_SUCCESS) {
+ gdm_session_worker_uninitialize_pam (worker, error_code);
+@@ -1629,6 +1807,26 @@ gdm_session_worker_get_environment (GdmSessionWorker *worker)
+ return (const char * const *) pam_getenvlist (worker->priv->pam_handle);
+ }
+
++#ifdef WITH_CONSOLE_KIT
++static void
++register_ck_session (GdmSessionWorker *worker)
++{
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ return;
++ }
++#endif
++
++ open_ck_session (worker);
++
++ if (worker->priv->session_cookie != NULL) {
++ gdm_session_worker_set_environment_variable (worker,
++ "XDG_SESSION_COOKIE",
++ worker->priv->session_cookie);
++ }
++}
++#endif
++
+ static gboolean
+ run_script (GdmSessionWorker *worker,
+ const char *dir)
+@@ -1659,6 +1857,9 @@ session_worker_child_watch (GPid pid,
+ : WIFSIGNALED (status) ? WTERMSIG (status)
+ : -1);
+
++#ifdef WITH_CONSOLE_KIT
++ close_ck_session (worker);
++#endif
+
+ gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
+
+@@ -1849,12 +2050,14 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
+
+ error_code = PAM_SUCCESS;
+
++#ifdef WITH_SYSTEMD
+ /* If we're in new vt mode, jump to the new vt now. There's no need to jump for
+ * the other two modes: in the logind case, the session will activate itself when
+ * ready, and in the reuse server case, we're already on the correct VT. */
+ if (worker->priv->display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) {
+ jump_to_vt (worker, worker->priv->session_vt);
+ }
++#endif
+
+ if (!worker->priv->is_program_session && !run_script (worker, GDMCONFDIR "/PostLogin")) {
+ g_set_error (error,
+@@ -1919,6 +2122,7 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
+ _exit (2);
+ }
+
++#ifdef WITH_SYSTEMD
+ /* Take control of the tty
+ */
+ if (needs_controlling_terminal) {
+@@ -1926,6 +2130,7 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
+ g_debug ("GdmSessionWorker: could not take control of tty: %m");
+ }
+ }
++#endif
+
+ #ifdef HAVE_LOGINCAP
+ if (setusercontext (NULL, passwd_entry, passwd_entry->pw_uid, LOGIN_SETALL) < 0) {
+@@ -2070,11 +2275,13 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
+ return TRUE;
+ }
+
++#ifdef WITH_SYSTEMD
+ static gboolean
+ set_up_for_new_vt (GdmSessionWorker *worker)
+ {
+ int fd;
+ char vt_string[256], tty_string[256];
++ struct vt_stat vt_state = { 0 };
+ int session_vt = 0;
+
+ fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
+@@ -2084,6 +2291,11 @@ set_up_for_new_vt (GdmSessionWorker *worker)
+ return FALSE;
+ }
+
++ if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
++ g_debug ("GdmSessionWorker: couldn't get current VT: %m");
++ goto fail;
++ }
++
+ if (worker->priv->display_is_initial) {
+ session_vt = atoi (GDM_INITIAL_VT);
+ } else {
+@@ -2093,6 +2305,7 @@ set_up_for_new_vt (GdmSessionWorker *worker)
+ }
+ }
+
++ worker->priv->login_vt = vt_state.v_active;
+ worker->priv->session_vt = session_vt;
+
+ close (fd);
+@@ -2155,6 +2368,7 @@ fail:
+ close (fd);
+ return FALSE;
+ }
++#endif
+
+ static gboolean
+ set_up_for_current_vt (GdmSessionWorker *worker,
+@@ -2222,12 +2436,14 @@ set_up_for_current_vt (GdmSessionWorker *worker,
+ }
+ #endif
+
++#ifdef WITH_SYSTEMD
+ if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
+ g_debug ("GdmSessionWorker: setting XDG_VTNR to current vt");
+ set_xdg_vtnr_to_current_vt (worker);
+ } else {
+ g_debug ("GdmSessionWorker: not setting XDG_VTNR since not seat0");
+ }
++#endif
+
+ return TRUE;
+ out:
+@@ -2251,6 +2467,7 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
+ return FALSE;
+ }
+ break;
++#ifdef WITH_SYSTEMD
+ case GDM_SESSION_DISPLAY_MODE_NEW_VT:
+ case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
+ if (!set_up_for_new_vt (worker)) {
+@@ -2261,6 +2478,7 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
+ return FALSE;
+ }
+ break;
++#endif
+ }
+
+ flags = 0;
+@@ -2282,7 +2500,17 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
+ g_debug ("GdmSessionWorker: state SESSION_OPENED");
+ worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED;
+
++#ifdef WITH_SYSTEMD
+ session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ register_ck_session (worker);
++
++ if (session_id == NULL) {
++ session_id = get_ck_session_id (worker);
++ }
++#endif
+
+ if (session_id != NULL) {
+ g_free (worker->priv->session_id);
+@@ -2388,6 +2616,19 @@ gdm_session_worker_handle_set_session_name (GdmDBusWorker *object,
+ }
+
+ static gboolean
++gdm_session_worker_handle_set_session_type (GdmDBusWorker *object,
++ GDBusMethodInvocation *invocation,
++ const char *session_type)
++{
++ GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
++ g_debug ("GdmSessionWorker: session type set to %s", session_type);
++ g_free (worker->priv->session_type);
++ worker->priv->session_type = g_strdup (session_type);
++ gdm_dbus_worker_complete_set_session_type (object, invocation);
++ return TRUE;
++}
++
++static gboolean
+ gdm_session_worker_handle_set_session_display_mode (GdmDBusWorker *object,
+ GDBusMethodInvocation *invocation,
+ const char *str)
+@@ -3194,6 +3435,7 @@ worker_interface_init (GdmDBusWorkerIface *interface)
+ interface->handle_open = gdm_session_worker_handle_open;
+ interface->handle_set_language_name = gdm_session_worker_handle_set_language_name;
+ interface->handle_set_session_name = gdm_session_worker_handle_set_session_name;
++ interface->handle_set_session_type = gdm_session_worker_handle_set_session_type;
+ interface->handle_set_session_display_mode = gdm_session_worker_handle_set_session_display_mode;
+ interface->handle_set_environment_variable = gdm_session_worker_handle_set_environment_variable;
+ interface->handle_start_program = gdm_session_worker_handle_start_program;
+diff --git a/daemon/gdm-session-worker.xml b/daemon/gdm-session-worker.xml
+index 9f6d8b35..853bc6a4 100644
+--- a/daemon/gdm-session-worker.xml
++++ b/daemon/gdm-session-worker.xml
+@@ -13,6 +13,9 @@
+ <method name="SetSessionName">
+ <arg name="session_name" direction="in" type="s" />
+ </method>
++ <method name="SetSessionType">
++ <arg name="session_type" direction="in" type="s"/>
++ </method>
+ <method name="SetSessionDisplayMode">
+ <arg name="mode" direction="in" type="s"/>
+ </method>
+diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
+index ff3a1acb..5e26c5b5 100644
+--- a/daemon/gdm-session.c
++++ b/daemon/gdm-session.c
+@@ -3076,6 +3076,10 @@ gdm_session_bypasses_xsession (GdmSession *self)
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
++ if (!LOGIND_RUNNING()) {
++ return GDM_SESSION_DISPLAY_MODE_REUSE_VT;
++ }
++
+ #ifdef ENABLE_WAYLAND_SUPPORT
+ if (gdm_session_is_wayland_session (self)) {
+ bypasses_xsession = TRUE;
+@@ -3171,6 +3175,27 @@ gdm_session_select_program (GdmSession *self,
+ }
+
+ void
++gdm_session_select_session_type (GdmSession *self,
++ const char *text)
++{
++ GHashTableIter iter;
++ gpointer key, value;
++
++ g_debug ("GdmSession: selecting session type '%s'", text);
++
++ g_hash_table_iter_init (&iter, self->priv->conversations);
++ while (g_hash_table_iter_next (&iter, &key, &value)) {
++ GdmSessionConversation *conversation;
++
++ conversation = (GdmSessionConversation *) value;
++
++ gdm_dbus_worker_call_set_session_type (conversation->worker_proxy,
++ text,
++ NULL, NULL, NULL);
++ }
++}
++
++void
+ gdm_session_select_session (GdmSession *self,
+ const char *text)
+ {
+diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
+index a22c0954..44b16f64 100644
+--- a/daemon/gdm-session.h
++++ b/daemon/gdm-session.h
+@@ -180,6 +180,8 @@ void gdm_session_answer_query (GdmSession *session,
+ const char *text);
+ void gdm_session_select_program (GdmSession *session,
+ const char *command_line);
++void gdm_session_select_session_type (GdmSession *session,
++ const char *session_type);
+ void gdm_session_select_session (GdmSession *session,
+ const char *session_name);
+ void gdm_session_select_user (GdmSession *session,
+diff --git a/libgdm/gdm-user-switching.c b/libgdm/gdm-user-switching.c
+index 3d4303e3..a195d052 100644
+--- a/libgdm/gdm-user-switching.c
++++ b/libgdm/gdm-user-switching.c
+@@ -31,12 +31,25 @@
+ #include <glib-object.h>
+ #include <gio/gio.h>
+
++#ifdef WITH_SYSTEMD
+ #include <systemd/sd-login.h>
++#endif
+
+ #include "common/gdm-common.h"
+ #include "gdm-user-switching.h"
+ #include "gdm-client.h"
+
++#ifdef WITH_CONSOLE_KIT
++#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_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
++#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
++#endif
++
+ static gboolean
+ create_transient_display (GDBusConnection *connection,
+ GCancellable *cancellable,
+@@ -67,12 +80,304 @@ create_transient_display (GDBusConnection *connection,
+ return TRUE;
+ }
+
++#ifdef WITH_CONSOLE_KIT
++
++static gboolean
++get_current_session_id (GDBusConnection *connection,
++ char **session_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ CK_MANAGER_PATH,
++ CK_MANAGER_INTERFACE,
++ "GetCurrentSession",
++ NULL, /* parameters */
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine session: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(o)", session_id);
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static gboolean
++get_seat_id_for_session (GDBusConnection *connection,
++ const char *session_id,
++ char **seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ session_id,
++ CK_SESSION_INTERFACE,
++ "GetSeatId",
++ NULL, /* parameters */
++ G_VARIANT_TYPE ("(o)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine seat: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(o)", seat_id);
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static char *
++get_current_seat_id (GDBusConnection *connection)
++{
++ gboolean res;
++ char *session_id;
++ char *seat_id;
++
++ session_id = NULL;
++ seat_id = NULL;
++
++ res = get_current_session_id (connection, &session_id);
++ if (res) {
++ res = get_seat_id_for_session (connection, session_id, &seat_id);
++ }
++ g_free (session_id);
++
++ return seat_id;
++}
++
++static gboolean
++activate_session_id_for_ck (GDBusConnection *connection,
++ GCancellable *cancellable,
++ const char *seat_id,
++ const char *session_id,
++ GError **error)
++{
++ GVariant *reply;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "ActivateSession",
++ g_variant_new ("(o)", session_id),
++ NULL,
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, error);
++ if (reply == NULL) {
++ g_prefix_error (error, _("Unable to activate session: "));
++ return FALSE;
++ }
++
++ g_variant_unref (reply);
++
++ return TRUE;
++}
++
++static gboolean
++session_is_login_window (GDBusConnection *connection,
++ const char *session_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ const char *value;
++ gboolean ret;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ session_id,
++ CK_SESSION_INTERFACE,
++ "GetSessionType",
++ NULL,
++ G_VARIANT_TYPE ("(s)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine session type: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(&s)", &value);
++
++ if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
++ ret = FALSE;
++ } else {
++ ret = TRUE;
++ }
++
++ g_variant_unref (reply);
++
++ return ret;
++}
++
++static gboolean
++seat_can_activate_sessions (GDBusConnection *connection,
++ const char *seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ gboolean ret;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "CanActivateSessions",
++ NULL,
++ G_VARIANT_TYPE ("(b)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to determine if can activate sessions: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(b)", &ret);
++ g_variant_unref (reply);
++
++ return ret;
++}
++
++static const char **
++seat_get_sessions (GDBusConnection *connection,
++ const char *seat_id)
++{
++ GError *local_error = NULL;
++ GVariant *reply;
++ const char **value;
++
++ reply = g_dbus_connection_call_sync (connection,
++ CK_NAME,
++ seat_id,
++ CK_SEAT_INTERFACE,
++ "GetSessions",
++ NULL,
++ G_VARIANT_TYPE ("(ao)"),
++ G_DBUS_CALL_FLAGS_NONE,
++ -1,
++ NULL, &local_error);
++ if (reply == NULL) {
++ g_warning ("Unable to list sessions: %s", local_error->message);
++ g_error_free (local_error);
++ return FALSE;
++ }
++
++ g_variant_get (reply, "(^ao)", &value);
++ g_variant_unref (reply);
++
++ return value;
++}
++
++static gboolean
++get_login_window_session_id_for_ck (GDBusConnection *connection,
++ const char *seat_id,
++ char **session_id)
++{
++ gboolean can_activate_sessions;
++ const char **sessions;
++ int i;
++
++ *session_id = NULL;
++ sessions = NULL;
++
++ g_debug ("checking if seat can activate sessions");
++
++ can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
++ if (! can_activate_sessions) {
++ g_debug ("seat is unable to activate sessions");
++ return FALSE;
++ }
++
++ sessions = seat_get_sessions (connection, seat_id);
++ for (i = 0; sessions [i] != NULL; i++) {
++ const char *ssid;
++
++ ssid = sessions [i];
++
++ if (session_is_login_window (connection, ssid)) {
++ *session_id = g_strdup (ssid);
++ break;
++ }
++ }
++ g_free (sessions);
++
++ return TRUE;
++}
++
+ static gboolean
+-activate_session_id (GDBusConnection *connection,
+- GCancellable *cancellable,
+- const char *seat_id,
+- const char *session_id,
+- GError **error)
++goto_login_session_for_ck (GDBusConnection *connection,
++ GCancellable *cancellable,
++ GError **error)
++{
++ gboolean ret;
++ gboolean res;
++ 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");
++ g_set_error (error, GDM_CLIENT_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_CLIENT_ERROR, 0, _("User unable to switch sessions."));
++ return FALSE;
++ }
++
++ if (session_id != NULL) {
++ res = activate_session_id_for_ck (connection, cancellable, seat_id, session_id, error);
++ if (res) {
++ ret = TRUE;
++ }
++ }
++
++ if (! ret && g_strcmp0 (seat_id, "/org/freedesktop/ConsoleKit/Seat1") == 0) {
++ res = create_transient_display (connection, cancellable, error);
++ if (res) {
++ ret = TRUE;
++ }
++ }
++
++ return ret;
++}
++#endif
++
++#ifdef WITH_SYSTEMD
++
++static gboolean
++activate_session_id_for_systemd (GDBusConnection *connection,
++ GCancellable *cancellable,
++ const char *seat_id,
++ const char *session_id,
++ GError **error)
+ {
+ GVariant *reply;
+
+@@ -97,8 +402,8 @@ activate_session_id (GDBusConnection *connection,
+ }
+
+ static gboolean
+-get_login_window_session_id (const char *seat_id,
+- char **session_id)
++get_login_window_session_id_for_systemd (const char *seat_id,
++ char **session_id)
+ {
+ gboolean ret;
+ int res, i;
+@@ -182,9 +487,9 @@ out:
+ }
+
+ static gboolean
+-goto_login_session (GDBusConnection *connection,
+- GCancellable *cancellable,
+- GError **error)
++goto_login_session_for_systemd (GDBusConnection *connection,
++ GCancellable *cancellable,
++ GError **error)
+ {
+ gboolean ret;
+ int res;
+@@ -238,9 +543,9 @@ goto_login_session (GDBusConnection *connection,
+ return FALSE;
+ }
+
+- res = get_login_window_session_id (seat_id, &session_id);
++ res = get_login_window_session_id_for_systemd (seat_id, &session_id);
+ if (res && session_id != NULL) {
+- res = activate_session_id (connection, cancellable, seat_id, session_id, error);
++ res = activate_session_id_for_systemd (connection, cancellable, seat_id, session_id, error);
+
+ if (res) {
+ ret = TRUE;
+@@ -259,10 +564,11 @@ goto_login_session (GDBusConnection *connection,
+
+ return ret;
+ }
++#endif
+
+ gboolean
+ gdm_goto_login_session_sync (GCancellable *cancellable,
+- GError **error)
++ GError **error)
+ {
+ GDBusConnection *connection;
+ gboolean retval;
+@@ -271,8 +577,23 @@ gdm_goto_login_session_sync (GCancellable *cancellable,
+ if (!connection)
+ return FALSE;
+
+- retval = goto_login_session (connection, cancellable, error);
++#ifdef WITH_SYSTEMD
++ if (LOGIND_RUNNING()) {
++ retval = goto_login_session_for_systemd (connection,
++ cancellable,
++ error);
++
++ g_object_unref (connection);
++ return retval;
++ }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++ retval = goto_login_session_for_ck (connection, cancellable, error);
+
+ g_object_unref (connection);
+ return retval;
++#else
++ return FALSE;
++#endif
+ }
+--
+2.13.0
+
diff --git a/testing/gdm/APKBUILD b/testing/gdm/APKBUILD
new file mode 100644
index 0000000000..fb395d5f0c
--- /dev/null
+++ b/testing/gdm/APKBUILD
@@ -0,0 +1,50 @@
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gdm
+pkgver=3.24.2
+pkgrel=0
+pkgdesc="GNOME display manager"
+url="https://wiki.gnome.org/Projects/GDM"
+arch="all"
+license="GPL"
+depends="dconf"
+depends_dev=""
+makedepends="dconf-dev gnome-desktop-dev accountsservice-dev libcanberra-dev intltool itstool libxml2-utils consolekit-dev linux-pam-dev autoconf automake libtool $depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-lang"
+source="http://ftp.gnome.org/pub/GNOME/sources/gdm/${pkgver%.*}/gdm-$pkgver.tar.xz
+ 0001-gdm-session-record-alpine-does-not-have-utmp.patch
+ 0002-configure-Alpine-does-not-use-PAM.patch
+ 0003-reintroduce-ConsoleKit-support.patch"
+builddir="$srcdir/gdm-$pkgver"
+
+prepare() {
+ default_prepare
+ autoreconf
+}
+
+build() {
+ cd "$builddir"
+ ./configure \
+ --build=$CBUILD \
+ --host=$CHOST \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --localstatedir=/var \
+ --without-systemd \
+ --without-plymouth \
+ --disable-systemd-journal \
+ --with-console-kit \
+ --with-pid-file=/var/run/gdm.pid
+ make
+}
+
+package() {
+ cd "$builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+sha512sums="6e2649bce5520532a2976bac8a47629fc4c852d7127b913c29a9c43a7dba26d75472a083cbfff7b64bab56deb38ed13d8387d4d302d55f263c80120255a4a270 gdm-3.24.2.tar.xz
+57ced6bf01ec45a0ab6147cd5235230c6e75f10b25c50bd046b6cec1668fa03db93404185394d61a83d5f144d325de36f9b62ebdfa67dcdda91757c1711852c3 0001-gdm-session-record-alpine-does-not-have-utmp.patch
+6b75dde1370aa03de1f6c47d2a3fd07610392d8e82e94128be0af7eb06be01b7c365d6c406b77ca7c239a80d086f247c6693e8398d9196ab104b237892346598 0002-configure-Alpine-does-not-use-PAM.patch
+b94ab78874ef7cfe67cc5dc6c9c4fbc746c1c83e7c44199c4d9a500ec4b042fd4aac767e7bb84070da31959ed80c7c79b6095546d3e71559dc8c4319df716f55 0003-reintroduce-ConsoleKit-support.patch"