|
|
400dab |
From d6aca6da3ab9c16e907c7f46cf6d7bc2abbc2890 Mon Sep 17 00:00:00 2001
|
|
|
400dab |
From: Iain Lane <iainl@gnome.org>
|
|
|
400dab |
Date: Tue, 7 May 2019 16:00:14 +0100
|
|
|
400dab |
Subject: [PATCH 50/51] Allow sessions to register with GDM
|
|
|
400dab |
MIME-Version: 1.0
|
|
|
400dab |
Content-Type: text/plain; charset=UTF-8
|
|
|
400dab |
Content-Transfer-Encoding: 8bit
|
|
|
400dab |
|
|
|
400dab |
Recording when sessions start, for Wayland → Xorg fallback or
|
|
|
400dab |
transitioning to the user session, is currently done with timeouts.
|
|
|
400dab |
|
|
|
400dab |
This isn't ideal, because on some very slow machines the timeout can be
|
|
|
400dab |
hit before the session has had a chance to fail: if gnome-session takes
|
|
|
400dab |
more than 3 seconds to fail then the session will be considered to have
|
|
|
400dab |
exited rather than failed, and so we don't do Xorg fallback.
|
|
|
400dab |
|
|
|
400dab |
We can do this more reliably if we allow sessions to optionally register
|
|
|
400dab |
themselves with GDM. Then we will know when they've started, so can shut
|
|
|
400dab |
down the greeter or fall back to Xorg as appropriate. The mechanism is
|
|
|
400dab |
that they specify X-GDM-SessionRegisters=true in their file, and then
|
|
|
400dab |
call RegsterSession on the DisplayManager interface on the bus (added in
|
|
|
400dab |
the previous commit) to say that they've started up.
|
|
|
400dab |
|
|
|
400dab |
If X-GDM-SessionRegisters is missing or false, GDM will call the same
|
|
|
400dab |
method for them after 10 seconds.
|
|
|
400dab |
|
|
|
400dab |
Closes: #483
|
|
|
400dab |
---
|
|
|
400dab |
common/gdm-common.h | 2 +
|
|
|
400dab |
daemon/gdm-display.c | 19 ++-----
|
|
|
400dab |
daemon/gdm-local-display-factory.c | 49 +++++++++---------
|
|
|
400dab |
daemon/gdm-session.c | 47 +++++++++++++++--
|
|
|
400dab |
daemon/gdm-session.h | 1 +
|
|
|
400dab |
daemon/gdm-wayland-session.c | 81 +++++++++++++++++++++++-------
|
|
|
400dab |
daemon/gdm-x-session.c | 81 +++++++++++++++++++++++-------
|
|
|
400dab |
7 files changed, 201 insertions(+), 79 deletions(-)
|
|
|
400dab |
|
|
|
400dab |
diff --git a/common/gdm-common.h b/common/gdm-common.h
|
|
|
400dab |
index 3fbf07653..7fd6458d7 100644
|
|
|
400dab |
--- a/common/gdm-common.h
|
|
|
400dab |
+++ b/common/gdm-common.h
|
|
|
400dab |
@@ -1,59 +1,61 @@
|
|
|
400dab |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
|
400dab |
*
|
|
|
400dab |
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
|
|
400dab |
*
|
|
|
400dab |
* This library is free software; you can redistribute it and/or
|
|
|
400dab |
* modify it under the terms of the GNU Library General Public
|
|
|
400dab |
* License as published by the Free Software Foundation; either
|
|
|
400dab |
* version 2 of the License, or (at your option) any later version.
|
|
|
400dab |
*
|
|
|
400dab |
* This library is distributed in the hope that it will be useful,
|
|
|
400dab |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
400dab |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
400dab |
* Library General Public License for more details.
|
|
|
400dab |
*
|
|
|
400dab |
* You should have received a copy of the GNU Library General Public
|
|
|
400dab |
* License along with this library; if not, write to the
|
|
|
400dab |
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
400dab |
* Boston, MA 02110-1301, USA.
|
|
|
400dab |
*/
|
|
|
400dab |
|
|
|
400dab |
#ifndef _GDM_COMMON_H
|
|
|
400dab |
#define _GDM_COMMON_H
|
|
|
400dab |
|
|
|
400dab |
#include <glib-unix.h>
|
|
|
400dab |
#include <gio/gio.h>
|
|
|
400dab |
|
|
|
400dab |
#include <pwd.h>
|
|
|
400dab |
#include <errno.h>
|
|
|
400dab |
|
|
|
400dab |
+#define REGISTER_SESSION_TIMEOUT 10
|
|
|
400dab |
+
|
|
|
400dab |
#define VE_IGNORE_EINTR(expr) \
|
|
|
400dab |
do { \
|
|
|
400dab |
errno = 0; \
|
|
|
400dab |
expr; \
|
|
|
400dab |
} while G_UNLIKELY (errno == EINTR);
|
|
|
400dab |
|
|
|
400dab |
GQuark gdm_common_error_quark (void);
|
|
|
400dab |
#define GDM_COMMON_ERROR gdm_common_error_quark()
|
|
|
400dab |
|
|
|
400dab |
typedef char * (*GdmExpandVarFunc) (const char *var,
|
|
|
400dab |
gpointer user_data);
|
|
|
400dab |
|
|
|
400dab |
G_BEGIN_DECLS
|
|
|
400dab |
|
|
|
400dab |
int gdm_wait_on_pid (int pid);
|
|
|
400dab |
int gdm_wait_on_and_disown_pid (int pid,
|
|
|
400dab |
int timeout);
|
|
|
400dab |
int gdm_signal_pid (int pid,
|
|
|
400dab |
int signal);
|
|
|
400dab |
gboolean gdm_get_pwent_for_name (const char *name,
|
|
|
400dab |
struct passwd **pwentp);
|
|
|
400dab |
|
|
|
400dab |
gboolean gdm_clear_close_on_exec_flag (int fd);
|
|
|
400dab |
|
|
|
400dab |
const char * gdm_make_temp_dir (char *template);
|
|
|
400dab |
|
|
|
400dab |
char *gdm_generate_random_bytes (gsize size,
|
|
|
400dab |
GError **error);
|
|
|
400dab |
gboolean gdm_get_login_window_session_id (const char *seat_id,
|
|
|
400dab |
char **session_id);
|
|
|
400dab |
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
|
|
|
400dab |
index 09cc2e116..ae20491cd 100644
|
|
|
400dab |
--- a/daemon/gdm-display.c
|
|
|
400dab |
+++ b/daemon/gdm-display.c
|
|
|
400dab |
@@ -39,61 +39,60 @@
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-common.h"
|
|
|
400dab |
#include "gdm-display.h"
|
|
|
400dab |
#include "gdm-display-glue.h"
|
|
|
400dab |
#include "gdm-display-access-file.h"
|
|
|
400dab |
#include "gdm-launch-environment.h"
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-settings-direct.h"
|
|
|
400dab |
#include "gdm-settings-keys.h"
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-launch-environment.h"
|
|
|
400dab |
#include "gdm-dbus-util.h"
|
|
|
400dab |
|
|
|
400dab |
#define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
|
|
|
400dab |
|
|
|
400dab |
#define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
|
|
|
400dab |
|
|
|
400dab |
struct GdmDisplayPrivate
|
|
|
400dab |
{
|
|
|
400dab |
char *id;
|
|
|
400dab |
char *seat_id;
|
|
|
400dab |
char *session_id;
|
|
|
400dab |
char *session_class;
|
|
|
400dab |
char *session_type;
|
|
|
400dab |
|
|
|
400dab |
char *remote_hostname;
|
|
|
400dab |
int x11_display_number;
|
|
|
400dab |
char *x11_display_name;
|
|
|
400dab |
int status;
|
|
|
400dab |
time_t creation_time;
|
|
|
400dab |
- GTimer *server_timer;
|
|
|
400dab |
|
|
|
400dab |
char *x11_cookie;
|
|
|
400dab |
gsize x11_cookie_size;
|
|
|
400dab |
GdmDisplayAccessFile *access_file;
|
|
|
400dab |
|
|
|
400dab |
guint finish_idle_id;
|
|
|
400dab |
|
|
|
400dab |
xcb_connection_t *xcb_connection;
|
|
|
400dab |
int xcb_screen_number;
|
|
|
400dab |
|
|
|
400dab |
GDBusConnection *connection;
|
|
|
400dab |
GdmDisplayAccessFile *user_access_file;
|
|
|
400dab |
|
|
|
400dab |
GdmDBusDisplay *display_skeleton;
|
|
|
400dab |
GDBusObjectSkeleton *object_skeleton;
|
|
|
400dab |
|
|
|
400dab |
/* this spawns and controls the greeter session */
|
|
|
400dab |
GdmLaunchEnvironment *launch_environment;
|
|
|
400dab |
|
|
|
400dab |
guint is_local : 1;
|
|
|
400dab |
guint is_initial : 1;
|
|
|
400dab |
guint allow_timed_login : 1;
|
|
|
400dab |
guint have_existing_user_accounts : 1;
|
|
|
400dab |
guint doing_initial_setup : 1;
|
|
|
400dab |
guint session_registered : 1;
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
enum {
|
|
|
400dab |
PROP_0,
|
|
|
400dab |
PROP_ID,
|
|
|
400dab |
@@ -510,62 +509,60 @@ gdm_display_prepare (GdmDisplay *self)
|
|
|
400dab |
* asynchronously
|
|
|
400dab |
*/
|
|
|
400dab |
look_for_existing_users_sync (self);
|
|
|
400dab |
|
|
|
400dab |
self->priv->doing_initial_setup = wants_initial_setup (self);
|
|
|
400dab |
|
|
|
400dab |
g_object_ref (self);
|
|
|
400dab |
ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
|
|
|
400dab |
g_object_unref (self);
|
|
|
400dab |
|
|
|
400dab |
return ret;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_display_manage (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
gboolean res;
|
|
|
400dab |
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmDisplay: Managing display: %s", self->priv->id);
|
|
|
400dab |
|
|
|
400dab |
/* If not explicitly prepared, do it now */
|
|
|
400dab |
if (self->priv->status == GDM_DISPLAY_UNMANAGED) {
|
|
|
400dab |
res = gdm_display_prepare (self);
|
|
|
400dab |
if (! res) {
|
|
|
400dab |
return FALSE;
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
- g_timer_start (self->priv->server_timer);
|
|
|
400dab |
-
|
|
|
400dab |
if (g_strcmp0 (self->priv->session_class, "greeter") == 0) {
|
|
|
400dab |
if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
|
|
|
400dab |
GDM_DISPLAY_GET_CLASS (self)->manage (self);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_display_finish (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->finish_idle_id != 0) {
|
|
|
400dab |
g_source_remove (self->priv->finish_idle_id);
|
|
|
400dab |
self->priv->finish_idle_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
_gdm_display_set_status (self, GDM_DISPLAY_FINISHED);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmDisplay: finish display");
|
|
|
400dab |
|
|
|
400dab |
return TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_display_disconnect (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
/* These 3 bits are reserved/unused by the X protocol */
|
|
|
400dab |
@@ -576,85 +573,80 @@ gdm_display_disconnect (GdmDisplay *self)
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->xcb_connection == NULL) {
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
setup = xcb_get_setup (self->priv->xcb_connection);
|
|
|
400dab |
|
|
|
400dab |
/* resource_id_mask is the bits given to each client for
|
|
|
400dab |
* addressing resources */
|
|
|
400dab |
highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
|
|
|
400dab |
client_increment = setup->resource_id_mask + 1;
|
|
|
400dab |
|
|
|
400dab |
/* Kill every client but ourselves, then close our own connection
|
|
|
400dab |
*/
|
|
|
400dab |
for (client = 0;
|
|
|
400dab |
client <= highest_client;
|
|
|
400dab |
client += client_increment) {
|
|
|
400dab |
|
|
|
400dab |
if (client != setup->resource_id_base)
|
|
|
400dab |
xcb_kill_client (self->priv->xcb_connection, client);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
xcb_flush (self->priv->xcb_connection);
|
|
|
400dab |
|
|
|
400dab |
g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_display_unmanage (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
- gdouble elapsed;
|
|
|
400dab |
-
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmDisplay: unmanage display");
|
|
|
400dab |
|
|
|
400dab |
gdm_display_disconnect (self);
|
|
|
400dab |
|
|
|
400dab |
- g_timer_stop (self->priv->server_timer);
|
|
|
400dab |
-
|
|
|
400dab |
if (self->priv->user_access_file != NULL) {
|
|
|
400dab |
gdm_display_access_file_close (self->priv->user_access_file);
|
|
|
400dab |
g_object_unref (self->priv->user_access_file);
|
|
|
400dab |
self->priv->user_access_file = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->access_file != NULL) {
|
|
|
400dab |
gdm_display_access_file_close (self->priv->access_file);
|
|
|
400dab |
g_object_unref (self->priv->access_file);
|
|
|
400dab |
self->priv->access_file = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
- elapsed = g_timer_elapsed (self->priv->server_timer, NULL);
|
|
|
400dab |
- if (elapsed < 3) {
|
|
|
400dab |
- g_warning ("GdmDisplay: display lasted %lf seconds", elapsed);
|
|
|
400dab |
+ if (!self->priv->session_registered) {
|
|
|
400dab |
+ g_warning ("GdmDisplay: Session never registered, failing");
|
|
|
400dab |
_gdm_display_set_status (self, GDM_DISPLAY_FAILED);
|
|
|
400dab |
} else {
|
|
|
400dab |
_gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_display_get_id (GdmDisplay *self,
|
|
|
400dab |
char **id,
|
|
|
400dab |
GError **error)
|
|
|
400dab |
{
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
if (id != NULL) {
|
|
|
400dab |
*id = g_strdup (self->priv->id);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_display_get_x11_display_name (GdmDisplay *self,
|
|
|
400dab |
char **x11_display,
|
|
|
400dab |
GError **error)
|
|
|
400dab |
{
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
if (x11_display != NULL) {
|
|
|
400dab |
@@ -898,61 +890,61 @@ gdm_display_get_property (GObject *object,
|
|
|
400dab |
case PROP_X11_DISPLAY_NAME:
|
|
|
400dab |
g_value_set_string (value, self->priv->x11_display_name);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_X11_COOKIE:
|
|
|
400dab |
g_value_set_string (value, self->priv->x11_cookie);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_X11_AUTHORITY_FILE:
|
|
|
400dab |
g_value_take_string (value,
|
|
|
400dab |
self->priv->access_file?
|
|
|
400dab |
gdm_display_access_file_get_path (self->priv->access_file) : NULL);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_IS_LOCAL:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->is_local);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_IS_CONNECTED:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->xcb_connection != NULL);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_LAUNCH_ENVIRONMENT:
|
|
|
400dab |
g_value_set_object (value, self->priv->launch_environment);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_IS_INITIAL:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->is_initial);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_HAVE_EXISTING_USER_ACCOUNTS:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->have_existing_user_accounts);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_DOING_INITIAL_SETUP:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->doing_initial_setup);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_SESSION_REGISTERED:
|
|
|
400dab |
- g_value_set_boolean (value, priv->session_registered);
|
|
|
400dab |
+ g_value_set_boolean (value, self->priv->session_registered);
|
|
|
400dab |
break;
|
|
|
400dab |
case PROP_ALLOW_TIMED_LOGIN:
|
|
|
400dab |
g_value_set_boolean (value, self->priv->allow_timed_login);
|
|
|
400dab |
break;
|
|
|
400dab |
default:
|
|
|
400dab |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
400dab |
break;
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
handle_get_id (GdmDBusDisplay *skeleton,
|
|
|
400dab |
GDBusMethodInvocation *invocation,
|
|
|
400dab |
GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
char *id;
|
|
|
400dab |
|
|
|
400dab |
gdm_display_get_id (self, &id, NULL);
|
|
|
400dab |
|
|
|
400dab |
gdm_dbus_display_complete_get_id (skeleton, invocation, id);
|
|
|
400dab |
|
|
|
400dab |
g_free (id);
|
|
|
400dab |
return TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
handle_get_remote_hostname (GdmDBusDisplay *skeleton,
|
|
|
400dab |
GDBusMethodInvocation *invocation,
|
|
|
400dab |
GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
@@ -1251,99 +1243,94 @@ gdm_display_class_init (GdmDisplayClass *klass)
|
|
|
400dab |
FALSE,
|
|
|
400dab |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
|
400dab |
|
|
|
400dab |
g_object_class_install_property (object_class,
|
|
|
400dab |
PROP_LAUNCH_ENVIRONMENT,
|
|
|
400dab |
g_param_spec_object ("launch-environment",
|
|
|
400dab |
NULL,
|
|
|
400dab |
NULL,
|
|
|
400dab |
GDM_TYPE_LAUNCH_ENVIRONMENT,
|
|
|
400dab |
G_PARAM_READWRITE));
|
|
|
400dab |
g_object_class_install_property (object_class,
|
|
|
400dab |
PROP_STATUS,
|
|
|
400dab |
g_param_spec_int ("status",
|
|
|
400dab |
"status",
|
|
|
400dab |
"status",
|
|
|
400dab |
-1,
|
|
|
400dab |
G_MAXINT,
|
|
|
400dab |
GDM_DISPLAY_UNMANAGED,
|
|
|
400dab |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
|
400dab |
|
|
|
400dab |
g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_display_init (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
|
|
|
400dab |
self->priv = GDM_DISPLAY_GET_PRIVATE (self);
|
|
|
400dab |
|
|
|
400dab |
self->priv->creation_time = time (NULL);
|
|
|
400dab |
- self->priv->server_timer = g_timer_new ();
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_display_finalize (GObject *object)
|
|
|
400dab |
{
|
|
|
400dab |
GdmDisplay *self;
|
|
|
400dab |
|
|
|
400dab |
g_return_if_fail (object != NULL);
|
|
|
400dab |
g_return_if_fail (GDM_IS_DISPLAY (object));
|
|
|
400dab |
|
|
|
400dab |
self = GDM_DISPLAY (object);
|
|
|
400dab |
|
|
|
400dab |
g_return_if_fail (self->priv != NULL);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id);
|
|
|
400dab |
g_free (self->priv->id);
|
|
|
400dab |
g_free (self->priv->seat_id);
|
|
|
400dab |
g_free (self->priv->session_class);
|
|
|
400dab |
g_free (self->priv->remote_hostname);
|
|
|
400dab |
g_free (self->priv->x11_display_name);
|
|
|
400dab |
g_free (self->priv->x11_cookie);
|
|
|
400dab |
|
|
|
400dab |
g_clear_object (&self->priv->display_skeleton);
|
|
|
400dab |
g_clear_object (&self->priv->object_skeleton);
|
|
|
400dab |
g_clear_object (&self->priv->connection);
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->access_file != NULL) {
|
|
|
400dab |
g_object_unref (self->priv->access_file);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->user_access_file != NULL) {
|
|
|
400dab |
g_object_unref (self->priv->user_access_file);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
- if (self->priv->server_timer != NULL) {
|
|
|
400dab |
- g_timer_destroy (self->priv->server_timer);
|
|
|
400dab |
- }
|
|
|
400dab |
-
|
|
|
400dab |
G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
GDBusObjectSkeleton *
|
|
|
400dab |
gdm_display_get_object_skeleton (GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
return self->priv->object_skeleton;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
|
|
|
400dab |
GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
char *session_id;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmDisplay: Greeter session opened");
|
|
|
400dab |
session_id = gdm_launch_environment_get_session_id (launch_environment);
|
|
|
400dab |
_gdm_display_set_session_id (self, session_id);
|
|
|
400dab |
g_free (session_id);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_launch_environment_session_started (GdmLaunchEnvironment *launch_environment,
|
|
|
400dab |
GdmDisplay *self)
|
|
|
400dab |
{
|
|
|
400dab |
g_debug ("GdmDisplay: Greeter started");
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
self_destruct (GdmDisplay *self)
|
|
|
400dab |
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
|
|
400dab |
index aae226750..35880563d 100644
|
|
|
400dab |
--- a/daemon/gdm-local-display-factory.c
|
|
|
400dab |
+++ b/daemon/gdm-local-display-factory.c
|
|
|
400dab |
@@ -39,61 +39,60 @@
|
|
|
400dab |
#include "gdm-settings-keys.h"
|
|
|
400dab |
#include "gdm-settings-direct.h"
|
|
|
400dab |
#include "gdm-display-store.h"
|
|
|
400dab |
#include "gdm-local-display.h"
|
|
|
400dab |
#include "gdm-legacy-display.h"
|
|
|
400dab |
|
|
|
400dab |
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
|
|
400dab |
|
|
|
400dab |
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
|
|
400dab |
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
|
|
400dab |
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
|
|
400dab |
|
|
|
400dab |
#define MAX_DISPLAY_FAILURES 5
|
|
|
400dab |
#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
|
|
|
400dab |
|
|
|
400dab |
struct GdmLocalDisplayFactoryPrivate
|
|
|
400dab |
{
|
|
|
400dab |
GdmDBusLocalDisplayFactory *skeleton;
|
|
|
400dab |
GDBusConnection *connection;
|
|
|
400dab |
GHashTable *used_display_numbers;
|
|
|
400dab |
|
|
|
400dab |
/* FIXME: this needs to be per seat? */
|
|
|
400dab |
guint num_failures;
|
|
|
400dab |
|
|
|
400dab |
guint seat_new_id;
|
|
|
400dab |
guint seat_removed_id;
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
unsigned int active_vt;
|
|
|
400dab |
guint active_vt_watch_id;
|
|
|
400dab |
- guint wait_to_finish_timeout_id;
|
|
|
400dab |
#endif
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
enum {
|
|
|
400dab |
PROP_0,
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
|
|
400dab |
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
|
|
400dab |
static void gdm_local_display_factory_finalize (GObject *object);
|
|
|
400dab |
|
|
|
400dab |
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
|
|
400dab |
const char *seat_id,
|
|
|
400dab |
const char *session_type,
|
|
|
400dab |
gboolean initial_display);
|
|
|
400dab |
|
|
|
400dab |
static void on_display_status_changed (GdmDisplay *display,
|
|
|
400dab |
GParamSpec *arg1,
|
|
|
400dab |
GdmLocalDisplayFactory *factory);
|
|
|
400dab |
|
|
|
400dab |
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
|
|
400dab |
static gpointer local_display_factory_object = NULL;
|
|
|
400dab |
static gboolean lookup_by_session_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data);
|
|
|
400dab |
|
|
|
400dab |
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
|
|
400dab |
|
|
|
400dab |
GQuark
|
|
|
400dab |
gdm_local_display_factory_error_quark (void)
|
|
|
400dab |
@@ -276,60 +275,79 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
|
|
400dab |
static gboolean
|
|
|
400dab |
finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
const char *seat_id)
|
|
|
400dab |
{
|
|
|
400dab |
if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
|
|
|
400dab |
return FALSE;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: finish background display\n");
|
|
|
400dab |
gdm_display_stop_greeter_session (display);
|
|
|
400dab |
gdm_display_unmanage (display);
|
|
|
400dab |
gdm_display_finish (display);
|
|
|
400dab |
|
|
|
400dab |
return FALSE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory,
|
|
|
400dab |
const char *seat_id)
|
|
|
400dab |
{
|
|
|
400dab |
GdmDisplayStore *store;
|
|
|
400dab |
|
|
|
400dab |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
400dab |
|
|
|
400dab |
gdm_display_store_foreach (store,
|
|
|
400dab |
(GdmDisplayStoreFunc) finish_display_on_seat_if_waiting,
|
|
|
400dab |
(gpointer)
|
|
|
400dab |
seat_id);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+static void
|
|
|
400dab |
+on_session_registered_cb (GObject *gobject,
|
|
|
400dab |
+ GParamSpec *pspec,
|
|
|
400dab |
+ gpointer user_data)
|
|
|
400dab |
+{
|
|
|
400dab |
+ GdmDisplay *display = GDM_DISPLAY (gobject);
|
|
|
400dab |
+ GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
|
|
|
400dab |
+ gboolean registered;
|
|
|
400dab |
+
|
|
|
400dab |
+ g_object_get (display, "session-registered", ®istered, NULL);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (!registered)
|
|
|
400dab |
+ return;
|
|
|
400dab |
+
|
|
|
400dab |
+ g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill");
|
|
|
400dab |
+
|
|
|
400dab |
+ finish_waiting_displays_on_seat (factory, "seat0");
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
static void
|
|
|
400dab |
on_display_status_changed (GdmDisplay *display,
|
|
|
400dab |
GParamSpec *arg1,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
int status;
|
|
|
400dab |
int num;
|
|
|
400dab |
char *seat_id = NULL;
|
|
|
400dab |
char *session_type = NULL;
|
|
|
400dab |
char *session_class = NULL;
|
|
|
400dab |
gboolean is_initial = TRUE;
|
|
|
400dab |
gboolean is_local = TRUE;
|
|
|
400dab |
|
|
|
400dab |
num = -1;
|
|
|
400dab |
gdm_display_get_x11_display_number (display, &num, NULL);
|
|
|
400dab |
|
|
|
400dab |
g_object_get (display,
|
|
|
400dab |
"seat-id", &seat_id,
|
|
|
400dab |
"is-initial", &is_initial,
|
|
|
400dab |
"is-local", &is_local,
|
|
|
400dab |
"session-type", &session_type,
|
|
|
400dab |
"session-class", &session_class,
|
|
|
400dab |
NULL);
|
|
|
400dab |
|
|
|
400dab |
status = gdm_display_get_status (display);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
|
|
400dab |
switch (status) {
|
|
|
400dab |
case GDM_DISPLAY_FINISHED:
|
|
|
400dab |
/* remove the display number from factory->priv->used_display_numbers
|
|
|
400dab |
@@ -359,60 +377,67 @@ on_display_status_changed (GdmDisplay *display,
|
|
|
400dab |
/* Create a new equivalent display if it was static */
|
|
|
400dab |
if (is_local) {
|
|
|
400dab |
|
|
|
400dab |
factory->priv->num_failures++;
|
|
|
400dab |
|
|
|
400dab |
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
|
|
400dab |
/* oh shit */
|
|
|
400dab |
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
|
|
400dab |
} else {
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
if (g_strcmp0 (session_type, "wayland") == 0) {
|
|
|
400dab |
g_free (session_type);
|
|
|
400dab |
session_type = NULL;
|
|
|
400dab |
|
|
|
400dab |
/* workaround logind race for now
|
|
|
400dab |
* bug 1643874
|
|
|
400dab |
*/
|
|
|
400dab |
g_usleep (2 * G_USEC_PER_SEC);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
#endif
|
|
|
400dab |
create_display (factory, seat_id, session_type, is_initial);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_UNMANAGED:
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_PREPARED:
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_MANAGED:
|
|
|
400dab |
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
+ g_signal_connect_object (display,
|
|
|
400dab |
+ "notify::session-registered",
|
|
|
400dab |
+ G_CALLBACK (on_session_registered_cb),
|
|
|
400dab |
+ factory,
|
|
|
400dab |
+ 0);
|
|
|
400dab |
+#endif
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_WAITING_TO_FINISH:
|
|
|
400dab |
break;
|
|
|
400dab |
default:
|
|
|
400dab |
g_assert_not_reached ();
|
|
|
400dab |
break;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_free (seat_id);
|
|
|
400dab |
g_free (session_type);
|
|
|
400dab |
g_free (session_class);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
lookup_by_seat_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *looking_for = user_data;
|
|
|
400dab |
char *current;
|
|
|
400dab |
gboolean res;
|
|
|
400dab |
|
|
|
400dab |
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
|
|
400dab |
|
|
|
400dab |
res = g_strcmp0 (current, looking_for) == 0;
|
|
|
400dab |
|
|
|
400dab |
g_free(current);
|
|
|
400dab |
|
|
|
400dab |
return res;
|
|
|
400dab |
}
|
|
|
400dab |
@@ -587,100 +612,83 @@ on_seat_new (GDBusConnection *connection,
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_seat_removed (GDBusConnection *connection,
|
|
|
400dab |
const gchar *sender_name,
|
|
|
400dab |
const gchar *object_path,
|
|
|
400dab |
const gchar *interface_name,
|
|
|
400dab |
const gchar *signal_name,
|
|
|
400dab |
GVariant *parameters,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *seat;
|
|
|
400dab |
|
|
|
400dab |
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
|
|
400dab |
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
static gboolean
|
|
|
400dab |
lookup_by_session_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *looking_for = user_data;
|
|
|
400dab |
const char *current;
|
|
|
400dab |
|
|
|
400dab |
current = gdm_display_get_session_id (display);
|
|
|
400dab |
return g_strcmp0 (current, looking_for) == 0;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
-static gboolean
|
|
|
400dab |
-wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
-{
|
|
|
400dab |
- finish_waiting_displays_on_seat (factory, "seat0");
|
|
|
400dab |
- factory->priv->wait_to_finish_timeout_id = 0;
|
|
|
400dab |
- return G_SOURCE_REMOVE;
|
|
|
400dab |
-}
|
|
|
400dab |
-
|
|
|
400dab |
static void
|
|
|
400dab |
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
|
|
400dab |
GdmDisplay *display)
|
|
|
400dab |
{
|
|
|
400dab |
gboolean doing_initial_setup = FALSE;
|
|
|
400dab |
|
|
|
400dab |
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_object_get (G_OBJECT (display),
|
|
|
400dab |
"doing-initial-setup", &doing_initial_setup,
|
|
|
400dab |
NULL);
|
|
|
400dab |
|
|
|
400dab |
/* we don't ever stop initial-setup implicitly */
|
|
|
400dab |
if (doing_initial_setup) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
|
|
400dab |
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
|
|
400dab |
-
|
|
|
400dab |
- /* We stop the greeter after a timeout to avoid flicker */
|
|
|
400dab |
- if (factory->priv->wait_to_finish_timeout_id != 0)
|
|
|
400dab |
- g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
|
|
400dab |
-
|
|
|
400dab |
- factory->priv->wait_to_finish_timeout_id =
|
|
|
400dab |
- g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
|
|
400dab |
- (GSourceFunc)wait_to_finish_timeout,
|
|
|
400dab |
- factory);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_vt_changed (GIOChannel *source,
|
|
|
400dab |
GIOCondition condition,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
GIOStatus status;
|
|
|
400dab |
g_autofree char *tty_of_active_vt = NULL;
|
|
|
400dab |
g_autofree char *login_session_id = NULL;
|
|
|
400dab |
g_autofree char *active_session_id = NULL;
|
|
|
400dab |
unsigned int previous_vt, new_vt;
|
|
|
400dab |
const char *session_type = NULL;
|
|
|
400dab |
int ret, n_returned;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
|
|
400dab |
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
|
|
400dab |
|
|
|
400dab |
if (condition & G_IO_PRI) {
|
|
|
400dab |
g_autoptr (GError) error = NULL;
|
|
|
400dab |
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
|
|
400dab |
|
|
|
400dab |
if (error != NULL) {
|
|
|
400dab |
g_warning ("could not read active VT from kernel: %s", error->message);
|
|
|
400dab |
}
|
|
|
400dab |
switch (status) {
|
|
|
400dab |
case G_IO_STATUS_ERROR:
|
|
|
400dab |
return G_SOURCE_REMOVE;
|
|
|
400dab |
case G_IO_STATUS_EOF:
|
|
|
400dab |
return G_SOURCE_REMOVE;
|
|
|
400dab |
@@ -722,61 +730,60 @@ on_vt_changed (GIOChannel *source,
|
|
|
400dab |
factory->priv->active_vt = new_vt;
|
|
|
400dab |
|
|
|
400dab |
/* don't do anything at start up */
|
|
|
400dab |
if (previous_vt == 0) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT is %u at startup",
|
|
|
400dab |
factory->priv->active_vt);
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT changed from %u to %u",
|
|
|
400dab |
previous_vt, factory->priv->active_vt);
|
|
|
400dab |
|
|
|
400dab |
/* if the old VT was running a wayland login screen kill it
|
|
|
400dab |
*/
|
|
|
400dab |
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
|
|
400dab |
unsigned int login_window_vt;
|
|
|
400dab |
|
|
|
400dab |
ret = sd_session_get_vt (login_session_id, &login_window_vt);
|
|
|
400dab |
if (ret == 0 && login_window_vt != 0) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT of login window is %u", login_window_vt);
|
|
|
400dab |
if (login_window_vt == previous_vt) {
|
|
|
400dab |
GdmDisplayStore *store;
|
|
|
400dab |
GdmDisplay *display;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
|
|
400dab |
|
|
|
400dab |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
400dab |
display = gdm_display_store_find (store,
|
|
|
400dab |
lookup_by_session_id,
|
|
|
400dab |
(gpointer) login_session_id);
|
|
|
400dab |
-
|
|
|
400dab |
if (display != NULL)
|
|
|
400dab |
maybe_stop_greeter_in_background (factory, display);
|
|
|
400dab |
} else {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
/* if user jumped back to initial vt and it's empty put a login screen
|
|
|
400dab |
* on it (unless a login screen is already running elsewhere, then
|
|
|
400dab |
* jump to that login screen)
|
|
|
400dab |
*/
|
|
|
400dab |
if (factory->priv->active_vt != GDM_INITIAL_VT) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (gdm_local_display_factory_use_wayland ())
|
|
|
400dab |
session_type = "wayland";
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
|
|
|
400dab |
|
|
|
400dab |
create_display (factory, "seat0", session_type, TRUE);
|
|
|
400dab |
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
@@ -805,64 +812,60 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
g_object_unref);
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
|
|
|
400dab |
|
|
|
400dab |
if (io_channel != NULL) {
|
|
|
400dab |
factory->priv->active_vt_watch_id =
|
|
|
400dab |
g_io_add_watch (io_channel,
|
|
|
400dab |
G_IO_PRI,
|
|
|
400dab |
(GIOFunc)
|
|
|
400dab |
on_vt_changed,
|
|
|
400dab |
factory);
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
if (factory->priv->seat_new_id) {
|
|
|
400dab |
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
|
|
400dab |
factory->priv->seat_new_id);
|
|
|
400dab |
factory->priv->seat_new_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
if (factory->priv->seat_removed_id) {
|
|
|
400dab |
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
|
|
400dab |
factory->priv->seat_removed_id);
|
|
|
400dab |
factory->priv->seat_removed_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
- if (factory->priv->wait_to_finish_timeout_id != 0) {
|
|
|
400dab |
- g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
|
|
400dab |
- factory->priv->wait_to_finish_timeout_id = 0;
|
|
|
400dab |
- }
|
|
|
400dab |
if (factory->priv->active_vt_watch_id) {
|
|
|
400dab |
g_source_remove (factory->priv->active_vt_watch_id);
|
|
|
400dab |
factory->priv->active_vt_watch_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_display_added (GdmDisplayStore *display_store,
|
|
|
400dab |
const char *id,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
GdmDisplay *display;
|
|
|
400dab |
|
|
|
400dab |
display = gdm_display_store_lookup (display_store, id);
|
|
|
400dab |
|
|
|
400dab |
if (display != NULL) {
|
|
|
400dab |
g_signal_connect_object (display, "notify::status",
|
|
|
400dab |
G_CALLBACK (on_display_status_changed),
|
|
|
400dab |
factory,
|
|
|
400dab |
0);
|
|
|
400dab |
|
|
|
400dab |
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_display_removed (GdmDisplayStore *display_store,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
|
|
|
400dab |
index 5b76ba129..540a2534d 100644
|
|
|
400dab |
--- a/daemon/gdm-session.c
|
|
|
400dab |
+++ b/daemon/gdm-session.c
|
|
|
400dab |
@@ -2849,132 +2849,139 @@ on_start_program_cb (GdmDBusWorker *worker,
|
|
|
400dab |
|
|
|
400dab |
self = conversation->session;
|
|
|
400dab |
service_name = conversation->service_name;
|
|
|
400dab |
|
|
|
400dab |
if (worked) {
|
|
|
400dab |
self->priv->session_pid = pid;
|
|
|
400dab |
self->priv->session_conversation = conversation;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'", pid);
|
|
|
400dab |
g_signal_emit (self, signals[SESSION_STARTED], 0, service_name, pid);
|
|
|
400dab |
} else {
|
|
|
400dab |
gdm_session_stop_conversation (self, service_name);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmSession: Emitting 'session-start-failed' signal");
|
|
|
400dab |
g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, error->message);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
void
|
|
|
400dab |
gdm_session_start_session (GdmSession *self,
|
|
|
400dab |
const char *service_name)
|
|
|
400dab |
{
|
|
|
400dab |
GdmSessionConversation *conversation;
|
|
|
400dab |
GdmSessionDisplayMode display_mode;
|
|
|
400dab |
gboolean is_x11 = TRUE;
|
|
|
400dab |
gboolean run_launcher = FALSE;
|
|
|
400dab |
gboolean allow_remote_connections = FALSE;
|
|
|
400dab |
gboolean run_separate_bus = FALSE;
|
|
|
400dab |
char *command;
|
|
|
400dab |
char *program;
|
|
|
400dab |
+ gboolean register_session;
|
|
|
400dab |
|
|
|
400dab |
g_return_if_fail (GDM_IS_SESSION (self));
|
|
|
400dab |
g_return_if_fail (self->priv->session_conversation == NULL);
|
|
|
400dab |
|
|
|
400dab |
conversation = find_conversation_by_name (self, service_name);
|
|
|
400dab |
|
|
|
400dab |
if (conversation == NULL) {
|
|
|
400dab |
g_warning ("GdmSession: Tried to start session of "
|
|
|
400dab |
"nonexistent conversation %s", service_name);
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
stop_all_other_conversations (self, conversation, FALSE);
|
|
|
400dab |
|
|
|
400dab |
display_mode = gdm_session_get_display_mode (self);
|
|
|
400dab |
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
is_x11 = g_strcmp0 (self->priv->session_type, "wayland") != 0;
|
|
|
400dab |
#endif
|
|
|
400dab |
|
|
|
400dab |
if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED ||
|
|
|
400dab |
display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) {
|
|
|
400dab |
run_launcher = TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0 && !run_launcher) {
|
|
|
400dab |
run_separate_bus = TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ register_session = !gdm_session_session_registers (self);
|
|
|
400dab |
+
|
|
|
400dab |
if (self->priv->selected_program == NULL) {
|
|
|
400dab |
gboolean run_xsession_script;
|
|
|
400dab |
|
|
|
400dab |
command = get_session_command (self);
|
|
|
400dab |
|
|
|
400dab |
run_xsession_script = !gdm_session_bypasses_xsession (self);
|
|
|
400dab |
|
|
|
400dab |
if (self->priv->display_is_local) {
|
|
|
400dab |
gboolean disallow_tcp = TRUE;
|
|
|
400dab |
gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disallow_tcp);
|
|
|
400dab |
allow_remote_connections = !disallow_tcp;
|
|
|
400dab |
} else {
|
|
|
400dab |
allow_remote_connections = TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (run_launcher) {
|
|
|
400dab |
if (is_x11) {
|
|
|
400dab |
- program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s %s\"%s\"",
|
|
|
400dab |
+ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"",
|
|
|
400dab |
+ register_session ? "--register-session " : "",
|
|
|
400dab |
run_xsession_script? "--run-script " : "",
|
|
|
400dab |
allow_remote_connections? "--allow-remote-connections " : "",
|
|
|
400dab |
command);
|
|
|
400dab |
} else {
|
|
|
400dab |
- program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
|
|
|
400dab |
+ program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
|
|
|
400dab |
+ register_session ? "--register-session " : "",
|
|
|
400dab |
command);
|
|
|
400dab |
}
|
|
|
400dab |
} else if (run_xsession_script) {
|
|
|
400dab |
if (run_separate_bus) {
|
|
|
400dab |
program = g_strdup_printf ("dbus-run-session -- " GDMCONFDIR "/Xsession \"%s\"", command);
|
|
|
400dab |
} else {
|
|
|
400dab |
program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
|
|
|
400dab |
}
|
|
|
400dab |
} else {
|
|
|
400dab |
program = g_strdup (command);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_free (command);
|
|
|
400dab |
} else {
|
|
|
400dab |
if (run_launcher) {
|
|
|
400dab |
if (is_x11) {
|
|
|
400dab |
- program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"",
|
|
|
400dab |
+ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"%s\"",
|
|
|
400dab |
+ register_session ? "--register-session " : "",
|
|
|
400dab |
self->priv->selected_program);
|
|
|
400dab |
} else {
|
|
|
400dab |
- program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
|
|
|
400dab |
+ program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
|
|
|
400dab |
+ register_session ? "--register-session " : "",
|
|
|
400dab |
self->priv->selected_program);
|
|
|
400dab |
}
|
|
|
400dab |
} else {
|
|
|
400dab |
if (run_separate_bus) {
|
|
|
400dab |
program = g_strdup_printf ("dbus-run-session -- %s",
|
|
|
400dab |
self->priv->selected_program);
|
|
|
400dab |
} else {
|
|
|
400dab |
program = g_strdup (self->priv->selected_program);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
set_up_session_environment (self);
|
|
|
400dab |
send_environment (self, conversation);
|
|
|
400dab |
|
|
|
400dab |
gdm_dbus_worker_call_start_program (conversation->worker_proxy,
|
|
|
400dab |
program,
|
|
|
400dab |
conversation->worker_cancellable,
|
|
|
400dab |
(GAsyncReadyCallback) on_start_program_cb,
|
|
|
400dab |
conversation);
|
|
|
400dab |
g_free (program);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
stop_all_conversations (GdmSession *self)
|
|
|
400dab |
{
|
|
|
400dab |
stop_all_other_conversations (self, NULL, TRUE);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
@@ -3199,60 +3206,92 @@ gdm_session_is_wayland_session (GdmSession *self)
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
|
|
|
400dab |
is_wayland_session = TRUE;
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
out:
|
|
|
400dab |
g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
|
|
|
400dab |
|
|
|
400dab |
return is_wayland_session;
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
update_session_type (GdmSession *self)
|
|
|
400dab |
{
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
gboolean is_wayland_session = FALSE;
|
|
|
400dab |
|
|
|
400dab |
is_wayland_session = gdm_session_is_wayland_session (self);
|
|
|
400dab |
|
|
|
400dab |
if (is_wayland_session) {
|
|
|
400dab |
set_session_type (self, "wayland");
|
|
|
400dab |
} else {
|
|
|
400dab |
set_session_type (self, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+gboolean
|
|
|
400dab |
+gdm_session_session_registers (GdmSession *self)
|
|
|
400dab |
+{
|
|
|
400dab |
+ g_autoptr(GError) error = NULL;
|
|
|
400dab |
+ g_autoptr(GKeyFile) key_file = NULL;
|
|
|
400dab |
+ gboolean session_registers = FALSE;
|
|
|
400dab |
+ g_autofree char *filename = NULL;
|
|
|
400dab |
+
|
|
|
400dab |
+ g_return_val_if_fail (self != NULL, FALSE);
|
|
|
400dab |
+ g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
|
|
|
400dab |
+
|
|
|
400dab |
+ filename = get_session_filename (self);
|
|
|
400dab |
+
|
|
|
400dab |
+ key_file = load_key_file_for_file (self, filename, NULL, NULL);
|
|
|
400dab |
+
|
|
|
400dab |
+ session_registers = g_key_file_get_boolean (key_file,
|
|
|
400dab |
+ G_KEY_FILE_DESKTOP_GROUP,
|
|
|
400dab |
+ "X-GDM-SessionRegisters",
|
|
|
400dab |
+ &error);
|
|
|
400dab |
+ if (!session_registers &&
|
|
|
400dab |
+ error != NULL &&
|
|
|
400dab |
+ !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
|
|
|
400dab |
+ g_warning ("GdmSession: Couldn't read session file '%s'", filename);
|
|
|
400dab |
+ return FALSE;
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
+ g_debug ("GdmSession: '%s' %s self", filename,
|
|
|
400dab |
+ session_registers ? "registers" : "does not register");
|
|
|
400dab |
+
|
|
|
400dab |
+ return session_registers;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
gboolean
|
|
|
400dab |
gdm_session_bypasses_xsession (GdmSession *self)
|
|
|
400dab |
{
|
|
|
400dab |
GError *error;
|
|
|
400dab |
GKeyFile *key_file;
|
|
|
400dab |
gboolean res;
|
|
|
400dab |
gboolean bypasses_xsession = FALSE;
|
|
|
400dab |
char *filename = NULL;
|
|
|
400dab |
|
|
|
400dab |
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
400dab |
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
|
|
|
400dab |
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
if (gdm_session_is_wayland_session (self)) {
|
|
|
400dab |
bypasses_xsession = TRUE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
|
|
|
400dab |
filename = get_session_filename (self);
|
|
|
400dab |
|
|
|
400dab |
key_file = load_key_file_for_file (self, filename, "x11", NULL);
|
|
|
400dab |
|
|
|
400dab |
error = NULL;
|
|
|
400dab |
res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", NULL);
|
|
|
400dab |
if (!res) {
|
|
|
400dab |
goto out;
|
|
|
400dab |
} else {
|
|
|
400dab |
bypasses_xsession = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", &error);
|
|
|
400dab |
if (error) {
|
|
|
400dab |
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
|
|
|
400dab |
index a22c09543..682d2c99f 100644
|
|
|
400dab |
--- a/daemon/gdm-session.h
|
|
|
400dab |
+++ b/daemon/gdm-session.h
|
|
|
400dab |
@@ -108,60 +108,61 @@ typedef struct
|
|
|
400dab |
void (* conversation_started) (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void (* conversation_stopped) (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void (* setup_complete) (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
} GdmSessionClass;
|
|
|
400dab |
|
|
|
400dab |
GType gdm_session_get_type (void);
|
|
|
400dab |
|
|
|
400dab |
GdmSession *gdm_session_new (GdmSessionVerificationMode verification_mode,
|
|
|
400dab |
uid_t allowed_user,
|
|
|
400dab |
const char *display_name,
|
|
|
400dab |
const char *display_hostname,
|
|
|
400dab |
const char *display_device,
|
|
|
400dab |
const char *display_seat_id,
|
|
|
400dab |
const char *display_x11_authority_file,
|
|
|
400dab |
gboolean display_is_local,
|
|
|
400dab |
const char * const *environment);
|
|
|
400dab |
uid_t gdm_session_get_allowed_user (GdmSession *session);
|
|
|
400dab |
void gdm_session_start_reauthentication (GdmSession *session,
|
|
|
400dab |
GPid pid_of_caller,
|
|
|
400dab |
uid_t uid_of_caller);
|
|
|
400dab |
|
|
|
400dab |
const char *gdm_session_get_server_address (GdmSession *session);
|
|
|
400dab |
const char *gdm_session_get_username (GdmSession *session);
|
|
|
400dab |
const char *gdm_session_get_display_device (GdmSession *session);
|
|
|
400dab |
const char *gdm_session_get_display_seat_id (GdmSession *session);
|
|
|
400dab |
const char *gdm_session_get_session_id (GdmSession *session);
|
|
|
400dab |
gboolean gdm_session_bypasses_xsession (GdmSession *session);
|
|
|
400dab |
+gboolean gdm_session_session_registers (GdmSession *session);
|
|
|
400dab |
GdmSessionDisplayMode gdm_session_get_display_mode (GdmSession *session);
|
|
|
400dab |
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
void gdm_session_set_ignore_wayland (GdmSession *session,
|
|
|
400dab |
gboolean ignore_wayland);
|
|
|
400dab |
#endif
|
|
|
400dab |
gboolean gdm_session_start_conversation (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void gdm_session_stop_conversation (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
const char *gdm_session_get_conversation_session_id (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void gdm_session_setup (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void gdm_session_setup_for_user (GdmSession *session,
|
|
|
400dab |
const char *service_name,
|
|
|
400dab |
const char *username);
|
|
|
400dab |
void gdm_session_setup_for_program (GdmSession *session,
|
|
|
400dab |
const char *service_name,
|
|
|
400dab |
const char *username,
|
|
|
400dab |
const char *log_file);
|
|
|
400dab |
void gdm_session_set_environment_variable (GdmSession *session,
|
|
|
400dab |
const char *key,
|
|
|
400dab |
const char *value);
|
|
|
400dab |
void gdm_session_send_environment (GdmSession *self,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
void gdm_session_reset (GdmSession *session);
|
|
|
400dab |
void gdm_session_cancel (GdmSession *session);
|
|
|
400dab |
void gdm_session_authenticate (GdmSession *session,
|
|
|
400dab |
const char *service_name);
|
|
|
400dab |
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
|
|
|
400dab |
index 94f49e19c..35679b194 100644
|
|
|
400dab |
--- a/daemon/gdm-wayland-session.c
|
|
|
400dab |
+++ b/daemon/gdm-wayland-session.c
|
|
|
400dab |
@@ -18,68 +18,71 @@
|
|
|
400dab |
* 02110-1301, USA.
|
|
|
400dab |
*/
|
|
|
400dab |
#include "config.h"
|
|
|
400dab |
|
|
|
400dab |
#include <locale.h>
|
|
|
400dab |
#include <sysexits.h>
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-common.h"
|
|
|
400dab |
#include "gdm-settings-direct.h"
|
|
|
400dab |
#include "gdm-settings-keys.h"
|
|
|
400dab |
#include "gdm-log.h"
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-manager-glue.h"
|
|
|
400dab |
|
|
|
400dab |
#include <glib/gi18n.h>
|
|
|
400dab |
#include <glib/gstdio.h>
|
|
|
400dab |
#include <glib-unix.h>
|
|
|
400dab |
#include <glib.h>
|
|
|
400dab |
|
|
|
400dab |
#include <gio/gunixinputstream.h>
|
|
|
400dab |
|
|
|
400dab |
#define BUS_ADDRESS_FILENO (STDERR_FILENO + 1)
|
|
|
400dab |
|
|
|
400dab |
typedef struct
|
|
|
400dab |
{
|
|
|
400dab |
GdmSettings *settings;
|
|
|
400dab |
GCancellable *cancellable;
|
|
|
400dab |
|
|
|
400dab |
GSubprocess *bus_subprocess;
|
|
|
400dab |
GDBusConnection *bus_connection;
|
|
|
400dab |
+ GdmDBusManager *display_manager_proxy;
|
|
|
400dab |
char *bus_address;
|
|
|
400dab |
|
|
|
400dab |
char **environment;
|
|
|
400dab |
|
|
|
400dab |
GSubprocess *session_subprocess;
|
|
|
400dab |
char *session_command;
|
|
|
400dab |
int session_exit_status;
|
|
|
400dab |
|
|
|
400dab |
+ guint register_session_id;
|
|
|
400dab |
+
|
|
|
400dab |
GMainLoop *main_loop;
|
|
|
400dab |
|
|
|
400dab |
guint32 debug_enabled : 1;
|
|
|
400dab |
} State;
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_bus_finished (GSubprocess *subprocess,
|
|
|
400dab |
GAsyncResult *result,
|
|
|
400dab |
State *state)
|
|
|
400dab |
{
|
|
|
400dab |
gboolean cancelled;
|
|
|
400dab |
|
|
|
400dab |
cancelled = !g_subprocess_wait_finish (subprocess, result, NULL);
|
|
|
400dab |
|
|
|
400dab |
if (cancelled) {
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (g_subprocess_get_if_exited (subprocess)) {
|
|
|
400dab |
int exit_status;
|
|
|
400dab |
|
|
|
400dab |
exit_status = g_subprocess_get_exit_status (subprocess);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("message bus exited with status %d", exit_status);
|
|
|
400dab |
} else {
|
|
|
400dab |
int signal_number;
|
|
|
400dab |
|
|
|
400dab |
signal_number = g_subprocess_get_term_sig (subprocess);
|
|
|
400dab |
g_debug ("message bus was killed with status %d", signal_number);
|
|
|
400dab |
}
|
|
|
400dab |
@@ -358,140 +361,170 @@ out:
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
signal_subprocesses (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
if (state->session_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_send_signal (state->session_subprocess, SIGTERM);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (state->bus_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_send_signal (state->bus_subprocess, SIGTERM);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
wait_on_subprocesses (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
if (state->bus_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_wait (state->bus_subprocess, NULL, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_wait (state->session_subprocess, NULL, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
register_display (State *state,
|
|
|
400dab |
GCancellable *cancellable)
|
|
|
400dab |
{
|
|
|
400dab |
- GdmDBusManager *manager = NULL;
|
|
|
400dab |
GError *error = NULL;
|
|
|
400dab |
gboolean registered = FALSE;
|
|
|
400dab |
GVariantBuilder details;
|
|
|
400dab |
|
|
|
400dab |
- manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
|
|
400dab |
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
|
|
400dab |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
|
400dab |
- "org.gnome.DisplayManager",
|
|
|
400dab |
- "/org/gnome/DisplayManager/Manager",
|
|
|
400dab |
- cancellable,
|
|
|
400dab |
- &error);
|
|
|
400dab |
-
|
|
|
400dab |
- if (!manager) {
|
|
|
400dab |
- g_debug ("could not contact display manager: %s", error->message);
|
|
|
400dab |
- g_error_free (error);
|
|
|
400dab |
- goto out;
|
|
|
400dab |
- }
|
|
|
400dab |
-
|
|
|
400dab |
g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
|
|
|
400dab |
g_variant_builder_add (&details, "{ss}", "session-type", "wayland");
|
|
|
400dab |
|
|
|
400dab |
- registered = gdm_dbus_manager_call_register_display_sync (manager,
|
|
|
400dab |
+ registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
|
|
|
400dab |
g_variant_builder_end (&details),
|
|
|
400dab |
cancellable,
|
|
|
400dab |
&error);
|
|
|
400dab |
if (error != NULL) {
|
|
|
400dab |
g_debug ("Could not register display: %s", error->message);
|
|
|
400dab |
g_error_free (error);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
-out:
|
|
|
400dab |
- g_clear_object (&manager);
|
|
|
400dab |
return registered;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
init_state (State **state)
|
|
|
400dab |
{
|
|
|
400dab |
static State state_allocation;
|
|
|
400dab |
|
|
|
400dab |
*state = &state_allocation;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
clear_state (State **out_state)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = *out_state;
|
|
|
400dab |
|
|
|
400dab |
g_clear_object (&state->cancellable);
|
|
|
400dab |
g_clear_object (&state->bus_connection);
|
|
|
400dab |
g_clear_object (&state->session_subprocess);
|
|
|
400dab |
g_clear_pointer (&state->environment, g_strfreev);
|
|
|
400dab |
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
|
|
400dab |
+ g_clear_handle_id (&state->register_session_id, g_source_remove);
|
|
|
400dab |
*out_state = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_sigterm (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
g_cancellable_cancel (state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (g_main_loop_is_running (state->main_loop)) {
|
|
|
400dab |
g_main_loop_quit (state->main_loop);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+static gboolean
|
|
|
400dab |
+register_session_timeout_cb (gpointer user_data)
|
|
|
400dab |
+{
|
|
|
400dab |
+ State *state;
|
|
|
400dab |
+ GError *error = NULL;
|
|
|
400dab |
+
|
|
|
400dab |
+ state = (State *) user_data;
|
|
|
400dab |
+
|
|
|
400dab |
+ gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
|
|
|
400dab |
+ g_variant_new ("a{sv}", NULL),
|
|
|
400dab |
+ state->cancellable,
|
|
|
400dab |
+ &error);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (error != NULL) {
|
|
|
400dab |
+ g_warning ("Could not register session: %s", error->message);
|
|
|
400dab |
+ g_error_free (error);
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
+ return G_SOURCE_REMOVE;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
+static gboolean
|
|
|
400dab |
+connect_to_display_manager (State *state)
|
|
|
400dab |
+{
|
|
|
400dab |
+ g_autoptr (GError) error = NULL;
|
|
|
400dab |
+
|
|
|
400dab |
+ state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
|
|
|
400dab |
+ G_BUS_TYPE_SYSTEM,
|
|
|
400dab |
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
|
400dab |
+ "org.gnome.DisplayManager",
|
|
|
400dab |
+ "/org/gnome/DisplayManager/Manager",
|
|
|
400dab |
+ state->cancellable,
|
|
|
400dab |
+ &error);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (state->display_manager_proxy == NULL) {
|
|
|
400dab |
+ g_printerr ("gdm-wayland-session: could not contact display manager: %s\n",
|
|
|
400dab |
+ error->message);
|
|
|
400dab |
+ return FALSE;
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
+ return TRUE;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
int
|
|
|
400dab |
main (int argc,
|
|
|
400dab |
char **argv)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = NULL;
|
|
|
400dab |
GOptionContext *context = NULL;
|
|
|
400dab |
static char **args = NULL;
|
|
|
400dab |
gboolean debug = FALSE;
|
|
|
400dab |
gboolean ret;
|
|
|
400dab |
int exit_status = EX_OK;
|
|
|
400dab |
+ static gboolean register_session = FALSE;
|
|
|
400dab |
+
|
|
|
400dab |
static GOptionEntry entries [] = {
|
|
|
400dab |
+ { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a delay", NULL },
|
|
|
400dab |
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
|
|
400dab |
{ NULL }
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
|
|
400dab |
textdomain (GETTEXT_PACKAGE);
|
|
|
400dab |
setlocale (LC_ALL, "");
|
|
|
400dab |
|
|
|
400dab |
gdm_log_init ();
|
|
|
400dab |
|
|
|
400dab |
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
|
|
|
400dab |
g_option_context_add_main_entries (context, entries, NULL);
|
|
|
400dab |
|
|
|
400dab |
g_option_context_parse (context, &argc, &argv, NULL);
|
|
|
400dab |
g_option_context_free (context);
|
|
|
400dab |
|
|
|
400dab |
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
|
|
400dab |
g_warning ("gdm-wayland-session takes one argument (the session)");
|
|
|
400dab |
exit_status = EX_USAGE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
init_state (&state);
|
|
|
400dab |
|
|
|
400dab |
state->session_command = args[0];
|
|
|
400dab |
|
|
|
400dab |
state->settings = gdm_settings_new ();
|
|
|
400dab |
ret = gdm_settings_direct_init (state->settings, DATADIR "/gdm/gdm.schemas", "/");
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
@@ -501,55 +534,67 @@ main (int argc,
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
|
|
|
400dab |
state->debug_enabled = debug;
|
|
|
400dab |
|
|
|
400dab |
gdm_log_set_debug (debug);
|
|
|
400dab |
|
|
|
400dab |
state->main_loop = g_main_loop_new (NULL, FALSE);
|
|
|
400dab |
state->cancellable = g_cancellable_new ();
|
|
|
400dab |
|
|
|
400dab |
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_bus (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session message bus\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
import_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_session (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ if (!connect_to_display_manager (state))
|
|
|
400dab |
+ goto out;
|
|
|
400dab |
+
|
|
|
400dab |
ret = register_display (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ if (register_session) {
|
|
|
400dab |
+ g_debug ("gdm-wayland-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
|
|
|
400dab |
+ state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
|
|
|
400dab |
+ register_session_timeout_cb,
|
|
|
400dab |
+ state);
|
|
|
400dab |
+ } else {
|
|
|
400dab |
+ g_debug ("gdm-wayland-session: Session will register itself");
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
g_main_loop_run (state->main_loop);
|
|
|
400dab |
|
|
|
400dab |
/* Only use exit status of session if we're here because it exit */
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess == NULL) {
|
|
|
400dab |
exit_status = state->session_exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
out:
|
|
|
400dab |
if (state != NULL) {
|
|
|
400dab |
signal_subprocesses (state);
|
|
|
400dab |
wait_on_subprocesses (state);
|
|
|
400dab |
clear_state (&state);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
|
|
|
400dab |
index d8e3c7d53..f0082fdc6 100644
|
|
|
400dab |
--- a/daemon/gdm-x-session.c
|
|
|
400dab |
+++ b/daemon/gdm-x-session.c
|
|
|
400dab |
@@ -24,68 +24,71 @@
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-common.h"
|
|
|
400dab |
#include "gdm-settings-direct.h"
|
|
|
400dab |
#include "gdm-settings-keys.h"
|
|
|
400dab |
#include "gdm-log.h"
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-manager-glue.h"
|
|
|
400dab |
|
|
|
400dab |
#include <glib/gi18n.h>
|
|
|
400dab |
#include <glib/gstdio.h>
|
|
|
400dab |
#include <glib-unix.h>
|
|
|
400dab |
#include <glib.h>
|
|
|
400dab |
#include <gio/gunixinputstream.h>
|
|
|
400dab |
#include <glib-unix.h>
|
|
|
400dab |
#include <X11/Xauth.h>
|
|
|
400dab |
|
|
|
400dab |
#define DISPLAY_FILENO (STDERR_FILENO + 1)
|
|
|
400dab |
#define BUS_ADDRESS_FILENO (DISPLAY_FILENO + 1)
|
|
|
400dab |
|
|
|
400dab |
typedef struct
|
|
|
400dab |
{
|
|
|
400dab |
GdmSettings *settings;
|
|
|
400dab |
GCancellable *cancellable;
|
|
|
400dab |
|
|
|
400dab |
GSubprocess *x_subprocess;
|
|
|
400dab |
char *auth_file;
|
|
|
400dab |
char *display_name;
|
|
|
400dab |
|
|
|
400dab |
GSubprocess *bus_subprocess;
|
|
|
400dab |
GDBusConnection *bus_connection;
|
|
|
400dab |
+ GdmDBusManager *display_manager_proxy;
|
|
|
400dab |
char *bus_address;
|
|
|
400dab |
|
|
|
400dab |
char **environment;
|
|
|
400dab |
|
|
|
400dab |
GSubprocess *session_subprocess;
|
|
|
400dab |
char *session_command;
|
|
|
400dab |
int session_exit_status;
|
|
|
400dab |
|
|
|
400dab |
+ guint register_session_id;
|
|
|
400dab |
+
|
|
|
400dab |
GMainLoop *main_loop;
|
|
|
400dab |
|
|
|
400dab |
guint32 debug_enabled : 1;
|
|
|
400dab |
} State;
|
|
|
400dab |
|
|
|
400dab |
static FILE *
|
|
|
400dab |
create_auth_file (char **filename)
|
|
|
400dab |
{
|
|
|
400dab |
char *auth_dir = NULL;
|
|
|
400dab |
char *auth_file = NULL;
|
|
|
400dab |
int fd;
|
|
|
400dab |
FILE *fp = NULL;
|
|
|
400dab |
|
|
|
400dab |
auth_dir = g_build_filename (g_get_user_runtime_dir (),
|
|
|
400dab |
"gdm",
|
|
|
400dab |
NULL);
|
|
|
400dab |
|
|
|
400dab |
g_mkdir_with_parents (auth_dir, 0711);
|
|
|
400dab |
auth_file = g_build_filename (auth_dir, "Xauthority", NULL);
|
|
|
400dab |
g_clear_pointer (&auth_dir, g_free);
|
|
|
400dab |
|
|
|
400dab |
fd = g_open (auth_file, O_RDWR | O_CREAT | O_TRUNC, 0700);
|
|
|
400dab |
|
|
|
400dab |
if (fd < 0) {
|
|
|
400dab |
g_debug ("could not open %s to store auth cookie: %m",
|
|
|
400dab |
auth_file);
|
|
|
400dab |
g_clear_pointer (&auth_file, g_free);
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
@@ -711,148 +714,178 @@ signal_subprocesses (State *state)
|
|
|
400dab |
|
|
|
400dab |
if (state->bus_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_send_signal (state->bus_subprocess, SIGTERM);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (state->x_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_send_signal (state->x_subprocess, SIGTERM);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
wait_on_subprocesses (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
if (state->x_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_wait (state->x_subprocess, NULL, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (state->bus_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_wait (state->bus_subprocess, NULL, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess != NULL) {
|
|
|
400dab |
g_subprocess_wait (state->session_subprocess, NULL, NULL);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
register_display (State *state,
|
|
|
400dab |
GCancellable *cancellable)
|
|
|
400dab |
{
|
|
|
400dab |
- GdmDBusManager *manager = NULL;
|
|
|
400dab |
GError *error = NULL;
|
|
|
400dab |
gboolean registered = FALSE;
|
|
|
400dab |
GVariantBuilder details;
|
|
|
400dab |
|
|
|
400dab |
- manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
|
|
400dab |
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
|
|
400dab |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
|
400dab |
- "org.gnome.DisplayManager",
|
|
|
400dab |
- "/org/gnome/DisplayManager/Manager",
|
|
|
400dab |
- cancellable,
|
|
|
400dab |
- &error);
|
|
|
400dab |
-
|
|
|
400dab |
- if (!manager) {
|
|
|
400dab |
- g_debug ("could not contact display manager: %s", error->message);
|
|
|
400dab |
- g_error_free (error);
|
|
|
400dab |
- goto out;
|
|
|
400dab |
- }
|
|
|
400dab |
-
|
|
|
400dab |
g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
|
|
|
400dab |
g_variant_builder_add (&details, "{ss}", "session-type", "x11");
|
|
|
400dab |
g_variant_builder_add (&details, "{ss}", "x11-display-name", state->display_name);
|
|
|
400dab |
|
|
|
400dab |
- registered = gdm_dbus_manager_call_register_display_sync (manager,
|
|
|
400dab |
+ registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
|
|
|
400dab |
g_variant_builder_end (&details),
|
|
|
400dab |
cancellable,
|
|
|
400dab |
&error);
|
|
|
400dab |
if (error != NULL) {
|
|
|
400dab |
g_debug ("Could not register display: %s", error->message);
|
|
|
400dab |
g_error_free (error);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
-out:
|
|
|
400dab |
- g_clear_object (&manager);
|
|
|
400dab |
return registered;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
init_state (State **state)
|
|
|
400dab |
{
|
|
|
400dab |
static State state_allocation;
|
|
|
400dab |
|
|
|
400dab |
*state = &state_allocation;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
clear_state (State **out_state)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = *out_state;
|
|
|
400dab |
|
|
|
400dab |
g_clear_object (&state->cancellable);
|
|
|
400dab |
g_clear_object (&state->bus_connection);
|
|
|
400dab |
g_clear_object (&state->session_subprocess);
|
|
|
400dab |
g_clear_object (&state->x_subprocess);
|
|
|
400dab |
g_clear_pointer (&state->environment, g_strfreev);
|
|
|
400dab |
g_clear_pointer (&state->auth_file, g_free);
|
|
|
400dab |
g_clear_pointer (&state->display_name, g_free);
|
|
|
400dab |
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
|
|
400dab |
+ g_clear_handle_id (&state->register_session_id, g_source_remove);
|
|
|
400dab |
*out_state = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_sigterm (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
g_cancellable_cancel (state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (g_main_loop_is_running (state->main_loop)) {
|
|
|
400dab |
g_main_loop_quit (state->main_loop);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+static gboolean
|
|
|
400dab |
+register_session_timeout_cb (gpointer user_data)
|
|
|
400dab |
+{
|
|
|
400dab |
+ State *state;
|
|
|
400dab |
+ GError *error = NULL;
|
|
|
400dab |
+
|
|
|
400dab |
+ state = (State *) user_data;
|
|
|
400dab |
+
|
|
|
400dab |
+ gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
|
|
|
400dab |
+ g_variant_new ("a{sv}", NULL),
|
|
|
400dab |
+ state->cancellable,
|
|
|
400dab |
+ &error);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (error != NULL) {
|
|
|
400dab |
+ g_warning ("Could not register session: %s", error->message);
|
|
|
400dab |
+ g_error_free (error);
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
+ return G_SOURCE_REMOVE;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
+static gboolean
|
|
|
400dab |
+connect_to_display_manager (State *state)
|
|
|
400dab |
+{
|
|
|
400dab |
+ g_autoptr (GError) error = NULL;
|
|
|
400dab |
+
|
|
|
400dab |
+ state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
|
|
|
400dab |
+ G_BUS_TYPE_SYSTEM,
|
|
|
400dab |
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
|
400dab |
+ "org.gnome.DisplayManager",
|
|
|
400dab |
+ "/org/gnome/DisplayManager/Manager",
|
|
|
400dab |
+ state->cancellable,
|
|
|
400dab |
+ &error);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (state->display_manager_proxy == NULL) {
|
|
|
400dab |
+ g_printerr ("gdm-x-session: could not contact display manager: %s\n",
|
|
|
400dab |
+ error->message);
|
|
|
400dab |
+ return FALSE;
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
+ return TRUE;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
int
|
|
|
400dab |
main (int argc,
|
|
|
400dab |
char **argv)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = NULL;
|
|
|
400dab |
GOptionContext *context = NULL;
|
|
|
400dab |
static char **args = NULL;
|
|
|
400dab |
static gboolean run_script = FALSE;
|
|
|
400dab |
static gboolean allow_remote_connections = FALSE;
|
|
|
400dab |
gboolean debug = FALSE;
|
|
|
400dab |
gboolean ret;
|
|
|
400dab |
int exit_status = EX_OK;
|
|
|
400dab |
+ static gboolean register_session = FALSE;
|
|
|
400dab |
+
|
|
|
400dab |
static GOptionEntry entries [] = {
|
|
|
400dab |
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
|
|
|
400dab |
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
|
|
|
400dab |
+ { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a delay", NULL },
|
|
|
400dab |
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
|
|
400dab |
{ NULL }
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
|
|
400dab |
textdomain (GETTEXT_PACKAGE);
|
|
|
400dab |
setlocale (LC_ALL, "");
|
|
|
400dab |
|
|
|
400dab |
gdm_log_init ();
|
|
|
400dab |
|
|
|
400dab |
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
|
|
|
400dab |
g_option_context_add_main_entries (context, entries, NULL);
|
|
|
400dab |
|
|
|
400dab |
g_option_context_parse (context, &argc, &argv, NULL);
|
|
|
400dab |
g_option_context_free (context);
|
|
|
400dab |
|
|
|
400dab |
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
|
|
400dab |
g_warning ("gdm-x-session takes one argument (the session)");
|
|
|
400dab |
exit_status = EX_USAGE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
init_state (&state);
|
|
|
400dab |
|
|
|
400dab |
state->session_command = args[0];
|
|
|
400dab |
|
|
|
400dab |
state->settings = gdm_settings_new ();
|
|
|
400dab |
ret = gdm_settings_direct_init (state->settings, DATADIR "/gdm/gdm.schemas", "/");
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
@@ -870,63 +903,75 @@ main (int argc,
|
|
|
400dab |
state->cancellable = g_cancellable_new ();
|
|
|
400dab |
|
|
|
400dab |
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run X server\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_bus (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session message bus\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
import_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
ret = update_bus_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to update bus environment\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ if (!connect_to_display_manager (state))
|
|
|
400dab |
+ goto out;
|
|
|
400dab |
+
|
|
|
400dab |
ret = register_display (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_session (state, run_script, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ if (register_session) {
|
|
|
400dab |
+ g_debug ("gdm-x-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
|
|
|
400dab |
+ state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
|
|
|
400dab |
+ register_session_timeout_cb,
|
|
|
400dab |
+ state);
|
|
|
400dab |
+ } else {
|
|
|
400dab |
+ g_debug ("gdm-x-session: Session will register itself");
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
g_main_loop_run (state->main_loop);
|
|
|
400dab |
|
|
|
400dab |
/* Only use exit status of session if we're here because it exit */
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess == NULL) {
|
|
|
400dab |
exit_status = state->session_exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
out:
|
|
|
400dab |
if (state != NULL) {
|
|
|
400dab |
signal_subprocesses (state);
|
|
|
400dab |
wait_on_subprocesses (state);
|
|
|
400dab |
clear_state (&state);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
--
|
|
|
400dab |
2.27.0
|
|
|
400dab |
|