|
|
795d2c |
From b7b492296a69bc5100ff5908048ed5ef121d3587 Mon Sep 17 00:00:00 2001
|
|
|
795d2c |
From: Ray Strode <rstrode@redhat.com>
|
|
|
795d2c |
Date: Mon, 30 Jul 2018 16:21:29 -0400
|
|
|
f62751 |
Subject: [PATCH 5/7] daemon: try harder to get to a login screen at logout
|
|
|
795d2c |
|
|
|
795d2c |
commit 22c332ba and some follow up commits try to ensure the
|
|
|
795d2c |
user never stays on a blank VT by jumping to a login screen in
|
|
|
795d2c |
the event they'd end up on one.
|
|
|
795d2c |
|
|
|
795d2c |
Unfortunately, that part of the code can't start a login screen
|
|
|
795d2c |
if there's not one running at all.
|
|
|
795d2c |
|
|
|
795d2c |
This commit moves the code to GdmLocalDisplyFactor where the
|
|
|
795d2c |
login screens are created, so users won't end up on a blank
|
|
|
795d2c |
VT even if no login screen is yet running.
|
|
|
795d2c |
---
|
|
|
795d2c |
daemon/gdm-local-display-factory.c | 161 ++++++++++++++++++++++++++++-
|
|
|
795d2c |
daemon/gdm-manager.c | 54 ----------
|
|
|
795d2c |
2 files changed, 156 insertions(+), 59 deletions(-)
|
|
|
795d2c |
|
|
|
795d2c |
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
|
|
795d2c |
index b29f5ac52..cf852b55a 100644
|
|
|
795d2c |
--- a/daemon/gdm-local-display-factory.c
|
|
|
795d2c |
+++ b/daemon/gdm-local-display-factory.c
|
|
|
795d2c |
@@ -1,60 +1,62 @@
|
|
|
795d2c |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
|
795d2c |
*
|
|
|
795d2c |
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
|
|
795d2c |
*
|
|
|
795d2c |
* This program is free software; you can redistribute it and/or modify
|
|
|
795d2c |
* it under the terms of the GNU General Public License as published by
|
|
|
795d2c |
* the Free Software Foundation; either version 2 of the License, or
|
|
|
795d2c |
* (at your option) any later version.
|
|
|
795d2c |
*
|
|
|
795d2c |
* This program is distributed in the hope that it will be useful,
|
|
|
795d2c |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
795d2c |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
795d2c |
* GNU General Public License for more details.
|
|
|
795d2c |
*
|
|
|
795d2c |
* You should have received a copy of the GNU General Public License
|
|
|
795d2c |
* along with this program; if not, write to the Free Software
|
|
|
795d2c |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
795d2c |
*
|
|
|
795d2c |
*/
|
|
|
795d2c |
|
|
|
795d2c |
#include "config.h"
|
|
|
795d2c |
|
|
|
795d2c |
#include <stdlib.h>
|
|
|
795d2c |
#include <stdio.h>
|
|
|
795d2c |
|
|
|
795d2c |
#include <glib.h>
|
|
|
795d2c |
#include <glib/gi18n.h>
|
|
|
795d2c |
#include <glib-object.h>
|
|
|
795d2c |
#include <gio/gio.h>
|
|
|
795d2c |
|
|
|
795d2c |
+#include <systemd/sd-login.h>
|
|
|
795d2c |
+
|
|
|
795d2c |
#include "gdm-common.h"
|
|
|
795d2c |
#include "gdm-manager.h"
|
|
|
795d2c |
#include "gdm-display-factory.h"
|
|
|
795d2c |
#include "gdm-local-display-factory.h"
|
|
|
795d2c |
#include "gdm-local-display-factory-glue.h"
|
|
|
795d2c |
|
|
|
795d2c |
#include "gdm-settings-keys.h"
|
|
|
795d2c |
#include "gdm-settings-direct.h"
|
|
|
795d2c |
#include "gdm-display-store.h"
|
|
|
795d2c |
#include "gdm-local-display.h"
|
|
|
795d2c |
#include "gdm-legacy-display.h"
|
|
|
795d2c |
|
|
|
795d2c |
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
|
|
795d2c |
|
|
|
795d2c |
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
|
|
795d2c |
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
|
|
795d2c |
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
|
|
795d2c |
|
|
|
795d2c |
#define MAX_DISPLAY_FAILURES 5
|
|
|
795d2c |
|
|
|
795d2c |
struct GdmLocalDisplayFactoryPrivate
|
|
|
795d2c |
{
|
|
|
795d2c |
GdmDBusLocalDisplayFactory *skeleton;
|
|
|
795d2c |
GDBusConnection *connection;
|
|
|
795d2c |
GHashTable *used_display_numbers;
|
|
|
795d2c |
|
|
|
795d2c |
/* FIXME: this needs to be per seat? */
|
|
|
795d2c |
guint num_failures;
|
|
|
795d2c |
|
|
|
795d2c |
guint seat_new_id;
|
|
|
795d2c |
@@ -226,171 +228,320 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
|
|
795d2c |
store_display (factory, display);
|
|
|
795d2c |
|
|
|
795d2c |
if (! gdm_display_manage (display)) {
|
|
|
795d2c |
display = NULL;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (! gdm_display_get_id (display, id, NULL)) {
|
|
|
795d2c |
display = NULL;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
ret = TRUE;
|
|
|
795d2c |
out:
|
|
|
795d2c |
/* ref either held by store or not at all */
|
|
|
795d2c |
g_object_unref (display);
|
|
|
795d2c |
|
|
|
795d2c |
return ret;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static void
|
|
|
795d2c |
on_display_status_changed (GdmDisplay *display,
|
|
|
795d2c |
GParamSpec *arg1,
|
|
|
795d2c |
GdmLocalDisplayFactory *factory)
|
|
|
795d2c |
{
|
|
|
795d2c |
int status;
|
|
|
795d2c |
GdmDisplayStore *store;
|
|
|
795d2c |
int num;
|
|
|
795d2c |
char *seat_id = NULL;
|
|
|
795d2c |
char *session_type = NULL;
|
|
|
795d2c |
+ char *session_class = NULL;
|
|
|
795d2c |
gboolean is_initial = TRUE;
|
|
|
795d2c |
gboolean is_local = TRUE;
|
|
|
795d2c |
|
|
|
795d2c |
num = -1;
|
|
|
795d2c |
gdm_display_get_x11_display_number (display, &num, NULL);
|
|
|
795d2c |
|
|
|
795d2c |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
795d2c |
|
|
|
795d2c |
g_object_get (display,
|
|
|
795d2c |
"seat-id", &seat_id,
|
|
|
795d2c |
"is-initial", &is_initial,
|
|
|
795d2c |
"is-local", &is_local,
|
|
|
795d2c |
"session-type", &session_type,
|
|
|
795d2c |
+ "session-class", &session_class,
|
|
|
795d2c |
NULL);
|
|
|
795d2c |
|
|
|
795d2c |
status = gdm_display_get_status (display);
|
|
|
795d2c |
|
|
|
795d2c |
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
|
|
795d2c |
switch (status) {
|
|
|
795d2c |
case GDM_DISPLAY_FINISHED:
|
|
|
795d2c |
/* remove the display number from factory->priv->used_display_numbers
|
|
|
795d2c |
so that it may be reused */
|
|
|
795d2c |
if (num != -1) {
|
|
|
795d2c |
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
|
|
|
795d2c |
}
|
|
|
795d2c |
gdm_display_store_remove (store, display);
|
|
|
795d2c |
|
|
|
795d2c |
/* if this is a local display, do a full resync. Only
|
|
|
795d2c |
* seats without displays will get created anyway. This
|
|
|
795d2c |
* ensures we get a new login screen when the user logs out,
|
|
|
795d2c |
* if there isn't one.
|
|
|
795d2c |
*/
|
|
|
795d2c |
- if (is_local) {
|
|
|
795d2c |
+ if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
|
|
|
795d2c |
/* reset num failures */
|
|
|
795d2c |
factory->priv->num_failures = 0;
|
|
|
795d2c |
|
|
|
795d2c |
gdm_local_display_factory_sync_seats (factory);
|
|
|
795d2c |
}
|
|
|
795d2c |
break;
|
|
|
795d2c |
case GDM_DISPLAY_FAILED:
|
|
|
795d2c |
/* leave the display number in factory->priv->used_display_numbers
|
|
|
795d2c |
so that it doesn't get reused */
|
|
|
795d2c |
gdm_display_store_remove (store, display);
|
|
|
795d2c |
|
|
|
795d2c |
/* Create a new equivalent display if it was static */
|
|
|
795d2c |
if (is_local) {
|
|
|
795d2c |
|
|
|
795d2c |
factory->priv->num_failures++;
|
|
|
795d2c |
|
|
|
795d2c |
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
|
|
795d2c |
/* oh shit */
|
|
|
795d2c |
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
|
|
795d2c |
} else {
|
|
|
795d2c |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
795d2c |
if (g_strcmp0 (session_type, "wayland") == 0) {
|
|
|
795d2c |
g_free (session_type);
|
|
|
795d2c |
session_type = NULL;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
#endif
|
|
|
795d2c |
create_display (factory, seat_id, session_type, is_initial);
|
|
|
795d2c |
}
|
|
|
795d2c |
}
|
|
|
795d2c |
break;
|
|
|
795d2c |
case GDM_DISPLAY_UNMANAGED:
|
|
|
795d2c |
break;
|
|
|
795d2c |
case GDM_DISPLAY_PREPARED:
|
|
|
795d2c |
break;
|
|
|
795d2c |
case GDM_DISPLAY_MANAGED:
|
|
|
795d2c |
break;
|
|
|
795d2c |
default:
|
|
|
795d2c |
g_assert_not_reached ();
|
|
|
795d2c |
break;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
g_free (seat_id);
|
|
|
795d2c |
g_free (session_type);
|
|
|
795d2c |
+ g_free (session_class);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static gboolean
|
|
|
795d2c |
lookup_by_seat_id (const char *id,
|
|
|
795d2c |
GdmDisplay *display,
|
|
|
795d2c |
gpointer user_data)
|
|
|
795d2c |
{
|
|
|
795d2c |
const char *looking_for = user_data;
|
|
|
795d2c |
char *current;
|
|
|
795d2c |
gboolean res;
|
|
|
795d2c |
|
|
|
795d2c |
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
|
|
795d2c |
|
|
|
795d2c |
res = g_strcmp0 (current, looking_for) == 0;
|
|
|
795d2c |
|
|
|
795d2c |
g_free(current);
|
|
|
795d2c |
|
|
|
795d2c |
return res;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
+static gboolean
|
|
|
795d2c |
+activate_session_id (GdmLocalDisplayFactory *self,
|
|
|
795d2c |
+ const char *seat_id,
|
|
|
795d2c |
+ const char *session_id)
|
|
|
795d2c |
+{
|
|
|
795d2c |
+ GError *error = NULL;
|
|
|
795d2c |
+ GVariant *reply;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ reply = g_dbus_connection_call_sync (self->priv->connection,
|
|
|
795d2c |
+ "org.freedesktop.login1",
|
|
|
795d2c |
+ "/org/freedesktop/login1",
|
|
|
795d2c |
+ "org.freedesktop.login1.Manager",
|
|
|
795d2c |
+ "ActivateSessionOnSeat",
|
|
|
795d2c |
+ g_variant_new ("(ss)", session_id, seat_id),
|
|
|
795d2c |
+ NULL, /* expected reply */
|
|
|
795d2c |
+ G_DBUS_CALL_FLAGS_NONE,
|
|
|
795d2c |
+ -1,
|
|
|
795d2c |
+ NULL,
|
|
|
795d2c |
+ &error);
|
|
|
795d2c |
+ if (reply == NULL) {
|
|
|
795d2c |
+ g_debug ("GdmManager: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n",
|
|
|
795d2c |
+ g_dbus_error_get_remote_error (error), error->message);
|
|
|
795d2c |
+ g_error_free (error);
|
|
|
795d2c |
+ return FALSE;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ g_variant_unref (reply);
|
|
|
795d2c |
+
|
|
|
795d2c |
+ return TRUE;
|
|
|
795d2c |
+}
|
|
|
795d2c |
+
|
|
|
795d2c |
+static gboolean
|
|
|
795d2c |
+get_login_window_session_id (const char *seat_id,
|
|
|
795d2c |
+ char **session_id)
|
|
|
795d2c |
+{
|
|
|
795d2c |
+ gboolean ret;
|
|
|
795d2c |
+ int res, i;
|
|
|
795d2c |
+ char **sessions;
|
|
|
795d2c |
+ char *service_id;
|
|
|
795d2c |
+ char *service_class;
|
|
|
795d2c |
+ char *state;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
|
|
795d2c |
+ if (res < 0) {
|
|
|
795d2c |
+ g_debug ("Failed to determine sessions: %s", strerror (-res));
|
|
|
795d2c |
+ return FALSE;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (sessions == NULL || sessions[0] == NULL) {
|
|
|
795d2c |
+ *session_id = NULL;
|
|
|
795d2c |
+ ret = TRUE;
|
|
|
795d2c |
+ goto out;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ for (i = 0; sessions[i]; i ++) {
|
|
|
795d2c |
+
|
|
|
795d2c |
+ res = sd_session_get_class (sessions[i], &service_class);
|
|
|
795d2c |
+ if (res < 0) {
|
|
|
795d2c |
+ if (res == -ENOENT || res == -ENXIO) {
|
|
|
795d2c |
+ continue;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
+ ret = FALSE;
|
|
|
795d2c |
+ goto out;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (strcmp (service_class, "greeter") != 0) {
|
|
|
795d2c |
+ free (service_class);
|
|
|
795d2c |
+ continue;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ free (service_class);
|
|
|
795d2c |
+
|
|
|
795d2c |
+ ret = sd_session_get_state (sessions[i], &state);
|
|
|
795d2c |
+ if (ret < 0) {
|
|
|
795d2c |
+ if (res == -ENOENT || res == -ENXIO)
|
|
|
795d2c |
+ continue;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
+ ret = FALSE;
|
|
|
795d2c |
+ goto out;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (g_strcmp0 (state, "closing") == 0) {
|
|
|
795d2c |
+ free (state);
|
|
|
795d2c |
+ continue;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+ free (state);
|
|
|
795d2c |
+
|
|
|
795d2c |
+ res = sd_session_get_service (sessions[i], &service_id);
|
|
|
795d2c |
+ if (res < 0) {
|
|
|
795d2c |
+ if (res == -ENOENT || res == -ENXIO)
|
|
|
795d2c |
+ continue;
|
|
|
795d2c |
+ g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
+ ret = FALSE;
|
|
|
795d2c |
+ goto out;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
|
|
795d2c |
+ *session_id = g_strdup (sessions[i]);
|
|
|
795d2c |
+ ret = TRUE;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ free (service_id);
|
|
|
795d2c |
+ goto out;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ free (service_id);
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ *session_id = NULL;
|
|
|
795d2c |
+ ret = FALSE;
|
|
|
795d2c |
+
|
|
|
795d2c |
+out:
|
|
|
795d2c |
+ if (sessions) {
|
|
|
795d2c |
+ for (i = 0; sessions[i]; i ++) {
|
|
|
795d2c |
+ free (sessions[i]);
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ free (sessions);
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+
|
|
|
795d2c |
+ return ret;
|
|
|
795d2c |
+}
|
|
|
795d2c |
+
|
|
|
795d2c |
static GdmDisplay *
|
|
|
795d2c |
create_display (GdmLocalDisplayFactory *factory,
|
|
|
795d2c |
const char *seat_id,
|
|
|
795d2c |
const char *session_type,
|
|
|
795d2c |
gboolean initial)
|
|
|
795d2c |
{
|
|
|
795d2c |
GdmDisplayStore *store;
|
|
|
795d2c |
GdmDisplay *display = NULL;
|
|
|
795d2c |
+ char *active_session_id = NULL;
|
|
|
795d2c |
+ int ret;
|
|
|
795d2c |
|
|
|
795d2c |
- /* Ensure we don't create the same display more than once */
|
|
|
795d2c |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
795d2c |
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
|
|
795d2c |
- if (display != NULL) {
|
|
|
795d2c |
- return NULL;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (ret == 0) {
|
|
|
795d2c |
+ char *login_session_id = NULL;
|
|
|
795d2c |
+
|
|
|
795d2c |
+ /* If we already have a login window, switch to it */
|
|
|
795d2c |
+ if (get_login_window_session_id (seat_id, &login_session_id)) {
|
|
|
795d2c |
+ if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
|
|
795d2c |
+ activate_session_id (factory, seat_id, login_session_id);
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+ g_clear_pointer (&login_session_id, g_free);
|
|
|
795d2c |
+ g_clear_pointer (&active_session_id, g_free);
|
|
|
795d2c |
+ return NULL;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
+ g_clear_pointer (&active_session_id, g_free);
|
|
|
795d2c |
+ } else {
|
|
|
795d2c |
+ /* Ensure we don't create the same display more than once */
|
|
|
795d2c |
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
|
|
795d2c |
+
|
|
|
795d2c |
+ if (display != NULL) {
|
|
|
795d2c |
+ return NULL;
|
|
|
795d2c |
+ }
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
|
|
795d2c |
|
|
|
795d2c |
#ifdef ENABLE_USER_DISPLAY_SERVER
|
|
|
795d2c |
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
|
|
795d2c |
display = gdm_local_display_new ();
|
|
|
795d2c |
if (session_type != NULL) {
|
|
|
795d2c |
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
|
|
795d2c |
}
|
|
|
795d2c |
}
|
|
|
795d2c |
#endif
|
|
|
795d2c |
|
|
|
795d2c |
if (display == NULL) {
|
|
|
795d2c |
guint32 num;
|
|
|
795d2c |
|
|
|
795d2c |
num = take_next_display_number (factory);
|
|
|
795d2c |
|
|
|
795d2c |
display = gdm_legacy_display_new (num);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
g_object_set (display, "seat-id", seat_id, NULL);
|
|
|
795d2c |
g_object_set (display, "is-initial", initial, NULL);
|
|
|
795d2c |
|
|
|
795d2c |
store_display (factory, display);
|
|
|
795d2c |
|
|
|
795d2c |
/* let store own the ref */
|
|
|
795d2c |
g_object_unref (display);
|
|
|
795d2c |
|
|
|
795d2c |
if (! gdm_display_manage (display)) {
|
|
|
795d2c |
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
|
|
795d2c |
index 34ee74033..031c61ce6 100644
|
|
|
795d2c |
--- a/daemon/gdm-manager.c
|
|
|
795d2c |
+++ b/daemon/gdm-manager.c
|
|
|
795d2c |
@@ -1318,171 +1318,118 @@ maybe_start_pending_initial_login (GdmManager *manager,
|
|
|
795d2c |
g_free (user_session_seat_id);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static gboolean
|
|
|
795d2c |
get_login_window_session_id (const char *seat_id,
|
|
|
795d2c |
char **session_id)
|
|
|
795d2c |
{
|
|
|
795d2c |
gboolean ret;
|
|
|
795d2c |
int res, i;
|
|
|
795d2c |
char **sessions;
|
|
|
795d2c |
char *service_id;
|
|
|
795d2c |
char *service_class;
|
|
|
795d2c |
char *state;
|
|
|
795d2c |
|
|
|
795d2c |
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
|
|
795d2c |
if (res < 0) {
|
|
|
795d2c |
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
|
|
795d2c |
return FALSE;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (sessions == NULL || sessions[0] == NULL) {
|
|
|
795d2c |
*session_id = NULL;
|
|
|
795d2c |
ret = FALSE;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
for (i = 0; sessions[i]; i ++) {
|
|
|
795d2c |
|
|
|
795d2c |
res = sd_session_get_class (sessions[i], &service_class);
|
|
|
795d2c |
if (res < 0) {
|
|
|
795d2c |
- if (res == -ENOENT || res == -ENXIO) {
|
|
|
795d2c |
- continue;
|
|
|
795d2c |
- }
|
|
|
795d2c |
-
|
|
|
795d2c |
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
ret = FALSE;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (strcmp (service_class, "greeter") != 0) {
|
|
|
795d2c |
free (service_class);
|
|
|
795d2c |
continue;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
free (service_class);
|
|
|
795d2c |
|
|
|
795d2c |
ret = sd_session_get_state (sessions[i], &state);
|
|
|
795d2c |
if (ret < 0) {
|
|
|
795d2c |
- if (res == -ENOENT || res == -ENXIO)
|
|
|
795d2c |
- continue;
|
|
|
795d2c |
-
|
|
|
795d2c |
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
ret = FALSE;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (g_strcmp0 (state, "closing") == 0) {
|
|
|
795d2c |
free (state);
|
|
|
795d2c |
continue;
|
|
|
795d2c |
}
|
|
|
795d2c |
free (state);
|
|
|
795d2c |
|
|
|
795d2c |
res = sd_session_get_service (sessions[i], &service_id);
|
|
|
795d2c |
if (res < 0) {
|
|
|
795d2c |
- if (res == -ENOENT || res == -ENXIO)
|
|
|
795d2c |
- continue;
|
|
|
795d2c |
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
|
|
795d2c |
ret = FALSE;
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
|
|
795d2c |
*session_id = g_strdup (sessions[i]);
|
|
|
795d2c |
ret = TRUE;
|
|
|
795d2c |
|
|
|
795d2c |
free (service_id);
|
|
|
795d2c |
goto out;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
free (service_id);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
*session_id = NULL;
|
|
|
795d2c |
ret = FALSE;
|
|
|
795d2c |
|
|
|
795d2c |
out:
|
|
|
795d2c |
if (sessions) {
|
|
|
795d2c |
for (i = 0; sessions[i]; i ++) {
|
|
|
795d2c |
free (sessions[i]);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
free (sessions);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
return ret;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
-static void
|
|
|
795d2c |
-activate_login_window_session_on_seat (GdmManager *self,
|
|
|
795d2c |
- const char *seat_id)
|
|
|
795d2c |
-{
|
|
|
795d2c |
- char *session_id;
|
|
|
795d2c |
-
|
|
|
795d2c |
- if (!get_login_window_session_id (seat_id, &session_id)) {
|
|
|
795d2c |
- return;
|
|
|
795d2c |
- }
|
|
|
795d2c |
-
|
|
|
795d2c |
- activate_session_id (self, seat_id, session_id);
|
|
|
795d2c |
-}
|
|
|
795d2c |
-
|
|
|
795d2c |
-static void
|
|
|
795d2c |
-maybe_activate_other_session (GdmManager *self,
|
|
|
795d2c |
- GdmDisplay *old_display)
|
|
|
795d2c |
-{
|
|
|
795d2c |
- char *seat_id = NULL;
|
|
|
795d2c |
- char *session_id = NULL;
|
|
|
795d2c |
- int ret;
|
|
|
795d2c |
-
|
|
|
795d2c |
- g_object_get (G_OBJECT (old_display),
|
|
|
795d2c |
- "seat-id", &seat_id,
|
|
|
795d2c |
- NULL);
|
|
|
795d2c |
-
|
|
|
795d2c |
- ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
|
|
795d2c |
-
|
|
|
795d2c |
- if (ret == 0) {
|
|
|
795d2c |
- GdmDisplay *display;
|
|
|
795d2c |
-
|
|
|
795d2c |
- display = gdm_display_store_find (self->priv->display_store,
|
|
|
795d2c |
- lookup_by_session_id,
|
|
|
795d2c |
- (gpointer) session_id);
|
|
|
795d2c |
-
|
|
|
795d2c |
- if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) {
|
|
|
795d2c |
- activate_login_window_session_on_seat (self, seat_id);
|
|
|
795d2c |
- }
|
|
|
795d2c |
-
|
|
|
795d2c |
- g_free (session_id);
|
|
|
795d2c |
- }
|
|
|
795d2c |
-
|
|
|
795d2c |
- g_free (seat_id);
|
|
|
795d2c |
-}
|
|
|
795d2c |
-
|
|
|
795d2c |
static const char *
|
|
|
795d2c |
get_username_for_greeter_display (GdmManager *manager,
|
|
|
795d2c |
GdmDisplay *display)
|
|
|
795d2c |
{
|
|
|
795d2c |
gboolean doing_initial_setup = FALSE;
|
|
|
795d2c |
|
|
|
795d2c |
g_object_get (G_OBJECT (display),
|
|
|
795d2c |
"doing-initial-setup", &doing_initial_setup,
|
|
|
795d2c |
NULL);
|
|
|
795d2c |
|
|
|
795d2c |
if (doing_initial_setup) {
|
|
|
795d2c |
return INITIAL_SETUP_USERNAME;
|
|
|
795d2c |
} else {
|
|
|
795d2c |
return GDM_USERNAME;
|
|
|
795d2c |
}
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static void
|
|
|
795d2c |
set_up_automatic_login_session (GdmManager *manager,
|
|
|
795d2c |
GdmDisplay *display)
|
|
|
795d2c |
{
|
|
|
795d2c |
GdmSession *session;
|
|
|
795d2c |
char *display_session_type = NULL;
|
|
|
795d2c |
gboolean is_initial;
|
|
|
795d2c |
|
|
|
795d2c |
/* 0 is root user; since the daemon talks to the session object
|
|
|
795d2c |
* directly, itself, for automatic login
|
|
|
795d2c |
*/
|
|
|
795d2c |
session = create_user_session_for_display (manager, display, 0);
|
|
|
795d2c |
|
|
|
795d2c |
@@ -1674,61 +1621,60 @@ on_display_status_changed (GdmDisplay *display,
|
|
|
795d2c |
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
|
|
795d2c |
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
|
|
795d2c |
char *session_class;
|
|
|
795d2c |
|
|
|
795d2c |
g_object_get (display,
|
|
|
795d2c |
"session-class", &session_class,
|
|
|
795d2c |
NULL);
|
|
|
795d2c |
if (g_strcmp0 (session_class, "greeter") == 0)
|
|
|
795d2c |
set_up_session (manager, display);
|
|
|
795d2c |
g_free (session_class);
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
if (status == GDM_DISPLAY_MANAGED) {
|
|
|
795d2c |
greeter_display_started (manager, display);
|
|
|
795d2c |
}
|
|
|
795d2c |
break;
|
|
|
795d2c |
case GDM_DISPLAY_FAILED:
|
|
|
795d2c |
case GDM_DISPLAY_UNMANAGED:
|
|
|
795d2c |
case GDM_DISPLAY_FINISHED:
|
|
|
795d2c |
#ifdef WITH_PLYMOUTH
|
|
|
795d2c |
if (quit_plymouth) {
|
|
|
795d2c |
plymouth_quit_without_transition ();
|
|
|
795d2c |
manager->priv->plymouth_is_running = FALSE;
|
|
|
795d2c |
}
|
|
|
795d2c |
#endif
|
|
|
795d2c |
|
|
|
795d2c |
if (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0) {
|
|
|
795d2c |
manager->priv->ran_once = TRUE;
|
|
|
795d2c |
}
|
|
|
795d2c |
maybe_start_pending_initial_login (manager, display);
|
|
|
795d2c |
- maybe_activate_other_session (manager, display);
|
|
|
795d2c |
break;
|
|
|
795d2c |
default:
|
|
|
795d2c |
break;
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static void
|
|
|
795d2c |
on_display_removed (GdmDisplayStore *display_store,
|
|
|
795d2c |
const char *id,
|
|
|
795d2c |
GdmManager *manager)
|
|
|
795d2c |
{
|
|
|
795d2c |
GdmDisplay *display;
|
|
|
795d2c |
|
|
|
795d2c |
display = gdm_display_store_lookup (display_store, id);
|
|
|
795d2c |
if (display != NULL) {
|
|
|
795d2c |
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
|
|
795d2c |
|
|
|
795d2c |
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
|
|
|
795d2c |
|
|
|
795d2c |
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, id);
|
|
|
795d2c |
}
|
|
|
795d2c |
}
|
|
|
795d2c |
|
|
|
795d2c |
static void
|
|
|
795d2c |
destroy_start_user_session_operation (StartUserSessionOperation *operation)
|
|
|
795d2c |
{
|
|
|
795d2c |
g_object_set_data (G_OBJECT (operation->session),
|
|
|
795d2c |
"start-user-session-operation",
|
|
|
795d2c |
NULL);
|
|
|
795d2c |
--
|
|
|
795d2c |
2.19.0
|
|
|
795d2c |
|