gdm r5698 - in trunk: . utils
- From: mccann svn gnome org
- To: svn-commits-list gnome org
- Subject: gdm r5698 - in trunk: . utils
- Date: Tue, 5 Feb 2008 21:20:19 +0000 (GMT)
Author: mccann
Date: Tue Feb 5 21:20:19 2008
New Revision: 5698
URL: http://svn.gnome.org/viewvc/gdm?rev=5698&view=rev
Log:
2008-02-05 William Jon McCann <jmccann redhat com>
* utils/gdmflexiserver.c: (create_transient_display),
(get_current_session_id), (get_seat_id_for_session),
(get_current_seat_id), (activate_session_id),
(session_is_login_window), (seat_can_activate_sessions),
(get_path_array_from_iter), (seat_get_sessions),
(get_login_window_session_id), (goto_login_session), (main):
Add support for finding and switching to existing greeters.
Modified:
trunk/ChangeLog
trunk/utils/gdmflexiserver.c
Modified: trunk/utils/gdmflexiserver.c
==============================================================================
--- trunk/utils/gdmflexiserver.c (original)
+++ trunk/utils/gdmflexiserver.c Tue Feb 5 21:20:19 2008
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -35,6 +36,15 @@
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH "/org/gnome/DisplayManager/LocalDisplayFactory"
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
+#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"
+
static const char *send_command = NULL;
static gboolean use_xnest = FALSE;
static gboolean no_lock = FALSE;
@@ -127,63 +137,502 @@
}
static gboolean
-create_transient_display (GError **error)
+create_transient_display (DBusConnection *connection)
{
- DBusGProxy *proxy;
- DBusGConnection *connection;
- GError *local_error;
- char *display_id;
- gboolean res;
- gboolean ret;
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ gboolean ret;
+ DBusMessageIter iter;
+ const char *value;
ret = FALSE;
- local_error = NULL;
- connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &local_error);
- if (connection == NULL) {
- if (local_error != NULL) {
- g_critical ("error getting system bus: %s", local_error->message);
- g_error_free (local_error);
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (GDM_DBUS_NAME,
+ GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
+ GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
+ "CreateTransientDisplay");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &local_error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("Unable to create transient display: %s", local_error.message);
+ dbus_error_free (&local_error);
+ goto out;
}
- exit (1);
}
- proxy = dbus_g_proxy_new_for_name (connection,
- GDM_DBUS_NAME,
- GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
- GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE);
- if (proxy == NULL) {
- g_warning ("Failed to create local display factory proxy");
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, &value);
+ g_debug ("Started %s", value);
+
+ dbus_message_unref (reply);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+get_current_session_id (DBusConnection *connection,
+ char **session_id)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ gboolean ret;
+ DBusMessageIter iter;
+ const char *value;
+
+ ret = FALSE;
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE,
+ "GetCurrentSession");
+ if (message == NULL) {
goto out;
}
- local_error = NULL;
- res = dbus_g_proxy_call (proxy,
- "CreateTransientDisplay",
- &local_error,
- G_TYPE_INVALID,
- DBUS_TYPE_G_OBJECT_PATH, &display_id,
- G_TYPE_INVALID);
- if (res) {
- g_print ("Started %s\n", display_id);
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &local_error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("Unable to determine session: %s", local_error.message);
+ dbus_error_free (&local_error);
+ goto out;
+ }
}
- g_free (display_id);
- if (! res) {
- if (local_error != NULL) {
- g_warning ("Failed to create transient display: %s", local_error->message);
- g_error_free (local_error);
- } else {
- g_warning ("Failed to create transient display");
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, &value);
+ if (session_id != NULL) {
+ *session_id = g_strdup (value);
+ }
+ dbus_message_unref (reply);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+get_seat_id_for_session (DBusConnection *connection,
+ const char *session_id,
+ char **seat_id)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ gboolean ret;
+ DBusMessageIter iter;
+ const char *value;
+
+ ret = FALSE;
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (CK_NAME,
+ session_id,
+ CK_SESSION_INTERFACE,
+ "GetSeatId");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &local_error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("Unable to determine seat: %s", local_error.message);
+ dbus_error_free (&local_error);
+ goto out;
}
+ }
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, &value);
+ if (seat_id != NULL) {
+ *seat_id = g_strdup (value);
+ }
+ dbus_message_unref (reply);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static char *
+get_current_seat_id (DBusConnection *connection)
+{
+ gboolean res;
+ char *session_id;
+ char *seat_id;
+
+ session_id = NULL;
+ seat_id = NULL;
+
+ res = get_current_session_id (connection, &session_id);
+ if (res) {
+ res = get_seat_id_for_session (connection, session_id, &seat_id);
+ }
+ g_free (session_id);
+
+ return seat_id;
+}
+
+static gboolean
+activate_session_id (DBusConnection *connection,
+ const char *seat_id,
+ const char *session_id)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ gboolean ret;
+
+ ret = FALSE;
+
+ g_debug ("Switching to session %s", session_id);
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (CK_NAME,
+ seat_id,
+ CK_SEAT_INTERFACE,
+ "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 (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;
+}
+
+static gboolean
+session_is_login_window (DBusConnection *connection,
+ const char *session_id)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ gboolean ret;
+ DBusMessageIter iter;
+ const char *value;
+
+ ret = FALSE;
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (CK_NAME,
+ session_id,
+ CK_SESSION_INTERFACE,
+ "GetSessionType");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &local_error);
+ if (reply == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("Unable to determine seat: %s", local_error.message);
+ dbus_error_free (&local_error);
+ goto out;
+ }
+ }
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, &value);
+
+ if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
+ goto out;
+ }
+
+ dbus_message_unref (reply);
+ ret = TRUE;
out:
return ret;
}
+static gboolean
+seat_can_activate_sessions (DBusConnection *connection,
+ const char *seat_id)
+{
+ DBusError local_error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ gboolean can_activate;
+
+ can_activate = FALSE;
+
+ dbus_error_init (&local_error);
+ message = dbus_message_new_method_call (CK_NAME,
+ seat_id,
+ CK_SEAT_INTERFACE,
+ "CanActivateSessions");
+ if (message == NULL) {
+ goto out;
+ }
+
+ dbus_error_init (&local_error);
+ reply = dbus_connection_send_with_reply_and_block (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;
+ }
+ }
+
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_get_basic (&iter, &can_activate);
+ dbus_message_unref (reply);
+
+ out:
+ return can_activate;
+}
+
+/* from libhal */
+static char **
+get_path_array_from_iter (DBusMessageIter *iter,
+ int *num_elements)
+{
+ int count;
+ char **buffer;
+
+ count = 0;
+ buffer = (char **)malloc (sizeof (char *) * 8);
+
+ if (buffer == NULL)
+ goto oom;
+
+ buffer[0] = NULL;
+ while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_OBJECT_PATH) {
+ const char *value;
+ char *str;
+
+ if ((count % 8) == 0 && count != 0) {
+ buffer = realloc (buffer, sizeof (char *) * (count + 8));
+ if (buffer == NULL)
+ goto oom;
+ }
+
+ dbus_message_iter_get_basic (iter, &value);
+ str = strdup (value);
+ if (str == NULL)
+ goto oom;
+
+ buffer[count] = str;
+
+ dbus_message_iter_next (iter);
+ count++;
+ }
+
+ if ((count % 8) == 0) {
+ buffer = realloc (buffer, sizeof (char *) * (count + 1));
+ if (buffer == NULL)
+ goto oom;
+ }
+
+ buffer[count] = NULL;
+ if (num_elements != NULL)
+ *num_elements = count;
+ return buffer;
+
+oom:
+ g_debug ("%s %d : error allocating memory\n", __FILE__, __LINE__);
+ return NULL;
+
+}
+
+static char **
+seat_get_sessions (DBusConnection *connection,
+ const char *seat_id)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusMessageIter iter_reply;
+ DBusMessageIter iter_array;
+ char **sessions;
+
+ sessions = NULL;
+ message = NULL;
+ reply = NULL;
+
+ dbus_error_init (&error);
+ message = dbus_message_new_method_call (CK_NAME,
+ seat_id,
+ CK_SEAT_INTERFACE,
+ "GetSessions");
+ if (message == NULL) {
+ g_debug ("Couldn't allocate the D-Bus message");
+ goto out;
+ }
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1, &error);
+ dbus_connection_flush (connection);
+
+ if (dbus_error_is_set (&error)) {
+ g_debug ("ConsoleKit %s raised:\n %s\n\n", error.name, error.message);
+ goto out;
+ }
+
+ if (reply == NULL) {
+ g_debug ("ConsoleKit: No reply for GetSessionsForUser");
+ goto out;
+ }
+
+ dbus_message_iter_init (reply, &iter_reply);
+ if (dbus_message_iter_get_arg_type (&iter_reply) != DBUS_TYPE_ARRAY) {
+ g_debug ("ConsoleKit Wrong reply for GetSessionsForUser - expecting an array.");
+ goto out;
+ }
+
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ sessions = get_path_array_from_iter (&iter_array, NULL);
+
+ out:
+ if (message != NULL) {
+ dbus_message_unref (message);
+ }
+ if (reply != NULL) {
+ dbus_message_unref (reply);
+ }
+
+ return sessions;
+}
+
+static char *
+get_login_window_session_id (DBusConnection *connection,
+ const char *seat_id)
+{
+ gboolean ret;
+ gboolean can_activate_sessions;
+ char **sessions;
+ char *session_id;
+ int i;
+
+ ret = FALSE;
+ session_id = NULL;
+ sessions = NULL;
+
+ g_debug ("checking if seat can activate sessions");
+
+ can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
+ if (! can_activate_sessions) {
+ g_debug ("seat is unable to activate sessions");
+ goto out;
+ }
+
+ sessions = seat_get_sessions (connection, seat_id);
+ for (i = 0; sessions [i] != NULL; i++) {
+ char *ssid;
+
+ ssid = sessions [i];
+
+ if (session_is_login_window (connection, ssid)) {
+ session_id = g_strdup (ssid);
+ break;
+ }
+ }
+ g_strfreev (sessions);
+
+ out:
+ return session_id;
+}
+
+static gboolean
+goto_login_session (GError **error)
+{
+ gboolean ret;
+ gboolean res;
+ char *session_id;
+ char *seat_id;
+ DBusError local_error;
+ DBusConnection *connection;
+
+ ret = FALSE;
+
+ dbus_error_init (&local_error);
+ connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
+ if (connection == NULL) {
+ g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
+ dbus_error_free (&local_error);
+ return FALSE;
+ }
+
+ /* First look for any existing LoginWindow sessions on the seat.
+ If none are found, create a new one. */
+
+ seat_id = get_current_seat_id (connection);
+ if (seat_id == NULL || seat_id[0] == '\0') {
+ g_debug ("seat id is not set; can't switch sessions");
+ return FALSE;
+ }
+
+ session_id = get_login_window_session_id (connection, seat_id);
+ if (session_id != NULL) {
+ res = activate_session_id (connection, seat_id, session_id);
+ if (res) {
+ ret = TRUE;
+ }
+ }
+
+ if (! ret) {
+ res = create_transient_display (connection);
+ if (res) {
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
int
main (int argc, char *argv[])
@@ -225,7 +674,7 @@
}
error = NULL;
- res = create_transient_display (&error);
+ res = goto_login_session (&error);
if (! res) {
GtkWidget *dialog;
char *message;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]