diff options
author | Brian Cameron <brian.cameron@oracle.com> | 2011-12-15 19:53:43 -0600 |
---|---|---|
committer | Brian Cameron <brian.cameron@oracle.com> | 2011-12-15 19:53:43 -0600 |
commit | d987eb9e59f837448ca08fe85bc1190a228934d1 (patch) | |
tree | 09c29041113c50dbf48e7fa0e53d3b4cc582a5fd | |
parent | feb2c3410a53ea806016ca8ee3582dcf66dbc9a7 (diff) | |
download | gdm-d987eb9e59f837448ca08fe85bc1190a228934d1.tar.gz |
Add ConsoleKit MultiSeat support. See bug 536355.wip/multi-seat
34 files changed, 2422 insertions, 266 deletions
diff --git a/common/Makefile.am b/common/Makefile.am index 34920416..2d911674 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -30,6 +30,8 @@ noinst_LTLIBRARIES = \ BUILT_SOURCES = \ gdm-settings-glue.h \ + gdm-marshal.c \ + gdm-marshal.h \ $(NULL) gdmdir = $(datadir)/gdm @@ -52,6 +54,13 @@ gdm_crash_logger_LDADD = $(GTHREAD_LIBS) gdm-settings-glue.h: gdm-settings.xml Makefile.am dbus-binding-tool --prefix=gdm_settings --mode=glib-server --output=gdm-settings-glue.h $(srcdir)/gdm-settings.xml +gdm-marshal.c: gdm-marshal.list + echo "#include \"gdm-marshal.h\"" > $@ && \ + @GLIB_GENMARSHAL@ $< --prefix=gdm_marshal --body >> $@ + +gdm-marshal.h: gdm-marshal.list + @GLIB_GENMARSHAL@ $< --prefix=gdm_marshal --header > $@ + if MKDTEMP_MISSING MKDTEMP_FILES = mkdtemp.c mkdtemp.h else @@ -61,6 +70,8 @@ endif libgdmcommon_la_SOURCES = \ gdm-address.h \ gdm-address.c \ + gdm-marshal.c \ + gdm-marshal.h \ gdm-common.h \ gdm-common.c \ gdm-common-unknown-origin.h \ @@ -144,6 +155,7 @@ CLEANFILES = \ EXTRA_DIST = \ gdm-settings.xml \ + gdm-marshal.list \ mkdtemp.c \ mkdtemp.h \ $(gdm_DATA) \ diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h index 65a16280..293ecb88 100644 --- a/common/gdm-settings-keys.h +++ b/common/gdm-settings-keys.h @@ -39,8 +39,6 @@ G_BEGIN_DECLS #define GDM_KEY_EXCLUDE "greeter/Exclude" #define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll" -#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP" - #define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable" #define GDM_KEY_MAX_PENDING "xdmcp/MaxPending" #define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions" diff --git a/configure.ac b/configure.ac index 78887807..873d5826 100644 --- a/configure.ac +++ b/configure.ac @@ -1124,95 +1124,6 @@ AC_CHECK_LIB(devinfo, di_devperm_login, [ PAM_LIBS="$PAM_LIBS -ldevinfo" ]) dnl --------------------------------------------------------------------------- -dnl - Check for X Server location -dnl --------------------------------------------------------------------------- - -# First check with "! -h" for /usr/X11R6 and /usr/X11 since they often -# symlink to each other, and configure should use the more stable -# location (the real directory) if possible. -# -# On Solaris, the /usr/bin/Xserver script is used to decide whether to -# use Xsun or Xorg, so this is used on Solaris. -# -# When testing for /usr/X11R6, first check with "! -h" for /usr/X11R6 -# and /usr/X11 since they often symlink to each other, and configure -# should use the more stable location (the real directory) if possible. -# -if test -x /usr/X11/bin/Xserver; then - X_PATH="/usr/X11/bin" - X_SERVER_PATH="/usr/X11/bin" - X_SERVER="/usr/X11/bin/Xserver" -elif test ! -h /usr/X11R6 -a -x /usr/X11R6/bin/X; then - X_PATH="/usr/X11R6/bin" - X_SERVER_PATH="/usr/X11R6/bin" - X_SERVER="/usr/X11R6/bin/X" -elif test ! -h /usr/X11 -a -x /usr/X11/bin/X; then - X_PATH="/usr/X11/bin" - X_SERVER_PATH="/usr/X11/bin" - X_SERVER="/usr/X11/bin/X" -elif test -x /usr/X11R6/bin/X; then - X_PATH="/usr/X11R6/bin" - X_SERVER_PATH="/usr/X11R6/bin" - X_SERVER="/usr/X11R6/bin/X" -elif test -x /usr/bin/Xorg; then - X_PATH="/usr/bin" - X_SERVER_PATH="/usr/bin" - X_SERVER="/usr/bin/Xorg" -elif test -x /usr/X11/bin/X; then - X_PATH="/usr/X11/bin" - X_SERVER_PATH="/usr/X11/bin" - X_SERVER="/usr/X11/bin/X" -elif test -x /usr/openwin/bin/Xsun; then - # Do not add /usr/openwin/bin here because on Solaris you need - # /usr/openwin/bin in your PATH even if you are using the Xorg - # Xserver. We add this to the path below. - X_PATH="/usr/openwin/bin" - X_SERVER_PATH="/usr/openwin/bin" - X_SERVER="/usr/openwin/bin/Xsun" -elif test -x /opt/X11R6/bin/X; then - X_PATH="/opt/X11R6/bin" - X_SERVER_PATH="/opt/X11R6/bin" - X_SERVER="/opt/X11R6/bin/X" -elif test -x /usr/bin/X; then - X_PATH="/usr/bin" - X_SERVER_PATH="/usr/bin" - X_SERVER="/usr/bin/X" -else - # what to do, what to do, this is wrong, but this just sets the - # defaults, perhaps this user is cross compiling or some such - X_PATH="/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin" - X_SERVER_PATH="/usr/bin" - X_SERVER="/usr/bin/X" -fi - -dnl --------------------------------------------------------------------------- -dnl - Check for Xnest / Xephyr support -dnl --------------------------------------------------------------------------- - -# Use Xephyr if it is available. It works better than Xnest since Xephyr -# supports the Xserver extensions, even if on a remote machine. -# -X_XNEST_UNSCALED_FONTPATH="true" -if test -x $X_SERVER_PATH/Xephyr; then - X_XNEST_CMD="$X_SERVER_PATH/Xephyr" - X_XNEST_CONFIG_OPTIONS="-audit 0" -else - if test -x /usr/openwin/bin/Xnest; then - # If on Solaris, Xnest is only shipped with the Xsun Xserver, so - # use this version. - # - X_XNEST_CMD="/usr/openwin/bin/Xnest" - X_XNEST_CONFIG_OPTIONS="-audit 0 -name Xnest -pn" - X_XNEST_UNSCALED_FONTPATH="false" - else - if test -x $X_SERVER_PATH/Xnest; then - X_XNEST_CMD="$X_SERVER_PATH/Xnest" - X_XNEST_CONFIG_OPTIONS="-audit 0 -name Xnest" - fi - fi -fi - -dnl --------------------------------------------------------------------------- dnl - Expand vars dnl --------------------------------------------------------------------------- @@ -1384,6 +1295,21 @@ else XSESSION_SHELL=/bin/sh fi +dnl --------------------------------------------------------------------------- +dnl - PATH in scripts +dnl --------------------------------------------------------------------------- +AC_ARG_WITH(script-path, + AS_HELP_STRING([--with-script-path=<dir>], + [script path])) + +if ! test -z "$with_script_path"; then + SCRIPT_PATH=$with_script_path +else + SCRIPT_PATH=/usr/bin +fi + +AC_SUBST(SCRIPT_PATH) + # Set configuration choices. # AC_SUBST(XSESSION_SHELL) @@ -1391,19 +1317,6 @@ AC_DEFINE_UNQUOTED(XSESSION_SHELL,"$XSESSION_SHELL",[xsession shell]) AC_SUBST(SOUND_PROGRAM) AC_DEFINE_UNQUOTED(SOUND_PROGRAM,"$SOUND_PROGRAM",[]) -AC_SUBST(X_PATH) -AC_SUBST(X_SERVER) -AC_SUBST(X_SERVER_PATH) -AC_DEFINE_UNQUOTED(X_SERVER,"$X_SERVER",[]) -AC_DEFINE_UNQUOTED(X_SERVER_PATH,"$X_SERVER_PATH",[]) - -AC_SUBST(X_XNEST_CMD) -AC_SUBST(X_XNEST_CONFIG_OPTIONS) -AC_SUBST(X_XNEST_UNSCALED_FONTPATH) -AC_DEFINE_UNQUOTED(X_XNEST_CMD,"$X_XNEST_CMD",[]) -AC_DEFINE_UNQUOTED(X_XNEST_CONFIG_OPTIONS,"$X_XNEST_CONFIG_OPTIONS",[]) -AC_DEFINE_UNQUOTED(X_XNEST_UNSCALED_FONTPATH,"$X_XNEST_UNSCALED_FONTPATH",[]) - ## Stuff for debian/changelog.in #if test -e "debian/changelog"; then # DEBIAN_DATESTAMP=`head -1 debian/changelog| sed -e 's/.*cvs.//' -e 's/).*//'` @@ -1439,6 +1352,9 @@ gui/simple-chooser/Makefile utils/Makefile data/gdm.conf data/Makefile +data/Init +data/PostSession +data/PreSession data/greeter-autostart/Makefile data/greeter-autostart/at-spi-registryd-wrapper.desktop.in data/pixmaps/Makefile @@ -1481,7 +1397,7 @@ echo " dbus-1 system.d dir: ${DBUS_SYS_DIR} PAM prefix: ${PAM_PREFIX} - X server: ${X_SERVER} + script path: ${SCRIPT_PATH} " dnl TCP Wrappers support? diff --git a/daemon/Makefile.am b/daemon/Makefile.am index da18835c..a3fad28a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -300,6 +300,8 @@ gdm_binary_SOURCES = \ gdm-static-display.h \ gdm-transient-display.c \ gdm-transient-display.h \ + gdm-dynamic-display.c \ + gdm-dynamic-display.h \ gdm-static-factory-display.c \ gdm-static-factory-display.h \ gdm-product-display.c \ diff --git a/daemon/ck-connector.c b/daemon/ck-connector.c index 0117eb99..8609ccbb 100644 --- a/daemon/ck-connector.c +++ b/daemon/ck-connector.c @@ -65,6 +65,7 @@ struct _CkConnector { int refcount; char *cookie; + char *session_id; dbus_bool_t session_created; DBusConnection *connection; }; @@ -76,8 +77,11 @@ static struct { { "display-device", DBUS_TYPE_STRING }, { "x11-display-device", DBUS_TYPE_STRING }, { "x11-display", DBUS_TYPE_STRING }, + { "seat-id", DBUS_TYPE_STRING }, + { "session", DBUS_TYPE_STRING }, { "remote-host-name", DBUS_TYPE_STRING }, { "session-type", DBUS_TYPE_STRING }, + { "display-type", DBUS_TYPE_STRING }, { "is-local", DBUS_TYPE_BOOLEAN }, { "unix-user", DBUS_TYPE_INT32 }, }; @@ -181,6 +185,10 @@ _ck_connector_free (CkConnector *connector) free (connector->cookie); } + if (connector->session_id != NULL) { + free (connector->session_id); + } + free (connector); } @@ -241,6 +249,7 @@ ck_connector_new (void) connector->refcount = 1; connector->connection = NULL; connector->cookie = NULL; + connector->session_id = NULL; connector->session_created = FALSE; oom: return connector; @@ -266,6 +275,7 @@ ck_connector_open_session (CkConnector *connector, DBusMessage *reply; dbus_bool_t ret; char *cookie; + char *session_id; _ck_return_val_if_fail (connector != NULL, FALSE); _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); @@ -334,10 +344,68 @@ ck_connector_open_session (CkConnector *connector, goto out; } + dbus_message_unref (message); + dbus_message_unref (reply); + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForCookie"); + if (message == NULL) { + goto out; + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, &connector->cookie, + DBUS_TYPE_INVALID); + + dbus_error_init (&local_error); + + reply = dbus_connection_send_with_reply_and_block (connector->connection, + message, + -1, + &local_error); + if (reply == NULL) { + if (dbus_error_is_set (&local_error)) { + dbus_set_error (error, + CK_CONNECTOR_ERROR, + "Unable to open session: %s", + local_error.message); + dbus_error_free (&local_error); + goto out; + } + } + + dbus_error_init (&local_error); + if (! dbus_message_get_args (reply, + &local_error, + DBUS_TYPE_OBJECT_PATH, &session_id, + DBUS_TYPE_INVALID)) { + if (dbus_error_is_set (&local_error)) { + dbus_set_error (error, + CK_CONNECTOR_ERROR, + "Unable to open session: %s", + local_error.message); + dbus_error_free (&local_error); + goto out; + } + } + + connector->session_id = strdup (session_id); + if (connector->session_id == NULL) { + goto out; + } + connector->session_created = TRUE; ret = TRUE; out: + if (!ret) { + free (connector->cookie); + connector->cookie = NULL; + free (connector->session_id); + connector->session_id = NULL; + } + if (reply != NULL) { dbus_message_unref (reply); } @@ -362,6 +430,7 @@ ck_connector_open_session_with_parameters_valist (CkConnector *connector, DBusMessageIter iter_array; dbus_bool_t ret; char *cookie; + char *session_id; const char *name; _ck_return_val_if_fail (connector != NULL, FALSE); @@ -470,6 +539,57 @@ ck_connector_open_session_with_parameters_valist (CkConnector *connector, goto out; } + dbus_message_unref (message); + dbus_message_unref (reply); + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForCookie"); + if (message == NULL) { + goto out; + } + + dbus_message_append_args (message, DBUS_TYPE_STRING, &connector->cookie, + DBUS_TYPE_INVALID); + + dbus_error_init (&local_error); + + reply = dbus_connection_send_with_reply_and_block (connector->connection, + message, + -1, + &local_error); + if (reply == NULL) { + if (dbus_error_is_set (&local_error)) { + dbus_set_error (error, + CK_CONNECTOR_ERROR, + "Unable to open session: %s", + local_error.message); + dbus_error_free (&local_error); + goto out; + } + } + + dbus_error_init (&local_error); + if (! dbus_message_get_args (reply, + &local_error, + DBUS_TYPE_OBJECT_PATH, &session_id, + DBUS_TYPE_INVALID)) { + if (dbus_error_is_set (&local_error)) { + dbus_set_error (error, + CK_CONNECTOR_ERROR, + "Unable to open session: %s", + local_error.message); + dbus_error_free (&local_error); + goto out; + } + } + + connector->session_id = strdup (session_id); + if (connector->session_id == NULL) { + goto out; + } + connector->session_created = TRUE; ret = TRUE; @@ -590,6 +710,73 @@ ck_connector_get_cookie (CkConnector *connector) } /** + * Gets the id for the current open session. + * Returns #NULL if no session is open. + * + * @returns a constant string with the session id. + */ +const char * +ck_connector_get_session_id (CkConnector *connector) +{ + _ck_return_val_if_fail (connector != NULL, NULL); + + if (! connector->session_created) { + return NULL; + } else { + return connector->session_id; + } +} + +dbus_bool_t +ck_connector_set_remove_on_close (CkConnector *connector, + gboolean remove_on_close, + DBusError *error) +{ + DBusMessage *message; + dbus_bool_t ret; + const char *ssid = ck_connector_get_session_id (connector); + + _ck_return_val_if_fail (connector != NULL, FALSE); + _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); + _ck_return_val_if_fail (ssid != NULL, FALSE); + + message = NULL; + ret = FALSE; + + if (!connector->session_created || connector->cookie == NULL) { + dbus_set_error (error, + CK_CONNECTOR_ERROR, + "Unable to close session: %s", + "no session open"); + goto out; + } + + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + ssid, + "org.freedesktop.ConsoleKit.Session", + "SetRemoveOnClose"); + if (message == NULL) { + goto out; + } + + if (! dbus_message_append_args (message, + DBUS_TYPE_BOOLEAN, &remove_on_close, + DBUS_TYPE_INVALID)) { + goto out; + } + + ret = dbus_connection_send (connector->connection, + message, + NULL); +out: + if (message != NULL) { + dbus_message_unref (message); + } + + return ret; +} + +/** * Issues the CloseSession method call on the ConsoleKit manager * interface. * diff --git a/daemon/ck-connector.h b/daemon/ck-connector.h index ab59f55f..e0a35d8c 100644 --- a/daemon/ck-connector.h +++ b/daemon/ck-connector.h @@ -32,6 +32,7 @@ #include <sys/types.h> #include <dbus/dbus.h> +#include <glib.h> DBUS_BEGIN_DECLS @@ -56,6 +57,10 @@ dbus_bool_t ck_connector_open_session (CkConnector *ckc, DBusError *error); const char *ck_connector_get_cookie (CkConnector *ckc); +const char *ck_connector_get_session_id (CkConnector *ckc); +dbus_bool_t ck_connector_set_remove_on_close (CkConnector *ckc, + gboolean remove_on_close, + DBusError *error); dbus_bool_t ck_connector_close_session (CkConnector *ckc, DBusError *error); diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c index abedc0b8..047d23e8 100644 --- a/daemon/gdm-display.c +++ b/daemon/gdm-display.c @@ -41,6 +41,7 @@ #include "gdm-settings-keys.h" #include "gdm-slave-proxy.h" +#include "gdm-dynamic-display.h" static guint32 display_serial = 1; @@ -51,11 +52,14 @@ static guint32 display_serial = 1; struct GdmDisplayPrivate { char *id; + char *session_id; char *seat_id; char *remote_hostname; + char *x11_command; int x11_display_number; char *x11_display_name; + char *x11_display_type; int status; time_t creation_time; GTimer *slave_timer; @@ -66,6 +70,8 @@ struct GdmDisplayPrivate GdmDisplayAccessFile *access_file; gboolean is_local; + gboolean use_auth; + gboolean block_console_session_requests; guint finish_idle_id; GdmSlaveProxy *slave_proxy; @@ -78,13 +84,18 @@ enum { PROP_ID, PROP_STATUS, PROP_SEAT_ID, + PROP_SESSION_ID, + PROP_X11_COMMAND, PROP_REMOTE_HOSTNAME, PROP_X11_DISPLAY_NUMBER, PROP_X11_DISPLAY_NAME, + PROP_X11_DISPLAY_TYPE, PROP_X11_COOKIE, PROP_X11_AUTHORITY_FILE, PROP_IS_LOCAL, + PROP_USE_AUTH, PROP_SLAVE_COMMAND, + PROP_BLOCK_CONSOLE_SESSION_REQUESTS, }; static void gdm_display_class_init (GdmDisplayClass *klass); @@ -489,6 +500,20 @@ gdm_display_get_seat_id (GdmDisplay *display, return TRUE; } +gboolean +gdm_display_get_session_id (GdmDisplay *display, + char **session_id, + GError **error) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + if (session_id != NULL) { + *session_id = g_strdup (display->priv->session_id); + } + + return TRUE; +} + static gboolean finish_idle (GdmDisplay *display) { @@ -513,6 +538,14 @@ slave_exited (GdmSlaveProxy *proxy, { g_debug ("GdmDisplay: Slave exited: %d", code); + if (GDM_IS_DYNAMIC_DISPLAY (display)) { + if (code != 0) { + gdm_dynamic_display_respawn (GDM_DYNAMIC_DISPLAY (display), TRUE); + } else { + gdm_dynamic_display_respawn (GDM_DYNAMIC_DISPLAY (display), FALSE); + } + } + queue_finish (display); } @@ -550,10 +583,12 @@ gdm_display_real_prepare (GdmDisplay *display) g_assert (display->priv->slave_proxy == NULL); - if (!gdm_display_create_authority (display)) { - g_warning ("Unable to set up access control for display %d", - display->priv->x11_display_number); - return FALSE; + if (display->priv->use_auth) { + if (!gdm_display_create_authority (display)) { + g_warning ("Unable to set up access control for display %d", + display->priv->x11_display_number); + return FALSE; + } } _gdm_display_set_status (display, GDM_DISPLAY_PREPARED); @@ -742,6 +777,20 @@ gdm_display_get_id (GdmDisplay *display, } gboolean +gdm_display_get_x11_command (GdmDisplay *display, + char **command, + GError **error) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + if (command != NULL) { + *command = g_strdup (display->priv->x11_command); + } + + return TRUE; +} + +gboolean gdm_display_get_x11_display_name (GdmDisplay *display, char **x11_display, GError **error) @@ -756,6 +805,20 @@ gdm_display_get_x11_display_name (GdmDisplay *display, } gboolean +gdm_display_get_x11_display_type (GdmDisplay *display, + char **type, + GError **error) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + if (type != NULL) { + *type = g_strdup (display->priv->x11_display_type); + } + + return TRUE; +} + +gboolean gdm_display_is_local (GdmDisplay *display, gboolean *local, GError **error) @@ -769,6 +832,20 @@ gdm_display_is_local (GdmDisplay *display, return TRUE; } +gboolean +gdm_display_use_auth (GdmDisplay *display, + gboolean *use_auth, + GError **error) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + if (use_auth != NULL) { + *use_auth = display->priv->use_auth; + } + + return TRUE; +} + static void _gdm_display_set_id (GdmDisplay *display, const char *id) @@ -778,6 +855,14 @@ _gdm_display_set_id (GdmDisplay *display, } static void +_gdm_display_set_x11_command (GdmDisplay *display, + const char *x11_command) +{ + g_free (display->priv->x11_command); + display->priv->x11_command = g_strdup (x11_command); +} + +static void _gdm_display_set_seat_id (GdmDisplay *display, const char *seat_id) { @@ -786,6 +871,24 @@ _gdm_display_set_seat_id (GdmDisplay *display, } static void +_gdm_display_set_session_id (GdmDisplay *display, + const char *session_id) +{ + g_free (display->priv->session_id); + display->priv->session_id = g_strdup (session_id); +} + +gboolean +gdm_display_set_session_id (GdmDisplay *display, + const char *session_id, + GError **error) +{ + _gdm_display_set_session_id (display, session_id); + g_object_notify (G_OBJECT (display), "session-id"); + return TRUE; +} + +static void _gdm_display_set_remote_hostname (GdmDisplay *display, const char *hostname) { @@ -809,6 +912,14 @@ _gdm_display_set_x11_display_name (GdmDisplay *display, } static void +_gdm_display_set_x11_display_type (GdmDisplay *display, + const char *display_type) +{ + g_free (display->priv->x11_display_type); + display->priv->x11_display_type = g_strdup (display_type); +} + +static void _gdm_display_set_x11_cookie (GdmDisplay *display, const char *x11_cookie) { @@ -824,6 +935,13 @@ _gdm_display_set_is_local (GdmDisplay *display, } static void +_gdm_display_set_use_auth (GdmDisplay *display, + gboolean use_auth) +{ + display->priv->use_auth = use_auth; +} + +static void _gdm_display_set_slave_command (GdmDisplay *display, const char *command) { @@ -832,6 +950,13 @@ _gdm_display_set_slave_command (GdmDisplay *display, } static void +_gdm_display_set_block_console_session_requests (GdmDisplay *display, + gboolean block_console_session_requests) +{ + display->priv->block_console_session_requests = block_console_session_requests; +} + +static void gdm_display_set_property (GObject *object, guint prop_id, const GValue *value, @@ -845,12 +970,18 @@ gdm_display_set_property (GObject *object, case PROP_ID: _gdm_display_set_id (self, g_value_get_string (value)); break; + case PROP_X11_COMMAND: + _gdm_display_set_x11_command (self, g_value_get_string (value)); + break; case PROP_STATUS: _gdm_display_set_status (self, g_value_get_int (value)); break; case PROP_SEAT_ID: _gdm_display_set_seat_id (self, g_value_get_string (value)); break; + case PROP_SESSION_ID: + _gdm_display_set_session_id (self, g_value_get_string (value)); + break; case PROP_REMOTE_HOSTNAME: _gdm_display_set_remote_hostname (self, g_value_get_string (value)); break; @@ -860,15 +991,24 @@ gdm_display_set_property (GObject *object, case PROP_X11_DISPLAY_NAME: _gdm_display_set_x11_display_name (self, g_value_get_string (value)); break; + case PROP_X11_DISPLAY_TYPE: + _gdm_display_set_x11_display_type (self, g_value_get_string (value)); + break; case PROP_X11_COOKIE: _gdm_display_set_x11_cookie (self, g_value_get_string (value)); break; case PROP_IS_LOCAL: _gdm_display_set_is_local (self, g_value_get_boolean (value)); break; + case PROP_USE_AUTH: + _gdm_display_set_use_auth (self, g_value_get_boolean (value)); + break; case PROP_SLAVE_COMMAND: _gdm_display_set_slave_command (self, g_value_get_string (value)); break; + case PROP_BLOCK_CONSOLE_SESSION_REQUESTS: + _gdm_display_set_block_console_session_requests (self, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -889,12 +1029,18 @@ gdm_display_get_property (GObject *object, case PROP_ID: g_value_set_string (value, self->priv->id); break; + case PROP_X11_COMMAND: + g_value_set_string (value, self->priv->x11_command); + break; case PROP_STATUS: g_value_set_int (value, self->priv->status); break; case PROP_SEAT_ID: g_value_set_string (value, self->priv->seat_id); break; + case PROP_SESSION_ID: + g_value_set_string (value, self->priv->session_id); + break; case PROP_REMOTE_HOSTNAME: g_value_set_string (value, self->priv->remote_hostname); break; @@ -904,6 +1050,9 @@ gdm_display_get_property (GObject *object, case PROP_X11_DISPLAY_NAME: g_value_set_string (value, self->priv->x11_display_name); break; + case PROP_X11_DISPLAY_TYPE: + g_value_set_string (value, self->priv->x11_display_type); + break; case PROP_X11_COOKIE: g_value_set_string (value, self->priv->x11_cookie); break; @@ -914,9 +1063,15 @@ gdm_display_get_property (GObject *object, case PROP_IS_LOCAL: g_value_set_boolean (value, self->priv->is_local); break; + case PROP_USE_AUTH: + g_value_set_boolean (value, self->priv->use_auth); + break; case PROP_SLAVE_COMMAND: g_value_set_string (value, self->priv->slave_command); break; + case PROP_BLOCK_CONSOLE_SESSION_REQUESTS: + g_value_set_boolean (value, self->priv->block_console_session_requests); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1033,6 +1188,13 @@ gdm_display_class_init (GdmDisplayClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, + PROP_X11_COMMAND, + g_param_spec_string ("x11-command", + "x11 command", + "x11 command", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_REMOTE_HOSTNAME, g_param_spec_string ("remote-hostname", "remote-hostname", @@ -1056,6 +1218,13 @@ gdm_display_class_init (GdmDisplayClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, + PROP_X11_DISPLAY_TYPE, + g_param_spec_string ("x11-display-type", + "x11-display-type", + "x11-display-type", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_SEAT_ID, g_param_spec_string ("seat-id", "seat id", @@ -1063,6 +1232,13 @@ gdm_display_class_init (GdmDisplayClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, + PROP_SESSION_ID, + g_param_spec_string ("session-id", + "session id", + "session id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_X11_COOKIE, g_param_spec_string ("x11-cookie", "cookie", @@ -1076,7 +1252,6 @@ gdm_display_class_init (GdmDisplayClass *klass) "authority file", NULL, G_PARAM_READABLE)); - g_object_class_install_property (object_class, PROP_IS_LOCAL, g_param_spec_boolean ("is-local", @@ -1084,7 +1259,13 @@ gdm_display_class_init (GdmDisplayClass *klass) NULL, TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - + g_object_class_install_property (object_class, + PROP_USE_AUTH, + g_param_spec_boolean ("use-auth", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_SLAVE_COMMAND, g_param_spec_string ("slave-command", @@ -1093,6 +1274,13 @@ gdm_display_class_init (GdmDisplayClass *klass) DEFAULT_SLAVE_COMMAND, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, + PROP_BLOCK_CONSOLE_SESSION_REQUESTS, + g_param_spec_boolean ("block-console-session-requests", + "Block Console Session Requests", + "Block session requests from ConsoleKit", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_STATUS, g_param_spec_int ("status", "status", @@ -1131,9 +1319,12 @@ gdm_display_finalize (GObject *object) g_debug ("GdmDisplay: Finalizing display: %s", display->priv->id); g_free (display->priv->id); + g_free (display->priv->x11_command); g_free (display->priv->seat_id); + g_free (display->priv->session_id); g_free (display->priv->remote_hostname); g_free (display->priv->x11_display_name); + g_free (display->priv->x11_display_type); g_free (display->priv->x11_cookie); g_free (display->priv->slave_command); @@ -1151,3 +1342,25 @@ gdm_display_finalize (GObject *object) G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object); } + +gboolean +gdm_display_block_console_session_requests (GdmDisplay *display, + GError **error) +{ + if (!display->priv->block_console_session_requests) { + _gdm_display_set_block_console_session_requests (display, TRUE); + g_object_notify (G_OBJECT (display), "block-console-session-requests"); + } + return TRUE; +} + +gboolean +gdm_display_unblock_console_session_requests (GdmDisplay *display, + GError **error) +{ + if (display->priv->block_console_session_requests) { + _gdm_display_set_block_console_session_requests (display, FALSE); + g_object_notify (G_OBJECT (display), "block-console-session-requests"); + } + return TRUE; +} diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h index 607ea1d4..b50549bf 100644 --- a/daemon/gdm-display.h +++ b/daemon/gdm-display.h @@ -102,6 +102,9 @@ gboolean gdm_display_unmanage (GdmDisplay *disp gboolean gdm_display_get_id (GdmDisplay *display, char **id, GError **error); +gboolean gdm_display_get_x11_command (GdmDisplay *display, + char **command, + GError **error); gboolean gdm_display_get_remote_hostname (GdmDisplay *display, char **hostname, GError **error); @@ -111,12 +114,21 @@ gboolean gdm_display_get_x11_display_number (GdmDisplay *disp gboolean gdm_display_get_x11_display_name (GdmDisplay *display, char **x11_display, GError **error); +gboolean gdm_display_get_x11_display_type (GdmDisplay *display, + char **type, + GError **error); gboolean gdm_display_get_seat_id (GdmDisplay *display, char **seat_id, GError **error); +gboolean gdm_display_get_session_id (GdmDisplay *display, + char **session_id, + GError **error); gboolean gdm_display_is_local (GdmDisplay *display, gboolean *local, GError **error); +gboolean gdm_display_use_auth (GdmDisplay *display, + gboolean *use_auth, + GError **error); gboolean gdm_display_get_timed_login_details (GdmDisplay *display, gboolean *enabled, char **username, @@ -130,6 +142,9 @@ gboolean gdm_display_get_x11_cookie (GdmDisplay *disp gboolean gdm_display_get_x11_authority_file (GdmDisplay *display, char **filename, GError **error); +gboolean gdm_display_set_session_id (GdmDisplay *display, + const char *text, + GError **error); gboolean gdm_display_add_user_authorization (GdmDisplay *display, const char *username, char **filename, @@ -140,6 +155,11 @@ gboolean gdm_display_remove_user_authorization (GdmDisplay *disp gboolean gdm_display_set_slave_bus_name (GdmDisplay *display, const char *name, GError **error); +gboolean gdm_display_block_console_session_requests (GdmDisplay *display, + GError **error); + +gboolean gdm_display_unblock_console_session_requests (GdmDisplay *display, + GError **error); G_END_DECLS diff --git a/daemon/gdm-display.xml b/daemon/gdm-display.xml index a92e37fc..c4d0b352 100644 --- a/daemon/gdm-display.xml +++ b/daemon/gdm-display.xml @@ -4,11 +4,17 @@ <method name="GetId"> <arg name="id" direction="out" type="o"/> </method> + <method name="GetX11Command"> + <arg name="command" direction="out" type="s"/> + </method> <method name="GetX11DisplayName"> <arg name="name" direction="out" type="s"/> </method> + <method name="GetX11DisplayType"> + <arg name="type" direction="out" type="s"/> + </method> <method name="GetX11DisplayNumber"> - <arg name="name" direction="out" type="i"/> + <arg name="number" direction="out" type="i"/> </method> <method name="GetX11Cookie"> <arg name="x11_cookie" direction="out" type="ay"/> @@ -17,7 +23,14 @@ <arg name="filename" direction="out" type="s"/> </method> <method name="GetSeatId"> - <arg name="filename" direction="out" type="s"/> + <arg name="seat_id" direction="out" type="s"/> + </method> + <method name="GetSessionId"> + <arg name="session_id" direction="out" type="s"/> + </method> + <method name="BlockConsoleSessionRequests"> + </method> + <method name="UnblockConsoleSessionRequests"> </method> <method name="GetRemoteHostname"> <arg name="hostname" direction="out" type="s"/> @@ -25,6 +38,9 @@ <method name="IsLocal"> <arg name="local" direction="out" type="b"/> </method> + <method name="UseAuth"> + <arg name="use_auth" direction="out" type="b"/> + </method> <method name="AddUserAuthorization"> <arg name="username" direction="in" type="s"/> <arg name="filename" direction="out" type="s"/> @@ -32,6 +48,9 @@ <method name="RemoveUserAuthorization"> <arg name="username" direction="in" type="s"/> </method> + <method name="SetSessionId"> + <arg name="session_id" direction="in" type="s"/> + </method> <method name="SetSlaveBusName"> <arg name="name" direction="in" type="s"/> </method> diff --git a/daemon/gdm-dynamic-display.c b/daemon/gdm-dynamic-display.c new file mode 100644 index 00000000..64831505 --- /dev/null +++ b/daemon/gdm-dynamic-display.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Authors: halton.huo@sun.com + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <pwd.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <glib.h> +#include <glib/gi18n.h> +#include <glib-object.h> + +#include "gdm-common.h" +#include "gdm-display.h" +#include "gdm-dynamic-display.h" + +#define GDM_DYNAMIC_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayPrivate)) + +struct _GdmDynamicDisplayPrivate +{ + gboolean removed; + gboolean do_respawn; +}; + +enum { + PROP_0, +}; + +static void gdm_dynamic_display_class_init (GdmDynamicDisplayClass *klass); +static void gdm_dynamic_display_init (GdmDynamicDisplay *display); +static void gdm_dynamic_display_finalize (GObject *object); + +G_DEFINE_TYPE (GdmDynamicDisplay, gdm_dynamic_display, GDM_TYPE_DISPLAY) + +void +gdm_dynamic_display_respawn (GdmDynamicDisplay *display, gboolean respawn) +{ + display->priv->do_respawn = respawn; + if (display->priv->do_respawn == TRUE) + g_debug ("GdmDynamicDisplay: Set respawn to TRUE."); + else + g_debug ("GdmDynamicDisplay: Set respawn to FALSE."); +} + +void +gdm_dynamic_display_removed (GdmDynamicDisplay *display) +{ + display->priv->removed = TRUE; +} + +static gboolean +gdm_dynamic_display_create_authority (GdmDisplay *display) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->create_authority (display); + + return TRUE; +} + +static gboolean +gdm_dynamic_display_add_user_authorization (GdmDisplay *display, + const char *username, + char **filename, + GError **error) +{ + return GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->add_user_authorization (display, username, filename, error); +} + +static gboolean +gdm_dynamic_display_remove_user_authorization (GdmDisplay *display, + const char *username, + GError **error) +{ + return GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->remove_user_authorization (display, username, error); +} + +static gboolean +gdm_dynamic_display_manage (GdmDisplay *display) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + g_debug ("GdmDynamicDisplay: Manage dynamic display"); + + GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->manage (display); + + return TRUE; +} + +static gboolean +gdm_dynamic_display_finish (GdmDisplay *display) +{ + int status; + + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + g_debug ("GdmDynamicDisplay: Finish dynamic display"); + + /* Don't call parent's finish since we don't ever + want to be put in the FINISHED state */ + + /* restart dynamic displays */ + gdm_display_unmanage (display); + + status = gdm_display_get_status (display); + if (GDM_DYNAMIC_DISPLAY (display)->priv->do_respawn == TRUE && + GDM_DYNAMIC_DISPLAY(display)->priv->removed == FALSE) { + if (status != GDM_DISPLAY_FAILED) { + g_debug ("Respawning..."); + gdm_display_manage (display); + } else { + g_debug ("Display failed, not respawning..."); + } + } else { + g_debug ("Not respawning..."); + } + GDM_DYNAMIC_DISPLAY (display)->priv->do_respawn = FALSE; + + return TRUE; +} + +static gboolean +gdm_dynamic_display_unmanage (GdmDisplay *display) +{ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + g_debug ("GdmDynamicDisplay: Unmanage dynamic display"); + + GDM_DISPLAY_CLASS (gdm_dynamic_display_parent_class)->unmanage (display); + + return TRUE; +} + +static void +gdm_dynamic_display_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdm_dynamic_display_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gdm_dynamic_display_class_init (GdmDynamicDisplayClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass); + + object_class->get_property = gdm_dynamic_display_get_property; + object_class->set_property = gdm_dynamic_display_set_property; + object_class->finalize = gdm_dynamic_display_finalize; + + display_class->create_authority = gdm_dynamic_display_create_authority; + display_class->add_user_authorization = gdm_dynamic_display_add_user_authorization; + display_class->remove_user_authorization = gdm_dynamic_display_remove_user_authorization; + display_class->manage = gdm_dynamic_display_manage; + display_class->finish = gdm_dynamic_display_finish; + display_class->unmanage = gdm_dynamic_display_unmanage; + + g_type_class_add_private (klass, sizeof (GdmDynamicDisplayPrivate)); +} + +static void +gdm_dynamic_display_init (GdmDynamicDisplay *display) +{ + display->priv = GDM_DYNAMIC_DISPLAY_GET_PRIVATE (display); + display->priv->removed = FALSE; + display->priv->do_respawn = FALSE; +} + +static void +gdm_dynamic_display_finalize (GObject *object) +{ + GdmDynamicDisplay *display; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_DYNAMIC_DISPLAY (object)); + + g_debug ("GdmDynamicDisplay: Finalize dynamic display"); + + display = GDM_DYNAMIC_DISPLAY (object); + + g_return_if_fail (display->priv != NULL); + + G_OBJECT_CLASS (gdm_dynamic_display_parent_class)->finalize (object); +} + +GdmDisplay * +gdm_dynamic_display_new (int display_number) +{ + GObject *object; + char *x11_display; + + x11_display = g_strdup_printf (":%d", display_number); + object = g_object_new (GDM_TYPE_DYNAMIC_DISPLAY, + "x11-display-number", display_number, + "x11-display-name", x11_display, + NULL); + g_free (x11_display); + + return GDM_DISPLAY (object); +} diff --git a/daemon/gdm-dynamic-display.h b/daemon/gdm-dynamic-display.h new file mode 100644 index 00000000..0c53ea98 --- /dev/null +++ b/daemon/gdm-dynamic-display.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Authors: halton.huo@sun.com + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __GDM_DYNAMIC_DISPLAY_H +#define __GDM_DYNAMIC_DISPLAY_H + +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include "gdm-display.h" + +G_BEGIN_DECLS + +#define GDM_TYPE_DYNAMIC_DISPLAY (gdm_dynamic_display_get_type ()) +#define GDM_DYNAMIC_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplay)) +#define GDM_DYNAMIC_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayClass)) +#define GDM_IS_DYNAMIC_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_DYNAMIC_DISPLAY)) +#define GDM_IS_DYNAMIC_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_DYNAMIC_DISPLAY)) +#define GDM_DYNAMIC_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_DYNAMIC_DISPLAY, GdmDynamicDisplayClass)) + +typedef struct _GdmDynamicDisplayPrivate GdmDynamicDisplayPrivate; + +typedef struct +{ + GdmDisplay parent; + GdmDynamicDisplayPrivate *priv; +} GdmDynamicDisplay; + +typedef struct +{ + GdmDisplayClass parent_class; + +} GdmDynamicDisplayClass; + +GType gdm_dynamic_display_get_type (void); +GdmDisplay * gdm_dynamic_display_new (int display_number); +void gdm_dynamic_display_respawn (GdmDynamicDisplay *display, gboolean respawn); +void gdm_dynamic_display_removed (GdmDynamicDisplay *display); + +G_END_DECLS + +#endif /* __GDM_DYNAMIC_DISPLAY_H */ diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c index 9e435f9f..158b6cb5 100644 --- a/daemon/gdm-factory-slave.c +++ b/daemon/gdm-factory-slave.c @@ -502,6 +502,7 @@ run_greeter (GdmFactorySlave *slave) char *display_id; char *display_name; char *seat_id; + char *session_id; char *display_device; char *display_hostname; char *auth_file; @@ -513,6 +514,7 @@ run_greeter (GdmFactorySlave *slave) display_id = NULL; display_name = NULL; seat_id = NULL; + session_id = NULL; auth_file = NULL; display_device = NULL; display_hostname = NULL; @@ -522,6 +524,7 @@ run_greeter (GdmFactorySlave *slave) "display-id", &display_id, "display-name", &display_name, "display-seat-id", &seat_id, + "display-session-id", &session_id, "display-hostname", &display_hostname, "display-x11-authority-file", &auth_file, NULL); @@ -579,6 +582,7 @@ run_greeter (GdmFactorySlave *slave) g_debug ("GdmFactorySlave: Creating greeter on %s %s", display_name, display_device); slave->priv->greeter = gdm_greeter_session_new (display_name, seat_id, + session_id, display_device, display_hostname, display_is_local); @@ -674,14 +678,12 @@ on_server_died (GdmServer *server, static gboolean gdm_factory_slave_run (GdmFactorySlave *slave) { - char *display_name; - char *auth_file; + char *display_id; gboolean display_is_local; g_object_get (slave, + "display-id", &display_id, "display-is-local", &display_is_local, - "display-name", &display_name, - "display-x11-authority-file", &auth_file, NULL); /* if this is local display start a server if one doesn't @@ -689,7 +691,7 @@ gdm_factory_slave_run (GdmFactorySlave *slave) if (display_is_local) { gboolean res; - slave->priv->server = gdm_server_new (display_name, auth_file); + slave->priv->server = gdm_server_new (display_id); g_signal_connect (slave->priv->server, "exited", G_CALLBACK (on_server_exited), @@ -721,8 +723,7 @@ gdm_factory_slave_run (GdmFactorySlave *slave) g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave); } - g_free (display_name); - g_free (auth_file); + g_free (display_id); return TRUE; } diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c index a401508d..08201728 100644 --- a/daemon/gdm-greeter-session.c +++ b/daemon/gdm-greeter-session.c @@ -141,6 +141,7 @@ gdm_greeter_session_finalize (GObject *object) GdmGreeterSession * gdm_greeter_session_new (const char *display_name, const char *seat_id, + const char *session_id, const char *display_device, const char *display_hostname, gboolean display_is_local) @@ -155,6 +156,7 @@ gdm_greeter_session_new (const char *display_name, "register-ck-session", TRUE, "x11-display-name", display_name, "x11-display-seat-id", seat_id, + "x11-display-session-id", session_id, "x11-display-device", display_device, "x11-display-hostname", display_hostname, "x11-display-is-local", display_is_local, diff --git a/daemon/gdm-greeter-session.h b/daemon/gdm-greeter-session.h index 6c19320c..c3c35061 100644 --- a/daemon/gdm-greeter-session.h +++ b/daemon/gdm-greeter-session.h @@ -51,6 +51,7 @@ typedef struct GType gdm_greeter_session_get_type (void); GdmGreeterSession * gdm_greeter_session_new (const char *display_name, const char *seat_id, + const char *session_id, const char *display_device, const char *display_hostname, gboolean display_is_local); diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 7ad27bec..f88f4e1c 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -27,18 +27,30 @@ #include <glib/gi18n.h> #include <glib-object.h> +#include <dbus/dbus-glib-lowlevel.h> + #include "gdm-display-factory.h" #include "gdm-local-display-factory.h" #include "gdm-local-display-factory-glue.h" +#include "gdm-marshal.h" #include "gdm-display-store.h" #include "gdm-static-display.h" +#include "gdm-dynamic-display.h" #include "gdm-transient-display.h" #include "gdm-static-factory-display.h" #include "gdm-product-display.h" #define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate)) +#define CK_NAME "org.freedesktop.ConsoleKit" +#define CK_PATH "/org/freedesktop/ConsoleKit" +#define CK_INTERFACE "org.freedesktop.ConsoleKit" +#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" +#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" +#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" +#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" + #define CK_SEAT1_PATH "/org/freedesktop/ConsoleKit/Seat1" #define GDM_DBUS_PATH "/org/gnome/DisplayManager" @@ -47,11 +59,17 @@ #define MAX_DISPLAY_FAILURES 5 +#define IS_STR_SET(x) (x != NULL && x[0] != '\0') + +#define GDM_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)) + struct GdmLocalDisplayFactoryPrivate { DBusGConnection *connection; DBusGProxy *proxy; + DBusGProxy *proxy_ck; GHashTable *displays; + GHashTable *managed_seat_proxies; /* FIXME: this needs to be per seat? */ guint num_failures; @@ -65,7 +83,14 @@ static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryC static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory); static void gdm_local_display_factory_finalize (GObject *object); -static GdmDisplay *create_display (GdmLocalDisplayFactory *factory); +static gboolean create_static_displays (GdmLocalDisplayFactory *factory); +static void on_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory); +static void on_block_console_session_requests_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory); +static gboolean connect_to_ck (GdmLocalDisplayFactory *factory); static gpointer local_display_factory_object = NULL; @@ -179,6 +204,100 @@ store_display (GdmLocalDisplayFactory *factory, g_hash_table_insert (factory->priv->displays, GUINT_TO_POINTER (num), NULL); } +static void +store_remove_display (GdmLocalDisplayFactory *factory, + guint32 num, + GdmDisplay *display) +{ + GdmDisplayStore *store; + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + gdm_display_store_remove (store, display); + + g_debug ("GdmLocalDisplayFactory: Remove display %d from store", num); + + /* remove from our reserved spot */ + g_hash_table_remove (factory->priv->displays, GUINT_TO_POINTER (num)); +} + +static gboolean +lookup_by_session (const char *id, + GdmDisplay *display, + gpointer user_data) +{ + char *key1 = user_data; + char *key2; + + if (!GDM_IS_DISPLAY (display)) { + return FALSE; + } + + gdm_display_get_session_id (display, &key2, NULL); + + if (strcmp (key1, key2) == 0) { + g_free (key2); + return TRUE; + } + g_free (key2); + + return FALSE; +} + +static gboolean +lookup_by_x11_display (const char *id, + GdmDisplay *display, + gpointer user_data) +{ + char *key1 = user_data; + char *key2; + + if (! GDM_IS_DISPLAY (display)) { + return FALSE; + } + + gdm_display_get_x11_display_name (display, &key2, NULL); + + if (strcmp (key1, key2) == 0) { + g_free (key2); + return TRUE; + } + g_free (key2); + + return FALSE; +} + +static gboolean +lookup_by_x11_display_num (const char *id, + GdmDisplay *display, + gpointer user_data) +{ + guint32 key1 = GPOINTER_TO_UINT (user_data); + int key2; + + if (! GDM_IS_DISPLAY (display)) { + return FALSE; + } + + gdm_display_get_x11_display_number (display, &key2, NULL); + + if (key1 == key2) { + return TRUE; + } + + return FALSE; +} + +static GdmDisplay * +factory_find_display (GdmLocalDisplayFactory *factory, + GdmDisplayStoreFunc predicate, + gpointer user_data) +{ + GdmDisplayStore *store; + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + return gdm_display_store_find (store, predicate, user_data); +} + /* Example: dbus-send --system --dest=org.gnome.DisplayManager \ @@ -275,14 +394,113 @@ gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factor return ret; } +static gboolean +display_has_pending_sessions (GdmLocalDisplayFactory *factory, + GdmDisplay *display) +{ + return g_object_get_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests") != NULL; +} + static void -on_static_display_status_changed (GdmDisplay *display, - GParamSpec *arg1, - GdmLocalDisplayFactory *factory) +manage_next_pending_session_on_display (GdmLocalDisplayFactory *factory, + GdmDisplay *display) +{ + GList *pending_sessions; + GList *next_session; + char *ssid; + + g_debug ("GdmLocalDisplayFactory: Manage next pending session on display"); + + pending_sessions = g_object_get_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests"); + next_session = g_list_last (pending_sessions); + + if (next_session == NULL) { + return; + } + + ssid = next_session->data; + pending_sessions = g_list_delete_link (pending_sessions, next_session); + g_object_set_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests", + pending_sessions); + + g_object_set (display, "session-id", ssid, NULL); + g_free (ssid); + + gdm_display_manage (display); +} + +static void +discard_pending_session_on_display (GdmLocalDisplayFactory *factory, + GdmDisplay *display, + const char *ssid) +{ + GList *pending_sessions; + GList *node; + + pending_sessions = g_object_get_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests"); + node = g_list_last (pending_sessions); + + while (node != NULL) { + GList *prev_node; + char *node_ssid; + + prev_node = node->prev; + node_ssid = node->data; + + if (strcmp (node_ssid, ssid) == 0) { + pending_sessions = g_list_delete_link (pending_sessions, node); + break; + } + + node = prev_node; + } + + g_object_set_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests", + pending_sessions); +} + +static void +on_block_console_session_requests_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory) +{ + gboolean display_is_blocked; + int status; + + g_object_get (G_OBJECT (display), + "status", &status, + "block-console-session-requests", + &display_is_blocked, NULL); + + if (display_is_blocked) { + int number; + + gdm_display_get_x11_display_number (display, &number, NULL); + g_debug ("GdmLocalDisplayFactory: display :%d is blocked", number); + return; + } + + if (status == GDM_DISPLAY_UNMANAGED) { + manage_next_pending_session_on_display (factory, display); + } +} + +static void +on_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory) { int status; GdmDisplayStore *store; int num; + gboolean display_is_blocked; + + g_debug ("GdmLocalDisplayFactory: Display Status Changed"); num = -1; gdm_display_get_x11_display_number (display, &num, NULL); @@ -292,16 +510,17 @@ on_static_display_status_changed (GdmDisplay *display, status = gdm_display_get_status (display); + g_object_get (G_OBJECT (display), + "block-console-session-requests", + &display_is_blocked, NULL); + g_debug ("GdmLocalDisplayFactory: static display status changed: %d", status); switch (status) { case GDM_DISPLAY_FINISHED: - /* remove the display number from factory->priv->displays - so that it may be reused */ - g_hash_table_remove (factory->priv->displays, GUINT_TO_POINTER (num)); - gdm_display_store_remove (store, display); - /* reset num failures */ + /* Do not remove the display number from factory->priv->displays + here because it should be remove under signal "SessionRemoved" + */ factory->priv->num_failures = 0; - create_display (factory); break; case GDM_DISPLAY_FAILED: /* leave the display number in factory->priv->displays @@ -313,11 +532,13 @@ on_static_display_status_changed (GdmDisplay *display, g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors"); /* FIXME: should monitor hardware changes to try again when seats change */ - } else { - create_display (factory); } break; case GDM_DISPLAY_UNMANAGED: + if (display_has_pending_sessions (factory, display) && !display_is_blocked) { + store_display (factory, num, display); + manage_next_pending_session_on_display (factory, display); + } break; case GDM_DISPLAY_PREPARED: break; @@ -329,38 +550,535 @@ on_static_display_status_changed (GdmDisplay *display, } } -static GdmDisplay * -create_display (GdmLocalDisplayFactory *factory) +static void +seat_open_session_request (DBusGProxy *seat_proxy, + const char *ssid, + const char *session_type, + const char *display_template_name, + GHashTable *display_variables, + const char *display_type, + GHashTable *parameters, + GdmLocalDisplayFactory *factory) { GdmDisplay *display; - guint32 num; + gint argc; + gchar **argv; + GError *error; + char *comm = NULL; + const char *sid = NULL; + gint32 display_number; + gboolean is_chooser = FALSE; + gboolean use_auth = FALSE; + int i; + char *xserver_command; + gboolean display_is_blocked; + GList *pending_sessions; + + g_return_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory)); + + g_debug ("GdmLocalDisplayFactory: Open Session Request"); + + display_is_blocked = FALSE; + + display = factory_find_display (factory, lookup_by_session, (gpointer)ssid); + + if (display != NULL) { + g_object_get (G_OBJECT (display), + "block-console-session-requests", + &display_is_blocked, NULL); + } - num = take_next_display_number (factory); + if (strcmp (display_type, "X11") != 0) { + g_warning ("Unknown display type '%s' requested", display_type); + return; + } -#if 0 - display = gdm_static_factory_display_new (num); -#else - display = gdm_static_display_new (num); -#endif + xserver_command = g_hash_table_lookup (parameters, "Exec"); - /* FIXME: don't hardcode seat1? */ - g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL); + if (! g_shell_parse_argv (xserver_command, &argc, &argv, &error)) { + g_warning ("Could not parse command %s: %s", xserver_command, error->message); + g_error_free (error); + return; + } - g_signal_connect (display, - "notify::status", - G_CALLBACK (on_static_display_status_changed), - factory); + g_debug("GdmLocalDisplayFactory: X11 server cmd pre-mangle: %s", + xserver_command); + for (i = 0; i < argc; i++) { + /* replase $display in case of not specified */ + if (g_str_equal (argv[i], "$display")) { + display_number = take_next_display_number (factory); + argv[i][0] = '\0'; + continue; + } - store_display (factory, num, display); + /* get display_number in case of specified */ + if (g_str_has_prefix (argv[i], ":")) { + display_number = atoi (argv[i]+1); + argv[i][0] = '\0'; + continue; + } - /* let store own the ref */ - g_object_unref (display); + if (! g_strcmp0 (argv[i], "-indirect")) { + is_chooser = TRUE; + continue; + } - if (! gdm_display_manage (display)) { - gdm_display_unmanage (display); + /* + * -auth is added by gdm_server_resolve_command_line() + * in gdm-server.c + */ + if (! g_strcmp0 (argv[i], "-auth") && + ! g_strcmp0 (argv[i+1], "$auth")) { + use_auth = TRUE; + argv[i][0] = '\0'; + argv[++i][0] = '\0'; + continue; + } + + if (!g_strcmp0 (argv[i], "$vt")) { + argv[i][0] = '\0'; + continue; + } } + comm = g_strjoinv (" ", argv); + g_debug ("GdmLocalDisplayFactory: X11 server cmd post-mangle: %s", + comm); + g_strfreev (argv); + + if (display == NULL) { + if (is_chooser) { + /* TODO: Start a xdmcp chooser as request */ + + /* display = gdm_xdmcp_chooser_display_new (display_number); */ + } else { + display = gdm_dynamic_display_new (display_number); + } + + if (display == NULL) { + g_warning ("Unable to create display: %d", display_number); + g_free (comm); + return; + } + + g_object_set (display, "session-id", ssid, NULL); + + sid = dbus_g_proxy_get_path (seat_proxy); + if (IS_STR_SET (sid)) + g_object_set (display, "seat-id", sid, NULL); + if (IS_STR_SET (comm)) + g_object_set (display, "x11-command", comm, NULL); + g_free (comm); + if (IS_STR_SET (display_template_name)) + g_object_set (display, "x11-display-type", display_template_name, NULL); + g_object_set (display, "use-auth", use_auth, NULL); + + g_signal_connect (display, + "notify::status", + G_CALLBACK (on_display_status_changed), + factory); + + g_signal_connect (display, + "notify::block-console-session-requests", + G_CALLBACK (on_block_console_session_requests_changed), + factory); + + store_display (factory, display_number, display); + + g_object_unref (display); + + if (! gdm_display_manage (display)) { + gdm_display_unmanage (display); + } + + return; + } + + /* FIXME: Make sure the display returned is compatible + */ + + if (!display_is_blocked) { + /* FIXME: What do we do here? + */ + g_debug ("Got console request to add display for session that " + "already has a display, and display is already in " + "use"); + return; + } + + pending_sessions = g_object_get_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests"); + pending_sessions = g_list_prepend (pending_sessions, g_strdup (ssid)); + + g_object_set_data (G_OBJECT (display), + "gdm-local-display-factory-console-session-requests", + pending_sessions); +} + +static void +seat_close_session_request (DBusGProxy *seat_proxy, + const char *ssid, + GdmLocalDisplayFactory *factory) +{ + GdmDisplay *display; + int display_number; + char *display_ssid; + + g_debug ("GdmLocalDisplayFactory: Close session request"); + + g_return_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory)); + + display = factory_find_display (factory, lookup_by_session, (gpointer)ssid); + + if (display == NULL) { + g_debug ("GdmLocalDisplayFactory: display for session '%s' doesn't exists", ssid); + return; + } + + g_object_get (G_OBJECT (display), "session-id", &display_ssid, NULL); + + if (display_ssid == NULL || strcmp (ssid, display_ssid) != 0) { + g_free (display_ssid); + discard_pending_session_on_display (factory, display, ssid); + return; + } + g_free (display_ssid); + + if (! gdm_display_unmanage (display)) { + display = NULL; + return; + } + + gdm_display_get_x11_display_number (display, &display_number, NULL); + store_remove_display (factory, display_number, display); +} + +static void +seat_session_no_respawn (DBusGProxy *seat_proxy, + const char *ssid, + GdmLocalDisplayFactory *factory) +{ + GdmDisplay *display; + int display_number; + char *display_ssid; + + g_debug ("GdmLocalDisplayFactory: No Respawn"); + + g_return_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory)); + + display = factory_find_display (factory, lookup_by_session, (gpointer)ssid); + + if (display == NULL) { + g_debug ("GdmLocalDisplayFactory: display for session '%s' doesn't exists", ssid); + return; + } + + if (GDM_IS_DYNAMIC_DISPLAY (display)) { + gdm_dynamic_display_removed (GDM_DYNAMIC_DISPLAY (display)); + } +} + +static gboolean +get_session_x11_display (GdmLocalDisplayFactory *factory, + const char *ssid, + char **x11_display) +{ + DBusGProxy *proxy; + gboolean res; + + if (!x11_display) + return FALSE; + + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, + CK_NAME, + ssid, + CK_SESSION_INTERFACE); + if (proxy == NULL) { + return FALSE; + } + + res = dbus_g_proxy_call (proxy, + "GetX11Display", + NULL, + G_TYPE_INVALID, + G_TYPE_STRING, x11_display, + G_TYPE_INVALID); + if (!res) { + return FALSE; + } + + return TRUE; +} + +static void +seat_session_added (DBusGProxy *seat_proxy, + const char *ssid, + GdmLocalDisplayFactory *factory) +{ + GdmDisplay *display; + char *x11_display; + gboolean res; + + g_debug ("GdmLocalDisplayFactory: Adding Seat Session"); + + res = get_session_x11_display (factory, ssid, &x11_display); + if (!res) { + g_warning ("Failed to get X11 display number for %s", ssid); + return; + } + + display = factory_find_display (factory, lookup_by_x11_display, +x11_display); + if (display) { + gdm_display_set_session_id (display, ssid, NULL); + g_debug ("Update session id for display %s to %s", + x11_display, ssid); + } + g_free (x11_display); +} + + +static void +seat_session_removed (DBusGProxy *seat_proxy, + const char *ssid, + GdmLocalDisplayFactory *factory) +{ + GdmDisplay *display = NULL; + gboolean res; + int status; + int num; + + g_debug ("GdmLocalDisplayFactory: Removed Seat Session"); + + display = factory_find_display (factory, lookup_by_session, +(gpointer)ssid); + if (display) { + num = -1; + gdm_display_get_x11_display_number (display, &num, NULL); + g_assert (num != -1); + store_remove_display (factory, num, display); + } +} + +static void +seat_remove_request (DBusGProxy *seat_proxy, + GdmLocalDisplayFactory *factory) +{ + GHashTableIter iter; + gpointer key, value; + const char *sid_to_remove; + GQueue ssids_to_remove; + + g_debug ("GdmLocalDisplayFactory: Seat Remove Request"); + + sid_to_remove = dbus_g_proxy_get_path (seat_proxy); + + g_queue_init (&ssids_to_remove); + g_hash_table_iter_init (&iter, factory->priv->displays); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GdmDisplay *display; + char *sid; + guint32 x11_display_num; + + x11_display_num = GPOINTER_TO_UINT (key); + display = factory_find_display (factory, + lookup_by_x11_display_num, + GUINT_TO_POINTER (x11_display_num)); + + gdm_display_get_seat_id (display, &sid, NULL); + + if (strcmp (sid, sid_to_remove) == 0) { + char *ssid; + + gdm_display_get_session_id (display, &ssid, NULL); + + g_queue_push_tail (&ssids_to_remove, ssid); + } + + g_free (sid); + } + + while (!g_queue_is_empty (&ssids_to_remove)) { + char *ssid; + + ssid = g_queue_pop_head (&ssids_to_remove); + + seat_close_session_request (seat_proxy, ssid, factory); + + g_free (ssid); + } + + g_hash_table_remove (factory->priv->managed_seat_proxies, sid_to_remove); + + dbus_g_proxy_call_no_reply (seat_proxy, + "Unmanage", + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (factory->priv->proxy_ck == NULL) { + connect_to_ck (factory); + } + + dbus_g_proxy_call_no_reply (factory->priv->proxy_ck, + "RemoveSeat", + DBUS_TYPE_G_OBJECT_PATH, sid_to_remove, + G_TYPE_INVALID, + G_TYPE_INVALID); +} + +static void +manage_static_sessions_per_seat (GdmLocalDisplayFactory *factory, + const char *sid) +{ + DBusGProxy *proxy; + + g_debug ("GdmLocalDisplayFactory: Manage Static Sessions Per Seat"); + + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, + CK_NAME, + sid, + CK_SEAT_INTERFACE); + + if (proxy == NULL) { + g_warning ("Failed to connect to the ConsoleKit seat object"); + return; + } + + dbus_g_object_register_marshaller (gdm_marshal_VOID__STRING_STRING_STRING_POINTER_STRING_POINTER, + G_TYPE_NONE, + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_STRING, + G_TYPE_STRING, + GDM_DBUS_TYPE_G_STRING_STRING_HASHTABLE, + G_TYPE_STRING, + GDM_DBUS_TYPE_G_STRING_STRING_HASHTABLE, + G_TYPE_INVALID); + + dbus_g_proxy_add_signal (proxy, + "OpenSessionRequest", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_STRING, + G_TYPE_STRING, + GDM_DBUS_TYPE_G_STRING_STRING_HASHTABLE, + G_TYPE_STRING, + GDM_DBUS_TYPE_G_STRING_STRING_HASHTABLE, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, + "CloseSessionRequest", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, + "NoRespawn", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, + "SessionAdded", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, + "SessionRemoved", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, + "RemoveRequest", + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (proxy, + "OpenSessionRequest", + G_CALLBACK (seat_open_session_request), + factory, + NULL); + dbus_g_proxy_connect_signal (proxy, + "CloseSessionRequest", + G_CALLBACK (seat_close_session_request), + factory, + NULL); + dbus_g_proxy_connect_signal (proxy, + "NoRespawn", + G_CALLBACK (seat_session_no_respawn), + factory, + NULL); + dbus_g_proxy_connect_signal (proxy, + "SessionAdded", + G_CALLBACK (seat_session_added), + factory, + NULL); + dbus_g_proxy_connect_signal (proxy, + "SessionRemoved", + G_CALLBACK (seat_session_removed), + factory, + NULL); + dbus_g_proxy_connect_signal (proxy, + "RemoveRequest", + G_CALLBACK (seat_remove_request), + factory, + NULL); + + dbus_g_proxy_call_no_reply (proxy, + "Manage", + G_TYPE_INVALID, + G_TYPE_INVALID); + + g_hash_table_insert (factory->priv->managed_seat_proxies, + g_strdup (dbus_g_proxy_get_path (proxy)), + proxy); +} + +static void +seat_added (DBusGProxy *mgr_proxy, + const char *sid, + const char *type, + GdmLocalDisplayFactory *factory) +{ + g_debug ("GdmLocalDisplayFactory: Seat Added"); + + if (strcmp (type, "Default") == 0) { + manage_static_sessions_per_seat (factory, sid); + } +} + +static gboolean +create_static_displays (GdmLocalDisplayFactory *factory) +{ + GError *error; + gboolean res; + GPtrArray *seats; + int i; + + g_debug ("GdmLocalDisplayFactory: Create Static Display"); + + seats = NULL; + + if (factory->priv->proxy_ck == NULL) { + connect_to_ck (factory); + } + + error = NULL; + res = dbus_g_proxy_call (factory->priv->proxy_ck, + "GetUnmanagedSeats", + &error, + G_TYPE_INVALID, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), + &seats, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get list of unmanaged seats: %s", error->message); + g_error_free (error); + } + return FALSE; + } + + for (i = 0; i < seats->len; i++) { + char *sid; + + sid = g_ptr_array_index (seats, i); + + manage_static_sessions_per_seat (factory, sid); + + g_free (sid); + } + + return TRUE; - return display; } static gboolean @@ -375,7 +1093,7 @@ gdm_local_display_factory_start (GdmDisplayFactory *base_factory) ret = TRUE; /* FIXME: use seat configuration */ - display = create_display (factory); + display = create_static_displays (factory); if (display == NULL) { ret = FALSE; } @@ -439,6 +1157,68 @@ register_factory (GdmLocalDisplayFactory *factory) return TRUE; } +static void +bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, + GdmLocalDisplayFactoryPrivate *priv) +{ + g_debug ("Local Display Factory - Disconnected from D-Bus"); + + if (priv == NULL) { + /* probably shutting down or something */ + return; + } + + priv->proxy_ck = NULL; +} + +static gboolean +connect_to_ck (GdmLocalDisplayFactory *factory) +{ + GdmLocalDisplayFactoryPrivate *priv; + + g_debug ("GdmLocalDisplayFactory: Connect To ConsoleKit"); + + priv = factory->priv; + + priv->proxy_ck = dbus_g_proxy_new_for_name (priv->connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + + if (priv->proxy_ck == NULL) { + g_warning ("Couldn't create proxy for ConsoleKit Manager"); + return FALSE; + } + + dbus_g_object_register_marshaller (gdm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + + dbus_g_proxy_add_signal (priv->proxy_ck, + "SeatAdded", + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy_ck, + "SeatAdded", + G_CALLBACK (seat_added), + factory, + NULL); + g_signal_connect (priv->proxy_ck, + "destroy", + G_CALLBACK (bus_proxy_destroyed_cb), + priv); +} + +static void +disconnect_from_ck (GdmLocalDisplayFactory *factory) +{ + if (factory->priv->proxy_ck == NULL) { + g_object_unref (factory->priv->proxy_ck); + } +} + static GObject * gdm_local_display_factory_constructor (GType type, guint n_construct_properties, @@ -456,6 +1236,8 @@ gdm_local_display_factory_constructor (GType type, g_warning ("Unable to register local display factory with system bus"); } + connect_to_ck (factory); + return G_OBJECT (factory); } @@ -484,6 +1266,11 @@ gdm_local_display_factory_init (GdmLocalDisplayFactory *factory) factory->priv = GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE (factory); factory->priv->displays = g_hash_table_new (NULL, NULL); + factory->priv->proxy_ck = NULL; + + factory->priv->managed_seat_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); } static void @@ -499,6 +1286,9 @@ gdm_local_display_factory_finalize (GObject *object) g_return_if_fail (factory->priv != NULL); g_hash_table_destroy (factory->priv->displays); + g_hash_table_destroy (factory->priv->managed_seat_proxies); + + disconnect_from_ck (factory); G_OBJECT_CLASS (gdm_local_display_factory_parent_class)->finalize (object); } diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c index af1c4804..27e79687 100644 --- a/daemon/gdm-product-slave.c +++ b/daemon/gdm-product-slave.c @@ -482,14 +482,12 @@ on_server_died (GdmServer *server, static gboolean gdm_product_slave_create_server (GdmProductSlave *slave) { - char *display_name; - char *auth_file; + char *display_id; gboolean display_is_local; g_object_get (slave, + "display-id", &display_id, "display-is-local", &display_is_local, - "display-name", &display_name, - "display-x11-authority-file", &auth_file, NULL); /* if this is local display start a server if one doesn't @@ -497,7 +495,7 @@ gdm_product_slave_create_server (GdmProductSlave *slave) if (display_is_local) { gboolean res; - slave->priv->server = gdm_server_new (display_name, auth_file); + slave->priv->server = gdm_server_new (display_id); g_signal_connect (slave->priv->server, "exited", G_CALLBACK (on_server_exited), @@ -529,8 +527,7 @@ gdm_product_slave_create_server (GdmProductSlave *slave) g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave); } - g_free (display_name); - g_free (auth_file); + g_free (display_id); return TRUE; } diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c index 7135ffaf..bb968da1 100644 --- a/daemon/gdm-server.c +++ b/daemon/gdm-server.c @@ -43,6 +43,8 @@ #include <glib/gstdio.h> #include <glib-object.h> +#include <dbus/dbus-glib.h> + #include <X11/Xlib.h> /* for Display */ #include "gdm-common.h" @@ -54,6 +56,9 @@ extern char **environ; #define GDM_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SERVER, GdmServerPrivate)) +#define GDM_DBUS_NAME "org.gnome.DisplayManager" +#define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display" + /* These are the servstat values, also used as server * process exit codes */ #define SERVER_TIMEOUT 2 /* Server didn't start */ @@ -69,12 +74,12 @@ struct GdmServerPrivate char *command; GPid pid; - gboolean disable_tcp; int priority; char *user_name; char *session_args; char *log_dir; + char *display_id; char *display_name; char *display_device; char *auth_file; @@ -101,7 +106,7 @@ enum { PROP_USER_NAME, PROP_SESSION_ARGS, PROP_LOG_DIR, - PROP_DISABLE_TCP, + PROP_DISPLAY_ID, }; enum { @@ -267,6 +272,11 @@ gdm_server_resolve_command_line (GdmServer *server, gboolean gotvtarg = FALSE; gboolean query_in_arglist = FALSE; + if (!server->priv->command) { + g_warning ("X11 server command line is missing"); + return FALSE; + } + g_shell_parse_argv (server->priv->command, &argc, &argv, NULL); for (len = 0; argv != NULL && argv[len] != NULL; len++) { @@ -307,11 +317,6 @@ gdm_server_resolve_command_line (GdmServer *server, query_in_arglist = TRUE; } - if (server->priv->disable_tcp && ! query_in_arglist) { - argv[len++] = g_strdup ("-nolisten"); - argv[len++] = g_strdup ("tcp"); - } - if (vtarg != NULL && ! gotvtarg) { argv[len++] = g_strdup (vtarg); } @@ -612,16 +617,20 @@ gdm_server_spawn (GdmServer *server, GPtrArray *env; gboolean ret; char *freeme; + char *tmp; ret = FALSE; /* Figure out the server command */ argv = NULL; argc = 0; - gdm_server_resolve_command_line (server, - vtarg, - &argc, - &argv); + if (! gdm_server_resolve_command_line (server, + vtarg, + &argc, + &argv)) { + g_warning ("unable to process X11 server command line"); + return FALSE; + } if (server->priv->session_args) { server_add_xserver_args (server, &argc, &argv); @@ -634,6 +643,29 @@ gdm_server_spawn (GdmServer *server, _exit (SERVER_ABORT); } + /* Sometimes quit X slowly, adding this to avoid restart session + failure */ + if ((tmp = strstr (server->priv->display_name, ":")) != NULL) { + char *socket_file; + int display_num; + int count; + char *p; + + tmp++; + display_num = g_ascii_strtod (tmp, &p); + + socket_file = g_strdup_printf ("/tmp/.X11-unix/X%d", + display_num); + count = 0; + while (count < 5) { + if (!g_file_test (socket_file, G_FILE_TEST_EXISTS)) + break; + sleep (1); + count ++; + } + g_free (socket_file); + } + env = get_server_environment (server); freeme = g_strjoinv (" ", argv); @@ -743,13 +775,12 @@ gdm_server_stop (GdmServer *server) return TRUE; } - static void -_gdm_server_set_display_name (GdmServer *server, - const char *name) +_gdm_server_set_display_id (GdmServer *server, + const char *id) { - g_free (server->priv->display_name); - server->priv->display_name = g_strdup (name); + g_free (server->priv->display_id); + server->priv->display_id = g_strdup (id); } static void @@ -769,13 +800,6 @@ _gdm_server_set_user_name (GdmServer *server, } static void -_gdm_server_set_disable_tcp (GdmServer *server, - gboolean disabled) -{ - server->priv->disable_tcp = disabled; -} - -static void gdm_server_set_property (GObject *object, guint prop_id, const GValue *value, @@ -786,8 +810,8 @@ gdm_server_set_property (GObject *object, self = GDM_SERVER (object); switch (prop_id) { - case PROP_DISPLAY_NAME: - _gdm_server_set_display_name (self, g_value_get_string (value)); + case PROP_DISPLAY_ID: + _gdm_server_set_display_id (self, g_value_get_string (value)); break; case PROP_AUTH_FILE: _gdm_server_set_auth_file (self, g_value_get_string (value)); @@ -795,9 +819,6 @@ gdm_server_set_property (GObject *object, case PROP_USER_NAME: _gdm_server_set_user_name (self, g_value_get_string (value)); break; - case PROP_DISABLE_TCP: - _gdm_server_set_disable_tcp (self, g_value_get_boolean (value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -815,8 +836,8 @@ gdm_server_get_property (GObject *object, self = GDM_SERVER (object); switch (prop_id) { - case PROP_DISPLAY_NAME: - g_value_set_string (value, self->priv->display_name); + case PROP_DISPLAY_ID: + g_value_set_string (value, self->priv->display_id); break; case PROP_DISPLAY_DEVICE: g_value_take_string (value, @@ -828,9 +849,6 @@ gdm_server_get_property (GObject *object, case PROP_USER_NAME: g_value_set_string (value, self->priv->user_name); break; - case PROP_DISABLE_TCP: - g_value_set_boolean (value, self->priv->disable_tcp); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -896,10 +914,10 @@ gdm_server_class_init (GdmServerClass *klass) G_TYPE_INT); g_object_class_install_property (object_class, - PROP_DISPLAY_NAME, - g_param_spec_string ("display-name", - "name", - "name", + PROP_DISPLAY_ID, + g_param_spec_string ("display-id", + "display id", + "display id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, @@ -924,13 +942,6 @@ gdm_server_class_init (GdmServerClass *klass) "user name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_DISABLE_TCP, - g_param_spec_boolean ("disable-tcp", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } @@ -941,7 +952,7 @@ gdm_server_init (GdmServer *server) server->priv = GDM_SERVER_GET_PRIVATE (server); server->priv->pid = -1; - server->priv->command = g_strdup (X_SERVER " -br -verbose -logverbose 7"); + server->priv->command = NULL; server->priv->log_dir = g_strdup (LOGDIR); add_ready_handler (server); @@ -978,15 +989,123 @@ gdm_server_finalize (GObject *object) } GdmServer * -gdm_server_new (const char *display_name, - const char *auth_file) +gdm_server_new (const char *display_id) { - GObject *object; + GObject *object; + GdmServer *server; + DBusGConnection *connection; + DBusGProxy *proxy; + GError *error; + gboolean res; + char *id; + + g_debug ("GdmServer: New Server"); object = g_object_new (GDM_TYPE_SERVER, - "display-name", display_name, - "auth-file", auth_file, + "display-id", display_id, NULL); - return GDM_SERVER (object); + server = GDM_SERVER (object); + + server->priv->pid = -1; + + g_assert (server->priv->display_id != NULL); + + error = NULL; + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (connection == NULL) { + if (error != NULL) { + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); + } + + exit (1); + } + + g_debug ("GdmServer: Creating proxy for %s", server->priv->display_id); + error = NULL; + proxy = dbus_g_proxy_new_for_name_owner (connection, + GDM_DBUS_NAME, + server->priv->display_id, + GDM_DBUS_DISPLAY_INTERFACE, + &error); + if (proxy == NULL) { + if (error != NULL) { + g_warning ("Failed to create display proxy %s: %s", server->priv->display_id, error->message); + g_error_free (error); + } else { + g_warning ("Unable to create display proxy"); + } + + exit (1); + } + + /* cache some values up front */ + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetX11DisplayName", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &server->priv->display_name, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + exit (1); + } + + /* If display_name is not set, quit */ + if (! server->priv->display_name || (strlen (server->priv->display_name) == 0)) { + g_warning ("Wrong value of method GetX11DisplayName for %s",server->priv->display_id); + exit (1); + } + + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetX11Command", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &server->priv->command, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + exit (1); + } + + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetX11AuthorityFile", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &server->priv->auth_file, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + exit (1); + } + + /* If auth_file is not set, set it NULL */ + if (server->priv->auth_file && (strlen (server->priv->auth_file) == 0)) { + g_free (server->priv->auth_file); + server->priv->auth_file = NULL; + } + + return server; } diff --git a/daemon/gdm-server.h b/daemon/gdm-server.h index 535a69a4..84feb1f1 100644 --- a/daemon/gdm-server.h +++ b/daemon/gdm-server.h @@ -53,8 +53,7 @@ typedef struct } GdmServerClass; GType gdm_server_get_type (void); -GdmServer * gdm_server_new (const char *display_id, - const char *auth_file); +GdmServer * gdm_server_new (const char *display_id); gboolean gdm_server_start (GdmServer *server); gboolean gdm_server_stop (GdmServer *server); char * gdm_server_get_display_device (GdmServer *server); diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c index e9774869..49705291 100644 --- a/daemon/gdm-session-direct.c +++ b/daemon/gdm-session-direct.c @@ -59,6 +59,8 @@ #include "gdm-session-worker-job.h" #include "gdm-common.h" +#define GDM_DBUS_NAME "org.gnome.DisplayManager" +#define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display" #define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" #define GDM_SESSION_DBUS_INTERFACE "org.gnome.DisplayManager.Session" #define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel" @@ -101,6 +103,9 @@ struct _GdmSessionDirectPrivate char *display_hostname; char *display_device; char *display_x11_authority_file; + char *display_console_session; + char *display_type; + char *display_seat_id; gboolean display_is_local; char *fallback_session_name; @@ -108,6 +113,7 @@ struct _GdmSessionDirectPrivate DBusServer *server; char *server_address; GHashTable *environment; + DBusGProxy *display_proxy; DBusGConnection *connection; }; @@ -119,7 +125,10 @@ enum { PROP_DISPLAY_IS_LOCAL, PROP_DISPLAY_DEVICE, PROP_DISPLAY_X11_AUTHORITY_FILE, + PROP_DISPLAY_CONSOLE_SESSION, PROP_USER_X11_AUTHORITY_FILE, + PROP_DISPLAY_TYPE, + PROP_DISPLAY_SEAT_ID, }; static void gdm_session_iface_init (GdmSessionIface *iface); @@ -826,6 +835,34 @@ gdm_session_direct_handle_username_changed (GdmSessionDirect *session, return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult +gdm_session_direct_handle_display_console_session_updated (GdmSessionDirect *session, + GdmSessionConversation *conversation, + DBusMessage *message) +{ + DBusMessage *reply; + DBusError error; + const char *text; + + dbus_error_init (&error); + if (! dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID)) { + g_warning ("ERROR: %s", error.message); + } + + reply = dbus_message_new_method_return (message); + dbus_connection_send (conversation->worker_connection, reply, NULL); + dbus_message_unref (reply); + + g_debug ("GdmSessionDirect: changing ck session id to '%s'", + text); + + + + return DBUS_HANDLER_RESULT_HANDLED; +} + static void cancel_pending_query (GdmSessionConversation *conversation) { @@ -1279,6 +1316,8 @@ session_worker_message (DBusConnection *connection, return gdm_session_direct_handle_accreditation_failed (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) { return gdm_session_direct_handle_username_changed (session, conversation, message); + } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "DisplayConsoleSessionUpdated")) { + return gdm_session_direct_handle_display_console_session_updated (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionOpened")) { return gdm_session_direct_handle_session_opened (session, conversation, message); } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "OpenFailed")) { @@ -1385,6 +1424,8 @@ do_introspect (DBusConnection *connection, " <signal name=\"Setup\">\n" " <arg name=\"service_name\" type=\"s\"/>\n" " <arg name=\"x11_display_name\" type=\"s\"/>\n" + " <arg name=\"x11_display_type\" type=\"s\"/>\n" + " <arg name=\"x11_display_seat_id\" type=\"s\"/>\n" " <arg name=\"display_device\" type=\"s\"/>\n" " <arg name=\"hostname\" type=\"s\"/>\n" " <arg name=\"x11_authority_file\" type=\"s\"/>\n" @@ -1392,6 +1433,8 @@ do_introspect (DBusConnection *connection, " <signal name=\"SetupForUser\">\n" " <arg name=\"service_name\" type=\"s\"/>\n" " <arg name=\"x11_display_name\" type=\"s\"/>\n" + " <arg name=\"x11_display_type\" type=\"s\"/>\n" + " <arg name=\"x11_seat_id\" type=\"s\"/>\n" " <arg name=\"display_device\" type=\"s\"/>\n" " <arg name=\"hostname\" type=\"s\"/>\n" " <arg name=\"x11_authority_file\" type=\"s\"/>\n" @@ -1922,6 +1965,8 @@ send_setup (GdmSessionDirect *session, DBusMessage *message; DBusMessageIter iter; const char *display_name; + const char *display_type; + const char *display_seat_id; const char *display_device; const char *display_hostname; const char *display_x11_authority_file; @@ -1934,6 +1979,16 @@ send_setup (GdmSessionDirect *session, } else { display_name = ""; } + if (session->priv->display_type != NULL) { + display_type = session->priv->display_type; + } else { + display_type = ""; + } + if (session->priv->display_seat_id!= NULL) { + display_seat_id = session->priv->display_seat_id; + } else { + display_seat_id = ""; + } if (session->priv->display_hostname != NULL) { display_hostname = session->priv->display_hostname; } else { @@ -1959,6 +2014,8 @@ send_setup (GdmSessionDirect *session, dbus_message_iter_init_append (message, &iter); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_type); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); @@ -1978,6 +2035,8 @@ send_setup_for_user (GdmSessionDirect *session, DBusMessage *message; DBusMessageIter iter; const char *display_name; + const char *display_type; + const char *display_seat_id; const char *display_device; const char *display_hostname; const char *display_x11_authority_file; @@ -1991,6 +2050,16 @@ send_setup_for_user (GdmSessionDirect *session, } else { display_name = ""; } + if (session->priv->display_type != NULL) { + display_type = session->priv->display_type; + } else { + display_type = ""; + } + if (session->priv->display_seat_id != NULL) { + display_seat_id = session->priv->display_seat_id; + } else { + display_seat_id = ""; + } if (session->priv->display_hostname != NULL) { display_hostname = session->priv->display_hostname; } else { @@ -2021,6 +2090,8 @@ send_setup_for_user (GdmSessionDirect *session, dbus_message_iter_init_append (message, &iter); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_type); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file); @@ -2600,6 +2671,30 @@ _gdm_session_direct_set_display_x11_authority_file (GdmSessionDirect *session, } static void +_gdm_session_direct_set_display_type (GdmSessionDirect *session, + const char *type) +{ + g_free (session->priv->display_type); + session->priv->display_type = g_strdup (type); +} + +static void +_gdm_session_direct_set_display_seat_id (GdmSessionDirect *session, + const char *sid) +{ + g_free (session->priv->display_seat_id); + session->priv->display_seat_id = g_strdup (sid); +} + +static void +_gdm_session_direct_set_display_console_session (GdmSessionDirect *session, + const char *console_session) +{ + g_free (session->priv->display_console_session); + session->priv->display_console_session = g_strdup (console_session); +} + +static void _gdm_session_direct_set_display_is_local (GdmSessionDirect *session, gboolean is) { @@ -2635,9 +2730,18 @@ gdm_session_direct_set_property (GObject *object, case PROP_DISPLAY_X11_AUTHORITY_FILE: _gdm_session_direct_set_display_x11_authority_file (self, g_value_get_string (value)); break; + case PROP_DISPLAY_CONSOLE_SESSION: + _gdm_session_direct_set_display_console_session (self, g_value_get_string (value)); + break; case PROP_DISPLAY_IS_LOCAL: _gdm_session_direct_set_display_is_local (self, g_value_get_boolean (value)); break; + case PROP_DISPLAY_TYPE: + _gdm_session_direct_set_display_type (self, g_value_get_string (value)); + break; + case PROP_DISPLAY_SEAT_ID: + _gdm_session_direct_set_display_seat_id (self, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2673,9 +2777,18 @@ gdm_session_direct_get_property (GObject *object, case PROP_DISPLAY_X11_AUTHORITY_FILE: g_value_set_string (value, self->priv->display_x11_authority_file); break; + case PROP_DISPLAY_CONSOLE_SESSION: + g_value_set_string (value, self->priv->display_console_session); + break; case PROP_DISPLAY_IS_LOCAL: g_value_set_boolean (value, self->priv->display_is_local); break; + case PROP_DISPLAY_TYPE: + g_value_set_string (value, self->priv->display_type); + break; + case PROP_DISPLAY_SEAT_ID: + g_value_set_string (value, self->priv->display_seat_id); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2711,6 +2824,12 @@ gdm_session_direct_dispose (GObject *object) g_free (session->priv->server_address); session->priv->server_address = NULL; + g_free (session->priv->display_type); + session->priv->display_type = NULL; + + g_free (session->priv->display_seat_id); + session->priv->display_seat_id = NULL; + if (session->priv->server != NULL) { dbus_server_disconnect (session->priv->server); dbus_server_unref (session->priv->server); @@ -2722,6 +2841,11 @@ gdm_session_direct_dispose (GObject *object) session->priv->environment = NULL; } + if (session->priv->display_proxy != NULL) { + g_object_unref (session->priv->display_proxy); + } + + G_OBJECT_CLASS (gdm_session_direct_parent_class)->dispose (object); } @@ -2872,6 +2996,14 @@ gdm_session_direct_class_init (GdmSessionDirectClass *session_class) "display x11 authority file", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_DISPLAY_CONSOLE_SESSION, + g_param_spec_string ("display-console-session", + "Display ConsoleKit session", + "The ConsoleKit Session Id for the display", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /* not construct only */ g_object_class_install_property (object_class, PROP_USER_X11_AUTHORITY_FILE, @@ -2887,11 +3019,140 @@ gdm_session_direct_class_init (GdmSessionDirectClass *session_class) "display device", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + PROP_DISPLAY_TYPE, + g_param_spec_string ("display-type", + "display type", + "display type", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + PROP_DISPLAY_SEAT_ID, + g_param_spec_string ("seat-id", + "seat id", + "seat id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); dbus_g_object_type_install_info (GDM_TYPE_SESSION_DIRECT, &dbus_glib_gdm_session_direct_object_info); } +static void +display_proxy_destroyed_cb (DBusGProxy *display_proxy, + GdmSessionDirect *session) +{ + g_debug ("GdmSessionDirect: Disconnected from display"); + + session->priv->display_proxy = NULL; +} + +static gboolean +init_display_data (GdmSessionDirect *session) +{ + gboolean res; + char *id; + GError *error; + + g_assert (session->priv->display_proxy == NULL); + + error = NULL; + session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (session->priv->connection == NULL) { + if (error != NULL) { + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); + } + exit (1); + } + + error = NULL; + session->priv->display_proxy = dbus_g_proxy_new_for_name_owner ( + session->priv->connection, + GDM_DBUS_NAME, + session->priv->display_id, + GDM_DBUS_DISPLAY_INTERFACE, + &error); + + g_signal_connect (session->priv->display_proxy, + "destroy", + G_CALLBACK (display_proxy_destroyed_cb), + session); + + if (session->priv->display_proxy == NULL) { + if (error != NULL) { + g_warning ("Failed to create display proxy %s: %s", session->priv->display_id, error->message); + g_error_free (error); + } else { + g_warning ("Unable to create display proxy"); + } + return FALSE; + } + + /* Make sure display ID works */ + error = NULL; + res = dbus_g_proxy_call (session->priv->display_proxy, + "GetId", + &error, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &id, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get display id %s: %s", session->priv->display_id, error->message); + g_error_free (error); + } else { + g_warning ("Failed to get display id %s", session->priv->display_id); + } + + return FALSE; + } + + if (strcmp (id, session->priv->display_id) != 0) { + g_critical ("Display ID doesn't match"); + exit (1); + } + + error = NULL; + res = dbus_g_proxy_call (session->priv->display_proxy, + "GetX11DisplayType", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &session->priv->display_type, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + return FALSE; + } + + error = NULL; + res = dbus_g_proxy_call (session->priv->display_proxy, + "GetSeatId", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &session->priv->display_seat_id, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + return FALSE; + } + + return TRUE; +} + + GdmSessionDirect * gdm_session_direct_new (const char *display_id, const char *display_name, @@ -2911,6 +3172,8 @@ gdm_session_direct_new (const char *display_id, "display-is-local", display_is_local, NULL); + init_display_data (session); + return session; } diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index ea12da34..ca0773e6 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -115,6 +115,8 @@ struct GdmSessionWorkerPrivate /* from Setup */ char *service; char *x11_display_name; + char *x11_display_type; + char *seat_id; char *x11_authority_file; char *display_device; char *hostname; @@ -174,6 +176,8 @@ open_ck_session (GdmSessionWorker *worker) int res; DBusError error; const char *display_name; + const char *display_type; + const char *seat_id; const char *display_device; const char *display_hostname; gboolean is_local; @@ -185,6 +189,16 @@ open_ck_session (GdmSessionWorker *worker) } else { display_name = ""; } + if (worker->priv->x11_display_type != NULL) { + display_type = worker->priv->x11_display_type; + } else { + display_type = ""; + } + if (worker->priv->seat_id != NULL) { + seat_id = worker->priv->seat_id; + } else { + seat_id = ""; + } if (worker->priv->hostname != NULL) { display_hostname = worker->priv->hostname; } else { @@ -221,6 +235,8 @@ open_ck_session (GdmSessionWorker *worker) dbus_error_init (&error); res = ck_connector_open_session_with_parameters (worker->priv->ckc, &error, + "display-type", &display_type, + "seat-id", &seat_id, "unix-user", &pwent->pw_uid, "x11-display", &display_name, "x11-display-device", &display_device, @@ -1553,6 +1569,7 @@ static void register_ck_session (GdmSessionWorker *worker) { const char *session_cookie; + const char *session_id; gboolean res; session_cookie = NULL; @@ -1565,6 +1582,11 @@ register_ck_session (GdmSessionWorker *worker) "XDG_SESSION_COOKIE", session_cookie); } + session_id = ck_connector_get_session_id (worker->priv->ckc); + + send_dbus_string_method (worker->priv->connection, + "DisplayConsoleSessionUpdated", + session_id); } static void @@ -1584,19 +1606,26 @@ session_worker_child_watch (GPid pid, if (WIFEXITED (status)) { int code = WEXITSTATUS (status); + ck_connector_set_remove_on_close (worker->priv->ckc, + TRUE, + NULL); + send_dbus_int_method (worker->priv->connection, "SessionExited", code); } else if (WIFSIGNALED (status)) { int num = WTERMSIG (status); + ck_connector_set_remove_on_close (worker->priv->ckc, + TRUE, + NULL); + send_dbus_int_method (worker->priv->connection, "SessionDied", num); } if (worker->priv->ckc != NULL) { - ck_connector_close_session (worker->priv->ckc, NULL); ck_connector_unref (worker->priv->ckc); worker->priv->ckc = NULL; } @@ -2352,6 +2381,8 @@ on_setup (GdmSessionWorker *worker, DBusError error; const char *service; const char *x11_display_name; + const char *x11_display_type; + const char *seat_id; const char *x11_authority_file; const char *console; const char *hostname; @@ -2367,6 +2398,8 @@ on_setup (GdmSessionWorker *worker, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &x11_display_name, + DBUS_TYPE_STRING, &x11_display_type, + DBUS_TYPE_STRING, &seat_id, DBUS_TYPE_STRING, &console, DBUS_TYPE_STRING, &hostname, DBUS_TYPE_STRING, &x11_authority_file, @@ -2374,6 +2407,8 @@ on_setup (GdmSessionWorker *worker, if (res) { worker->priv->service = g_strdup (service); worker->priv->x11_display_name = g_strdup (x11_display_name); + worker->priv->x11_display_type = g_strdup (x11_display_type); + worker->priv->seat_id = g_strdup (seat_id); worker->priv->x11_authority_file = g_strdup (x11_authority_file); worker->priv->display_device = g_strdup (console); worker->priv->hostname = g_strdup (hostname); @@ -2394,6 +2429,8 @@ on_setup_for_user (GdmSessionWorker *worker, DBusError error; const char *service; const char *x11_display_name; + const char *x11_display_type; + const char *seat_id; const char *x11_authority_file; const char *console; const char *hostname; @@ -2410,6 +2447,8 @@ on_setup_for_user (GdmSessionWorker *worker, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &x11_display_name, + DBUS_TYPE_STRING, &x11_display_type, + DBUS_TYPE_STRING, &seat_id, DBUS_TYPE_STRING, &console, DBUS_TYPE_STRING, &hostname, DBUS_TYPE_STRING, &x11_authority_file, @@ -2418,6 +2457,8 @@ on_setup_for_user (GdmSessionWorker *worker, if (res) { worker->priv->service = g_strdup (service); worker->priv->x11_display_name = g_strdup (x11_display_name); + worker->priv->x11_display_type = g_strdup (x11_display_type); + worker->priv->seat_id = g_strdup (seat_id); worker->priv->x11_authority_file = g_strdup (x11_authority_file); worker->priv->display_device = g_strdup (console); worker->priv->hostname = g_strdup (hostname); @@ -2615,6 +2656,10 @@ worker_dbus_filter_function (DBusConnection *connection, g_debug ("GdmSessionWorker: Got disconnected from the server"); + ck_connector_set_remove_on_close (worker->priv->ckc, + TRUE, + NULL); + dbus_connection_unref (connection); worker->priv->connection = NULL; diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 7b9d7d8b..925378a4 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -472,6 +472,10 @@ start_session_timeout (GdmSimpleSlave *slave) goto out; } + /* Defer requests to use this display from ConsoleKit + * for the time being + */ + gdm_slave_block_console_session_requests_on_display (GDM_SLAVE (slave)); stop_greeter (slave); auth_file = NULL; @@ -487,6 +491,7 @@ start_session_timeout (GdmSimpleSlave *slave) gdm_session_start_session (GDM_SESSION (slave->priv->session), slave->priv->start_session_service_name); + gdm_slave_unblock_console_session_requests_on_display (GDM_SLAVE (slave)); out: slave->priv->start_session_id = 0; g_free (slave->priv->start_session_service_name); @@ -729,6 +734,16 @@ start_autologin_conversation_if_necessary (GdmSimpleSlave *slave) } static void +on_console_session_changed (GdmSession *session, + const char *text, + GdmSimpleSlave *slave) +{ + g_debug ("GdmSimpleSlave: Default session name changed: %s", text); + + gdm_slave_set_console_session_id (GDM_SLAVE (slave), text); +} + +static void create_new_session (GdmSimpleSlave *slave) { gboolean display_is_local; @@ -763,6 +778,7 @@ create_new_session (GdmSimpleSlave *slave) g_free (display_name); g_free (display_device); g_free (display_hostname); + g_free (display_x11_authority_file); g_signal_connect (slave->priv->session, "conversation-started", @@ -873,6 +889,11 @@ create_new_session (GdmSimpleSlave *slave) G_CALLBACK (on_default_session_name_changed), slave); + g_signal_connect (slave->priv->session, + "notify::display-console-session", + G_CALLBACK (on_console_session_changed), + slave); + start_autologin_conversation_if_necessary (slave); } @@ -992,7 +1013,7 @@ on_greeter_session_exited (GdmGreeterSession *greeter, GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: Greeter exited: %d", code); - gdm_slave_stopped (GDM_SLAVE (slave)); + gdm_slave_failed (GDM_SLAVE (slave)); } static void @@ -1192,6 +1213,7 @@ start_greeter (GdmSimpleSlave *slave) char *display_id; char *display_name; char *seat_id; + char *session_id; char *display_device; char *display_hostname; char *auth_file; @@ -1204,6 +1226,7 @@ start_greeter (GdmSimpleSlave *slave) display_id = NULL; display_name = NULL; seat_id = NULL; + session_id = NULL; auth_file = NULL; display_device = NULL; display_hostname = NULL; @@ -1213,6 +1236,7 @@ start_greeter (GdmSimpleSlave *slave) "display-is-local", &display_is_local, "display-name", &display_name, "display-seat-id", &seat_id, + "display-session-id", &session_id, "display-hostname", &display_hostname, "display-x11-authority-file", &auth_file, NULL); @@ -1297,6 +1321,7 @@ start_greeter (GdmSimpleSlave *slave) g_debug ("GdmSimpleSlave: Creating greeter on %s %s %s", display_name, display_device, display_hostname); slave->priv->greeter = gdm_greeter_session_new (display_name, seat_id, + session_id, display_device, display_hostname, display_is_local); @@ -1385,7 +1410,11 @@ on_server_exited (GdmServer *server, { g_debug ("GdmSimpleSlave: server exited with code %d\n", exit_code); - gdm_slave_stopped (GDM_SLAVE (slave)); + if (exit_code != 0) { + gdm_slave_failed (GDM_SLAVE (slave)); + } else { + gdm_slave_stopped (GDM_SLAVE (slave)); + } } static void @@ -1403,31 +1432,20 @@ on_server_died (GdmServer *server, static gboolean gdm_simple_slave_run (GdmSimpleSlave *slave) { - char *display_name; - char *auth_file; + char *display_id; gboolean display_is_local; g_object_get (slave, + "display-id", &display_id, "display-is-local", &display_is_local, - "display-name", &display_name, - "display-x11-authority-file", &auth_file, NULL); /* if this is local display start a server if one doesn't * exist */ if (display_is_local) { gboolean res; - gboolean disable_tcp; - - slave->priv->server = gdm_server_new (display_name, auth_file); - disable_tcp = TRUE; - if (gdm_settings_client_get_boolean (GDM_KEY_DISALLOW_TCP, - &disable_tcp)) { - g_object_set (slave->priv->server, - "disable-tcp", disable_tcp, - NULL); - } + slave->priv->server = gdm_server_new (display_id); g_signal_connect (slave->priv->server, "exited", @@ -1460,8 +1478,7 @@ gdm_simple_slave_run (GdmSimpleSlave *slave) g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave); } - g_free (display_name); - g_free (auth_file); + g_free (display_id); return TRUE; } diff --git a/daemon/gdm-slave-proxy.c b/daemon/gdm-slave-proxy.c index 48efbd14..a0c72392 100644 --- a/daemon/gdm-slave-proxy.c +++ b/daemon/gdm-slave-proxy.c @@ -245,6 +245,7 @@ kill_slave (GdmSlaveProxy *slave) g_warning ("Unable to kill slave process"); } else { exit_status = gdm_wait_on_pid (slave->priv->pid); + g_debug ("GdmSlaveProxy: Slave exit status %d", exit_status); g_spawn_close_pid (slave->priv->pid); slave->priv->pid = 0; } diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index 2dc0323f..695f6cf6 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -83,11 +83,13 @@ struct GdmSlavePrivate /* cached display values */ char *display_id; char *display_name; + char *display_type; int display_number; char *display_hostname; gboolean display_is_local; gboolean display_is_parented; char *display_seat_id; + char *display_session_id; char *display_x11_authority_file; char *parent_display_name; char *parent_display_x11_authority_file; @@ -103,15 +105,18 @@ enum { PROP_0, PROP_DISPLAY_ID, PROP_DISPLAY_NAME, + PROP_DISPLAY_TYPE, PROP_DISPLAY_NUMBER, PROP_DISPLAY_HOSTNAME, PROP_DISPLAY_IS_LOCAL, PROP_DISPLAY_SEAT_ID, + PROP_DISPLAY_SESSION_ID, PROP_DISPLAY_X11_AUTHORITY_FILE }; enum { STOPPED, + FAILED, LAST_SIGNAL }; @@ -749,6 +754,24 @@ gdm_slave_real_start (GdmSlave *slave) error = NULL; res = dbus_g_proxy_call (slave->priv->display_proxy, + "GetX11DisplayType", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &slave->priv->display_type, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + return FALSE; + } + + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, "GetX11DisplayNumber", &error, G_TYPE_INVALID, @@ -838,6 +861,24 @@ gdm_slave_real_start (GdmSlave *slave) return FALSE; } + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "GetSessionId", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &slave->priv->display_session_id, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get value"); + } + + return FALSE; + } + return TRUE; } @@ -893,6 +934,42 @@ gdm_slave_stopped (GdmSlave *slave) g_signal_emit (slave, signals [STOPPED], 0); } +void +gdm_slave_failed (GdmSlave *slave) +{ + g_return_if_fail (GDM_IS_SLAVE (slave)); + + g_signal_emit (slave, signals [FAILED], 0); +} + +void +gdm_slave_set_console_session_id (GdmSlave *slave, + const char *session_id) +{ + gboolean res; + GError *error; + + g_debug ("GdmSlave: Informing display of new session id"); + + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "SetConsoleSessionId", + &error, + G_TYPE_STRING, session_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (! res) { + if (error != NULL) { + g_warning ("Failed to set console session id: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to set console session id"); + } + } else { + g_debug ("GdmSlave: Set console session id"); + } +} + gboolean gdm_slave_add_user_authorization (GdmSlave *slave, const char *username, @@ -1476,6 +1553,59 @@ gdm_slave_switch_to_user_session (GdmSlave *slave, return ret; } +void +gdm_slave_block_console_session_requests_on_display (GdmSlave *slave) +{ + gboolean res; + GError *error; + + g_debug ("GdmSlave: Asking display to ignore ConsoleKit"); + + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "BlockConsoleSessionRequests", + &error, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (! res) { + if (error != NULL) { + g_warning ("Failed to get display to ignore ConsoleKit: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get display to ignore ConsoleKit"); + } + } else { + g_debug ("GdmSlave: Display is now ignoring ConsoleKit"); + } +} + +void +gdm_slave_unblock_console_session_requests_on_display (GdmSlave *slave) +{ + gboolean res; + GError *error; + + g_debug ("GdmSlave: Informing display to stop ignoring ConsoleKit"); + + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "UnblockConsoleSessionRequests", + &error, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (! res) { + if (error != NULL) { + g_warning ("Failed to get display to stop ignoring ConsoleKit: %s", error->message); + g_error_free (error); + } else { + g_warning ("Failed to get display to stop ignoring ConsoleKit"); + } + } else { + g_debug ("GdmSlave: Display is no longer ignoring ConsoleKit"); + } +} + + static void _gdm_slave_set_display_id (GdmSlave *slave, const char *id) @@ -1492,6 +1622,15 @@ _gdm_slave_set_display_name (GdmSlave *slave, slave->priv->display_name = g_strdup (name); } + +static void +_gdm_slave_set_display_type (GdmSlave *slave, + const char *type) +{ + g_free (slave->priv->display_type); + slave->priv->display_type = g_strdup (type); +} + static void _gdm_slave_set_display_number (GdmSlave *slave, int number) @@ -1524,6 +1663,14 @@ _gdm_slave_set_display_seat_id (GdmSlave *slave, } static void +_gdm_slave_set_display_session_id (GdmSlave *slave, + const char *id) +{ + g_free (slave->priv->display_session_id); + slave->priv->display_session_id = g_strdup (id); +} + +static void _gdm_slave_set_display_is_local (GdmSlave *slave, gboolean is) { @@ -1547,6 +1694,9 @@ gdm_slave_set_property (GObject *object, case PROP_DISPLAY_NAME: _gdm_slave_set_display_name (self, g_value_get_string (value)); break; + case PROP_DISPLAY_TYPE: + _gdm_slave_set_display_type (self, g_value_get_string (value)); + break; case PROP_DISPLAY_NUMBER: _gdm_slave_set_display_number (self, g_value_get_int (value)); break; @@ -1556,6 +1706,9 @@ gdm_slave_set_property (GObject *object, case PROP_DISPLAY_SEAT_ID: _gdm_slave_set_display_seat_id (self, g_value_get_string (value)); break; + case PROP_DISPLAY_SESSION_ID: + _gdm_slave_set_display_session_id (self, g_value_get_string (value)); + break; case PROP_DISPLAY_X11_AUTHORITY_FILE: _gdm_slave_set_display_x11_authority_file (self, g_value_get_string (value)); break; @@ -1585,6 +1738,9 @@ gdm_slave_get_property (GObject *object, case PROP_DISPLAY_NAME: g_value_set_string (value, self->priv->display_name); break; + case PROP_DISPLAY_TYPE: + g_value_set_string (value, self->priv->display_type); + break; case PROP_DISPLAY_NUMBER: g_value_set_int (value, self->priv->display_number); break; @@ -1594,6 +1750,9 @@ gdm_slave_get_property (GObject *object, case PROP_DISPLAY_SEAT_ID: g_value_set_string (value, self->priv->display_seat_id); break; + case PROP_DISPLAY_SESSION_ID: + g_value_set_string (value, self->priv->display_session_id); + break; case PROP_DISPLAY_X11_AUTHORITY_FILE: g_value_set_string (value, self->priv->display_x11_authority_file); break; @@ -1688,6 +1847,13 @@ gdm_slave_class_init (GdmSlaveClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, + PROP_DISPLAY_TYPE, + g_param_spec_string ("display-type", + "display type", + "display type", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_DISPLAY_NUMBER, g_param_spec_int ("display-number", "display number", @@ -1711,6 +1877,13 @@ gdm_slave_class_init (GdmSlaveClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, + PROP_DISPLAY_SESSION_ID, + g_param_spec_string ("display-session-id", + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_DISPLAY_X11_AUTHORITY_FILE, g_param_spec_string ("display-x11-authority-file", "", @@ -1736,6 +1909,17 @@ gdm_slave_class_init (GdmSlaveClass *klass) G_TYPE_NONE, 0); + signals [FAILED] = + g_signal_new ("failed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmSlaveClass, failed), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + dbus_g_object_type_install_info (GDM_TYPE_SLAVE, &dbus_glib_gdm_slave_object_info); } @@ -1765,6 +1949,7 @@ gdm_slave_finalize (GObject *object) g_free (slave->priv->id); g_free (slave->priv->display_id); g_free (slave->priv->display_name); + g_free (slave->priv->display_type); g_free (slave->priv->display_hostname); g_free (slave->priv->display_seat_id); g_free (slave->priv->display_x11_authority_file); diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h index eda2e193..ef40a0c1 100644 --- a/daemon/gdm-slave.h +++ b/daemon/gdm-slave.h @@ -51,6 +51,7 @@ typedef struct /* signals */ void (*stopped) (GdmSlave *slave); + void (*failed) (GdmSlave *slave); } GdmSlaveClass; GType gdm_slave_get_type (void); @@ -72,6 +73,9 @@ gboolean gdm_slave_add_user_authorization (GdmSlave *slave, gboolean gdm_slave_switch_to_user_session (GdmSlave *slave, const char *username); +void gdm_slave_block_console_session_requests_on_display (GdmSlave *slave); +void gdm_slave_unblock_console_session_requests_on_display (GdmSlave *slave); + gboolean gdm_slave_connect_to_x11_display (GdmSlave *slave); void gdm_slave_set_initial_cursor_position (GdmSlave *slave); @@ -81,6 +85,8 @@ gboolean gdm_slave_run_script (GdmSlave *slave, const char *dir, const char *username); void gdm_slave_stopped (GdmSlave *slave); +void gdm_slave_set_console_session_id (GdmSlave *slave, + const char *session_id); G_END_DECLS diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c index 438a95a9..54d81254 100644 --- a/daemon/gdm-welcome-session.c +++ b/daemon/gdm-welcome-session.c @@ -67,6 +67,7 @@ struct GdmWelcomeSessionPrivate char *x11_display_name; char *x11_display_seat_id; + char *x11_display_session_id; char *x11_display_device; char *x11_display_hostname; char *x11_authority_file; @@ -88,6 +89,7 @@ enum { PROP_0, PROP_X11_DISPLAY_NAME, PROP_X11_DISPLAY_SEAT_ID, + PROP_X11_DISPLAY_SESSION_ID, PROP_X11_DISPLAY_DEVICE, PROP_X11_DISPLAY_HOSTNAME, PROP_X11_AUTHORITY_FILE, @@ -137,6 +139,8 @@ open_welcome_session (GdmWelcomeSession *welcome_session) const char *session_type; const char *hostname; const char *x11_display_device; + const char *seat_id; + const char *session_id; int res; gboolean ret; DBusError error; @@ -172,6 +176,18 @@ open_welcome_session (GdmWelcomeSession *welcome_session) x11_display_device = ""; } + if (welcome_session->priv->x11_display_seat_id != NULL) { + seat_id = welcome_session->priv->x11_display_seat_id; + } else { + seat_id = ""; + } + + if (welcome_session->priv->x11_display_session_id != NULL) { + session_id = welcome_session->priv->x11_display_session_id; + } else { + session_id = ""; + } + g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d", pwent->pw_uid, welcome_session->priv->x11_display_name, @@ -185,6 +201,8 @@ open_welcome_session (GdmWelcomeSession *welcome_session) "unix-user", &pwent->pw_uid, "session-type", &session_type, "x11-display", &welcome_session->priv->x11_display_name, + "seat-id", &seat_id, + "session", &session_id, "x11-display-device", &x11_display_device, "remote-host-name", &hostname, "is-local", &welcome_session->priv->x11_display_is_local, @@ -1060,6 +1078,14 @@ _gdm_welcome_session_set_x11_display_seat_id (GdmWelcomeSession *welcome_session } static void +_gdm_welcome_session_set_x11_display_session_id (GdmWelcomeSession *welcome_session, + const char *ssid) +{ + g_free (welcome_session->priv->x11_display_session_id); + welcome_session->priv->x11_display_session_id = g_strdup (ssid); +} + +static void _gdm_welcome_session_set_x11_display_hostname (GdmWelcomeSession *welcome_session, const char *name) { @@ -1082,7 +1108,6 @@ _gdm_welcome_session_set_x11_display_is_local (GdmWelcomeSession *welcome_sessio welcome_session->priv->x11_display_is_local = is_local; } - static void _gdm_welcome_session_set_x11_authority_file (GdmWelcomeSession *welcome_session, const char *file) @@ -1171,6 +1196,9 @@ gdm_welcome_session_set_property (GObject *object, case PROP_X11_DISPLAY_SEAT_ID: _gdm_welcome_session_set_x11_display_seat_id (self, g_value_get_string (value)); break; + case PROP_X11_DISPLAY_SESSION_ID: + _gdm_welcome_session_set_x11_display_session_id (self, g_value_get_string (value)); + break; case PROP_X11_DISPLAY_HOSTNAME: _gdm_welcome_session_set_x11_display_hostname (self, g_value_get_string (value)); break; @@ -1233,6 +1261,9 @@ gdm_welcome_session_get_property (GObject *object, case PROP_X11_DISPLAY_SEAT_ID: g_value_set_string (value, self->priv->x11_display_seat_id); break; + case PROP_X11_DISPLAY_SESSION_ID: + g_value_set_string (value, self->priv->x11_display_session_id); + break; case PROP_X11_DISPLAY_HOSTNAME: g_value_set_string (value, self->priv->x11_display_hostname); break; @@ -1318,6 +1349,29 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass) "seat id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_X11_DISPLAY_SESSION_ID, + g_param_spec_string ("x11-display-session-id", + "session id", + "session id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_X11_DISPLAY_SEAT_ID, + g_param_spec_string ("x11-display-seat-id", + "seat id", + "seat id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_X11_DISPLAY_SESSION_ID, + g_param_spec_string ("x11-display-session-id", + "session id", + "session id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_X11_DISPLAY_HOSTNAME, g_param_spec_string ("x11-display-hostname", @@ -1488,6 +1542,7 @@ gdm_welcome_session_finalize (GObject *object) g_free (welcome_session->priv->runtime_dir); g_free (welcome_session->priv->x11_display_name); g_free (welcome_session->priv->x11_display_seat_id); + g_free (welcome_session->priv->x11_display_session_id); g_free (welcome_session->priv->x11_display_device); g_free (welcome_session->priv->x11_display_hostname); g_free (welcome_session->priv->x11_authority_file); diff --git a/daemon/gdm-xdmcp-chooser-display.c b/daemon/gdm-xdmcp-chooser-display.c index 85bd3b71..f7b5a0be 100644 --- a/daemon/gdm-xdmcp-chooser-display.c +++ b/daemon/gdm-xdmcp-chooser-display.c @@ -224,7 +224,7 @@ gdm_xdmcp_chooser_display_new (const char *hostname, "remote-hostname", hostname, "x11-display-number", number, "x11-display-name", x11_display, - "is-local", FALSE, + "is-local", TRUE, "remote-address", address, "session-number", session_number, NULL); diff --git a/daemon/main.c b/daemon/main.c index 5b8d66b2..26e14f55 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -215,7 +215,19 @@ bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, g_object_unref (*managerp); *managerp = NULL; +#if __sun + /* + * This function is only called when the D-Bus Service exits. Calling + * this timeout function causes all GDM sessions to exit anyway. The + * timeout function just cauess GDM to act like it is starting again. + * Since SMF already takes care of restarting GDM on Solaris, and since + * using the timeout confuses SMF, just exit and let SMF take care of + * this. + */ + exit (-1); +#else g_timeout_add_seconds (3, (GSourceFunc)bus_reconnect, managerp); +#endif } static void diff --git a/daemon/simple-slave-main.c b/daemon/simple-slave-main.c index 7751b61f..0bf2352d 100644 --- a/daemon/simple-slave-main.c +++ b/daemon/simple-slave-main.c @@ -154,6 +154,15 @@ on_slave_stopped (GdmSlave *slave, g_main_loop_quit (main_loop); } +static void +on_slave_failed (GdmSlave *slave, + GMainLoop *main_loop) +{ + g_debug ("slave failed"); + gdm_return_code = 1; + g_main_loop_quit (main_loop); +} + static gboolean is_debug_set (void) { @@ -256,6 +265,10 @@ main (int argc, "stopped", G_CALLBACK (on_slave_stopped), main_loop); + g_signal_connect (slave, + "failed", + G_CALLBACK (on_slave_failed), + main_loop); gdm_slave_start (slave); g_main_loop_run (main_loop); diff --git a/data/Init.in b/data/Init.in index ec6fd395..16c9bd83 100644 --- a/data/Init.in +++ b/data/Init.in @@ -3,7 +3,7 @@ # Plus a lot of fun stuff added # -George -PATH="@X_PATH@:$PATH" +PATH="@SCRIPT_PATH@" OLD_IFS=$IFS gdmwhich () { diff --git a/data/Makefile.am b/data/Makefile.am index d5632889..0916560b 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -20,17 +20,6 @@ Xsession: $(srcdir)/Xsession.in -e 's,[@]libexecdir[@],$(libexecdir),g' \ <$(srcdir)/Xsession.in >Xsession -Init: $(srcdir)/Init.in - sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ - <$(srcdir)/Init.in >Init - -PreSession: $(srcdir)/PreSession.in - sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ - <$(srcdir)/PreSession.in >PreSession -PostSession: $(srcdir)/PostSession.in - sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ - <$(srcdir)/PostSession.in >PostSession - gdm.conf-custom: $(srcdir)/gdm.conf-custom.in sed -e 's,[@]GDM_DEFAULTS_CONF[@],$(GDM_DEFAULTS_CONF),g' \ <$(srcdir)/gdm.conf-custom.in >gdm.conf-custom diff --git a/data/PostSession.in b/data/PostSession.in index c52d3c26..54276fdc 100755 --- a/data/PostSession.in +++ b/data/PostSession.in @@ -1,3 +1,4 @@ #!/bin/sh +PATH="@SCRIPT_PATH@" exit 0 diff --git a/data/PreSession.in b/data/PreSession.in index cfabee75..09ad05b8 100755 --- a/data/PreSession.in +++ b/data/PreSession.in @@ -6,4 +6,4 @@ # # Note that output goes into the .xsession-errors file for easy debugging # -PATH="@X_PATH@:$PATH" +PATH="@SCRIPT_PATH@" diff --git a/data/gdm.schemas.in.in b/data/gdm.schemas.in.in index 514117d7..8c551ceb 100644 --- a/data/gdm.schemas.in.in +++ b/data/gdm.schemas.in.in @@ -55,12 +55,6 @@ </schema> <schema> - <key>security/DisallowTCP</key> - <signature>b</signature> - <default>true</default> - </schema> - - <schema> <key>greeter/Include</key> <signature>s</signature> <default></default> diff --git a/docs/C/gdm.xml b/docs/C/gdm.xml index fc8b57b4..ed50a1fb 100644 --- a/docs/C/gdm.xml +++ b/docs/C/gdm.xml @@ -1383,18 +1383,6 @@ TimedLogin=you <variablelist> <title>[security]</title> - <varlistentry> - <term>DisallowTCP</term> - <listitem> - <synopsis>DisallowTCP=true</synopsis> - <para> - If true, then always append <filename>-nolisten tcp</filename> - to the command line when starting attached Xservers, thus - disallowing TCP connection. This is a more secure - configuration if you are not using remote connections. - </para> - </listitem> - </varlistentry> </variablelist> </sect3> |