summaryrefslogtreecommitdiff
path: root/gconf/gconfd-dbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'gconf/gconfd-dbus.c')
-rw-r--r--gconf/gconfd-dbus.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/gconf/gconfd-dbus.c b/gconf/gconfd-dbus.c
new file mode 100644
index 00000000..cb0ecac1
--- /dev/null
+++ b/gconf/gconfd-dbus.c
@@ -0,0 +1,392 @@
+/* GConf
+ * Copyright (C) 2003 Imendio HB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <string.h>
+#include "gconf-database-dbus.h"
+#include "gconf-dbus-utils.h"
+#include "gconfd.h"
+#include "gconfd-dbus.h"
+
+static DBusConnection *bus_conn;
+static const char *server_path = "/org/gnome/GConf/Server";
+static gint nr_of_connections = 0;
+
+static void server_unregistered_func (DBusConnection *connection,
+ void *user_data);
+static DBusHandlerResult server_message_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+static DBusHandlerResult server_filter_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+static void server_handle_get_db (DBusConnection *connection,
+ DBusMessage *message);
+static void server_handle_shutdown (DBusConnection *connection,
+ DBusMessage *message);
+static void server_handle_get_default_db (DBusConnection *connection,
+ DBusMessage *message);
+
+
+static DBusObjectPathVTable
+server_vtable = {
+ server_unregistered_func,
+ server_message_func,
+ NULL,
+};
+
+static void
+server_unregistered_func (DBusConnection *connection, void *user_data)
+{
+ g_print ("Server object unregistered\n");
+ nr_of_connections = 0;
+}
+
+static DBusHandlerResult
+server_message_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (gconfd_dbus_check_in_shutdown (connection, message))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ {
+ g_print ("Not a method call\n");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (strcmp (dbus_message_get_interface (message),
+ GCONF_DBUS_SERVER_INTERFACE) != 0)
+ {
+ g_print ("Not correct interface: \"%s\"\n",
+ dbus_message_get_interface (message));
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (dbus_message_is_method_call (message,
+ GCONF_DBUS_SERVER_INTERFACE,
+ GCONF_DBUS_SERVER_GET_DEFAULT_DB))
+ server_handle_get_default_db (connection, message);
+ else if (dbus_message_is_method_call (message,
+ GCONF_DBUS_SERVER_INTERFACE,
+ GCONF_DBUS_SERVER_GET_DB))
+ server_handle_get_db (connection, message);
+ else if (dbus_message_is_method_call (message,
+ GCONF_DBUS_SERVER_INTERFACE,
+ GCONF_DBUS_SERVER_SHUTDOWN))
+ server_handle_shutdown (connection, message);
+ else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+server_filter_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected")) {
+ /* Exit cleanly. */
+ gconfd_main_quit ();
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+server_real_handle_get_db (DBusConnection *connection,
+ DBusMessage *message,
+ GSList *addresses)
+{
+ GConfDatabase *db;
+ DBusMessage *reply;
+ GError *gerror = NULL;
+ const gchar *str;
+
+ if (gconfd_dbus_check_in_shutdown (connection, message))
+ return;
+
+ db = gconfd_obtain_database (addresses, &gerror);
+
+ if (gconfd_dbus_set_exception (connection, message, &gerror))
+ return;
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ g_error ("No memory");
+
+ str = gconf_database_dbus_get_path (db);
+ dbus_message_append_args (reply,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ g_error ("No memory");
+
+ dbus_message_unref (reply);
+}
+
+static void
+server_handle_get_default_db (DBusConnection *connection,
+ DBusMessage *message)
+{
+ server_real_handle_get_db (connection, message, NULL);
+}
+
+static void
+server_handle_get_db (DBusConnection *connection, DBusMessage *message)
+{
+ char *addresses;
+ GSList *list;
+
+ if (!gconfd_dbus_get_message_args (connection, message,
+ DBUS_TYPE_STRING, &addresses,
+ DBUS_TYPE_INVALID))
+ return;
+
+ list = gconf_persistent_name_get_address_list (addresses);
+
+ server_real_handle_get_db (connection, message, list);
+
+ g_slist_foreach (list, (GFunc) g_free, NULL);
+ g_slist_free (list);
+}
+
+static void
+server_handle_shutdown (DBusConnection *connection, DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ if (gconfd_dbus_check_in_shutdown (connection, message))
+ return;
+
+ gconf_log(GCL_DEBUG, _("Shutdown request received"));
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ dbus_connection_unregister_object_path (connection, server_path);
+
+ gconfd_main_quit();
+}
+
+gboolean
+gconfd_dbus_init (void)
+{
+ DBusError error;
+ gint ret;
+
+ dbus_error_init (&error);
+
+ bus_conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (!bus_conn)
+ {
+ gconf_log (GCL_ERR, _("Daemon failed to connect to the D-BUS daemon:\n%s"),
+ error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ /* We handle exiting ourselves on disconnect. */
+ dbus_connection_set_exit_on_disconnect (bus_conn, FALSE);
+
+ /* Add message filter to handle Disconnected. */
+ dbus_connection_add_filter (bus_conn,
+ (DBusHandleMessageFunction) server_filter_func,
+ NULL, NULL);
+
+ ret = dbus_bus_request_name (bus_conn,
+ GCONF_DBUS_SERVICE,
+ 0,
+ &error);
+
+ if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ gconf_log (GCL_ERR, "Daemon could not become primary owner");
+ return FALSE;
+ }
+
+ if (dbus_error_is_set (&error))
+ {
+ gconf_log (GCL_ERR, _("Daemon failed to acquire gconf service:\n%s"),
+ error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ if (!dbus_connection_register_object_path (bus_conn,
+ server_path,
+ &server_vtable,
+ NULL))
+ {
+ gconf_log (GCL_ERR, _("Failed to register server object with the D-BUS bus daemon"));
+ return FALSE;
+ }
+
+
+ nr_of_connections = 1;
+ dbus_connection_setup_with_g_main (bus_conn, NULL);
+
+ return TRUE;
+}
+
+guint
+gconfd_dbus_client_count (void)
+{
+ return nr_of_connections;
+}
+
+gboolean
+gconfd_dbus_get_message_args (DBusConnection *connection,
+ DBusMessage *message,
+ int first_arg_type,
+ ...)
+{
+ gboolean retval;
+ va_list var_args;
+
+ va_start (var_args, first_arg_type);
+ retval = dbus_message_get_args_valist (message, NULL, first_arg_type, var_args);
+ va_end (var_args);
+
+ if (!retval)
+ {
+ DBusMessage *reply;
+
+ reply = dbus_message_new_error (message, GCONF_DBUS_ERROR_FAILED,
+ _("Got a malformed message."));
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gconfd_dbus_set_exception (DBusConnection *connection,
+ DBusMessage *message,
+ GError **error)
+{
+ GConfError en;
+ const char *name = NULL;
+ DBusMessage *reply;
+
+ if (error == NULL || *error == NULL)
+ return FALSE;
+
+ en = (*error)->code;
+
+ /* success is not supposed to get set */
+ g_return_val_if_fail(en != GCONF_ERROR_SUCCESS, FALSE);
+
+ switch (en)
+ {
+ case GCONF_ERROR_FAILED:
+ name = GCONF_DBUS_ERROR_FAILED;
+ break;
+ case GCONF_ERROR_NO_PERMISSION:
+ name = GCONF_DBUS_ERROR_NO_PERMISSION;
+ break;
+ case GCONF_ERROR_BAD_ADDRESS:
+ name = GCONF_DBUS_ERROR_BAD_ADDRESS;
+ break;
+ case GCONF_ERROR_BAD_KEY:
+ name = GCONF_DBUS_ERROR_BAD_KEY;
+ break;
+ case GCONF_ERROR_PARSE_ERROR:
+ name = GCONF_DBUS_ERROR_PARSE_ERROR;
+ break;
+ case GCONF_ERROR_CORRUPT:
+ name = GCONF_DBUS_ERROR_CORRUPT;
+ break;
+ case GCONF_ERROR_TYPE_MISMATCH:
+ name = GCONF_DBUS_ERROR_TYPE_MISMATCH;
+ break;
+ case GCONF_ERROR_IS_DIR:
+ name = GCONF_DBUS_ERROR_IS_DIR;
+ break;
+ case GCONF_ERROR_IS_KEY:
+ name = GCONF_DBUS_ERROR_IS_KEY;
+ break;
+ case GCONF_ERROR_NO_WRITABLE_DATABASE:
+ name = GCONF_DBUS_ERROR_NO_WRITABLE_DATABASE;
+ break;
+ case GCONF_ERROR_IN_SHUTDOWN:
+ name = GCONF_DBUS_ERROR_IN_SHUTDOWN;
+ break;
+ case GCONF_ERROR_OVERRIDDEN:
+ name = GCONF_DBUS_ERROR_OVERRIDDEN;
+ break;
+ case GCONF_ERROR_LOCK_FAILED:
+ name = GCONF_DBUS_ERROR_LOCK_FAILED;
+ break;
+ case GCONF_ERROR_OAF_ERROR:
+ case GCONF_ERROR_LOCAL_ENGINE:
+ case GCONF_ERROR_NO_SERVER:
+ case GCONF_ERROR_SUCCESS:
+ default:
+ gconf_log (GCL_ERR, "Unhandled error code %d", en);
+ g_assert_not_reached();
+ break;
+ }
+
+ reply = dbus_message_new_error (message, name, (*error)->message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+gboolean
+gconfd_dbus_check_in_shutdown (DBusConnection *connection,
+ DBusMessage *message)
+{
+ if (gconfd_in_shutdown ())
+ {
+ DBusMessage *reply;
+
+ reply = dbus_message_new_error (message,
+ GCONF_DBUS_ERROR_IN_SHUTDOWN,
+ _("The GConf daemon is currently shutting down."));
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+DBusConnection *
+gconfd_dbus_get_connection (void)
+{
+ return bus_conn;
+}
+