From f4a1a8c560796804e0ec763ab50f5e56e2ff05c4 Mon Sep 17 00:00:00 2001 From: William Pitcock 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 +#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 #include +#ifdef WITH_SYSTEMD #include +#endif #include #include @@ -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 +#ifdef WITH_SYSTEMD #include +#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 #endif +#ifdef WITH_SYSTEMD #include +#endif #ifdef ENABLE_SYSTEMD_JOURNAL #include @@ -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 #endif +#ifdef WITH_SYSTEMD #include +#endif #ifdef ENABLE_SYSTEMD_JOURNAL #include 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 #include #include +#ifdef WITH_SYSTEMD #include #include #include +#endif #include #include #include @@ -49,7 +51,9 @@ #include +#ifdef WITH_SYSTEMD #include +#endif #ifdef ENABLE_SYSTEMD_JOURNAL #include @@ -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 (¶meters, 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 @@ + + + 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 #include +#ifdef WITH_SYSTEMD #include +#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