diff options
author | William Jon McCann <mccann@jhu.edu> | 2008-01-28 21:28:43 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2008-01-28 21:28:43 +0000 |
commit | e8c48d691567be8bbdf00bf3df9f51fc3b2b0f62 (patch) | |
tree | 233aa0cd3b1acd7f2084bc1cb57f49cce5eb73a0 /daemon/gdm-slave.c | |
parent | eb7ba82351d599ba647de440e692dc6f32076817 (diff) | |
download | gdm-e8c48d691567be8bbdf00bf3df9f51fc3b2b0f62.tar.gz |
Initial session migration support. We still need to make the slave die
2008-01-28 William Jon McCann <mccann@jhu.edu>
* daemon/gdm-display.c: (gdm_display_get_seat_id),
(gdm_display_class_init):
* daemon/gdm-display.h:
* daemon/gdm-display.xml:
* daemon/gdm-local-display-factory.c:
(gdm_local_display_factory_create_transient_display),
(gdm_local_display_factory_create_product_display),
(create_display):
* daemon/gdm-simple-slave.c: (on_session_authorized),
(try_migrate_session), (start_session_timeout),
(queue_start_session), (on_session_accredited),
(on_session_accreditation_failed):
* daemon/gdm-slave.c: (gdm_slave_real_start),
(_get_uid_and_gid_for_user), (x11_session_is_on_seat),
(_get_primary_user_session_id), (activate_session_id),
(gdm_slave_switch_to_user_session),
(_gdm_slave_set_display_seat_id), (gdm_slave_set_property),
(gdm_slave_get_property), (gdm_slave_class_init):
* daemon/gdm-slave.h:
Initial session migration support. We still need to
make the slave die after if it is a transient display.
svn path=/trunk/; revision=5639
Diffstat (limited to 'daemon/gdm-slave.c')
-rw-r--r-- | daemon/gdm-slave.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index d6521b8e..b25cbff4 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -53,6 +53,15 @@ #define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate)) +#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 GDM_DBUS_NAME "org.gnome.DisplayManager" #define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display" @@ -74,6 +83,7 @@ struct GdmSlavePrivate char *display_hostname; gboolean display_is_local; gboolean display_is_parented; + char *display_seat_id; char *display_x11_authority_file; char *parent_display_name; char *parent_display_x11_authority_file; @@ -93,6 +103,7 @@ enum { PROP_DISPLAY_NUMBER, PROP_DISPLAY_HOSTNAME, PROP_DISPLAY_IS_LOCAL, + PROP_DISPLAY_SEAT_ID, PROP_DISPLAY_X11_AUTHORITY_FILE }; @@ -555,6 +566,24 @@ gdm_slave_real_start (GdmSlave *slave) return FALSE; } + error = NULL; + res = dbus_g_proxy_call (slave->priv->display_proxy, + "GetSeatId", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &slave->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; } @@ -650,6 +679,317 @@ gdm_slave_add_user_authorization (GdmSlave *slave, return res; } +static gboolean +_get_uid_and_gid_for_user (const char *username, + uid_t *uid, + gid_t *gid) +{ + struct passwd *passwd_entry; + + g_assert (username != NULL); + + errno = 0; + passwd_entry = getpwnam (username); + + if (passwd_entry == NULL) { + return FALSE; + } + + if (uid != NULL) { + *uid = passwd_entry->pw_uid; + } + + if (gid != NULL) { + *gid = passwd_entry->pw_gid; + } + + return TRUE; +} + +static gboolean +x11_session_is_on_seat (GdmSlave *slave, + const char *session_id, + const char *seat_id) +{ + DBusGProxy *proxy; + GError *error; + char *sid; + gboolean res; + gboolean ret; + char *x11_display_device; + char *x11_display; + + ret = FALSE; + + if (seat_id == NULL || seat_id[0] == '\0' || session_id == NULL || session_id[0] == '\0') { + return FALSE; + } + + proxy = dbus_g_proxy_new_for_name (slave->priv->connection, + CK_NAME, + session_id, + CK_SESSION_INTERFACE); + if (proxy == NULL) { + g_warning ("Failed to connect to the ConsoleKit seat object"); + goto out; + } + + sid = NULL; + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetSeatId", + &error, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &sid, + G_TYPE_INVALID); + if (! res) { + g_debug ("Failed to identify the current seat: %s", error->message); + g_error_free (error); + goto out; + } + + if (sid == NULL || sid[0] == '\0' || strcmp (sid, seat_id) != 0) { + g_debug ("GdmSlave: session not on current seat: %s", seat_id); + goto out; + } + + x11_display = NULL; + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetX11Display", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &x11_display, + G_TYPE_INVALID); + if (! res) { + g_error_free (error); + goto out; + } + + /* don't try to switch to our own session */ + if (x11_display == NULL || x11_display[0] == '\0' + || strcmp (slave->priv->display_name, x11_display) == 0) { + g_free (x11_display); + goto out; + } + g_free (x11_display); + + x11_display_device = NULL; + error = NULL; + res = dbus_g_proxy_call (proxy, + "GetX11DisplayDevice", + &error, + G_TYPE_INVALID, + G_TYPE_STRING, &x11_display_device, + G_TYPE_INVALID); + if (! res) { + g_error_free (error); + goto out; + } + + if (x11_display_device == NULL || x11_display_device[0] == '\0') { + g_free (x11_display_device); + goto out; + } + g_free (x11_display_device); + + ret = TRUE; + + out: + if (proxy != NULL) { + g_object_unref (proxy); + } + + return ret; +} + +static char * +_get_primary_user_session_id (GdmSlave *slave, + const char *username) +{ + gboolean res; + gboolean ret; + gboolean can_activate_sessions; + GError *error; + DBusGProxy *manager_proxy; + DBusGProxy *seat_proxy; + GPtrArray *sessions; + char *primary_ssid; + int i; + uid_t uid; + + if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') { + g_debug ("GdmSlave: display seat id is not set; can't switch sessions"); + return FALSE; + } + + ret = FALSE; + manager_proxy = NULL; + primary_ssid = NULL; + sessions = NULL; + + g_debug ("GdmSlave: getting proxy for seat: %s", slave->priv->display_seat_id); + + seat_proxy = dbus_g_proxy_new_for_name (slave->priv->connection, + CK_NAME, + slave->priv->display_seat_id, + CK_SEAT_INTERFACE); + + g_debug ("GdmSlave: checking if seat can activate sessions"); + + error = NULL; + res = dbus_g_proxy_call (seat_proxy, + "CanActivateSessions", + &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &can_activate_sessions, + G_TYPE_INVALID); + if (! res) { + g_warning ("unable to determine if seat can activate sessions: %s", + error->message); + g_error_free (error); + goto out; + } + + if (! can_activate_sessions) { + g_debug ("GdmSlave: seat is unable to activate sessions"); + goto out; + } + + manager_proxy = dbus_g_proxy_new_for_name (slave->priv->connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + + if (! _get_uid_and_gid_for_user (username, &uid, NULL)) { + g_debug ("GdmSlave: unable to determine uid for user: %s", username); + goto out; + } + + error = NULL; + res = dbus_g_proxy_call (manager_proxy, + "GetSessionsForUnixUser", + &error, + G_TYPE_UINT, uid, + G_TYPE_INVALID, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, + G_TYPE_INVALID); + if (! res) { + g_warning ("unable to determine sessions for user: %s", + error->message); + g_error_free (error); + goto out; + } + + for (i = 0; i < sessions->len; i++) { + char *ssid; + + ssid = g_ptr_array_index (sessions, i); + + if (! x11_session_is_on_seat (slave, ssid, slave->priv->display_seat_id)) { + goto next; + } + + /* FIXME: better way to choose? */ + if (primary_ssid == NULL) { + primary_ssid = g_strdup (ssid); + } + + next: + g_free (ssid); + } + g_ptr_array_free (sessions, TRUE); + + out: + + if (seat_proxy != NULL) { + g_object_unref (seat_proxy); + } + if (manager_proxy != NULL) { + g_object_unref (manager_proxy); + } + + return primary_ssid; +} + +static gboolean +activate_session_id (GdmSlave *slave, + const char *seat_id, + const char *session_id) +{ + DBusError local_error; + DBusMessage *message; + DBusMessage *reply; + gboolean ret; + + ret = FALSE; + + dbus_error_init (&local_error); + message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", + seat_id, + "org.freedesktop.ConsoleKit.Seat", + "ActivateSession"); + if (message == NULL) { + goto out; + } + + if (! dbus_message_append_args (message, + DBUS_TYPE_OBJECT_PATH, &session_id, + DBUS_TYPE_INVALID)) { + goto out; + } + + + dbus_error_init (&local_error); + reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection), + message, + -1, + &local_error); + if (reply == NULL) { + if (dbus_error_is_set (&local_error)) { + g_warning ("Unable to activate session: %s", local_error.message); + dbus_error_free (&local_error); + goto out; + } + } + + ret = TRUE; + out: + return ret; +} + +gboolean +gdm_slave_switch_to_user_session (GdmSlave *slave, + const char *username) +{ + gboolean res; + gboolean ret; + char *ssid_to_activate; + + ret = FALSE; + + ssid_to_activate = _get_primary_user_session_id (slave, username); + if (ssid_to_activate == NULL) { + g_debug ("GdmSlave: unable to determine session to activate"); + goto out; + } + + g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate); + + res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate); + if (! res) { + g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate); + goto out; + } + + ret = TRUE; + + out: + g_free (ssid_to_activate); + + return ret; +} + static void _gdm_slave_set_display_id (GdmSlave *slave, const char *id) @@ -690,6 +1030,14 @@ _gdm_slave_set_display_x11_authority_file (GdmSlave *slave, } static void +_gdm_slave_set_display_seat_id (GdmSlave *slave, + const char *id) +{ + g_free (slave->priv->display_seat_id); + slave->priv->display_seat_id = g_strdup (id); +} + +static void _gdm_slave_set_display_is_local (GdmSlave *slave, gboolean is) { @@ -719,6 +1067,9 @@ gdm_slave_set_property (GObject *object, case PROP_DISPLAY_HOSTNAME: _gdm_slave_set_display_hostname (self, g_value_get_string (value)); break; + case PROP_DISPLAY_SEAT_ID: + _gdm_slave_set_display_seat_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; @@ -754,6 +1105,9 @@ gdm_slave_get_property (GObject *object, case PROP_DISPLAY_HOSTNAME: g_value_set_string (value, self->priv->display_hostname); break; + case PROP_DISPLAY_SEAT_ID: + g_value_set_string (value, self->priv->display_seat_id); + break; case PROP_DISPLAY_X11_AUTHORITY_FILE: g_value_set_string (value, self->priv->display_x11_authority_file); break; @@ -864,6 +1218,13 @@ gdm_slave_class_init (GdmSlaveClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, + PROP_DISPLAY_SEAT_ID, + g_param_spec_string ("display-seat-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", "", |