|
|
2e9516 |
From 4e4918c7d6dea3f03f3ae49f2d5721beb03936f2 Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
9fa8e4 |
Date: Tue, 19 Jul 2016 16:54:43 -0400
|
|
|
2e9516 |
Subject: [PATCH 1/5] xdmcp-display-factory: notify remote display when session
|
|
|
9fa8e4 |
ended
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gnome-shell and the session dbus daemon don't automatically exit
|
|
|
9fa8e4 |
when gnome-session does. They, instead, wait for the display to
|
|
|
9fa8e4 |
exit or regenerate. If the display is remote, that won't happen
|
|
|
9fa8e4 |
until the keep alive timeout.
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
This commit changes GDM to explicitly notify the remote display
|
|
|
9fa8e4 |
when the session is over, so that it can regenerate immediately.
|
|
|
9fa8e4 |
---
|
|
|
9fa8e4 |
daemon/gdm-xdmcp-display-factory.c | 15 ++++++++++++++-
|
|
|
9fa8e4 |
1 file changed, 14 insertions(+), 1 deletion(-)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
index d01f7ff..4132dd1 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-xdmcp-display-factory.c
|
|
|
9fa8e4 |
@@ -183,61 +183,64 @@ struct GdmXdmcpDisplayFactoryPrivate
|
|
|
9fa8e4 |
/* configuration */
|
|
|
9fa8e4 |
guint port;
|
|
|
9fa8e4 |
gboolean use_multicast;
|
|
|
9fa8e4 |
char *multicast_address;
|
|
|
9fa8e4 |
gboolean honor_indirect;
|
|
|
9fa8e4 |
char *willing_script;
|
|
|
9fa8e4 |
guint max_displays_per_host;
|
|
|
9fa8e4 |
guint max_displays;
|
|
|
9fa8e4 |
guint max_pending_displays;
|
|
|
9fa8e4 |
guint max_wait;
|
|
|
9fa8e4 |
guint max_wait_indirect;
|
|
|
9fa8e4 |
};
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
enum {
|
|
|
9fa8e4 |
PROP_0,
|
|
|
9fa8e4 |
PROP_PORT,
|
|
|
9fa8e4 |
PROP_USE_MULTICAST,
|
|
|
9fa8e4 |
PROP_MULTICAST_ADDRESS,
|
|
|
9fa8e4 |
PROP_HONOR_INDIRECT,
|
|
|
9fa8e4 |
PROP_WILLING_SCRIPT,
|
|
|
9fa8e4 |
PROP_MAX_DISPLAYS_PER_HOST,
|
|
|
9fa8e4 |
PROP_MAX_DISPLAYS,
|
|
|
9fa8e4 |
PROP_MAX_PENDING_DISPLAYS,
|
|
|
9fa8e4 |
PROP_MAX_WAIT,
|
|
|
9fa8e4 |
PROP_MAX_WAIT_INDIRECT,
|
|
|
9fa8e4 |
};
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_class_init (GdmXdmcpDisplayFactoryClass *klass);
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_init (GdmXdmcpDisplayFactory *manager);
|
|
|
9fa8e4 |
static void gdm_xdmcp_display_factory_finalize (GObject *object);
|
|
|
9fa8e4 |
-
|
|
|
9fa8e4 |
+static void gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory,
|
|
|
9fa8e4 |
+ GdmAddress *address,
|
|
|
9fa8e4 |
+ CARD16 dspnum,
|
|
|
9fa8e4 |
+ CARD32 sessid);
|
|
|
9fa8e4 |
static gpointer xdmcp_display_factory_object = NULL;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* Theory of operation:
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Process idles waiting for UDP packets on port 177.
|
|
|
9fa8e4 |
* Incoming packets are decoded and checked against tcp_wrapper.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* A typical session looks like this:
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Display sends Query/BroadcastQuery to Manager.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Manager selects an appropriate authentication scheme from the
|
|
|
9fa8e4 |
* display's list of supported ones and sends Willing/Unwilling.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* Assuming the display accepts the auth. scheme it sends back a
|
|
|
9fa8e4 |
* Request.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* If the manager accepts to service the display (i.e. loadavg is low)
|
|
|
9fa8e4 |
* it sends back an Accept containing a unique SessionID. The
|
|
|
9fa8e4 |
* SessionID is stored in an accept queue by the Manager. Should the
|
|
|
9fa8e4 |
* manager refuse to start a session a Decline is sent to the display.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* The display returns a Manage request containing the supplied
|
|
|
9fa8e4 |
* SessionID. The manager will then start a session on the display. In
|
|
|
9fa8e4 |
* case the SessionID is not on the accept queue the manager returns
|
|
|
9fa8e4 |
* Refuse. If the manager fails to open the display for connections
|
|
|
9fa8e4 |
* Failed is returned.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
@@ -2026,68 +2029,78 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
|
|
|
9fa8e4 |
g_warning ("Unable to get address: %s", gai_strerror (gaierr));
|
|
|
9fa8e4 |
g_free (xdmcp_port);
|
|
|
9fa8e4 |
return;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
g_free (xdmcp_port);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* just take the first one */
|
|
|
9fa8e4 |
ai = ai_list;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
if (ai != NULL) {
|
|
|
9fa8e4 |
char *ip;
|
|
|
9fa8e4 |
ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
ip = NULL;
|
|
|
9fa8e4 |
gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
|
|
|
9fa8e4 |
ip ? ip : "(null)");
|
|
|
9fa8e4 |
g_free (ip);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
freeaddrinfo (ai_list);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
on_display_status_changed (GdmDisplay *display,
|
|
|
9fa8e4 |
GParamSpec *arg1,
|
|
|
9fa8e4 |
GdmXdmcpDisplayFactory *factory)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
int status;
|
|
|
9fa8e4 |
GdmDisplayStore *store;
|
|
|
9fa8e4 |
+ GdmAddress *address;
|
|
|
9fa8e4 |
+ gint32 session_number;
|
|
|
9fa8e4 |
+ int display_number;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
status = gdm_display_get_status (display);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
|
|
|
9fa8e4 |
switch (status) {
|
|
|
9fa8e4 |
case GDM_DISPLAY_FINISHED:
|
|
|
9fa8e4 |
+ g_object_get (display,
|
|
|
9fa8e4 |
+ "remote-address", &address,
|
|
|
9fa8e4 |
+ "x11-display-number", &display_number,
|
|
|
9fa8e4 |
+ "session-number", &session_number,
|
|
|
9fa8e4 |
+ NULL);
|
|
|
9fa8e4 |
+ gdm_xdmcp_send_alive (factory, address, display_number, session_number);
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
gdm_display_store_remove (store, display);
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_FAILED:
|
|
|
9fa8e4 |
gdm_display_store_remove (store, display);
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_UNMANAGED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_PREPARED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
case GDM_DISPLAY_MANAGED:
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
default:
|
|
|
9fa8e4 |
g_assert_not_reached ();
|
|
|
9fa8e4 |
break;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static GdmDisplay *
|
|
|
9fa8e4 |
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
|
|
|
9fa8e4 |
const char *hostname,
|
|
|
9fa8e4 |
GdmAddress *address,
|
|
|
9fa8e4 |
int displaynum)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
GdmDisplay *display;
|
|
|
9fa8e4 |
GdmDisplayStore *store;
|
|
|
9fa8e4 |
gboolean use_chooser;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
|
|
|
9fa8e4 |
hostname ? hostname : "(null)", displaynum);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
--
|
|
|
2e9516 |
2.9.3
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
|
|
|
2e9516 |
From 7b9f559b6b5c8217840e3441b4eb5a29080a19c4 Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
9fa8e4 |
Date: Wed, 20 Jul 2016 11:43:45 -0400
|
|
|
2e9516 |
Subject: [PATCH 2/5] worker: kill process group when session exits
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
Send a hangup signal to the session pg when it exits, so things
|
|
|
9fa8e4 |
have a chance to get cleaned up.
|
|
|
9fa8e4 |
---
|
|
|
9fa8e4 |
daemon/gdm-session-worker.c | 2 ++
|
|
|
9fa8e4 |
1 file changed, 2 insertions(+)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
|
|
2e9516 |
index f37b92a..ffb728f 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-session-worker.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-session-worker.c
|
|
|
9fa8e4 |
@@ -1603,60 +1603,62 @@ run_script (GdmSessionWorker *worker,
|
|
|
9fa8e4 |
worker->priv->username,
|
|
|
9fa8e4 |
worker->priv->x11_display_name,
|
|
|
9fa8e4 |
worker->priv->display_is_local? NULL : worker->priv->hostname,
|
|
|
9fa8e4 |
worker->priv->x11_authority_file);
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
session_worker_child_watch (GPid pid,
|
|
|
9fa8e4 |
int status,
|
|
|
9fa8e4 |
GdmSessionWorker *worker)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
|
|
|
9fa8e4 |
(int) pid,
|
|
|
9fa8e4 |
WIFEXITED (status) ? "status"
|
|
|
9fa8e4 |
: WIFSIGNALED (status) ? "signal"
|
|
|
9fa8e4 |
: "unknown",
|
|
|
9fa8e4 |
WIFEXITED (status) ? WEXITSTATUS (status)
|
|
|
9fa8e4 |
: WIFSIGNALED (status) ? WTERMSIG (status)
|
|
|
9fa8e4 |
: -1);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#ifdef WITH_CONSOLE_KIT
|
|
|
9fa8e4 |
close_ck_session (worker);
|
|
|
9fa8e4 |
#endif
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
|
|
|
9fa8e4 |
worker->priv->service,
|
|
|
9fa8e4 |
status);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
+ killpg (pid, SIGHUP);
|
|
|
9fa8e4 |
+
|
|
|
9fa8e4 |
worker->priv->child_pid = -1;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
run_script (worker, GDMCONFDIR "/PostSession");
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
gdm_session_worker_watch_child (GdmSessionWorker *worker)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
|
|
|
9fa8e4 |
worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
|
|
|
9fa8e4 |
(GChildWatchFunc)session_worker_child_watch,
|
|
|
9fa8e4 |
worker);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static gboolean
|
|
|
9fa8e4 |
_is_loggable_file (const char* filename)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
struct stat file_info;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
if (g_lstat (filename, &file_info) < 0) {
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static void
|
|
|
9fa8e4 |
rotate_logs (const char *path,
|
|
|
9fa8e4 |
guint n_copies)
|
|
|
9fa8e4 |
--
|
|
|
2e9516 |
2.9.3
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
|
|
|
2e9516 |
From ede6833989a691b0ee4a27834c572814564fc541 Mon Sep 17 00:00:00 2001
|
|
|
9fa8e4 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
2e9516 |
Date: Mon, 12 Dec 2016 10:35:32 -0500
|
|
|
2e9516 |
Subject: [PATCH 3/5] display: port GdmDisplay to xcb
|
|
|
9fa8e4 |
|
|
|
2e9516 |
Xlib will kill the process if it notices the display connection has
|
|
|
2e9516 |
gone away. This is suboptimal for the main gdm process!
|
|
|
2e9516 |
|
|
|
2e9516 |
This commit ports the Xlib code to xcb, so it won't have the above
|
|
|
2e9516 |
fragility.
|
|
|
2e9516 |
|
|
|
2e9516 |
https://bugzilla.gnome.org/show_bug.cgi?id=776059
|
|
|
9fa8e4 |
---
|
|
|
2e9516 |
configure.ac | 1 +
|
|
|
2e9516 |
daemon/gdm-slave.c | 312 ++++++++++++++++++++++++-----------------------------
|
|
|
2e9516 |
2 files changed, 142 insertions(+), 171 deletions(-)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
diff --git a/configure.ac b/configure.ac
|
|
|
2e9516 |
index a131535..f9ad18a 100644
|
|
|
9fa8e4 |
--- a/configure.ac
|
|
|
9fa8e4 |
+++ b/configure.ac
|
|
|
2e9516 |
@@ -57,60 +57,61 @@ AC_SUBST(GETTEXT_PACKAGE)
|
|
|
2e9516 |
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package])
|
|
|
2e9516 |
|
|
|
2e9516 |
dnl ---------------------------------------------------------------------------
|
|
|
2e9516 |
dnl - Dependencies
|
|
|
2e9516 |
dnl ---------------------------------------------------------------------------
|
|
|
2e9516 |
|
|
|
9fa8e4 |
GLIB_REQUIRED_VERSION=2.36.0
|
|
|
9fa8e4 |
GTK_REQUIRED_VERSION=2.91.1
|
|
|
9fa8e4 |
LIBCANBERRA_GTK_REQUIRED_VERSION=0.4
|
|
|
9fa8e4 |
ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.12
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
EXTRA_COMPILE_WARNINGS(yes)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
|
|
|
9fa8e4 |
AC_SUBST(GTHREAD_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(GTHREAD_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(COMMON,
|
|
|
9fa8e4 |
gobject-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(COMMON_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(COMMON_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(DAEMON,
|
|
|
9fa8e4 |
gobject-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
|
|
|
9fa8e4 |
accountsservice >= $ACCOUNTS_SERVICE_REQUIRED_VERSION
|
|
|
2e9516 |
+ xcb
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(DAEMON_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(DAEMON_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
GLIB_GSETTINGS
|
|
|
9fa8e4 |
|
|
|
2e9516 |
PKG_CHECK_MODULES(XLIB, x11 xau xrandr, ,
|
|
|
9fa8e4 |
[AC_PATH_XTRA
|
|
|
9fa8e4 |
if test "x$no_x" = xyes; then
|
|
|
9fa8e4 |
AC_MSG_ERROR("no (requires X development libraries)")
|
|
|
9fa8e4 |
else
|
|
|
9fa8e4 |
XLIB_LIBS="$X_PRE_LIBS $X_LIBS -lXau -lX11 -lXext -lXrandr $X_EXTRA_LIBS"
|
|
|
9fa8e4 |
XLIB_CFLAGS=$X_CFLAGS
|
|
|
9fa8e4 |
fi])
|
|
|
9fa8e4 |
AC_SUBST(XLIB_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(XLIB_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(GTK,
|
|
|
9fa8e4 |
gtk+-3.0 >= $GTK_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(GTK_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(GTK_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
PKG_CHECK_MODULES(CANBERRA_GTK,
|
|
|
9fa8e4 |
libcanberra-gtk3 >= $LIBCANBERRA_GTK_REQUIRED_VERSION
|
|
|
9fa8e4 |
)
|
|
|
9fa8e4 |
AC_SUBST(CANBERRA_GTK_CFLAGS)
|
|
|
9fa8e4 |
AC_SUBST(CANBERRA_GTK_LIBS)
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
AC_ARG_WITH(selinux,
|
|
|
9fa8e4 |
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
|
|
|
2e9516 |
index b4bbcfd..c0a53fe 100644
|
|
|
9fa8e4 |
--- a/daemon/gdm-slave.c
|
|
|
9fa8e4 |
+++ b/daemon/gdm-slave.c
|
|
|
2e9516 |
@@ -10,398 +10,358 @@
|
|
|
2e9516 |
* This program is distributed in the hope that it will be useful,
|
|
|
9fa8e4 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
9fa8e4 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
9fa8e4 |
* GNU General Public License for more details.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
* You should have received a copy of the GNU General Public License
|
|
|
9fa8e4 |
* along with this program; if not, write to the Free Software
|
|
|
9fa8e4 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
9fa8e4 |
*
|
|
|
9fa8e4 |
*/
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "config.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include <stdlib.h>
|
|
|
9fa8e4 |
#include <stdio.h>
|
|
|
9fa8e4 |
#include <stdint.h>
|
|
|
9fa8e4 |
#include <fcntl.h>
|
|
|
9fa8e4 |
#include <unistd.h>
|
|
|
9fa8e4 |
#include <string.h>
|
|
|
9fa8e4 |
#include <sys/types.h>
|
|
|
9fa8e4 |
#include <sys/wait.h>
|
|
|
9fa8e4 |
#include <errno.h>
|
|
|
9fa8e4 |
#include <pwd.h>
|
|
|
9fa8e4 |
#include <grp.h>
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include <glib.h>
|
|
|
9fa8e4 |
#include <glib/gstdio.h>
|
|
|
9fa8e4 |
#include <glib/gi18n.h>
|
|
|
9fa8e4 |
#include <glib-object.h>
|
|
|
9fa8e4 |
|
|
|
2e9516 |
-#include <X11/Xlib.h> /* for Display */
|
|
|
2e9516 |
-#include <X11/Xatom.h> /* for XA_PIXMAP */
|
|
|
2e9516 |
+#include <xcb/xcb.h>
|
|
|
2e9516 |
+
|
|
|
9fa8e4 |
#include <X11/cursorfont.h> /* for watch cursor */
|
|
|
9fa8e4 |
#include <X11/extensions/Xrandr.h>
|
|
|
9fa8e4 |
#include <X11/Xatom.h>
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#ifdef WITH_SYSTEMD
|
|
|
9fa8e4 |
#include <systemd/sd-login.h>
|
|
|
9fa8e4 |
#endif
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-common.h"
|
|
|
9fa8e4 |
#include "gdm-xerrors.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-slave.h"
|
|
|
9fa8e4 |
#include "gdm-display.h"
|
|
|
9fa8e4 |
#include "gdm-display-glue.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#include "gdm-server.h"
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
#define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate))
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
struct GdmSlavePrivate
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
GPid pid;
|
|
|
9fa8e4 |
guint output_watch_id;
|
|
|
9fa8e4 |
guint error_watch_id;
|
|
|
9fa8e4 |
|
|
|
2e9516 |
- Display *server_display;
|
|
|
2e9516 |
+ xcb_connection_t *xcb_connection;
|
|
|
2e9516 |
+ int xcb_screen_number;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
char *session_id;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
GdmDisplay *display;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
/* cached display values */
|
|
|
9fa8e4 |
char *display_name;
|
|
|
9fa8e4 |
int display_number;
|
|
|
2e9516 |
char *display_hostname;
|
|
|
2e9516 |
gboolean display_is_local;
|
|
|
2e9516 |
char *display_seat_id;
|
|
|
2e9516 |
char *display_x11_authority_file;
|
|
|
2e9516 |
char *windowpath;
|
|
|
2e9516 |
GBytes *display_x11_cookie;
|
|
|
2e9516 |
gboolean display_is_initial;
|
|
|
2e9516 |
};
|
|
|
2e9516 |
|
|
|
2e9516 |
enum {
|
|
|
2e9516 |
PROP_0,
|
|
|
2e9516 |
PROP_SESSION_ID,
|
|
|
2e9516 |
PROP_DISPLAY,
|
|
|
2e9516 |
PROP_DISPLAY_NAME,
|
|
|
2e9516 |
PROP_DISPLAY_NUMBER,
|
|
|
2e9516 |
PROP_DISPLAY_HOSTNAME,
|
|
|
2e9516 |
PROP_DISPLAY_IS_LOCAL,
|
|
|
2e9516 |
PROP_DISPLAY_SEAT_ID,
|
|
|
2e9516 |
PROP_DISPLAY_X11_AUTHORITY_FILE,
|
|
|
2e9516 |
PROP_DISPLAY_IS_INITIAL,
|
|
|
2e9516 |
};
|
|
|
2e9516 |
|
|
|
2e9516 |
enum {
|
|
|
2e9516 |
STARTED,
|
|
|
2e9516 |
STOPPED,
|
|
|
2e9516 |
LAST_SIGNAL
|
|
|
2e9516 |
};
|
|
|
2e9516 |
|
|
|
2e9516 |
static guint signals [LAST_SIGNAL] = { 0, };
|
|
|
2e9516 |
|
|
|
2e9516 |
static void gdm_slave_class_init (GdmSlaveClass *klass);
|
|
|
2e9516 |
static void gdm_slave_init (GdmSlave *slave);
|
|
|
2e9516 |
static void gdm_slave_finalize (GObject *object);
|
|
|
2e9516 |
|
|
|
2e9516 |
G_DEFINE_ABSTRACT_TYPE (GdmSlave, gdm_slave, G_TYPE_OBJECT)
|
|
|
2e9516 |
|
|
|
2e9516 |
#define CURSOR_WATCH XC_watch
|
|
|
2e9516 |
|
|
|
2e9516 |
GQuark
|
|
|
2e9516 |
gdm_slave_error_quark (void)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
static GQuark ret = 0;
|
|
|
2e9516 |
if (ret == 0) {
|
|
|
2e9516 |
ret = g_quark_from_static_string ("gdm-slave-error-quark");
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
return ret;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
-static XRRScreenResources *
|
|
|
2e9516 |
-get_screen_resources (Display *dpy)
|
|
|
2e9516 |
+static xcb_screen_t *
|
|
|
2e9516 |
+get_screen (xcb_connection_t *connection,
|
|
|
2e9516 |
+ int screen_number)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
- int major = 0, minor = 0;
|
|
|
2e9516 |
+ xcb_screen_t *screen = NULL;
|
|
|
2e9516 |
+ xcb_screen_iterator_t iter;
|
|
|
2e9516 |
|
|
|
2e9516 |
- if (!XRRQueryVersion(dpy, &major, &minor)) {
|
|
|
2e9516 |
- return NULL;
|
|
|
2e9516 |
+ iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
|
|
|
2e9516 |
+ while (iter.rem) {
|
|
|
2e9516 |
+ if (screen_number == 0)
|
|
|
2e9516 |
+ screen = iter.data;
|
|
|
2e9516 |
+ screen_number--;
|
|
|
2e9516 |
+ xcb_screen_next (&iter);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- if (major > 1) {
|
|
|
2e9516 |
- return NULL;
|
|
|
2e9516 |
+ if (screen != NULL) {
|
|
|
2e9516 |
+ return screen;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- if (minor >= 3) {
|
|
|
2e9516 |
- return XRRGetScreenResourcesCurrent (dpy,
|
|
|
2e9516 |
- DefaultRootWindow (dpy));
|
|
|
2e9516 |
+ return NULL;
|
|
|
2e9516 |
+}
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+static xcb_window_t
|
|
|
2e9516 |
+get_root_window (xcb_connection_t *connection,
|
|
|
2e9516 |
+ int screen_number)
|
|
|
2e9516 |
+{
|
|
|
2e9516 |
+ xcb_screen_t *screen = NULL;
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ screen = get_screen (connection, screen_number);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (screen != NULL) {
|
|
|
2e9516 |
+ return screen->root;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- return XRRGetScreenResources (dpy, DefaultRootWindow (dpy));
|
|
|
2e9516 |
+ return XCB_WINDOW_NONE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static void
|
|
|
2e9516 |
determine_initial_cursor_position (GdmSlave *slave,
|
|
|
2e9516 |
int *x,
|
|
|
2e9516 |
int *y)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
- XRRScreenResources *resources;
|
|
|
2e9516 |
- RROutput primary_output;
|
|
|
2e9516 |
- int i;
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- /* If this function fails for whatever reason,
|
|
|
2e9516 |
- * put the pointer in the lower right corner of the screen.
|
|
|
2e9516 |
- */
|
|
|
2e9516 |
- *x = .9 * DisplayWidth (slave->priv->server_display,
|
|
|
2e9516 |
- DefaultScreen (slave->priv->server_display));
|
|
|
2e9516 |
- *y = .9 * DisplayHeight (slave->priv->server_display,
|
|
|
2e9516 |
- DefaultScreen (slave->priv->server_display));
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- gdm_error_trap_push ();
|
|
|
2e9516 |
- resources = get_screen_resources (slave->priv->server_display);
|
|
|
2e9516 |
- primary_output = XRRGetOutputPrimary (slave->priv->server_display,
|
|
|
2e9516 |
- DefaultRootWindow (slave->priv->server_display));
|
|
|
2e9516 |
- gdm_error_trap_pop ();
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- if (resources == NULL) {
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- for (i = 0; i < resources->noutput; i++) {
|
|
|
2e9516 |
- XRROutputInfo *output_info;
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- if (primary_output == None) {
|
|
|
2e9516 |
- primary_output = resources->outputs[0];
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- if (resources->outputs[i] != primary_output) {
|
|
|
2e9516 |
- continue;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- output_info = XRRGetOutputInfo (slave->priv->server_display,
|
|
|
2e9516 |
- resources,
|
|
|
2e9516 |
- resources->outputs[i]);
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- if (output_info->connection != RR_Disconnected &&
|
|
|
2e9516 |
- output_info->crtc != 0) {
|
|
|
2e9516 |
- XRRCrtcInfo *crtc_info;
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- crtc_info = XRRGetCrtcInfo (slave->priv->server_display,
|
|
|
2e9516 |
- resources,
|
|
|
2e9516 |
- output_info->crtc);
|
|
|
2e9516 |
- /* position it sort of in the lower right
|
|
|
2e9516 |
- */
|
|
|
2e9516 |
- *x = crtc_info->x + .9 * crtc_info->width;
|
|
|
2e9516 |
- *y = crtc_info->y + .9 * crtc_info->height;
|
|
|
2e9516 |
- XRRFreeCrtcInfo (crtc_info);
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- XRRFreeOutputInfo (output_info);
|
|
|
2e9516 |
- break;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- XRRFreeScreenResources (resources);
|
|
|
2e9516 |
+ *x = 50;
|
|
|
2e9516 |
+ *y = 50;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
void
|
|
|
2e9516 |
gdm_slave_set_initial_cursor_position (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
- if (slave->priv->server_display != NULL) {
|
|
|
2e9516 |
+ if (slave->priv->xcb_connection != NULL) {
|
|
|
2e9516 |
int x, y;
|
|
|
2e9516 |
+ xcb_window_t root_window = XCB_WINDOW_NONE;
|
|
|
2e9516 |
|
|
|
2e9516 |
determine_initial_cursor_position (slave, &x, &y);
|
|
|
2e9516 |
- XWarpPointer(slave->priv->server_display,
|
|
|
2e9516 |
- None,
|
|
|
2e9516 |
- DefaultRootWindow (slave->priv->server_display),
|
|
|
2e9516 |
- 0, 0,
|
|
|
2e9516 |
- 0, 0,
|
|
|
2e9516 |
- x, y);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ root_window = get_root_window (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ slave->priv->xcb_screen_number);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (root_window != XCB_WINDOW_NONE) {
|
|
|
2e9516 |
+ xcb_warp_pointer (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ XCB_WINDOW_NONE,
|
|
|
2e9516 |
+ root_window,
|
|
|
2e9516 |
+ 0, 0,
|
|
|
2e9516 |
+ 0, 0,
|
|
|
2e9516 |
+ x, y);
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
}
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static void
|
|
|
2e9516 |
-gdm_slave_setup_xhost_auth (XHostAddress *host_entries, XServerInterpretedAddress *si_entries)
|
|
|
2e9516 |
+gdm_slave_setup_xhost_auth (XHostAddress *host_entries)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
- si_entries[0].type = "localuser";
|
|
|
2e9516 |
- si_entries[0].typelength = strlen ("localuser");
|
|
|
2e9516 |
- si_entries[1].type = "localuser";
|
|
|
2e9516 |
- si_entries[1].typelength = strlen ("localuser");
|
|
|
2e9516 |
- si_entries[2].type = "localuser";
|
|
|
2e9516 |
- si_entries[2].typelength = strlen ("localuser");
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- si_entries[0].value = "root";
|
|
|
2e9516 |
- si_entries[0].valuelength = strlen ("root");
|
|
|
2e9516 |
- si_entries[1].value = GDM_USERNAME;
|
|
|
2e9516 |
- si_entries[1].valuelength = strlen (GDM_USERNAME);
|
|
|
2e9516 |
- si_entries[2].value = "gnome-initial-setup";
|
|
|
2e9516 |
- si_entries[2].valuelength = strlen ("gnome-initial-setup");
|
|
|
2e9516 |
-
|
|
|
2e9516 |
host_entries[0].family = FamilyServerInterpreted;
|
|
|
2e9516 |
- host_entries[0].address = (char *) &si_entries[0];
|
|
|
2e9516 |
- host_entries[0].length = sizeof (XServerInterpretedAddress);
|
|
|
2e9516 |
+ host_entries[0].address = "localuser\0root";
|
|
|
2e9516 |
+ host_entries[0].length = sizeof ("localuser\0root");
|
|
|
2e9516 |
host_entries[1].family = FamilyServerInterpreted;
|
|
|
2e9516 |
- host_entries[1].address = (char *) &si_entries[1];
|
|
|
2e9516 |
- host_entries[1].length = sizeof (XServerInterpretedAddress);
|
|
|
2e9516 |
+ host_entries[1].address = "localuser\0" GDM_USERNAME;
|
|
|
2e9516 |
+ host_entries[1].length = sizeof ("localuser\0" GDM_USERNAME);
|
|
|
2e9516 |
host_entries[2].family = FamilyServerInterpreted;
|
|
|
2e9516 |
- host_entries[2].address = (char *) &si_entries[2];
|
|
|
2e9516 |
- host_entries[2].length = sizeof (XServerInterpretedAddress);
|
|
|
2e9516 |
+ host_entries[2].address = "localuser\0gnome-initial-setup";
|
|
|
2e9516 |
+ host_entries[2].length = sizeof ("localuser\0gnome-initial-setup");
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static void
|
|
|
2e9516 |
gdm_slave_set_windowpath (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
/* setting WINDOWPATH for clients */
|
|
|
2e9516 |
- Atom prop;
|
|
|
2e9516 |
- Atom actualtype;
|
|
|
2e9516 |
- int actualformat;
|
|
|
2e9516 |
- unsigned long nitems;
|
|
|
2e9516 |
- unsigned long bytes_after;
|
|
|
2e9516 |
- unsigned char *buf;
|
|
|
2e9516 |
+ xcb_intern_atom_cookie_t atom_cookie;
|
|
|
2e9516 |
+ xcb_intern_atom_reply_t *atom_reply = NULL;
|
|
|
2e9516 |
+ xcb_get_property_cookie_t get_property_cookie;
|
|
|
2e9516 |
+ xcb_get_property_reply_t *get_property_reply = NULL;
|
|
|
2e9516 |
+ xcb_window_t root_window = XCB_WINDOW_NONE;
|
|
|
2e9516 |
const char *windowpath;
|
|
|
2e9516 |
char *newwindowpath;
|
|
|
2e9516 |
- unsigned long num;
|
|
|
2e9516 |
+ uint32_t num;
|
|
|
2e9516 |
char nums[10];
|
|
|
2e9516 |
int numn;
|
|
|
2e9516 |
|
|
|
2e9516 |
- prop = XInternAtom (slave->priv->server_display, "XFree86_VT", False);
|
|
|
2e9516 |
- if (prop == None) {
|
|
|
2e9516 |
+ atom_cookie = xcb_intern_atom (slave->priv->xcb_connection, 0, strlen("XFree86_VT"), "XFree86_VT");
|
|
|
2e9516 |
+ atom_reply = xcb_intern_atom_reply (slave->priv->xcb_connection, atom_cookie, NULL);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (atom_reply == NULL) {
|
|
|
2e9516 |
g_debug ("no XFree86_VT atom\n");
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ goto out;
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ root_window = get_root_window (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ slave->priv->xcb_screen_number);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (root_window == XCB_WINDOW_NONE) {
|
|
|
2e9516 |
+ g_debug ("couldn't find root window\n");
|
|
|
2e9516 |
+ goto out;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
- if (XGetWindowProperty (slave->priv->server_display,
|
|
|
2e9516 |
- DefaultRootWindow (slave->priv->server_display), prop, 0, 1,
|
|
|
2e9516 |
- False, AnyPropertyType, &actualtype, &actualformat,
|
|
|
2e9516 |
- &nitems, &bytes_after, &buf)) {
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ get_property_cookie = xcb_get_property (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ FALSE,
|
|
|
2e9516 |
+ root_window,
|
|
|
2e9516 |
+ atom_reply->atom,
|
|
|
2e9516 |
+ XCB_ATOM_INTEGER,
|
|
|
2e9516 |
+ 0,
|
|
|
2e9516 |
+ 1);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ get_property_reply = xcb_get_property_reply (slave->priv->xcb_connection, get_property_cookie, NULL);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (get_property_reply == NULL) {
|
|
|
2e9516 |
g_debug ("no XFree86_VT property\n");
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- if (nitems != 1) {
|
|
|
2e9516 |
- g_debug ("%lu items in XFree86_VT property!\n", nitems);
|
|
|
2e9516 |
- XFree (buf);
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- switch (actualtype) {
|
|
|
2e9516 |
- case XA_CARDINAL:
|
|
|
2e9516 |
- case XA_INTEGER:
|
|
|
2e9516 |
- case XA_WINDOW:
|
|
|
2e9516 |
- switch (actualformat) {
|
|
|
2e9516 |
- case 8:
|
|
|
2e9516 |
- num = (*(uint8_t *)(void *)buf);
|
|
|
2e9516 |
- break;
|
|
|
2e9516 |
- case 16:
|
|
|
2e9516 |
- num = (*(uint16_t *)(void *)buf);
|
|
|
2e9516 |
- break;
|
|
|
2e9516 |
- case 32:
|
|
|
2e9516 |
- num = (*(long *)(void *)buf);
|
|
|
2e9516 |
- break;
|
|
|
2e9516 |
- default:
|
|
|
2e9516 |
- g_debug ("format %d in XFree86_VT property!\n", actualformat);
|
|
|
2e9516 |
- XFree (buf);
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
- }
|
|
|
2e9516 |
- break;
|
|
|
2e9516 |
- default:
|
|
|
2e9516 |
- g_debug ("type %lx in XFree86_VT property!\n", actualtype);
|
|
|
2e9516 |
- XFree (buf);
|
|
|
2e9516 |
- return;
|
|
|
2e9516 |
+ goto out;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
- XFree (buf);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ num = ((uint32_t *) xcb_get_property_value (get_property_reply))[0];
|
|
|
2e9516 |
|
|
|
2e9516 |
windowpath = getenv ("WINDOWPATH");
|
|
|
2e9516 |
- numn = snprintf (nums, sizeof (nums), "%lu", num);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ numn = snprintf (nums, sizeof (nums), "%u", num);
|
|
|
2e9516 |
if (!windowpath) {
|
|
|
2e9516 |
newwindowpath = malloc (numn + 1);
|
|
|
2e9516 |
sprintf (newwindowpath, "%s", nums);
|
|
|
2e9516 |
} else {
|
|
|
2e9516 |
newwindowpath = malloc (strlen (windowpath) + 1 + numn + 1);
|
|
|
2e9516 |
sprintf (newwindowpath, "%s:%s", windowpath, nums);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- slave->priv->windowpath = newwindowpath;
|
|
|
2e9516 |
-
|
|
|
2e9516 |
g_setenv ("WINDOWPATH", newwindowpath, TRUE);
|
|
|
2e9516 |
+out:
|
|
|
2e9516 |
+ g_clear_pointer (&atom_reply, free);
|
|
|
2e9516 |
+ g_clear_pointer (&get_property_reply, free);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gboolean
|
|
|
2e9516 |
gdm_slave_connect_to_x11_display (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
+ xcb_auth_info_t *auth_info = NULL;
|
|
|
2e9516 |
gboolean ret;
|
|
|
2e9516 |
|
|
|
2e9516 |
ret = FALSE;
|
|
|
2e9516 |
|
|
|
2e9516 |
/* We keep our own (windowless) connection (dsp) open to avoid the
|
|
|
2e9516 |
* X server resetting due to lack of active connections. */
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: Server is ready - opening display %s", slave->priv->display_name);
|
|
|
2e9516 |
|
|
|
2e9516 |
/* Give slave access to the display independent of current hostname */
|
|
|
2e9516 |
if (slave->priv->display_x11_cookie != NULL) {
|
|
|
2e9516 |
- XSetAuthorization ("MIT-MAGIC-COOKIE-1",
|
|
|
2e9516 |
- strlen ("MIT-MAGIC-COOKIE-1"),
|
|
|
2e9516 |
- (gpointer)
|
|
|
2e9516 |
- g_bytes_get_data (slave->priv->display_x11_cookie, NULL),
|
|
|
2e9516 |
- g_bytes_get_size (slave->priv->display_x11_cookie));
|
|
|
2e9516 |
+ auth_info = g_alloca (sizeof (xcb_auth_info_t));
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ auth_info->namelen = strlen ("MIT-MAGIC-COOKIE-1");
|
|
|
2e9516 |
+ auth_info->name = "MIT-MAGIC-COOKIE-1";
|
|
|
2e9516 |
+ auth_info->datalen = g_bytes_get_size (slave->priv->display_x11_cookie);
|
|
|
2e9516 |
+ auth_info->data = (gpointer) g_bytes_get_data (slave->priv->display_x11_cookie, NULL);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- slave->priv->server_display = XOpenDisplay (slave->priv->display_name);
|
|
|
2e9516 |
+ slave->priv->xcb_connection = xcb_connect_to_display_with_auth_info (slave->priv->display_name,
|
|
|
2e9516 |
+ auth_info,
|
|
|
2e9516 |
+ &slave->priv->xcb_screen_number);
|
|
|
2e9516 |
|
|
|
2e9516 |
- if (slave->priv->server_display == NULL) {
|
|
|
2e9516 |
+ if (xcb_connection_has_error (slave->priv->xcb_connection)) {
|
|
|
2e9516 |
+ g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
|
|
|
2e9516 |
g_warning ("Unable to connect to display %s", slave->priv->display_name);
|
|
|
2e9516 |
ret = FALSE;
|
|
|
2e9516 |
} else if (slave->priv->display_is_local) {
|
|
|
2e9516 |
- XServerInterpretedAddress si_entries[3];
|
|
|
2e9516 |
XHostAddress host_entries[3];
|
|
|
2e9516 |
+ xcb_void_cookie_t cookies[3];
|
|
|
2e9516 |
int i;
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
|
|
|
2e9516 |
ret = TRUE;
|
|
|
2e9516 |
|
|
|
2e9516 |
/* Give programs run by the slave and greeter access to the
|
|
|
2e9516 |
* display independent of current hostname
|
|
|
2e9516 |
*/
|
|
|
2e9516 |
- gdm_slave_setup_xhost_auth (host_entries, si_entries);
|
|
|
2e9516 |
-
|
|
|
2e9516 |
- gdm_error_trap_push ();
|
|
|
2e9516 |
+ gdm_slave_setup_xhost_auth (host_entries);
|
|
|
2e9516 |
|
|
|
2e9516 |
for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
|
|
|
2e9516 |
- XAddHost (slave->priv->server_display, &host_entries[i]);
|
|
|
2e9516 |
+ cookies[i] = xcb_change_hosts_checked (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ XCB_HOST_MODE_INSERT,
|
|
|
2e9516 |
+ host_entries[i].family,
|
|
|
2e9516 |
+ host_entries[i].length,
|
|
|
2e9516 |
+ (uint8_t *) host_entries[i].address);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
- XSync (slave->priv->server_display, False);
|
|
|
2e9516 |
- if (gdm_error_trap_pop ()) {
|
|
|
2e9516 |
- g_warning ("Failed to give slave programs access to the display. Trying to proceed.");
|
|
|
2e9516 |
+ for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
|
|
|
2e9516 |
+ xcb_generic_error_t *xcb_error;
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ xcb_error = xcb_request_check (slave->priv->xcb_connection, cookies[i]);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (xcb_error != NULL) {
|
|
|
2e9516 |
+ g_debug ("Failed to give system user '%s' access to the display. Trying to proceed.", host_entries[i].address + sizeof ("localuser"));
|
|
|
2e9516 |
+ free (xcb_error);
|
|
|
2e9516 |
+ } else {
|
|
|
2e9516 |
+ g_debug ("Gave system user '%s' access to the display.", host_entries[i].address + sizeof ("localuser"));
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gdm_slave_set_windowpath (slave);
|
|
|
2e9516 |
} else {
|
|
|
2e9516 |
g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
|
|
|
2e9516 |
ret = TRUE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
if (ret) {
|
|
|
2e9516 |
g_signal_emit (slave, signals [STARTED], 0);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
return ret;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static gboolean
|
|
|
2e9516 |
gdm_slave_real_start (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
gboolean res;
|
|
|
2e9516 |
GError *error;
|
|
|
2e9516 |
const char *x11_cookie;
|
|
|
2e9516 |
gsize x11_cookie_size;
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: Starting slave");
|
|
|
2e9516 |
|
|
|
2e9516 |
/* cache some values up front */
|
|
|
2e9516 |
error = NULL;
|
|
|
2e9516 |
res = gdm_display_is_local (slave->priv->display, &slave->priv->display_is_local, &error);
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
2e9516 |
@@ -495,104 +455,114 @@ gdm_slave_start (GdmSlave *slave)
|
|
|
2e9516 |
g_object_ref (slave);
|
|
|
2e9516 |
ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
|
|
|
2e9516 |
g_object_unref (slave);
|
|
|
2e9516 |
|
|
|
2e9516 |
return ret;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gboolean
|
|
|
2e9516 |
gdm_slave_stop (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
gboolean ret;
|
|
|
2e9516 |
|
|
|
2e9516 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: stopping slave");
|
|
|
2e9516 |
|
|
|
2e9516 |
g_object_ref (slave);
|
|
|
2e9516 |
|
|
|
2e9516 |
ret = GDM_SLAVE_GET_CLASS (slave)->stop (slave);
|
|
|
2e9516 |
g_signal_emit (slave, signals [STOPPED], 0);
|
|
|
2e9516 |
|
|
|
2e9516 |
g_object_unref (slave);
|
|
|
2e9516 |
return ret;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gboolean
|
|
|
2e9516 |
gdm_slave_add_user_authorization (GdmSlave *slave,
|
|
|
2e9516 |
const char *username,
|
|
|
2e9516 |
char **filenamep)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
- XServerInterpretedAddress si_entries[3];
|
|
|
2e9516 |
XHostAddress host_entries[3];
|
|
|
2e9516 |
+ xcb_void_cookie_t cookies[3];
|
|
|
2e9516 |
int i;
|
|
|
2e9516 |
gboolean res;
|
|
|
2e9516 |
GError *error;
|
|
|
2e9516 |
char *filename;
|
|
|
2e9516 |
|
|
|
2e9516 |
filename = NULL;
|
|
|
2e9516 |
|
|
|
2e9516 |
if (filenamep != NULL) {
|
|
|
2e9516 |
*filenamep = NULL;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: Requesting user authorization");
|
|
|
2e9516 |
|
|
|
2e9516 |
error = NULL;
|
|
|
2e9516 |
res = gdm_display_add_user_authorization (slave->priv->display,
|
|
|
2e9516 |
username,
|
|
|
2e9516 |
&filename,
|
|
|
2e9516 |
&error);
|
|
|
2e9516 |
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to add user authorization: %s", error->message);
|
|
|
2e9516 |
g_error_free (error);
|
|
|
2e9516 |
} else {
|
|
|
2e9516 |
g_debug ("GdmSlave: Got user authorization: %s", filename);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
if (filenamep != NULL) {
|
|
|
2e9516 |
*filenamep = g_strdup (filename);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
g_free (filename);
|
|
|
2e9516 |
|
|
|
2e9516 |
/* Remove access for the programs run by slave and greeter now that the
|
|
|
2e9516 |
* user session is starting.
|
|
|
2e9516 |
*/
|
|
|
2e9516 |
- gdm_slave_setup_xhost_auth (host_entries, si_entries);
|
|
|
2e9516 |
- gdm_error_trap_push ();
|
|
|
2e9516 |
+ gdm_slave_setup_xhost_auth (host_entries);
|
|
|
2e9516 |
for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
|
|
|
2e9516 |
- XRemoveHost (slave->priv->server_display, &host_entries[i]);
|
|
|
2e9516 |
+ cookies[i] = xcb_change_hosts_checked (slave->priv->xcb_connection,
|
|
|
2e9516 |
+ XCB_HOST_MODE_DELETE,
|
|
|
2e9516 |
+ host_entries[i].family,
|
|
|
2e9516 |
+ host_entries[i].length,
|
|
|
2e9516 |
+ (uint8_t *) host_entries[i].address);
|
|
|
2e9516 |
}
|
|
|
2e9516 |
- XSync (slave->priv->server_display, False);
|
|
|
2e9516 |
- if (gdm_error_trap_pop ()) {
|
|
|
2e9516 |
- g_warning ("Failed to remove slave program access to the display. Trying to proceed.");
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
|
|
|
2e9516 |
+ xcb_generic_error_t *xcb_error;
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ xcb_error = xcb_request_check (slave->priv->xcb_connection, cookies[i]);
|
|
|
2e9516 |
+
|
|
|
2e9516 |
+ if (xcb_error != NULL) {
|
|
|
2e9516 |
+ g_warning ("Failed to remove greeter program access to the display. Trying to proceed.");
|
|
|
2e9516 |
+ free (xcb_error);
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
return res;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static char *
|
|
|
2e9516 |
gdm_slave_parse_enriched_login (GdmSlave *slave,
|
|
|
2e9516 |
const char *username)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
char **argv;
|
|
|
2e9516 |
int username_len;
|
|
|
2e9516 |
GPtrArray *env;
|
|
|
2e9516 |
GError *error;
|
|
|
2e9516 |
gboolean res;
|
|
|
2e9516 |
char *parsed_username;
|
|
|
2e9516 |
char *command;
|
|
|
2e9516 |
char *std_output;
|
|
|
2e9516 |
char *std_error;
|
|
|
2e9516 |
|
|
|
2e9516 |
parsed_username = NULL;
|
|
|
2e9516 |
|
|
|
2e9516 |
if (username == NULL || username[0] == '\0') {
|
|
|
2e9516 |
return NULL;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
/* A script may be used to generate the automatic/timed login name
|
|
|
2e9516 |
based on the display/host by ending the name with the pipe symbol
|
|
|
2e9516 |
'|'. */
|
|
|
2e9516 |
|
|
|
2e9516 |
username_len = strlen (username);
|
|
|
2e9516 |
--
|
|
|
2e9516 |
2.9.3
|
|
|
2e9516 |
|
|
|
2e9516 |
|
|
|
2e9516 |
From 89b3bc7ba5fbfa0948a02644cbe031961435e23d Mon Sep 17 00:00:00 2001
|
|
|
2e9516 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
2e9516 |
Date: Mon, 19 Dec 2016 10:56:27 -0500
|
|
|
2e9516 |
Subject: [PATCH 4/5] slave: close display connection when done with it
|
|
|
2e9516 |
|
|
|
2e9516 |
---
|
|
|
2e9516 |
daemon/gdm-slave.c | 1 +
|
|
|
2e9516 |
1 file changed, 1 insertion(+)
|
|
|
2e9516 |
|
|
|
2e9516 |
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
|
|
|
2e9516 |
index c0a53fe..cd26965 100644
|
|
|
2e9516 |
--- a/daemon/gdm-slave.c
|
|
|
2e9516 |
+++ b/daemon/gdm-slave.c
|
|
|
2e9516 |
@@ -411,60 +411,61 @@ gdm_slave_real_start (GdmSlave *slave)
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
error = NULL;
|
|
|
9fa8e4 |
res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error);
|
|
|
9fa8e4 |
if (! res) {
|
|
|
9fa8e4 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
error = NULL;
|
|
|
9fa8e4 |
res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error);
|
|
|
9fa8e4 |
if (! res) {
|
|
|
9fa8e4 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
9fa8e4 |
g_error_free (error);
|
|
|
9fa8e4 |
return FALSE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return TRUE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
static gboolean
|
|
|
9fa8e4 |
gdm_slave_real_stop (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
g_debug ("GdmSlave: Stopping slave");
|
|
|
9fa8e4 |
|
|
|
2e9516 |
+ g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
|
|
|
9fa8e4 |
g_clear_object (&slave->priv->display);
|
|
|
9fa8e4 |
|
|
|
2e9516 |
return TRUE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gboolean
|
|
|
2e9516 |
gdm_slave_start (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
gboolean ret;
|
|
|
2e9516 |
|
|
|
2e9516 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: starting slave");
|
|
|
2e9516 |
|
|
|
2e9516 |
g_object_ref (slave);
|
|
|
2e9516 |
ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
|
|
|
2e9516 |
g_object_unref (slave);
|
|
|
2e9516 |
|
|
|
2e9516 |
return ret;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
gboolean
|
|
|
2e9516 |
gdm_slave_stop (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
gboolean ret;
|
|
|
2e9516 |
|
|
|
2e9516 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
2e9516 |
|
|
|
2e9516 |
g_debug ("GdmSlave: stopping slave");
|
|
|
2e9516 |
|
|
|
2e9516 |
--
|
|
|
2e9516 |
2.9.3
|
|
|
2e9516 |
|
|
|
2e9516 |
|
|
|
2e9516 |
From 122433b95dd3e099b300bce97ce1a5c99d7e2ccd Mon Sep 17 00:00:00 2001
|
|
|
2e9516 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
2e9516 |
Date: Wed, 20 Jul 2016 17:23:05 -0400
|
|
|
2e9516 |
Subject: [PATCH 5/5] slave: kill off clients from display when finished
|
|
|
2e9516 |
|
|
|
2e9516 |
When we're done with the display we need to kill off any clients
|
|
|
2e9516 |
that are lingering and close our own connection to the display.
|
|
|
2e9516 |
|
|
|
2e9516 |
This is so, for instance, processes from the session don't
|
|
|
2e9516 |
stick around on a -noreset Xvnc server (or something)
|
|
|
2e9516 |
|
|
|
2e9516 |
https://bugzilla.gnome.org/show_bug.cgi?id=776059
|
|
|
2e9516 |
---
|
|
|
2e9516 |
daemon/gdm-slave.c | 32 +++++++++++++++++++++++++++++---
|
|
|
2e9516 |
1 file changed, 29 insertions(+), 3 deletions(-)
|
|
|
2e9516 |
|
|
|
2e9516 |
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
|
|
|
2e9516 |
index cd26965..d965d4c 100644
|
|
|
2e9516 |
--- a/daemon/gdm-slave.c
|
|
|
2e9516 |
+++ b/daemon/gdm-slave.c
|
|
|
2e9516 |
@@ -411,64 +411,90 @@ gdm_slave_real_start (GdmSlave *slave)
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
2e9516 |
g_error_free (error);
|
|
|
2e9516 |
return FALSE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
error = NULL;
|
|
|
2e9516 |
res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error);
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
2e9516 |
g_error_free (error);
|
|
|
2e9516 |
return FALSE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
error = NULL;
|
|
|
2e9516 |
res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error);
|
|
|
2e9516 |
if (! res) {
|
|
|
2e9516 |
g_warning ("Failed to get value: %s", error->message);
|
|
|
2e9516 |
g_error_free (error);
|
|
|
2e9516 |
return FALSE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
return TRUE;
|
|
|
2e9516 |
}
|
|
|
2e9516 |
|
|
|
2e9516 |
static gboolean
|
|
|
2e9516 |
gdm_slave_real_stop (GdmSlave *slave)
|
|
|
2e9516 |
{
|
|
|
2e9516 |
g_debug ("GdmSlave: Stopping slave");
|
|
|
2e9516 |
|
|
|
2e9516 |
- g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
|
|
|
2e9516 |
- g_clear_object (&slave->priv->display);
|
|
|
2e9516 |
+ if (slave->priv->xcb_connection) {
|
|
|
2e9516 |
+ const xcb_setup_t *setup;
|
|
|
2e9516 |
|
|
|
2e9516 |
- return TRUE;
|
|
|
2e9516 |
+ /* These 3 bits are reserved/unused by the X protocol */
|
|
|
2e9516 |
+ guint32 unused_bits = 0b11100000000000000000000000000000;
|
|
|
2e9516 |
+ XID highest_client, client;
|
|
|
2e9516 |
+ guint32 client_increment;
|
|
|
9fa8e4 |
+
|
|
|
2e9516 |
+ setup = xcb_get_setup (slave->priv->xcb_connection);
|
|
|
9fa8e4 |
+
|
|
|
2e9516 |
+ /* resource_id_mask is the bits given to each client for
|
|
|
2e9516 |
+ * addressing resources */
|
|
|
2e9516 |
+ highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
|
|
|
2e9516 |
+ client_increment = setup->resource_id_mask + 1;
|
|
|
9fa8e4 |
+
|
|
|
2e9516 |
+ /* Kill every client but ourselves, then close our own connection
|
|
|
2e9516 |
+ */
|
|
|
2e9516 |
+ for (client = 0;
|
|
|
2e9516 |
+ client <= highest_client;
|
|
|
2e9516 |
+ client += client_increment) {
|
|
|
9fa8e4 |
+
|
|
|
2e9516 |
+ if (client != setup->resource_id_base)
|
|
|
2e9516 |
+ xcb_kill_client (slave->priv->xcb_connection, client);
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
+ xcb_flush (slave->priv->xcb_connection);
|
|
|
2e9516 |
+ g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
|
|
|
2e9516 |
+ }
|
|
|
2e9516 |
+ g_clear_object (&slave->priv->display);
|
|
|
9fa8e4 |
+
|
|
|
2e9516 |
+ return TRUE;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gboolean
|
|
|
9fa8e4 |
gdm_slave_start (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
gboolean ret;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmSlave: starting slave");
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_object_ref (slave);
|
|
|
9fa8e4 |
ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
|
|
|
9fa8e4 |
g_object_unref (slave);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
return ret;
|
|
|
9fa8e4 |
}
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
gboolean
|
|
|
9fa8e4 |
gdm_slave_stop (GdmSlave *slave)
|
|
|
9fa8e4 |
{
|
|
|
9fa8e4 |
gboolean ret;
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_debug ("GdmSlave: stopping slave");
|
|
|
9fa8e4 |
|
|
|
9fa8e4 |
g_object_ref (slave);
|
|
|
9fa8e4 |
|
|
|
2e9516 |
ret = GDM_SLAVE_GET_CLASS (slave)->stop (slave);
|
|
|
9fa8e4 |
--
|
|
|
2e9516 |
2.9.3
|
|
|
9fa8e4 |
|