From 8046501448837c2d7c2bb5b6484975567d31ae80 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 22 Feb 2013 15:25:06 +0000 Subject: [PATCH 2/3] Pick up an up-to-date DISPLAY from logind if possible In the systemd user bus design, a user bus can span across more than one login session, so the most appropriate DISPLAY to use can change. --- bus/activation.c | 39 ++++++++++++++++++++++ configure.ac | 10 ++++++ dbus/dbus-sysdeps-util-unix.c | 71 +++++++++++++++++++++++++++++++++++++++++ dbus/dbus-sysdeps-util-win.c | 14 ++++++++ dbus/dbus-sysdeps.h | 3 ++ 5 files changed, 137 insertions(+) diff --git a/bus/activation.c b/bus/activation.c index 3dfba78..cecc206 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -990,6 +990,45 @@ add_bus_environment (BusActivation *activation, if (strcmp (type, "session") == 0) { + DBusString display; + DBusError inner_error; + + dbus_error_init (&inner_error); + + if (!_dbus_string_init (&display)) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + if (_dbus_get_user_session_display (&display, &inner_error)) + { + if (_dbus_string_get_length (&display) == 0) + { + _dbus_hash_table_remove_string (activation->environment, + "DISPLAY"); + } + else if (!bus_activation_set_environment_variable (activation, + "DISPLAY", + _dbus_string_get_const_data (&display), + error)) + { + _dbus_string_free (&display); + return FALSE; + } + + _dbus_string_free (&display); + } + else if (dbus_error_has_name (&inner_error, DBUS_ERROR_NOT_SUPPORTED)) + { + dbus_error_free (&inner_error); + } + else + { + dbus_move_error (&inner_error, error); + return FALSE; + } + if (!bus_activation_set_environment_variable (activation, "DBUS_SESSION_BUS_ADDRESS", activation->server_address, diff --git a/configure.ac b/configure.ac index 226ed9a..cb067dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1214,6 +1214,16 @@ fi if test x$have_systemd = xyes; then AC_DEFINE(HAVE_SYSTEMD,1,[Have systemd]) + + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $SYSTEMD_CFLAGS" + saved_LIBS="$LIBS" + LIBS="$LIBS $SYSTEMD_LIBS" + + AC_CHECK_FUNCS([sd_uid_get_display]) + + CFLAGS="$saved_CFLAGS" + LIBS="$saved_LIBS" fi if test x$enable_systemd = xyes -a x$have_systemd != xyes ; then diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 7beab20..0b4483b 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -58,6 +58,11 @@ #include #endif +#if HAVE_SYSTEMD +#include +#include +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -1174,3 +1179,69 @@ fail: _dbus_string_free (&path); return FALSE; } + +/** + * Get the user session's X11 DISPLAY from logind. + * + * Possible results: + * + * - We are not running under systemd. Return #FALSE with + * #DBUS_ERROR_NOT_SUPPORTED. + * + * - We are running under systemd and there is no DISPLAY. + * Return #TRUE, but put nothing in str. + * + * - We are running under systemd and there is a DISPLAY. Put it in str + * and return #TRUE. + * + * Returns: #FALSE on error + */ +dbus_bool_t +_dbus_get_user_session_display (DBusString *str, + DBusError *error) +{ + _dbus_string_set_length (str, 0); + +#if defined(HAVE_SYSTEMD) && defined(HAVE_SD_UID_GET_DISPLAY) + if (sd_booted ()) + { + int r; + char *display = NULL; + + r = sd_uid_get_display (getuid (), &display); + + if (r == ENOENT || display == NULL || display[0] == '\0') + { + if (display != NULL) + free (display); + + return TRUE; + } + else if (r >= 0) + { + + if (!_dbus_string_append (str, display)) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + free (display); + return TRUE; + } + else + { + dbus_set_error (error, _dbus_error_from_errno (-r), + "Failed to get DISPLAY from logind: %s", + _dbus_strerror (-r)); + return FALSE; + } + } + else +#endif + { + dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to get DISPLAY from logind: unsupported"); + return FALSE; + } +} diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c index 111db9e..53a6748 100644 --- a/dbus/dbus-sysdeps-util-win.c +++ b/dbus/dbus-sysdeps-util-win.c @@ -1530,3 +1530,17 @@ _dbus_command_for_pid (unsigned long pid, // FIXME return FALSE; } + +/** + * Get the user session's X11 DISPLAY from logind. On Windows, this is a stub. + * + * Returns: #FALSE + */ +dbus_bool_t +_dbus_get_user_session_display (DBusString *str, + DBusError *error) +{ + dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to get DISPLAY from logind: unsupported"); + return FALSE; +} diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index f4b0ac9..11397af 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -549,6 +549,9 @@ void _dbus_request_file_descriptor_limit (unsigned int limit); const char * _dbus_replace_install_prefix (const char *configure_time_path); +dbus_bool_t _dbus_get_user_session_display (DBusString *str, + DBusError *error); + /** @} */ DBUS_END_DECLS -- 1.7.10.4