diff -up GConf-2.22.0/configure.in.defaults GConf-2.22.0/configure.in --- GConf-2.22.0/configure.in.defaults 2008-03-10 10:52:28.000000000 -0400 +++ GConf-2.22.0/configure.in 2008-05-04 18:15:22.000000000 -0400 @@ -166,6 +166,7 @@ AC_SUBST(DEPENDENT_WITH_GTK_CFLAGS) AC_SUBST(DEPENDENT_WITH_XML_AND_GTK_LIBS) AC_SUBST(DEPENDENT_WITH_XML_AND_GTK_CFLAGS) +PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-dbus) ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`" AC_SUBST(ORBIT_IDL) @@ -261,6 +262,7 @@ doc/Makefile doc/gconf/Makefile examples/Makefile tests/Makefile +defaults/Makefile gconf-2.0.pc ]) diff -up /dev/null GConf-2.22.0/defaults/gconf-defaults.c --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/gconf-defaults.c 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,704 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Matthias Clasen + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#define GCONF_ENABLE_INTERNALS +#include +#include + +#include "gconf-defaults.h" +#include "gconf-defaults-glue.h" + +static gboolean +do_exit (gpointer user_data) +{ + g_debug ("Exiting due to inactivity"); + exit (1); + return FALSE; +} + +static guint timer_id = 0; + +static void +stop_killtimer (void) +{ + if (timer_id > 0) { + g_source_remove (timer_id); + timer_id = 0; + } +} + +static void +start_killtimer (void) +{ + g_debug ("Setting killtimer to 30 seconds..."); + timer_id = g_timeout_add_seconds (30, do_exit, NULL); +} + +struct GConfDefaultsPrivate +{ + DBusGConnection *system_bus_connection; + DBusGProxy *system_bus_proxy; + PolKitContext *pol_ctx; +}; + +static void gconf_defaults_finalize (GObject *object); + +G_DEFINE_TYPE (GConfDefaults, gconf_defaults, G_TYPE_OBJECT) + +#define GCONF_DEFAULTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCONF_TYPE_DEFAULTS, GConfDefaultsPrivate)) + +GQuark +gconf_defaults_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) { + ret = g_quark_from_static_string ("gconf_defaults_error"); + } + + return ret; +} + + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +gconf_defaults_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) + { + static const GEnumValue values[] = + { + ENUM_ENTRY (GCONF_DEFAULTS_ERROR_GENERAL, "GeneralError"), + ENUM_ENTRY (GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, "NotPrivileged"), + { 0, 0, 0 } + }; + + g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1); + + etype = g_enum_register_static ("GConfDefaultsError", values); + } + + return etype; +} + + +static GObject * +gconf_defaults_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GConfDefaults *mechanism; + GConfDefaultsClass *klass; + + klass = GCONF_DEFAULTS_CLASS (g_type_class_peek (GCONF_TYPE_DEFAULTS)); + + mechanism = GCONF_DEFAULTS (G_OBJECT_CLASS (gconf_defaults_parent_class)->constructor ( + type, + n_construct_properties, + construct_properties)); + + return G_OBJECT (mechanism); +} + +static void +gconf_defaults_class_init (GConfDefaultsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructor = gconf_defaults_constructor; + object_class->finalize = gconf_defaults_finalize; + + g_type_class_add_private (klass, sizeof (GConfDefaultsPrivate)); + + dbus_g_object_type_install_info (GCONF_TYPE_DEFAULTS, &dbus_glib_gconf_defaults_object_info); + + dbus_g_error_domain_register (GCONF_DEFAULTS_ERROR, NULL, GCONF_DEFAULTS_TYPE_ERROR); + +} + +static void +gconf_defaults_init (GConfDefaults *mechanism) +{ + mechanism->priv = GCONF_DEFAULTS_GET_PRIVATE (mechanism); +} + +static void +gconf_defaults_finalize (GObject *object) +{ + GConfDefaults *mechanism; + + g_return_if_fail (object != NULL); + g_return_if_fail (GCONF_IS_DEFAULTS (object)); + + mechanism = GCONF_DEFAULTS (object); + + g_return_if_fail (mechanism->priv != NULL); + + g_object_unref (mechanism->priv->system_bus_proxy); + + G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object); +} + +static gboolean +pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + int fd; + PolKitContext *pk_context = user_data; + fd = g_io_channel_unix_get_fd (channel); + polkit_context_io_func (pk_context, fd); + return TRUE; +} + +static int +pk_io_add_watch (PolKitContext *pk_context, int fd) +{ + guint id = 0; + GIOChannel *channel; + channel = g_io_channel_unix_new (fd); + if (channel == NULL) + goto out; + id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context); + if (id == 0) { + g_io_channel_unref (channel); + goto out; + } + g_io_channel_unref (channel); +out: + return id; +} + +static void +pk_io_remove_watch (PolKitContext *pk_context, int watch_id) +{ + g_source_remove (watch_id); +} + +static gboolean +register_mechanism (GConfDefaults *mechanism) +{ + GError *error = NULL; + + mechanism->priv->pol_ctx = polkit_context_new (); + polkit_context_set_io_watch_functions (mechanism->priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch); + if (!polkit_context_init (mechanism->priv->pol_ctx, NULL)) { + g_critical ("cannot initialize libpolkit"); + goto error; + } + + error = NULL; + mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (mechanism->priv->system_bus_connection == NULL) { + if (error != NULL) { + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); + } + goto error; + } + + dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/", + G_OBJECT (mechanism)); + + mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + + start_killtimer (); + + return TRUE; + +error: + return FALSE; +} + + +GConfDefaults * +gconf_defaults_new (void) +{ + GObject *object; + gboolean res; + + object = g_object_new (GCONF_TYPE_DEFAULTS, NULL); + + res = register_mechanism (GCONF_DEFAULTS (object)); + if (! res) { + g_object_unref (object); + return NULL; + } + + return GCONF_DEFAULTS (object); +} + +static const char * +polkit_action_for_gconf_path (GConfDefaults *mechanism, + const char *annotation_key, + const char *path) +{ + PolKitPolicyCache *cache; + PolKitPolicyFileEntry *entry; + char *prefix, *p; + const char *action; + + cache = polkit_context_get_policy_cache (mechanism->priv->pol_ctx); + prefix = g_strdup (path); + + while (1) { + entry = polkit_policy_cache_get_entry_by_annotation (cache, + annotation_key, + prefix); + if (entry) { + action = polkit_policy_file_entry_get_id (entry); + break; + } + + p = strrchr (prefix, '/'); + + if (p == NULL || p == prefix) { + action = NULL; + break; + } + + *p = 0; + } + + g_free (prefix); + + return action; +} + +static gboolean +check_polkit_for_action (GConfDefaults *mechanism, + DBusGMethodInvocation *context, + const char *action) +{ + const char *sender; + GError *error; + DBusError dbus_error; + PolKitCaller *pk_caller; + PolKitAction *pk_action; + PolKitResult pk_result; + + error = NULL; + + /* Check that caller is privileged */ + sender = dbus_g_method_get_sender (context); + dbus_error_init (&dbus_error); + pk_caller = polkit_caller_new_from_dbus_name ( + dbus_g_connection_get_connection (mechanism->priv->system_bus_connection), + sender, + &dbus_error); + if (pk_caller == NULL) { + error = g_error_new (GCONF_DEFAULTS_ERROR, + GCONF_DEFAULTS_ERROR_GENERAL, + "Error getting information about caller: %s: %s", + dbus_error.name, dbus_error.message); + dbus_error_free (&dbus_error); + dbus_g_method_return_error (context, error); + g_error_free (error); + return FALSE; + } + + pk_action = polkit_action_new (); + polkit_action_set_action_id (pk_action, action); + pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, pk_action, pk_caller, TRUE, NULL); + polkit_caller_unref (pk_caller); + + if (pk_result != POLKIT_RESULT_YES) { + dbus_error_init (&dbus_error); + polkit_dbus_error_generate (pk_action, pk_result, &dbus_error); + dbus_set_g_error (&error, &dbus_error); + dbus_g_method_return_error (context, error); + dbus_error_free (&dbus_error); + g_error_free (error); + polkit_action_unref (pk_action); + return FALSE; + } + + polkit_action_unref (pk_action); + return TRUE; +} + +static char * +gconf_address_for_caller (GConfDefaults *mechanism, + DBusGMethodInvocation *context, + GError **gerror) +{ + char *sender; + DBusConnection *conn; + uid_t uid; + struct passwd *pwd; + char *result; + DBusError error; + + conn = dbus_g_connection_get_connection (mechanism->priv->system_bus_connection); + sender = dbus_g_method_get_sender (context); + + dbus_error_init (&error); + uid = dbus_bus_get_unix_user (conn, sender, &error); + g_free (sender); + if (uid == (unsigned)-1) { + dbus_set_g_error (gerror, &error); + dbus_error_free (&error); + return NULL; + } + + pwd = getpwuid (uid); + if (pwd == NULL) { + g_set_error (gerror, + 0, 0, + "Failed to get passwd information for uid %d", uid); + return NULL; + } + + result = g_strconcat ("xml:merged:", pwd->pw_dir, "/.gconf", NULL); + return result; +} + +static gboolean +path_is_excluded (const char *path, + const char **excludes) +{ + int i; + + for (i = 0; excludes && excludes[i]; i++) { + if (g_str_has_prefix (path, excludes[i])) + return TRUE; + } + + return FALSE; +} + +static void +copy_tree (GConfClient *src, + const char *path, + GConfChangeSet *changes, + const char **excludes) +{ + GSList *list, *l; + GConfEntry *entry; + + if (path_is_excluded (path, excludes)) + return; + + list = gconf_client_all_entries (src, path, NULL); + for (l = list; l; l = l->next) { + entry = l->data; + if (!path_is_excluded (entry->key, excludes)) + gconf_change_set_set (changes, entry->key, entry->value); + } + g_slist_foreach (list, (GFunc)gconf_entry_free, NULL); + g_slist_free (list); + + list = gconf_client_all_dirs (src, path, NULL); + for (l = list; l; l = l->next) + copy_tree (src, (const char *)l->data, changes, excludes); + g_slist_foreach (list, (GFunc)g_free, NULL); + g_slist_free (list); +} + +static void +copy_entry (GConfClient *src, + const char *path, + GConfChangeSet *changes, + const char **excludes) +{ + GConfValue *value; + + if (path_is_excluded (path, excludes)) + return; + + value = gconf_client_get (src, path, NULL); + if (value) { + gconf_change_set_set (changes, path, value); + gconf_value_free (value); + } +} + + +void +do_copy (GConfDefaults *mechanism, + gboolean mandatory, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context) +{ + char *address = NULL; + GConfClient *source = NULL; + GConfClient *dest = NULL; + GConfChangeSet *changes = NULL; + GConfEngine *engine; + GError *error; + GError *error2; + const char *action; + const char *annotation_key; + const char *default_action; + const char *dest_address; + int i; + + stop_killtimer (); + + /* check privileges for each include */ + if (mandatory) { + annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; + default_action = "org.gnome.gconf.defaults.set-mandatory"; + dest_address = "xml:merged:/etc/gconf/gconf.xml.mandatory"; + } + else { + annotation_key = "org.gnome.gconf.defaults.set-system.prefix"; + default_action = "org.gnome.gconf.defaults.set-system"; + dest_address = "xml:merged:/etc/gconf/gconf.xml.system"; + } + + for (i = 0; includes[i]; i++) { + action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]); + if (action == NULL) + action = default_action; + + if (!check_polkit_for_action (mechanism, context, action)) + goto out; + } + + error = NULL; + engine = gconf_engine_get_local (dest_address, &error); + if (error) + goto cleanup; + + dest = gconf_client_get_for_engine (engine); + gconf_engine_unref (engine); + + /* find the address to from the caller id */ + address = gconf_address_for_caller (mechanism, context, &error); + if (error) + goto cleanup; + + engine = gconf_engine_get_local (address, &error); + if (error) + goto cleanup; + + source = gconf_client_get_for_engine (engine); + gconf_engine_unref (engine); + + changes = gconf_change_set_new (); + + /* recursively copy each include, leaving out the excludes */ + for (i = 0; includes[i]; i++) { + if (gconf_client_dir_exists (source, includes[i], NULL)) + copy_tree (source, includes[i], changes, excludes); + else + copy_entry (source, includes[i], changes, excludes); + } + + gconf_client_commit_change_set (dest, changes, TRUE, &error); + gconf_client_suggest_sync (dest, NULL); + +cleanup: + g_free (address); + if (changes) + gconf_change_set_unref (changes); + if (dest) + g_object_unref (dest); + if (source) + g_object_unref (source); + + if (error) { + g_print ("failed to set GConf values: %s\n", error->message); + error2 = g_error_new (GCONF_DEFAULTS_ERROR, + GCONF_DEFAULTS_ERROR_GENERAL, + error->message); + g_error_free (error); + + dbus_g_method_return_error (context, error2); + g_error_free (error2); + } + else + dbus_g_method_return (context); + +out: + start_killtimer (); +} + +void +gconf_defaults_set_system (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context) +{ + do_copy (mechanism, FALSE, includes, excludes, context); +} + + +void +gconf_defaults_set_mandatory (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context) +{ + do_copy (mechanism, TRUE, includes, excludes, context); +} + +static void +unset_tree (GConfClient *dest, + const char *path, + GConfChangeSet *changes, + const char **excludes) +{ + GSList *list, *l; + GConfEntry *entry; + + if (path_is_excluded (path, excludes)) + return; + + list = gconf_client_all_entries (dest, path, NULL); + for (l = list; l; l = l->next) { + entry = l->data; + if (!path_is_excluded (entry->key, excludes)) + gconf_change_set_unset (changes, entry->key); + } + g_slist_foreach (list, (GFunc)gconf_entry_free, NULL); + g_slist_free (list); + + list = gconf_client_all_dirs (dest, path, NULL); + for (l = list; l; l = l->next) + unset_tree (dest, (const char *)l->data, changes, excludes); + g_slist_foreach (list, (GFunc)g_free, NULL); + g_slist_free (list); +} + +static void +unset_entry (GConfClient *dest, + const char *path, + GConfChangeSet *changes, + const char **excludes) +{ + if (path_is_excluded (path, excludes)) + return; + + gconf_change_set_unset (changes, path); +} + +static void +unset_in_db (GConfDefaults *mechanism, + const char *address, + const char **includes, + const char **excludes, + GError **error) +{ + GConfEngine *engine; + GConfClient *dest = NULL; + GConfChangeSet *changes = NULL; + int i; + + engine = gconf_engine_get_local (address, error); + if (*error) + goto out; + + dest = gconf_client_get_for_engine (engine); + gconf_engine_unref (engine); + + changes = gconf_change_set_new (); + + /* recursively copy each include, leaving out the excludes */ + for (i = 0; includes[i]; i++) { + if (gconf_client_dir_exists (dest, includes[i], NULL)) + unset_tree (dest, includes[i], changes, excludes); + else + unset_entry (dest, includes[i], changes, excludes); + } + + gconf_client_commit_change_set (dest, changes, TRUE, error); + gconf_client_suggest_sync (dest, NULL); + +out: + if (dest) + g_object_unref (dest); + if (changes) + gconf_change_set_unref (changes); +} + +void +gconf_defaults_unset_mandatory (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context) +{ + const char *annotation_key; + const char *default_action; + int i; + const char *action; + GError *error; + GError *error2; + + stop_killtimer (); + + annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; + default_action = "org.gnome.gconf.defaults.set-mandatory"; + + for (i = 0; includes[i]; i++) { + action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]); + if (action == NULL) + action = default_action; + + if (!check_polkit_for_action (mechanism, context, action)) + goto out; + } + + error = NULL; + unset_in_db (mechanism,"xml:merged:/etc/gconf/gconf.xml.mandatory", + includes, excludes, &error); + + if (error) { + error2 = g_error_new (GCONF_DEFAULTS_ERROR, + GCONF_DEFAULTS_ERROR_GENERAL, + error->message); + g_error_free (error); + + dbus_g_method_return_error (context, error2); + g_error_free (error2); + } + else + dbus_g_method_return (context); +out: + start_killtimer(); +} diff -up /dev/null GConf-2.22.0/defaults/gconf-defaults.h --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/gconf-defaults.h 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,84 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Matthias Clasen + * + * 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 GCONF_DEFAULTS_H +#define GCONF_DEFAULTS_H + +#include +#include + +G_BEGIN_DECLS + +#define GCONF_TYPE_DEFAULTS (gconf_defaults_get_type ()) +#define GCONF_DEFAULTS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GCONF_TYPE_DEFAULTS, GConfDefaults)) +#define GCONF_DEFAULTS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GCONF_TYPE_DEFAULTS, GConfDefaultsClass)) +#define GCONF_IS_DEFAULTS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCONF_TYPE_DEFAULTS)) +#define GCONF_IS_DEFAULTS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GCONF_TYPE_DEFAULTS)) +#define GCONF_DEFAULTS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GCONF_TYPE_DEFAULTS, GConfDefaultsClass)) + +typedef struct GConfDefaultsPrivate GConfDefaultsPrivate; + +typedef struct +{ + GObject parent; + GConfDefaultsPrivate *priv; +} GConfDefaults; + +typedef struct +{ + GObjectClass parent_class; +} GConfDefaultsClass; + +typedef enum +{ + GCONF_DEFAULTS_ERROR_GENERAL, + GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, + GCONF_DEFAULTS_NUM_ERRORS +} GConfDefaultsError; + +#define GCONF_DEFAULTS_ERROR gconf_defaults_error_quark () + +GType gconf_defaults_error_get_type (void); +#define GCONF_DEFAULTS_TYPE_ERROR (gconf_defaults_error_get_type ()) + + +GQuark gconf_defaults_error_quark (void); +GType gconf_defaults_get_type (void); +GConfDefaults *gconf_defaults_new (void); + +/* exported methods */ +void gconf_defaults_set_system (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context); + +void gconf_defaults_set_mandatory (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context); + +void gconf_defaults_unset_mandatory (GConfDefaults *mechanism, + const char **includes, + const char **excludes, + DBusGMethodInvocation *context); + +G_END_DECLS + +#endif /* GCONF_DEFAULTS_H */ diff -up /dev/null GConf-2.22.0/defaults/gconf-defaults-main.c --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/gconf-defaults-main.c 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,174 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Matthias Clasen + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +#include "gconf-defaults.h" + +static DBusGProxy * +get_bus_proxy (DBusGConnection *connection) +{ + DBusGProxy *bus_proxy; + + bus_proxy = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + return bus_proxy; +} + +#define BUS_NAME "org.gnome.GConf.Defaults" + +static gboolean +acquire_name_on_proxy (DBusGProxy *bus_proxy) +{ + GError *error; + guint result; + gboolean res; + gboolean ret; + + ret = FALSE; + + if (bus_proxy == NULL) { + goto out; + } + + error = NULL; + res = dbus_g_proxy_call (bus_proxy, + "RequestName", + &error, + G_TYPE_STRING, BUS_NAME, + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &result, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message); + g_error_free (error); + } else { + g_warning ("Failed to acquire %s", BUS_NAME); + } + goto out; + } + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + if (error != NULL) { + g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message); + g_error_free (error); + } else { + g_warning ("Failed to acquire %s", BUS_NAME); + } + goto out; + } + + ret = TRUE; + + out: + return ret; +} + +static DBusGConnection * +get_system_bus (void) +{ + GError *error; + DBusGConnection *bus; + DBusConnection *connection; + + error = NULL; + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + g_warning ("Couldn't connect to system bus: %s", error->message); + g_error_free (error); + goto out; + } + + connection = dbus_g_connection_get_connection (bus); + out: + return bus; +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + GConfDefaults *mechanism; + DBusGProxy *bus_proxy; + DBusGConnection *connection; + int ret; + + ret = 1; + + if (! g_thread_supported ()) { + g_thread_init (NULL); + } + dbus_g_thread_init (); + g_type_init (); + + connection = get_system_bus (); + if (connection == NULL) { + goto out; + } + + bus_proxy = get_bus_proxy (connection); + if (bus_proxy == NULL) { + g_warning ("Could not construct bus_proxy object; bailing out"); + goto out; + } + + mechanism = gconf_defaults_new (); + + if (mechanism == NULL) { + goto out; + } + + if (!acquire_name_on_proxy (bus_proxy)) { + g_warning ("Could not acquire name; bailing out"); + goto out; + } + + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + g_object_unref (mechanism); + g_main_loop_unref (loop); + ret = 0; + +out: + return ret; +} diff -up /dev/null GConf-2.22.0/defaults/gconf-defaults.xml --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/gconf-defaults.xml 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff -up /dev/null GConf-2.22.0/defaults/Makefile.am --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/Makefile.am 2008-05-04 18:18:04.000000000 -0400 @@ -0,0 +1,56 @@ +libexec_PROGRAMS = gconf-defaults-mechanism + +gconf-defaults-glue.h: $(srcdir)/gconf-defaults.xml + dbus-binding-tool --prefix=gconf_defaults --mode=glib-server \ + --output=gconf-defaults-glue.h \ + $(srcdir)/gconf-defaults.xml + + +gconf_defaults_mechanism_SOURCES = \ + gconf-defaults.h \ + gconf-defaults.c \ + gconf-defaults-glue.h \ + gconf-defaults-main.c + +INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(DEFAULTS_CFLAGS) + +gconf_defaults_mechanism_LDADD = \ + $(top_builddir}/gconf/libgconf-2.la \ + $(DEFAULTS_LIBS) + +BUILT_SOURCES = gconf-defaults-glue.h + +dbus_servicesdir = $(datadir)/dbus-1/system-services +dbus_confdir = $(sysconfdir)/dbus-1/system.d +polkitdir = $(datadir)/PolicyKit/policy + +dbus_services_in_files = org.gnome.GConf.Defaults.service.in +polkit_in_files = org.gnome.gconf.defaults.policy.in + +dbus_services_DATA = $(dbus_services_in_files:.service.in=.service) + +$(dbus_services_DATA): $(dbus_services_in_files) + sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@ + +dbus_conf_DATA = org.gnome.GConf.Defaults.conf + +@INTLTOOL_POLICY_RULE@ +polkit_DATA = $(polkit_in_files:.policy.in=.policy) + +check: + $(POLKIT_POLICY_FILE_VALIDATE) $(polkit_DATA) + +EXTRA_DIST = \ + $(dbus_services_in_files) \ + org.gnome.GConf.Defaults.conf \ + $(polkit_in_files) \ + gconf-defaults.xml + +CLEANFILES = \ + $(BUILT_SOURCES) \ + $(polkit_DATA) \ + $(dbus_services_DATA) + diff -up /dev/null GConf-2.22.0/defaults/org.gnome.GConf.Defaults.conf --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/org.gnome.GConf.Defaults.conf 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff -up /dev/null GConf-2.22.0/defaults/org.gnome.gconf.defaults.policy.in --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/org.gnome.gconf.defaults.policy.in 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,28 @@ + + + + The GNOME Project + http://www.gnome.org/projects/gconf/ + gconf-editor + + + Change GConf system values + Privileges are required to change GConf system values + + no + auth_admin + + + + + Change GConf mandatory values + Privileges are required to change GConf mandatory values + + no + auth_admin + + + + diff -up /dev/null GConf-2.22.0/defaults/org.gnome.GConf.Defaults.service.in --- /dev/null 2008-05-04 08:09:30.807030239 -0400 +++ GConf-2.22.0/defaults/org.gnome.GConf.Defaults.service.in 2008-05-04 18:15:22.000000000 -0400 @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.gnome.GConf.Defaults +Exec=@LIBEXECDIR@/gconf-defaults-mechanism +User=root diff -up GConf-2.22.0/Makefile.am.defaults GConf-2.22.0/Makefile.am --- GConf-2.22.0/Makefile.am.defaults 2007-06-25 07:11:31.000000000 -0400 +++ GConf-2.22.0/Makefile.am 2008-05-04 18:15:22.000000000 -0400 @@ -1,5 +1,5 @@ -SUBDIRS = gconf backends po doc examples +SUBDIRS = gconf backends po doc examples defaults DIST_SUBDIRS=tests $(SUBDIRS) EXTRA_DIST = \ diff -up GConf-2.22.0/po/POTFILES.in.defaults GConf-2.22.0/po/POTFILES.in --- GConf-2.22.0/po/POTFILES.in.defaults 2007-06-25 07:11:31.000000000 -0400 +++ GConf-2.22.0/po/POTFILES.in 2008-05-04 18:15:22.000000000 -0400 @@ -9,6 +9,7 @@ backends/xml-backend.c backends/xml-cache.c backends/xml-dir.c backends/xml-entry.c +defaults/org.gnome.gconf.defaults.policy.in gconf/gconf-backend.c gconf/gconf-client.c gconf/gconf-database.c