Index: daemon/gdmconsolekit.c =================================================================== --- daemon/gdmconsolekit.c (revision 4556) +++ daemon/gdmconsolekit.c (working copy) @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2006 William Jon McCann + * Copyright (C) 2006-2007 William Jon McCann * * 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 @@ -20,11 +20,11 @@ #include "config.h" +#include #include #define DBUS_API_SUBJECT_TO_CHANGE #include -#include #include #include "misc.h" /* for gdm_debug */ @@ -38,182 +38,360 @@ #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" -#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \ - G_TYPE_STRING, \ - G_TYPE_VALUE, \ - G_TYPE_INVALID)) -#define CK_TYPE_PARAMETER_LIST (dbus_g_type_get_collection ("GPtrArray", \ - CK_TYPE_PARAMETER_STRUCT)) +static DBusConnection *private_connection = NULL; + static void -add_param_int (GPtrArray *parameters, +add_param_int (DBusMessageIter *iter_struct, const char *key, int value) { - GValue val = { 0, }; - GValue param_val = { 0, }; + DBusMessageIter iter_struct_entry; + DBusMessageIter iter_var; + + dbus_message_iter_open_container (iter_struct, + DBUS_TYPE_STRUCT, + NULL, + &iter_struct_entry); + + dbus_message_iter_append_basic (&iter_struct_entry, + DBUS_TYPE_STRING, + &key); + + dbus_message_iter_open_container (&iter_struct_entry, + DBUS_TYPE_VARIANT, + DBUS_TYPE_INT32_AS_STRING, + &iter_var); + + dbus_message_iter_append_basic (&iter_var, + DBUS_TYPE_INT32, + &value); + + dbus_message_iter_close_container (&iter_struct_entry, + &iter_var); - g_value_init (&val, G_TYPE_INT); - g_value_set_int (&val, value); - g_value_init (¶m_val, CK_TYPE_PARAMETER_STRUCT); - g_value_take_boxed (¶m_val, - dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT)); - dbus_g_type_struct_set (¶m_val, - 0, key, - 1, &val, - G_MAXUINT); - g_ptr_array_add (parameters, g_value_get_boxed (¶m_val)); + dbus_message_iter_close_container (iter_struct, &iter_struct_entry); } static void -add_param_boolean (GPtrArray *parameters, +add_param_boolean (DBusMessageIter *iter_struct, const char *key, gboolean value) { - GValue val = { 0, }; - GValue param_val = { 0, }; + DBusMessageIter iter_struct_entry; + DBusMessageIter iter_var; - g_value_init (&val, G_TYPE_BOOLEAN); - g_value_set_boolean (&val, value); - g_value_init (¶m_val, CK_TYPE_PARAMETER_STRUCT); - g_value_take_boxed (¶m_val, - dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT)); - dbus_g_type_struct_set (¶m_val, - 0, key, - 1, &val, - G_MAXUINT); - g_ptr_array_add (parameters, g_value_get_boxed (¶m_val)); + dbus_message_iter_open_container (iter_struct, + DBUS_TYPE_STRUCT, + NULL, + &iter_struct_entry); + + dbus_message_iter_append_basic (&iter_struct_entry, + DBUS_TYPE_STRING, + &key); + + dbus_message_iter_open_container (&iter_struct_entry, + DBUS_TYPE_VARIANT, + DBUS_TYPE_BOOLEAN_AS_STRING, + &iter_var); + + dbus_message_iter_append_basic (&iter_var, + DBUS_TYPE_BOOLEAN, + &value); + + dbus_message_iter_close_container (&iter_struct_entry, + &iter_var); + + dbus_message_iter_close_container (iter_struct, &iter_struct_entry); } static void -add_param_string (GPtrArray *parameters, +add_param_string (DBusMessageIter *iter_struct, const char *key, const char *value) { - GValue val = { 0, }; - GValue param_val = { 0, }; + DBusMessageIter iter_struct_entry; + DBusMessageIter iter_var; + + dbus_message_iter_open_container (iter_struct, + DBUS_TYPE_STRUCT, + NULL, + &iter_struct_entry); + + dbus_message_iter_append_basic (&iter_struct_entry, + DBUS_TYPE_STRING, + &key); + + dbus_message_iter_open_container (&iter_struct_entry, + DBUS_TYPE_VARIANT, + DBUS_TYPE_STRING_AS_STRING, + &iter_var); + + dbus_message_iter_append_basic (&iter_var, + DBUS_TYPE_STRING, + &value); + + dbus_message_iter_close_container (&iter_struct_entry, + &iter_var); + + dbus_message_iter_close_container (iter_struct, &iter_struct_entry); +} + +static gboolean +session_get_x11_display (DBusConnection *connection, + const char *ssid, + char **str) +{ + DBusError error; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + const char *value; + + if (str != NULL) { + *str = NULL; + } + + message = dbus_message_new_method_call (CK_NAME, + ssid, + CK_SESSION_INTERFACE, + "GetX11Display"); + if (message == NULL) { + gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); + return FALSE; + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, + message, + -1, &error); + if (dbus_error_is_set (&error)) { + gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); + reply = NULL; + } + + dbus_connection_flush (connection); + dbus_message_unref (message); + + if (reply == NULL) { + return FALSE; + } - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, value); + dbus_message_iter_init (reply, &iter); + dbus_message_iter_get_basic (&iter, &value); + if (str != NULL) { + *str = g_strdup (value); + } + dbus_message_unref (reply); - g_value_init (¶m_val, CK_TYPE_PARAMETER_STRUCT); - g_value_take_boxed (¶m_val, - dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT)); - - dbus_g_type_struct_set (¶m_val, - 0, key, - 1, &val, - G_MAXUINT); - g_ptr_array_add (parameters, g_value_get_boxed (¶m_val)); + return TRUE; } static gboolean -get_string (DBusGProxy *proxy, - const char *method, - char **str) +session_unlock (DBusConnection *connection, + const char *ssid) +{ + DBusError error; + DBusMessage *message; + DBusMessage *reply; + + gdm_debug ("ConsoleKit: Unlocking session %s", ssid); + message = dbus_message_new_method_call (CK_NAME, + ssid, + CK_SESSION_INTERFACE, + "Unlock"); + if (message == NULL) { + gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); + return FALSE; + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, + message, + -1, &error); + dbus_message_unref (message); + dbus_message_unref (reply); + dbus_connection_flush (connection); + + if (dbus_error_is_set (&error)) { + gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); + return FALSE; + } + + return TRUE; +} + +/* 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: + fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__); + return NULL; + +} + +static char ** +get_sessions_for_user (DBusConnection *connection, + const char *user, + const char *x11_display) { - GError *error; - gboolean res; + DBusError error; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter iter_reply; + DBusMessageIter iter_array; + struct passwd *pwent; + char **sessions; + + sessions = NULL; + message = NULL; + reply = NULL; - error = NULL; - res = dbus_g_proxy_call (proxy, - method, - &error, - G_TYPE_INVALID, - G_TYPE_STRING, str, - G_TYPE_INVALID); - if (! res) { - g_warning ("%s failed: %s", method, error->message); - g_error_free (error); + pwent = getpwnam (user); + + dbus_error_init (&error); + message = dbus_message_new_method_call (CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE, + "GetSessionsForUser"); + if (message == NULL) { + gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); + goto out; + } + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, + DBUS_TYPE_UINT32, + &pwent->pw_uid); + + 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)) { + gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); + goto out; + } + + if (reply == NULL) { + gdm_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) { + gdm_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 res; + return sessions; } void unlock_ck_session (const char *user, const char *x11_display) { - DBusGConnection *connection; - DBusGProxy *proxy; - GError *error; - gboolean res; - struct passwd *pwent; - GPtrArray *sessions; - int i; + DBusError error; + DBusConnection *connection; + char **sessions; + int i; - gdm_debug ("Unlocking ConsoleKit session for %s on %s", user, x11_display); + gdm_debug ("ConsoleKit: Unlocking session for %s on %s", user, x11_display); - error = NULL; - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); if (connection == NULL) { - gdm_debug ("Failed to connect to the D-Bus daemon: %s", error->message); - g_error_free (error); + gdm_debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message); + dbus_error_free (&error); return; } - proxy = dbus_g_proxy_new_for_name (connection, - CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE); - if (proxy == NULL) { + sessions = get_sessions_for_user (connection, user, x11_display); + if (sessions == NULL || sessions[0] == NULL) { + gdm_debug ("ConsoleKit: no sessions found"); return; } - pwent = getpwnam (user); - - error = NULL; - res = dbus_g_proxy_call (proxy, - "GetSessionsForUser", - &error, - G_TYPE_UINT, - pwent->pw_uid, - G_TYPE_INVALID, - dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), - &sessions, - G_TYPE_INVALID); - if (! res) { - g_warning ("Failed to get list of sessions: %s", error->message); - g_error_free (error); - goto out; - } - - for (i = 0; i < sessions->len; i++) { - char *ssid; - DBusGProxy *session_proxy; - - ssid = g_ptr_array_index (sessions, i); - - session_proxy = dbus_g_proxy_new_for_name (connection, - CK_NAME, - ssid, - CK_SESSION_INTERFACE); - if (session_proxy != NULL) { - char *xdisplay; - - get_string (session_proxy, "GetX11Display", &xdisplay); - if (xdisplay != NULL - && x11_display != NULL - && strcmp (xdisplay, x11_display) == 0) { - res = dbus_g_proxy_call (session_proxy, - "Unlock", - &error, - G_TYPE_INVALID, - G_TYPE_INVALID); - if (! res) { - g_warning ("Unable to unlock %s: %s", ssid, error->message); - g_error_free (error); - } + for (i = 0; sessions[i] != NULL; i++) { + char *ssid; + char *xdisplay; + + ssid = sessions[i]; + session_get_x11_display (connection, ssid, &xdisplay); + gdm_debug ("ConsoleKit: session %s has DISPLAY %s", ssid, xdisplay); + + if (xdisplay != NULL + && x11_display != NULL + && strcmp (xdisplay, x11_display) == 0) { + gboolean res; + + res = session_unlock (connection, ssid); + if (! res) { + gdm_error ("ConsoleKit: Unable to unlock %s", ssid); } } - g_object_unref (session_proxy); - g_free (ssid); + g_free (xdisplay); } - g_ptr_array_free (sessions, TRUE); - - out: - g_object_unref (proxy); + g_strfreev (sessions); } char * @@ -221,70 +399,89 @@ open_ck_session (struct passwd *pwent, GdmDisplay *d, const char *session) { - DBusGConnection *connection; - DBusGProxy *proxy; - GError *error; - gboolean res; - char *cookie; - GPtrArray *parameters; + DBusConnection *connection; + DBusError error; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter iter_struct; + char *cookie; cookie = NULL; - gdm_debug ("Opening ConsoleKit session for %s", pwent->pw_name); + gdm_debug ("ConsoleKit: Opening session for %s", pwent->pw_name); + + dbus_error_init (&error); + connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error); + private_connection = connection; - error = NULL; - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); if (connection == NULL) { - gdm_debug ("Failed to connect to the D-Bus daemon: %s", error->message); - g_error_free (error); + gdm_debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message); + dbus_error_free (&error); return NULL; } - proxy = dbus_g_proxy_new_for_name (connection, - CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE); - if (proxy == NULL) { + dbus_connection_set_exit_on_disconnect (connection, FALSE); + dbus_connection_setup_with_g_main (connection, NULL); + + dbus_error_init (&error); + message = dbus_message_new_method_call (CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE, + "OpenSessionWithParameters"); + if (message == NULL) { + gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); return NULL; } - parameters = g_ptr_array_sized_new (10); - - add_param_int (parameters, "user", pwent->pw_uid); - add_param_string (parameters, "x11-display", d->name); - add_param_string (parameters, "host-name", d->hostname); - add_param_boolean (parameters, "is-local", d->attached); - + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_open_container (&iter, + DBUS_TYPE_ARRAY, + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING, + &iter_struct); + + add_param_int (&iter_struct, "user", pwent->pw_uid); + add_param_string (&iter_struct, "x11-display", d->name); + add_param_string (&iter_struct, "host-name", d->hostname); + add_param_boolean (&iter_struct, "is-local", d->attached); /* FIXME: this isn't really a reliable value to use */ - add_param_string (parameters, "session-type", session); + add_param_string (&iter_struct, "session-type", session); if (d->vt > 0) { char *device; /* FIXME: how does xorg construct this */ device = g_strdup_printf ("/dev/tty%d", d->vt); - add_param_string (parameters, "display-device", device); + add_param_string (&iter_struct, "display-device", device); g_free (device); } - error = NULL; - res = dbus_g_proxy_call (proxy, - "OpenSessionWithParameters", - &error, - CK_TYPE_PARAMETER_LIST, - parameters, - G_TYPE_INVALID, - G_TYPE_STRING, - &cookie, - G_TYPE_INVALID); - if (! res) { - g_warning ("OpenSession failed: %s", error->message); - g_error_free (error); + dbus_message_iter_close_container (&iter, &iter_struct); + + reply = dbus_connection_send_with_reply_and_block (connection, + message, + -1, &error); + if (dbus_error_is_set (&error)) { + gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); + reply = NULL; } - g_object_unref (proxy); + dbus_connection_flush (connection); + + dbus_message_unref (message); + dbus_error_free (&error); - g_ptr_array_free (parameters, TRUE); + if (reply != NULL) { + const char *value; + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_get_basic (&iter, &value); + cookie = g_strdup (value); + dbus_message_unref (reply); + } return cookie; } @@ -292,41 +489,47 @@ open_ck_session (struct passwd *pwent, void close_ck_session (const char *cookie) { - DBusGConnection *connection; - DBusGProxy *proxy; - GError *error; - gboolean res; + DBusError error; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; - g_return_if_fail (cookie != NULL); + if (cookie == NULL) { + return; + } - error = NULL; - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); - if (connection == NULL) { - gdm_debug ("Failed to connect to the D-Bus daemon: %s", error->message); - g_error_free (error); + if (private_connection == NULL) { return; } - proxy = dbus_g_proxy_new_for_name (connection, - CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE); - if (proxy == NULL) { + dbus_error_init (&error); + message = dbus_message_new_method_call (CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE, + "CloseSession"); + if (message == NULL) { + gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); return; } - error = NULL; - res = dbus_g_proxy_call (proxy, - "CloseSession", - &error, - G_TYPE_STRING, - &cookie, - G_TYPE_INVALID, - G_TYPE_INVALID); - if (! res) { - g_warning ("CloseSession failed: %s", error->message); - g_error_free (error); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, + DBUS_TYPE_STRING, + &cookie); + + reply = dbus_connection_send_with_reply_and_block (private_connection, + message, + -1, &error); + if (dbus_error_is_set (&error)) { + gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); + reply = NULL; } - g_object_unref (proxy); + dbus_connection_flush (private_connection); + + dbus_message_unref (message); + dbus_error_free (&error); + + dbus_connection_close (private_connection); + private_connection = NULL; }