/* GConf * Copyright (C) 1999, 2000 Red Hat Inc. * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include "gconf.h" #include "gconf-internals.h" #include #include #include #include #include #include #include #include #include #include #include #include typedef enum { LOAD_SCHEMA_FILE, LOAD_ENTRY_FILE } LoadType; static int set_mode = FALSE; static int get_mode = FALSE; static int unset_mode = FALSE; static int toggle_mode = FALSE; static int all_entries_mode = FALSE; static int all_subdirs_mode = FALSE; static char* dir_exists = NULL; static int recursive_list = FALSE; static int search_key = FALSE; static int search_key_regex = FALSE; static int dump_values = FALSE; static int set_schema_mode = FALSE; static char* value_type = NULL; static int get_type_mode = FALSE; static int get_list_size_mode = FALSE; static int get_list_element_mode = FALSE; static char* value_list_type = NULL; static char* value_car_type = NULL; static char* value_cdr_type = NULL; static int shutdown_gconfd = FALSE; static int ping_gconfd = FALSE; static int spawn_gconfd = FALSE; static char* short_desc = NULL; static char* long_desc = NULL; static char* owner = NULL; static char* schema_file = NULL; static char* entry_file = NULL; static char* unload_entry_file = NULL; static const char* config_source = NULL; static int use_local_source = FALSE; static int makefile_install_mode = FALSE; static int makefile_uninstall_mode = FALSE; static int break_key_mode = FALSE; static int break_dir_mode = FALSE; static int short_docs_mode = FALSE; static int long_docs_mode = FALSE; static int schema_name_mode = FALSE; static int associate_schema_mode = FALSE; static int dissociate_schema_mode = FALSE; static int ignore_schema_defaults = FALSE; static int default_source_mode = FALSE; static int recursive_unset_mode = FALSE; static int do_version = FALSE; static const gchar **args = NULL; static const GOptionEntry client_entries[] = { { "set", 's', 0, G_OPTION_ARG_NONE, &set_mode, N_("Set a key to a value and sync. Use with --type."), NULL }, { "get", 'g', 0, G_OPTION_ARG_NONE, &get_mode, N_("Print the value of a key to standard output."), NULL }, { "unset", 'u', 0, G_OPTION_ARG_NONE, &unset_mode, N_("Unset the keys on the command line"), NULL }, { "recursive-unset", '\0', 0, G_OPTION_ARG_NONE, &recursive_unset_mode, N_("Recursively unset all keys at or below the key/directory names on the command line"), NULL }, { "toggle", '\0', 0, G_OPTION_ARG_NONE, &toggle_mode, N_("Toggles a boolean key."), NULL }, { "all-entries", 'a', 0, G_OPTION_ARG_NONE, &all_entries_mode, N_("Print all key/value pairs in a directory."), NULL }, { "all-dirs", '\0', 0, G_OPTION_ARG_NONE, &all_subdirs_mode, N_("Print all subdirectories in a directory."), NULL }, { "recursive-list", 'R', 0, G_OPTION_ARG_NONE, &recursive_list, N_("Print all subdirectories and entries under a directory, recursively."), NULL }, { "search-key", 'S', 0, G_OPTION_ARG_NONE, &search_key, N_("Search for a key, recursively."), NULL }, { "search-key-regex", 0, 0, G_OPTION_ARG_NONE, &search_key_regex, N_("Search for a key, recursively."), NULL }, { "short-docs", '\0', 0, G_OPTION_ARG_NONE, &short_docs_mode, N_("Get the short doc string for a key"), NULL }, { "long-docs", '\0', 0, G_OPTION_ARG_NONE, &long_docs_mode, N_("Get the long doc string for a key"), NULL }, { "dir-exists", '\0', 0, G_OPTION_ARG_STRING, &dir_exists, N_("Return 0 if the directory exists, 2 if it does not."), NULL }, { "ignore-schema-defaults", '\0', 0, G_OPTION_ARG_NONE, &ignore_schema_defaults, N_("Ignore schema defaults when reading values."), NULL }, { NULL } }; static const GOptionEntry load_entries[] = { { "dump", '\0', 0, G_OPTION_ARG_NONE, &dump_values, N_("Dump to standard output an XML description of all entries under a directory, recursively."), NULL }, { "load", '\0', 0, G_OPTION_ARG_FILENAME, &entry_file, N_("Load from the specified file an XML description of values and set them relative to a directory."), NULL }, { "unload", '\0', 0, G_OPTION_ARG_FILENAME, &unload_entry_file, N_("Unload a set of values described in an XML file."), NULL }, { NULL } }; static const GOptionEntry server_entries[] = { { "get-default-source", '\0', 0, G_OPTION_ARG_NONE, &default_source_mode, N_("Get the name of the default source"), NULL }, { "shutdown", '\0', 0, G_OPTION_ARG_NONE, &shutdown_gconfd, N_("Shut down gconfd. DON'T USE THIS OPTION WITHOUT GOOD REASON."), NULL }, { "ping", 'p', 0, G_OPTION_ARG_NONE, &ping_gconfd, N_("Return 0 if gconfd is running, 2 if not."), NULL }, { "spawn", '\0', 0, G_OPTION_ARG_NONE, &spawn_gconfd, N_("Launch the configuration server (gconfd). (Normally happens automatically when needed.)"), NULL }, { NULL } }; static const GOptionEntry type_entries[] = { { "type", 't', 0, G_OPTION_ARG_STRING, &value_type, N_("Specify the type of the value being set, or the type of the value a schema describes. Unique abbreviations OK."), N_("int|bool|float|string|list|pair") }, { "get-type", 'T', 0, G_OPTION_ARG_NONE, &get_type_mode, N_("Print the data type of a key to standard output."), NULL }, { "get-list-size", '\0', 0, G_OPTION_ARG_NONE, &get_list_size_mode, N_("Get the number of elements in a list key."), NULL }, { "get-list-element", '\0', 0, G_OPTION_ARG_NONE, &get_list_element_mode, N_("Get a specific element from a list key, numerically indexed."), NULL }, { "list-type", '\0', 0, G_OPTION_ARG_STRING, &value_list_type, N_("Specify the type of the list value being set, or the type of the value a schema describes. Unique abbreviations OK."), N_("int|bool|float|string") }, { "car-type", '\0', 0, G_OPTION_ARG_STRING, &value_car_type, N_("Specify the type of the car pair value being set, or the type of the value a schema describes. Unique abbreviations OK."), N_("int|bool|float|string") }, { "cdr-type", '\0', 0, G_OPTION_ARG_STRING, &value_cdr_type, N_("Specify the type of the cdr pair value being set, or the type of the value a schema describes. Unique abbreviations OK."), N_("int|bool|float|string") }, { NULL } }; static const GOptionEntry install_entries[] = { { "install-schema-file", '\0', 0, G_OPTION_ARG_FILENAME, &schema_file, N_("Specify a schema file to be installed"), N_("FILENAME") }, { "config-source", '\0', 0, G_OPTION_ARG_STRING, &config_source, N_("Specify a configuration source to use rather than the default path"), N_("SOURCE") }, { "direct", '\0', 0, G_OPTION_ARG_NONE, &use_local_source, N_("Bypass server, and access the configuration database directly. Requires that gconfd is not running."), NULL }, { "makefile-install-rule", '\0', 0, G_OPTION_ARG_NONE, &makefile_install_mode, N_("Properly installs schema files on the command line into the database. Specify a custom configuration source in the GCONF_CONFIG_SOURCE environment variable, or set set the variable to an empty string to use the default configuration source."), NULL }, { "makefile-uninstall-rule", '\0', 0, G_OPTION_ARG_NONE, &makefile_uninstall_mode, N_("Properly uninstalls schema files on the command line from the database. GCONF_CONFIG_SOURCE environment variable should be set to a non-default configuration source or set to the empty string to use the default."), NULL }, { NULL } }; static const GOptionEntry test_entries[] = { { "break-key", '\0', 0, G_OPTION_ARG_NONE, &break_key_mode, N_("Torture-test an application by setting and unsetting a bunch of values of different types for keys on the command line."), NULL }, { "break-directory", '\0', 0, G_OPTION_ARG_NONE, &break_dir_mode, N_("Torture-test an application by setting and unsetting a bunch of keys inside the directories on the command line."), NULL }, { NULL } }; static const GOptionEntry schema_entries[] = { { "set-schema", '\0', 0, G_OPTION_ARG_NONE, &set_schema_mode, N_("Set a schema and sync. Use with --short-desc, --long-desc, --owner, and --type."), NULL }, { "short-desc", '\0', 0, G_OPTION_ARG_STRING, &short_desc, N_("Specify a short half-line description to go in a schema."), N_("DESCRIPTION") }, { "long-desc", '\0', 0, G_OPTION_ARG_STRING, &long_desc, N_("Specify a several-line description to go in a schema."), N_("DESCRIPTION") }, { "owner", '\0', 0, G_OPTION_ARG_STRING, &owner, N_("Specify the owner of a schema"), N_("OWNER") }, { "get-schema-name", '\0', 0, G_OPTION_ARG_NONE, &schema_name_mode, N_("Get the name of the schema applied to this key"), NULL }, { "apply-schema", '\0', 0, G_OPTION_ARG_NONE, &associate_schema_mode, N_("Specify the schema name followed by the key to apply the schema name to"), NULL }, { "unapply-schema", '\0', 0, G_OPTION_ARG_NONE, &dissociate_schema_mode, N_("Remove any schema name applied to the given keys"), NULL }, { NULL } }; static const GOptionEntry main_entries[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &do_version, N_("Print version"), NULL }, { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &args, N_("[FILE...]|[KEY...]|[DIR...]"), NULL }, { NULL } }; static int do_break_key(GConfEngine* conf, const gchar** args); static int do_break_directory(GConfEngine* conf, const gchar** args); static int do_makefile_install(GConfEngine* conf, const gchar** args, gboolean unload); static int do_recursive_list(GConfEngine* conf, const gchar** args); static int do_search_key(GConfEngine* conf, const gchar** args); static int do_search_key_regex(GConfEngine* conf, const gchar** args); static int do_dump_values(GConfEngine* conf, const gchar** args); static int do_all_pairs(GConfEngine* conf, const gchar** args); static void list_pairs_in_dir(GConfEngine* conf, const gchar* dir, guint depth); static int get_schema_from_xml(xmlNodePtr node, gchar **schema_key, GHashTable** schemas_hash, GSList **applyto_list); static int get_first_value_from_xml(xmlNodePtr node, GConfValue** ret_value); static void print_value_in_xml(GConfValue* value, int indent); static void dump_entries_in_dir(GConfEngine* conf, const gchar* dir, const gchar *base_dir); static gboolean do_dir_exists(GConfEngine* conf, const gchar* dir); static void do_spawn_daemon(GConfEngine* conf); static int do_get(GConfEngine* conf, const gchar** args); static int do_set(GConfEngine* conf, const gchar** args); static int do_toggle(GConfEngine* conf, const gchar** args); static int do_get_type(GConfEngine* conf, const gchar** args); static int do_get_list_size(GConfEngine* conf, const gchar** args); static int do_get_list_element(GConfEngine* conf, const gchar** args); static int do_set_schema(GConfEngine* conf, const gchar** args); static int do_all_entries(GConfEngine* conf, const gchar** args); static int do_unset(GConfEngine* conf, const gchar** args); static int do_recursive_unset (GConfEngine* conf, const gchar** args); static int do_all_subdirs(GConfEngine* conf, const gchar** args); static int do_load_file(GConfEngine* conf, LoadType load_type, gboolean unload, const gchar* file, const gchar** base_dirs); static int do_sync(GConfEngine* conf); static int do_short_docs (GConfEngine *conf, const gchar **args); static int do_long_docs (GConfEngine *conf, const gchar **args); static int do_get_schema_name (GConfEngine *conf, const gchar **args); static int do_associate_schema (GConfEngine *conf, const gchar **args); static int do_dissociate_schema (GConfEngine *conf, const gchar **args); static int do_get_default_source (const gchar **args); int main (int argc, char** argv) { GConfEngine* conf; GOptionContext *context; GOptionGroup *group; GError* err = NULL; LIBXML_TEST_VERSION; xmlKeepBlanksDefault(1); setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE,GCONF_LOCALE_DIR); textdomain (GETTEXT_PACKAGE); g_thread_init (NULL); _gconf_init_i18n (); context = g_option_context_new (N_("- Tool to manipulate a GConf configuration")); #if GLIB_CHECK_VERSION (2, 12, 0) g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); #endif group = g_option_group_new ("client", N_("Client options:"), N_("Show client options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, client_entries); g_option_context_add_group (context, group); group = g_option_group_new ("key-type", N_("Key type options:"), N_("Show key type options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, type_entries); g_option_context_add_group (context, group); group = g_option_group_new ("load", N_("Load/Save options:"), N_("Show load/save options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, load_entries); g_option_context_add_group (context, group); group = g_option_group_new ("server", N_("Server options:"), N_("Show server options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, server_entries); g_option_context_add_group (context, group); group = g_option_group_new ("install", N_("Installation options:"), N_("Show installation options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, install_entries); g_option_context_add_group (context, group); group = g_option_group_new ("test", N_("Test options:"), N_("Show test options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, test_entries); g_option_context_add_group (context, group); group = g_option_group_new ("schema", N_("Schema options:"), N_("Show schema options"), NULL, NULL); g_option_group_set_translation_domain (group, GETTEXT_PACKAGE); g_option_group_add_entries (group, schema_entries); g_option_context_add_group (context, group); g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE); if (argc < 2) { g_printerr (_("Run '%s --help' to see a full list of available command line options.\n"), argv[0]); return 1; } g_option_context_parse (context, &argc, &argv, &err); g_option_context_free (context); if (err) { g_printerr (_("Error while parsing options: %s.\nRun '%s --help' to see a full list of available command line options.\n"), err->message, argv[0]); g_error_free (err); return 1; } /* Um, this is a mess. Not using compatible options? */ if (do_version) { g_print ("%s\n", VERSION); return 0; } if ((get_mode && set_mode) || (get_mode && unset_mode)) { g_printerr (_("Can't get and set/unset simultaneously\n")); return 1; } if ((set_mode && get_mode) || (set_mode && unset_mode) || (set_mode && get_type_mode) || (set_mode && get_list_size_mode) || (set_mode && get_list_element_mode)) { g_printerr (_("Can't set and get/unset simultaneously\n")); return 1; } if ((get_type_mode && set_mode) || (get_type_mode && unset_mode)) { g_printerr (_("Can't get type and set/unset simultaneously\n")); return 1; } if ((toggle_mode && set_mode) || (toggle_mode && get_mode) || (toggle_mode && unset_mode)) { g_printerr (_("Can't toggle and get/set/unset simultaneously\n")); return 1; } if ((all_entries_mode && get_mode) || (all_entries_mode && set_mode) || (all_entries_mode && get_type_mode) || (all_entries_mode && unset_mode) || (all_entries_mode && get_list_size_mode) || (all_entries_mode && get_list_element_mode)) { g_printerr (_("Can't use --all-entries with --get or --set\n")); return 1; } if ((all_subdirs_mode && get_mode) || (all_subdirs_mode && set_mode) || (all_subdirs_mode && get_type_mode) || (all_subdirs_mode && unset_mode) || (all_subdirs_mode && get_list_size_mode) || (all_subdirs_mode && get_list_element_mode)) { g_printerr (_("Can't use --all-dirs with --get or --set\n")); return 1; } if ((recursive_list && get_mode) || (recursive_list && set_mode) || (recursive_list && unset_mode) || (recursive_list && get_type_mode) || (recursive_list && get_list_size_mode) || (recursive_list && get_list_element_mode) || (recursive_list && all_entries_mode) || (recursive_list && all_subdirs_mode) || (recursive_list && (search_key || search_key_regex))) { g_printerr (_("--recursive-list should not be used with --get, --set, --unset, --all-entries, --all-dirs, or --search-key\n")); return 1; } if ((set_schema_mode && get_mode) || (set_schema_mode && set_mode) || (set_schema_mode && unset_mode) || (set_schema_mode && get_type_mode) || (set_schema_mode && get_list_size_mode) || (set_schema_mode && get_list_element_mode) || (set_schema_mode && all_entries_mode) || (set_schema_mode && all_subdirs_mode) || (set_schema_mode && (search_key || search_key_regex))) { g_printerr (_("--set_schema should not be used with --get, --set, --unset, --all-entries, --all-dirs, or --search-key\n")); return 1; } if ((value_type != NULL) && !(set_mode || set_schema_mode)) { g_printerr (_("Value type is only relevant when setting a value\n")); return 1; } if (set_mode && (value_type == NULL)) { g_printerr (_("Must specify a type when setting a value\n")); return 1; } if (ignore_schema_defaults && !(get_mode || all_entries_mode || dump_values || recursive_list || get_list_size_mode || get_list_element_mode)) { g_printerr (_("--ignore-schema-defaults is only relevant with --get, --all-entries, --dump, --recursive-list, --get-list-size or --get-list-element\n")); return 1; } if (ping_gconfd && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || get_type_mode || get_list_size_mode || get_list_element_mode || spawn_gconfd || dir_exists || schema_file || makefile_install_mode || makefile_uninstall_mode || break_key_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "-p/--ping"); return 1; } if (dir_exists && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || get_type_mode || get_list_size_mode || get_list_element_mode || spawn_gconfd || schema_file || makefile_install_mode || makefile_uninstall_mode || break_key_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--dir-exists"); return 1; } if (schema_file && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || get_type_mode || get_list_size_mode || get_list_element_mode || spawn_gconfd || dir_exists || makefile_install_mode || makefile_uninstall_mode || break_key_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--install-schema-file"); return 1; } if (makefile_install_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || get_type_mode || get_list_size_mode || get_list_element_mode || makefile_uninstall_mode || spawn_gconfd || dir_exists || schema_file || break_key_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--makefile-install-rule"); return 1; } if (makefile_uninstall_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || makefile_install_mode || spawn_gconfd || dir_exists || schema_file || break_key_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--makefile-uninstall-rule"); return 1; } if (break_key_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || get_type_mode || get_list_size_mode || get_list_element_mode || spawn_gconfd || dir_exists || schema_file || makefile_install_mode || makefile_uninstall_mode || break_dir_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--break-key"); return 1; } if (break_dir_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex || get_type_mode || get_list_size_mode || get_list_element_mode || spawn_gconfd || dir_exists || schema_file || break_key_mode || makefile_install_mode || makefile_uninstall_mode || short_docs_mode || long_docs_mode || schema_name_mode)) { g_printerr (_("%s option must be used by itself.\n"), "--break-directory"); return 1; } /* FIXME not checking that --recursive-unset, --dump or --load are used alone */ if (use_local_source && config_source == NULL) { g_printerr (_("You must specify a configuration source with --config-source when using --direct\n")); return 1; } if (!gconf_init(argc, argv, &err)) { g_printerr (_("Failed to init GConf: %s\n"), err->message); g_error_free(err); err = NULL; return 1; } /* Do this first, since we want to do only this if the user selected it. */ if (ping_gconfd) { if (gconf_ping_daemon()) return 0; else return 2; } /* Before creating engine */ if (default_source_mode) { if (do_get_default_source (args) == 1) return 1; else return 0; } if (makefile_install_mode && g_getenv ("GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL")) { g_print (_("GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL is set, not installing schemas\n")); makefile_install_mode = FALSE; } if (makefile_uninstall_mode && g_getenv ("GCONF_DISABLE_MAKEFILE_SCHEMA_UNINSTALL")) { g_print (_("GCONF_DISABLE_MAKEFILE_SCHEMA_UNINSTALL is set, not uninstalling schemas\n")); makefile_uninstall_mode = FALSE; } if (makefile_install_mode || makefile_uninstall_mode) { g_assert (config_source == NULL); /* Try the environment variable */ config_source = g_getenv ("GCONF_CONFIG_SOURCE"); if (config_source == NULL) { g_printerr (_("Must set the GCONF_CONFIG_SOURCE environment variable\n")); return 1; } if (*config_source == '\0') { /* Properly set, but set to nothing (use default source) */ config_source = NULL; } use_local_source = TRUE; /* shut down daemon, this is a race condition, but will usually work. */ gconf_shutdown_daemon (NULL); } if (config_source == NULL) { /* If we aren't running from within a session, * assume we'll be touching the database locally */ conf = NULL; if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) { char *conffile; GSList *addresses; conffile = g_strconcat (GCONF_CONFDIR, "/path", NULL); addresses = gconf_load_source_path (conffile, NULL); g_free(conffile); conf = gconf_engine_get_local_for_addresses (addresses, &err); gconf_address_list_free (addresses); } if (conf == NULL) conf = gconf_engine_get_default(); } else { GSList *addresses; addresses = gconf_persistent_name_get_address_list (config_source); if (use_local_source) conf = gconf_engine_get_local_for_addresses (addresses, &err); else conf = gconf_engine_get_for_addresses (addresses, &err); gconf_address_list_free (addresses); } if (conf == NULL) { g_assert(err != NULL); g_printerr (_("Failed to access configuration source(s): %s\n"), err->message); g_error_free(err); err = NULL; return 1; } else { g_assert(err == NULL); } g_assert(conf != NULL); if (dir_exists != NULL) { gboolean success; success = do_dir_exists(conf, dir_exists); gconf_engine_unref(conf); if (success) return 0; /* TRUE */ else return 2; /* FALSE */ } if (schema_file != NULL) { gint retval; retval = do_load_file(conf, LOAD_SCHEMA_FILE, FALSE, schema_file, NULL); if (!retval) retval = do_sync(conf); gconf_engine_unref(conf); return retval; } if (entry_file != NULL) { gint retval; retval = do_load_file(conf, LOAD_ENTRY_FILE, FALSE, entry_file, args); if (!retval) retval = do_sync(conf); gconf_engine_unref(conf); return retval; } if (unload_entry_file != NULL) { gint retval; retval = do_load_file(conf, LOAD_ENTRY_FILE, TRUE, unload_entry_file, args); if (!retval) retval = do_sync(conf); gconf_engine_unref(conf); return retval; } if (spawn_gconfd) { do_spawn_daemon(conf); /* don't exit, it's OK to have this along with other options (however, it's probably pointless) */ } if (makefile_install_mode) { gint retval; umask (022); retval = do_makefile_install (conf, args, FALSE); gconf_engine_unref (conf); return retval; } if (makefile_uninstall_mode) { gint retval; umask (022); retval = do_makefile_install (conf, args, TRUE); gconf_engine_unref (conf); return retval; } if (break_key_mode) { gint retval = do_break_key(conf, args); gconf_engine_unref(conf); return retval; } if (break_dir_mode) { gint retval = do_break_directory(conf, args); gconf_engine_unref(conf); return retval; } if (get_mode) { if (do_get(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (set_mode) { if (do_set(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (toggle_mode) { if (do_toggle(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (get_type_mode) { if (do_get_type (conf, args) == 1) { gconf_engine_unref (conf); return 1; } } if (get_list_size_mode) { if (do_get_list_size (conf, args) == 1) { gconf_engine_unref (conf); return 1; } } if (get_list_element_mode) { if (do_get_list_element (conf, args) == 1) { gconf_engine_unref (conf); return 1; } } if (set_schema_mode) { if (do_set_schema(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (short_docs_mode) { if (do_short_docs(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (long_docs_mode) { if (do_long_docs(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (schema_name_mode) { if (do_get_schema_name(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (associate_schema_mode) { if (do_associate_schema(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (dissociate_schema_mode) { if (do_dissociate_schema (conf, args) == 1) { gconf_engine_unref (conf); return 1; } } if (all_entries_mode) { if (do_all_entries(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (unset_mode) { if (do_unset(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (recursive_unset_mode) { if (do_recursive_unset(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (all_subdirs_mode) { if (do_all_subdirs(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (recursive_list) { if (do_recursive_list(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (search_key) { if (do_search_key(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (search_key_regex) { if (do_search_key_regex(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } if (dump_values) { if (do_dump_values(conf, args) == 1) { gconf_engine_unref(conf); return 1; } } gconf_engine_unref(conf); if (shutdown_gconfd) { err = NULL; gconf_shutdown_daemon(&err); } if (err != NULL) { g_printerr (_("Shutdown error: %s\n"), err->message); g_error_free(err); err = NULL; } return 0; } static void recurse_subdir_list(GConfEngine* conf, GSList* subdirs, const gchar* parent, guint depth) { GSList* tmp; gchar* whitespace; whitespace = g_strnfill(depth, ' '); tmp = subdirs; while (tmp != NULL) { gchar* s = tmp->data; g_print ("%s%s:\n", whitespace, s); list_pairs_in_dir(conf, s, depth); recurse_subdir_list(conf, gconf_engine_all_dirs(conf, s, NULL), s, depth+1); g_free(s); tmp = g_slist_next(tmp); } g_slist_free(subdirs); g_free(whitespace); } static int do_recursive_list(GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify one or more directories to recursively list.\n")); return 1; } while (*args) { GSList* subdirs; subdirs = gconf_engine_all_dirs(conf, *args, NULL); list_pairs_in_dir(conf, *args, 0); recurse_subdir_list(conf, subdirs, *args, 1); ++args; } return 0; } static gboolean match_pattern (gpointer pattern, const char *key) { return g_pattern_match_string((GPatternSpec*) pattern, key); } static gboolean match_regex (gpointer regex, const char *key) { return g_regex_match((GRegex*) regex, key, 0, NULL); } typedef gboolean (* MatchFunc) (gpointer match_data, const char *key); static void search_key_in_dir(GConfEngine* conf, const gchar* dir, MatchFunc match_func, gpointer match_data) { GSList* pairs; GSList* tmp; GError* err = NULL; pairs = gconf_engine_all_entries(conf, dir, &err); if (err != NULL) { g_printerr (_("Failure listing entries in `%s': %s\n"), dir, err->message); g_error_free(err); err = NULL; } if (pairs != NULL) { tmp = pairs; while (tmp != NULL) { GConfEntry* pair = tmp->data; gchar* s; const gchar *k; if (gconf_entry_get_value (pair) && (!ignore_schema_defaults || !gconf_entry_get_is_default (pair))) s = gconf_value_to_string (gconf_entry_get_value (pair)); else s = g_strdup(_("(no value set)")); k = gconf_key_key (gconf_entry_get_key (pair)); if (match_func(match_data, k)) g_print (" %s/%s = %s\n", dir, k, s); g_free(s); gconf_entry_free(pair); tmp = g_slist_next(tmp); } g_slist_free(pairs); } } static void recurse_subdir_search(GConfEngine* conf, GSList* subdirs, const gchar* parent, MatchFunc match_func, gpointer match_data) { GSList* tmp; tmp = subdirs; while (tmp != NULL) { gchar* s = tmp->data; search_key_in_dir(conf, s, match_func, match_data); recurse_subdir_search(conf, gconf_engine_all_dirs(conf, s, NULL), s, match_func, match_data); g_free(s); tmp = g_slist_next(tmp); } g_slist_free(subdirs); } static int do_search(GConfEngine* conf, MatchFunc match_func, gpointer match_data) { GSList* subdirs; subdirs = gconf_engine_all_dirs(conf, "/", NULL); search_key_in_dir(conf, "/", match_func, match_data); recurse_subdir_search(conf, subdirs, "/", match_func, match_data); return 0; } static int do_search_key(GConfEngine* conf, const gchar** args) { GPatternSpec* pattern; if (args == NULL) { g_printerr (_("Must specify a key pattern to search for.\n")); return 1; } pattern = g_pattern_spec_new (*args); do_search(conf, match_pattern, pattern); g_pattern_spec_free (pattern); return 0; } static int do_search_key_regex(GConfEngine* conf, const gchar** args) { GRegex* regex; GError *error = NULL; if (args == NULL) { g_printerr(_("Must specify a PCRE regex to search for.\n")); return 1; } regex = g_regex_new(args[0], G_REGEX_OPTIMIZE, 0, &error); if (!regex) { g_printerr(_("Error compiling regex: %s\n"), error->message); g_error_free(error); return 1; } do_search(conf, match_regex, regex); g_regex_unref(regex); return 0; } static void recurse_subdir_dump(GConfEngine* conf, GSList* dirs, const gchar* base_dir) { GSList* tmp; tmp = dirs; while (tmp != NULL) { gchar* s = tmp->data; GSList* subdirs; dump_entries_in_dir(conf, s, base_dir); subdirs = g_slist_sort(gconf_engine_all_dirs(conf, s, NULL), (GCompareFunc)strcmp); recurse_subdir_dump(conf, subdirs, base_dir); g_free(s); tmp = tmp->next; } g_slist_free(dirs); } static int do_dump_values(GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify one or more directories to dump.\n")); return 1; } g_print ("\n"); while (*args) { GSList* subdirs; g_print (" \n", *args); subdirs = g_slist_sort(gconf_engine_all_dirs(conf, *args, NULL), (GCompareFunc)strcmp); dump_entries_in_dir(conf, *args, *args); recurse_subdir_dump(conf, subdirs, *args); g_print (" \n"); ++args; } g_print ("\n"); return 0; } static void list_pairs_in_dir(GConfEngine* conf, const gchar* dir, guint depth) { GSList* pairs; GSList* tmp; gchar* whitespace; GError* err = NULL; whitespace = g_strnfill(depth, ' '); pairs = gconf_engine_all_entries(conf, dir, &err); if (err != NULL) { g_printerr (_("Failure listing entries in `%s': %s\n"), dir, err->message); g_error_free(err); err = NULL; } if (pairs != NULL) { tmp = pairs; while (tmp != NULL) { GConfEntry* pair = tmp->data; gchar* s; if (gconf_entry_get_value (pair) && (!ignore_schema_defaults || !gconf_entry_get_is_default (pair))) s = gconf_value_to_string (gconf_entry_get_value (pair)); else s = g_strdup(_("(no value set)")); g_print (" %s%s = %s\n", whitespace, gconf_key_key (gconf_entry_get_key (pair)), s); g_free(s); gconf_entry_free(pair); tmp = g_slist_next(tmp); } g_slist_free(pairs); } g_free(whitespace); } static int do_all_pairs(GConfEngine* conf, const gchar** args) { while (*args) { list_pairs_in_dir(conf, *args, 0); ++args; } return 0; } /* FIXME: only prints the schema for the current locale. * Need some way of getting the schemas for all locales. */ static void print_schema_in_xml(GConfValue* value, int indent) { GConfSchema* schema; GConfValueType type; GConfValueType list_type; GConfValueType car_type; GConfValueType cdr_type; GConfValue* default_value; const gchar* owner; const gchar* short_desc; const gchar* long_desc; gchar* whitespace; whitespace = g_strnfill(indent, ' '); schema = gconf_value_get_schema(value); type = gconf_schema_get_type(schema); list_type = gconf_schema_get_list_type(schema); car_type = gconf_schema_get_car_type(schema); cdr_type = gconf_schema_get_cdr_type(schema); owner = gconf_schema_get_owner(schema); default_value = gconf_schema_get_default_value(schema); short_desc = gconf_schema_get_short_desc(schema); long_desc = gconf_schema_get_long_desc(schema); g_print ("%s\n", whitespace); if (owner) g_print ("%s %s\n", whitespace, owner); g_print ("%s %s\n", whitespace, gconf_value_type_to_string(type)); if (type == GCONF_VALUE_LIST) g_print ("%s %s\n", whitespace, gconf_value_type_to_string(list_type)); else if (type == GCONF_VALUE_PAIR) { g_print ("%s %s\n", whitespace, gconf_value_type_to_string(car_type)); g_print ("%s %s\n", whitespace, gconf_value_type_to_string(cdr_type)); } g_print ("%s \n", whitespace, gconf_schema_get_locale (schema)); if (default_value) { g_print ("%s \n", whitespace); print_value_in_xml(default_value, indent + 6); g_print ("%s \n", whitespace); } if (short_desc) { gchar* tmp = g_markup_escape_text(short_desc, -1); g_print ("%s %s\n", whitespace, tmp); g_free(tmp); } if (long_desc) { gchar* tmp = g_markup_escape_text(long_desc, -1); g_print ("%s %s\n", whitespace, tmp); g_free(tmp); } g_print ("%s \n", whitespace); g_print ("%s\n", whitespace); g_free(whitespace); } static void print_pair_in_xml(GConfValue* value, int indent) { gchar* whitespace; whitespace = g_strnfill(indent, ' '); g_print ("%s\n", whitespace); g_print ("%s \n", whitespace); print_value_in_xml(gconf_value_get_car(value), indent + 4); g_print ("%s \n", whitespace); g_print ("%s \n", whitespace); print_value_in_xml(gconf_value_get_cdr(value), indent + 4); g_print ("%s \n", whitespace); g_print ("%s\n", whitespace); g_free(whitespace); } static void print_list_in_xml(GConfValue* value, int indent) { GConfValueType list_type; GSList* tmp; gchar* whitespace; whitespace = g_strnfill(indent, ' '); list_type = gconf_value_get_list_type(value); g_print ("%s\n", whitespace, gconf_value_type_to_string(list_type)); tmp = gconf_value_get_list(value); while (tmp) { print_value_in_xml(tmp->data, indent + 4); tmp = tmp->next; } g_print ("%s\n", whitespace); g_free(whitespace); } static void print_value_in_xml(GConfValue* value, int indent) { gchar* whitespace; gchar* tmp; whitespace = g_strnfill(indent, ' '); g_print ("%s\n", whitespace); switch (value->type) { case GCONF_VALUE_INT: tmp = gconf_value_to_string(value); g_print ("%s %s\n", whitespace, tmp); g_free(tmp); break; case GCONF_VALUE_FLOAT: tmp = gconf_value_to_string(value); g_print ("%s %s\n", whitespace, tmp); g_free(tmp); break; case GCONF_VALUE_STRING: tmp = g_markup_escape_text(gconf_value_get_string(value), -1); g_print ("%s %s\n", whitespace, (tmp[0] == ' ' && tmp[1] == '\0') ? "" : tmp); g_free(tmp); break; case GCONF_VALUE_BOOL: tmp = gconf_value_to_string(value); g_print ("%s %s\n", whitespace, tmp); g_free(tmp); break; case GCONF_VALUE_LIST: print_list_in_xml(value, indent + 2); break; case GCONF_VALUE_PAIR: print_pair_in_xml(value, indent + 2); break; case GCONF_VALUE_SCHEMA: print_schema_in_xml(value, indent + 2); break; default: g_assert_not_reached(); break; } g_print ("%s\n", whitespace); g_free(whitespace); } static inline const gchar* get_key_relative(const gchar* key, const gchar* dir) { int i; g_assert(key != NULL); g_assert(dir != NULL); i = 0; while (dir [i]) { if (dir [i] != key [i]) return key; ++i; } if (key [i] != '/' || key [i] == '\0') return key; ++i; return key + i; } static int compare_entries (GConfEntry* a, GConfEntry *b) { return strcmp(gconf_entry_get_key(a), gconf_entry_get_key(b)); } static void dump_entries_in_dir(GConfEngine* conf, const gchar* dir, const gchar* base_dir) { GSList* entries; GSList* tmp; GError* err = NULL; entries = g_slist_sort(gconf_engine_all_entries(conf, dir, &err), (GCompareFunc)compare_entries); if (err != NULL) { g_printerr (_("Failure listing entries in `%s': %s\n"), dir, err->message); g_error_free(err); err = NULL; } tmp = entries; while (tmp != NULL) { GConfEntry* entry = tmp->data; g_print (" \n"); g_print (" %s\n", get_key_relative(gconf_entry_get_key(entry), base_dir)); /* will only be relative if its under the base dir */ if (gconf_entry_get_schema_name(entry)) g_print (" %s\n", get_key_relative(gconf_entry_get_schema_name(entry), base_dir)); if (entry->value && (!ignore_schema_defaults || !gconf_entry_get_is_default(entry))) print_value_in_xml(entry->value, 6); g_print (" \n"); gconf_entry_free(entry); tmp = tmp->next; } g_slist_free(entries); } static gboolean do_dir_exists(GConfEngine* conf, const gchar* dir) { GError* err = NULL; gboolean exists = FALSE; exists = gconf_engine_dir_exists(conf, dir_exists, &err); if (err != NULL) { g_printerr ("%s\n", err->message); g_error_free(err); err = NULL; } return exists; } static void do_spawn_daemon(GConfEngine* conf) { GError* err = NULL; if (!gconf_spawn_daemon(&err)) { g_printerr (_("Failed to spawn the configuration server (gconfd): %s\n"), err->message); g_error_free(err); err = NULL; } } static inline GConfValue * get_maybe_without_default (GConfEngine *conf, const gchar *key, GError **err) { if (!ignore_schema_defaults) { return gconf_engine_get (conf, key, err); } else { return gconf_engine_get_without_default (conf, key, err); } } static int do_get(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify a key or keys to get\n")); return 1; } while (*args) { GConfValue* value; gchar* s; err = NULL; value = get_maybe_without_default (conf, *args, &err); if (value != NULL) { if (value->type != GCONF_VALUE_SCHEMA) { s = gconf_value_to_string(value); g_print ("%s\n", s); g_free(s); } else { GConfSchema* sc = gconf_value_get_schema(value); GConfValueType stype = gconf_schema_get_type(sc); GConfValueType slist_type = gconf_schema_get_list_type(sc); GConfValueType scar_type = gconf_schema_get_car_type(sc); GConfValueType scdr_type = gconf_schema_get_cdr_type(sc); const gchar* long_desc = gconf_schema_get_long_desc(sc); const gchar* short_desc = gconf_schema_get_short_desc(sc); const gchar* owner = gconf_schema_get_owner(sc); GConfValue* def_value = gconf_schema_get_default_value(sc); g_print (_("Type: %s\n"), gconf_value_type_to_string(stype)); g_print (_("List Type: %s\n"), gconf_value_type_to_string(slist_type)); g_print (_("Car Type: %s\n"), gconf_value_type_to_string(scar_type)); g_print (_("Cdr Type: %s\n"), gconf_value_type_to_string(scdr_type)); if (def_value) s = gconf_value_to_string (def_value); else s = NULL; g_print (_("Default Value: %s\n"), def_value ? s : _("Unset")); g_free (s); g_print (_("Owner: %s\n"), owner ? owner : _("Unset")); g_print (_("Short Desc: %s\n"), short_desc ? short_desc : _("Unset")); g_print (_("Long Desc: %s\n"), long_desc ? long_desc : _("Unset")); } gconf_value_free(value); } else { if (err == NULL) { g_printerr (_("No value set for `%s'\n"), *args); } else { g_printerr (_("Failed to get value for `%s': %s\n"), *args, err->message); g_error_free(err); err = NULL; } } ++args; } return 0; } static GConfValueType read_value_type(const char *string) { GConfValueType type = GCONF_VALUE_INVALID; switch (*string) { case 'i': case 'I': type = GCONF_VALUE_INT; break; case 'f': case 'F': type = GCONF_VALUE_FLOAT; break; case 'b': case 'B': type = GCONF_VALUE_BOOL; break; case 's': case 'S': switch (string[1]) { case 't': case 'T': type = GCONF_VALUE_STRING; break; case 'c': case 'C': type = GCONF_VALUE_SCHEMA; break; default: g_printerr (_("Don't understand type `%s'\n"), string); } break; case 'l': case 'L': type = GCONF_VALUE_LIST; break; case 'p': case 'P': type = GCONF_VALUE_PAIR; break; default: g_printerr (_("Don't understand type `%s'\n"), string); } return type; } static int do_set(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify alternating keys/values as arguments\n")); return 1; } while (*args) { const gchar* key; const gchar* value; GConfValueType type = GCONF_VALUE_INVALID; GConfValueType list_type = GCONF_VALUE_INVALID; GConfValueType car_type = GCONF_VALUE_INVALID; GConfValueType cdr_type = GCONF_VALUE_INVALID; GConfValue* gval; key = *args; ++args; value = *args; if (value == NULL) { g_printerr (_("No value to set for key: `%s'\n"), key); return 1; } type = read_value_type(value_type); if (type == GCONF_VALUE_INVALID) return 1; if (value_list_type != NULL) { list_type = read_value_type(value_list_type); if (list_type == GCONF_VALUE_INVALID) return 1; } if (value_car_type != NULL) { car_type = read_value_type(value_car_type); if (car_type == GCONF_VALUE_INVALID) return 1; } if (value_cdr_type != NULL) { cdr_type = read_value_type(value_cdr_type); if (cdr_type == GCONF_VALUE_INVALID) return 1; } if (type == GCONF_VALUE_SCHEMA) { g_printerr (_("Cannot set schema as value\n")); return 1; } if (type == GCONF_VALUE_LIST && list_type != GCONF_VALUE_STRING && list_type != GCONF_VALUE_INT && list_type != GCONF_VALUE_FLOAT && list_type != GCONF_VALUE_BOOL) { g_printerr (_("When setting a list you must specify a primitive list-type\n")); return 1; } if (type == GCONF_VALUE_PAIR && ((car_type != GCONF_VALUE_STRING && car_type != GCONF_VALUE_INT && car_type != GCONF_VALUE_FLOAT && car_type != GCONF_VALUE_BOOL) || (cdr_type != GCONF_VALUE_STRING && cdr_type != GCONF_VALUE_INT && cdr_type != GCONF_VALUE_FLOAT && cdr_type != GCONF_VALUE_BOOL))) { g_printerr (_("When setting a pair you must specify a primitive car-type and cdr-type\n")); return 1; } err = NULL; if (type == GCONF_VALUE_LIST) gval = gconf_value_new_list_from_string(list_type, value, &err); else if (type == GCONF_VALUE_PAIR) gval = gconf_value_new_pair_from_string(car_type, cdr_type, value, &err); else gval = gconf_value_new_from_string(type, value, &err); if (gval == NULL) { g_printerr (_("Error: %s\n"), err->message); g_error_free(err); err = NULL; return 1; } err = NULL; gconf_engine_set (conf, key, gval, &err); if (err != NULL) { g_printerr (_("Error setting value: %s\n"), err->message); g_error_free(err); err = NULL; return 1; } gconf_value_free(gval); ++args; } err = NULL; gconf_engine_suggest_sync(conf, &err); if (err != NULL) { g_printerr (_("Error syncing: %s\n"), err->message); return 1; } return 0; } static int do_toggle(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify one or more keys as arguments\n")); return 1; } while (*args) { const gchar* key; GConfValue* value; key = *args; err = NULL; value = get_maybe_without_default (conf, key, &err); if (value == NULL) { g_printerr (_("No value found for key %s\n"), key); return 1; } if (value->type != GCONF_VALUE_BOOL) { g_printerr (_("Not a boolean value: %s\n"), key); return 1; } gconf_value_set_bool (value, !gconf_value_get_bool (value)); gconf_engine_set (conf, key, value, &err); if (err != NULL) { g_printerr (_("Error setting value: %s\n"), err->message); g_error_free(err); err = NULL; return 1; } gconf_value_free (value); ++args; } return 0; } static int do_get_type(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify a key or keys to get type\n")); return 1; } while (*args) { GConfValue* value; err = NULL; value = get_maybe_without_default (conf, *args, &err); if (value != NULL) { g_print ("%s\n", gconf_value_type_to_string (value->type)); } else { if (err == NULL) { g_printerr (_("No value set for `%s'\n"), *args); } else { g_printerr (_("Failed to get value for `%s': %s\n"), *args, err->message); g_error_free (err); err = NULL; } } ++args; } return 0; } static int do_get_list_size(GConfEngine* conf, const gchar** args) { GError* err = NULL; GConfValue *list = NULL; if (args == NULL || *args == NULL) { g_printerr (_("Must specify a key to lookup size of.\n")); return 1; } list = get_maybe_without_default (conf, *args, &err); if (list == NULL) { if (err == NULL) { g_printerr (_("No value set for `%s'\n"), *args); } else { g_printerr (_("Failed to get value for `%s': %s\n"), *args, err->message); g_error_free (err); err = NULL; } return 1; } if (list->type != GCONF_VALUE_LIST) { g_printerr (_("Key %s is not a list.\n"), *args); return 1; } g_print ("%u\n", g_slist_length (gconf_value_get_list (list))); return 0; } static int do_get_list_element(GConfEngine* conf, const gchar** args) { GError* err = NULL; GConfValue *list = NULL, *element = NULL; GSList *iter = NULL; gchar* s = NULL; int idx = 0; if (args == NULL || *args == NULL) { g_printerr (_("Must specify a key from which to get list element.\n")); return 1; } list = get_maybe_without_default (conf, *args, &err); if (list == NULL) { if (err == NULL) { g_printerr (_("No value set for `%s'\n"), *args); } else { g_printerr (_("Failed to get value for `%s': %s\n"), *args, err->message); g_error_free (err); err = NULL; } return 1; } if (list->type != GCONF_VALUE_LIST) { g_printerr (_("Key %s is not a list.\n"), *args); return 1; } if (args[1] == NULL) { g_printerr (_("Must specify list index.\n")); return 1; } idx = atoi (args[1]); if (idx < 0) { g_printerr (_("List index must be non-negative.\n")); return 1; } iter = gconf_value_get_list (list); element = g_slist_nth_data (iter, idx); if (element == NULL) { g_printerr (_("List index is out of bounds.\n")); return 1; } s = gconf_value_to_string (element); g_print ("%s\n", s); g_free (s); return 0; } enum { SCHEMA_INFO_SHORT_DOCS, SCHEMA_INFO_LONG_DOCS, SCHEMA_INFO_SCHEMA_NAME }; static int do_schema_info (GConfEngine *conf, const gchar **args, int info) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify a key or keys on the command line\n")); return 1; } while (*args) { GConfEntry* entry; err = NULL; entry = gconf_engine_get_entry (conf, *args, NULL, TRUE, &err); if (entry != NULL) { const char *s; s = gconf_entry_get_schema_name (entry); if (s == NULL) { g_printerr (_("No schema known for `%s'\n"), *args); } else if (info == SCHEMA_INFO_SCHEMA_NAME) { g_print ("%s\n", s); } else { GConfValue *val; err = NULL; val = gconf_engine_get (conf, s, &err); if (val != NULL && val->type == GCONF_VALUE_SCHEMA) { GConfSchema *schema; const char *docs; docs = NULL; schema = gconf_value_get_schema (val); if (schema) { if (info == SCHEMA_INFO_SHORT_DOCS) docs = gconf_schema_get_short_desc (schema); else if (info == SCHEMA_INFO_LONG_DOCS) docs = gconf_schema_get_long_desc (schema); } if (docs) g_print ("%s\n", docs); else g_printerr (_("No doc string stored in schema at '%s'\n"), s); } else if (err != NULL) { g_printerr (_("Error getting schema at '%s': %s\n"), s, err->message); g_error_free (err); } else { if (val == NULL) g_printerr (_("No schema stored at '%s'\n"), s); else g_printerr (_("Value at '%s' is not a schema\n"), s); } if (val) gconf_value_free (val); } gconf_entry_free (entry); } else { if (err == NULL) { g_printerr (_("No value set for `%s'\n"), *args); } else { g_printerr (_("Failed to get value for `%s': %s\n"), *args, err->message); g_error_free(err); err = NULL; } } ++args; } return 0; } static int do_short_docs (GConfEngine *conf, const gchar **args) { return do_schema_info (conf, args, SCHEMA_INFO_SHORT_DOCS); } static int do_long_docs (GConfEngine *conf, const gchar **args) { return do_schema_info (conf, args, SCHEMA_INFO_LONG_DOCS); } static int do_get_schema_name (GConfEngine *conf, const gchar **args) { return do_schema_info (conf, args, SCHEMA_INFO_SCHEMA_NAME); } static int do_associate_schema (GConfEngine *conf, const gchar **args) { GError *err; if (!args || args[0] == NULL || args[1] == NULL || args[2] != NULL) { g_printerr (_("Must specify a schema name followed by the key name to apply it to\n")); return 1; } err = NULL; if (!gconf_engine_associate_schema (conf, args[1], args[0], &err)) { g_printerr (_("Error associating schema name '%s' with key name '%s': %s\n"), args[0], args[1], err->message); g_error_free (err); return 1; } return 0; } static int do_dissociate_schema (GConfEngine *conf, const gchar **args) { GError *err; gboolean failed; if (!args || args[0] == NULL) { g_printerr (_("Must specify keys to unapply schema from\n")); return 1; } failed = FALSE; while (*args) { err = NULL; if (!gconf_engine_associate_schema (conf, *args, NULL, &err)) { g_printerr (_("Error removing schema name from '%s': %s\n"), *args, err->message); g_error_free (err); failed = TRUE; } ++args; } if (failed) return 1; else return 0; } static int do_set_schema(GConfEngine* conf, const gchar** args) { GConfSchema* sc; GConfValue* val; const gchar* key; GError* err = NULL; if ((args == NULL) || (args[1] != NULL)) { g_printerr (_("Must specify key (schema name) as the only argument\n")); return 1; } key = *args; val = gconf_value_new(GCONF_VALUE_SCHEMA); sc = gconf_schema_new(); gconf_value_set_schema_nocopy(val, sc); if (short_desc) gconf_schema_set_short_desc(sc, short_desc); if (long_desc) gconf_schema_set_long_desc(sc, long_desc); if (owner) gconf_schema_set_owner(sc, owner); if (value_type) { GConfValueType type = GCONF_VALUE_INVALID; type = read_value_type(value_type); if (type != GCONF_VALUE_INVALID) gconf_schema_set_type(sc, type); } if (value_list_type) { GConfValueType type = GCONF_VALUE_INVALID; type = read_value_type(value_list_type); if (type != GCONF_VALUE_STRING && type != GCONF_VALUE_INT && type != GCONF_VALUE_FLOAT && type != GCONF_VALUE_BOOL) { g_printerr (_("List type must be a primitive type: string, int, float or bool\n")); return 1; } if (type != GCONF_VALUE_INVALID) gconf_schema_set_list_type(sc, type); } if (value_car_type) { GConfValueType type = GCONF_VALUE_INVALID; type = read_value_type(value_car_type); if (type != GCONF_VALUE_STRING && type != GCONF_VALUE_INT && type != GCONF_VALUE_FLOAT && type != GCONF_VALUE_BOOL) { g_printerr (_("Pair car type must be a primitive type: string, int, float or bool\n")); return 1; } if (type != GCONF_VALUE_INVALID) gconf_schema_set_car_type(sc, type); } if (value_cdr_type) { GConfValueType type = GCONF_VALUE_INVALID; type = read_value_type(value_cdr_type); if (type != GCONF_VALUE_STRING && type != GCONF_VALUE_INT && type != GCONF_VALUE_FLOAT && type != GCONF_VALUE_BOOL) { g_printerr (_("Pair cdr type must be a primitive type: string, int, float or bool\n")); return 1; } if (type != GCONF_VALUE_INVALID) gconf_schema_set_cdr_type(sc, type); } err = NULL; gconf_engine_set (conf, key, val, &err); if (err != NULL) { g_printerr (_("Error setting value: %s"), err->message); g_error_free(err); err = NULL; return 1; } gconf_value_free(val); err = NULL; gconf_engine_suggest_sync(conf, &err); if (err != NULL) { g_printerr (_("Error syncing: %s"), err->message); g_error_free(err); err = NULL; return 1; } return 0; } static int do_all_entries(GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify one or more directories to get key/value pairs from.\n")); return 1; } return do_all_pairs(conf, args); } static int do_unset(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify one or more keys to unset.\n")); return 1; } while (*args) { err = NULL; gconf_engine_unset(conf, *args, &err); if (err != NULL) { g_printerr (_("Error unsetting `%s': %s\n"), *args, err->message); g_error_free(err); err = NULL; } ++args; } err = NULL; gconf_engine_suggest_sync(conf, NULL); /* ignore errors */ return 0; } static int do_recursive_unset (GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify one or more keys to recursively unset.\n")); return 1; } while (*args) { GError *err; err = NULL; gconf_engine_recursive_unset (conf, *args, GCONF_UNSET_INCLUDING_SCHEMA_NAMES, &err); if (err != NULL) { g_printerr (_("Failure during recursive unset of \"%s\": %s\n"), *args, err->message); g_error_free (err); } ++args; } gconf_engine_suggest_sync (conf, NULL); /* ignore errors */ return 0; } static int do_all_subdirs(GConfEngine* conf, const gchar** args) { GError* err = NULL; if (args == NULL) { g_printerr (_("Must specify one or more directories to get subdirs from.\n")); return 1; } while (*args) { GSList* subdirs; GSList* tmp; err = NULL; subdirs = gconf_engine_all_dirs(conf, *args, &err); if (subdirs != NULL) { tmp = subdirs; while (tmp != NULL) { gchar* s = tmp->data; g_print (" %s\n", s); g_free(s); tmp = g_slist_next(tmp); } g_slist_free(subdirs); } else { if (err != NULL) { g_printerr (_("Error listing dirs: %s\n"), err->message); g_error_free(err); err = NULL; } } ++args; } return 0; } static void hash_listify_foreach(gpointer key, gpointer val, gpointer user_data) { GSList** values; GConfSchema* schema; GConfValue* value; values = user_data; schema = val; value = gconf_value_new(GCONF_VALUE_SCHEMA); gconf_value_set_schema_nocopy(value, schema); *values = g_slist_prepend(*values, value); } static int get_list_value_from_xml(xmlNodePtr node, GConfValue** ret_value) { xmlNodePtr iter; GConfValue* value = NULL; GConfValueType list_type; GSList* list = NULL; char* list_type_str; list_type_str = (char *)xmlGetProp(node, (xmlChar *)"type"); if (!list_type_str) { g_printerr ("WARNING: must specify a list type for using \n"); return 1; } list_type = gconf_value_type_from_string(list_type_str); xmlFree(list_type_str); if (list_type == GCONF_VALUE_INVALID) { g_printerr ("WARNING: invalid list type '%s'\n", list_type_str); return 1; } iter = node->xmlChildrenNode; while (iter != NULL) { if (strcmp((char *)iter->name, "value") == 0) { GConfValue* element = NULL; if (get_first_value_from_xml(iter, &element) == 0) { if (element->type == list_type) list = g_slist_prepend (list, element); else g_printerr ("WARNING: list type and element type do not match: %s != %s\n", gconf_value_type_to_string (list_type), gconf_value_type_to_string (element->type)); } } iter = iter->next; } list = g_slist_reverse(list); value = gconf_value_new(GCONF_VALUE_LIST); gconf_value_set_list_type(value, list_type); gconf_value_set_list_nocopy(value, list); *ret_value = value; return 0; } static inline void get_car_cdr_value(xmlNodePtr node, GConfValue** ret_value) { xmlNodePtr iter; iter = node->xmlChildrenNode; while (iter != NULL) { if (strcmp((char *)iter->name, "value") == 0) get_first_value_from_xml(iter, ret_value); iter = iter->next; } } static int get_pair_value_from_xml(xmlNodePtr node, GConfValue** ret_value) { xmlNodePtr iter; GConfValue* value = NULL; GConfValue* cdr = NULL; GConfValue* car = NULL; int retval = 0; iter = node->xmlChildrenNode; while (iter != NULL) { if (strcmp((char *)iter->name, "car") == 0) get_car_cdr_value(iter, &car); else if (strcmp((char *)iter->name, "cdr") == 0) get_car_cdr_value(iter, &cdr); iter = iter->next; } if (car && cdr) { value = gconf_value_new(GCONF_VALUE_PAIR); gconf_value_set_car(value, car); gconf_value_set_cdr(value, cdr); } else { g_printerr (_("WARNING: must specify both a and a in a \n")); retval = 1; } if (car) gconf_value_free(car); if (cdr) gconf_value_free(cdr); *ret_value = value; return retval; } static int get_schema_values_from_xml(xmlNodePtr node, GSList** ret_values) { GHashTable* schemas_hash; GSList* values = NULL; GSList* applyto_list; GSList* tmp; gchar* schema_key; if (get_schema_from_xml(node, &schema_key, &schemas_hash, &applyto_list) == 1) return 1; if (schema_key != NULL) g_printerr (_("WARNING: key specified (%s) for schema under a - ignoring\n"), schema_key); g_hash_table_foreach(schemas_hash, hash_listify_foreach, &values); g_hash_table_destroy(schemas_hash); tmp = applyto_list; while (tmp != NULL) { g_free(tmp->data); tmp = tmp->next; } g_slist_free(applyto_list); g_free(schema_key); *ret_values = values; return 0; } static int get_values_from_xml(xmlNodePtr node, GSList** ret_values) { xmlNodePtr iter; GSList* values = NULL; GConfValue* value = NULL; iter = node->xmlChildrenNode; if (!iter) { g_printerr (_("WARNING: must have a child node under \n")); return 1; } if (strcmp((char *)node->name, "value") != 0) { g_printerr (_("WARNING: node <%s> not understood\n"), node->name); return 1; } while (iter) { GError* error = NULL; char* content; if (strcmp((char *)iter->name, "int") == 0) { if ((content = (char *)xmlNodeGetContent(iter)) != NULL) { value = gconf_value_new_from_string(GCONF_VALUE_INT, content, &error); if (value == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse int value `%s'\n"), content); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } xmlFree(content); } } else if (strcmp((char *)iter->name, "float") == 0) { if ((content = (char *)xmlNodeGetContent(iter)) != NULL) { value = gconf_value_new_from_string(GCONF_VALUE_FLOAT, content, &error); if (value == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse float value `%s'\n"), content); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } xmlFree(content); } } else if (strcmp((char *)iter->name, "string") == 0) { if ((content = (char *)xmlNodeGetContent(iter)) != NULL) { value = gconf_value_new_from_string(GCONF_VALUE_STRING, content, &error); if (value == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse string value `%s'\n"), content); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } xmlFree(content); } } else if (strcmp((char *)iter->name, "bool") == 0) { if ((content = (char *)xmlNodeGetContent(iter)) != NULL) { value = gconf_value_new_from_string(GCONF_VALUE_BOOL, content, &error); if (value == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse boolean value `%s'\n"), content); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } xmlFree(content); } } else if (strcmp((char *)iter->name, "list") == 0) get_list_value_from_xml(iter, &value); else if (strcmp((char *)iter->name, "pair") == 0) get_pair_value_from_xml(iter, &value); else if (strcmp((char *)iter->name, "schema") == 0) get_schema_values_from_xml(iter, &values); iter = iter->next; } /* common case */ if (value) { g_assert (values == NULL); values = g_slist_prepend(values, value); } *ret_values = values; return 0; } /* Confusingly, parsing a can give you multiple * values in the case of schemas. Use this if you're sure * there it can't be a schema. */ static int get_first_value_from_xml(xmlNodePtr node, GConfValue** ret_value) { GConfValue* value = NULL; GSList* values; GSList* tmp; if (get_values_from_xml(node, &values) == 1) return 1; g_assert (g_slist_length(values) <= 1); tmp = values; while (tmp) { if (!value) value = tmp->data; else gconf_value_free(tmp->data); tmp = tmp->next; } g_slist_free(values); *ret_value = value; return 0; } /* * Loading entries */ typedef struct { gchar *key; GConfValueType type; GConfValueType list_type; GConfValueType car_type; GConfValueType cdr_type; GConfValue* value; } EntryInfo; static void set_values(GConfEngine* conf, gboolean unload, const gchar* base_dir, const gchar* key, const char* schema_key, GSList* values) { GSList* tmp; gchar* full_key; if (base_dir) full_key = gconf_concat_dir_and_key(base_dir, key); else full_key = g_strdup(key); if (unload || schema_key) { gchar* full_schema_key = NULL; GError* error = NULL; if (!unload) { if (base_dir && *schema_key != '/') full_schema_key = gconf_concat_dir_and_key(base_dir, schema_key); else full_schema_key = g_strdup(schema_key); } if (!gconf_engine_associate_schema(conf, full_key, full_schema_key, &error)) { g_assert(error != NULL); g_printerr (_("WARNING: failed to associate schema `%s' with key `%s': %s\n"), full_schema_key, full_key, error->message); g_error_free(error); } g_free(full_schema_key); } tmp = values; while (tmp) { GConfValue* value = tmp->data; GError* error; error = NULL; if (!unload) gconf_engine_set(conf, full_key, value, &error); else gconf_engine_unset(conf, full_key, &error); if (error != NULL) { g_printerr (_("Error setting value: %s\n"), error->message); g_error_free(error); error = NULL; } tmp = tmp->next; } g_free(full_key); } static int process_entry(GConfEngine* conf, gboolean unload, xmlNodePtr node, const gchar** base_dirs, const char* orig_base) { xmlNodePtr iter; GSList* values = NULL; GSList* tmp; char* key = NULL; char* schema_key = NULL; int retval = 0; iter = node->xmlChildrenNode; while (iter) { if (strcmp((char *)iter->name, "key") == 0) key = (char *)xmlNodeGetContent(iter); else if (strcmp((char *)iter->name, "value") == 0) get_values_from_xml(iter, &values); else if (strcmp((char *)iter->name, "schema_key") == 0) schema_key = (char *)xmlNodeGetContent(iter); iter = iter->next; } if (key && (values || schema_key)) { if (!base_dirs) set_values(conf, unload, orig_base, key, schema_key, values); else while (*base_dirs) { set_values(conf, unload, *base_dirs, key, schema_key, values); ++base_dirs; } } else retval = 1; tmp = values; while (tmp) { gconf_value_free(tmp->data); tmp = tmp->next; } g_slist_free(values); if (key) xmlFree(key); if (schema_key) xmlFree(schema_key); return retval; } /* * Schema stuff */ typedef struct _SchemaInfo SchemaInfo; struct _SchemaInfo { gchar* key; gchar* owner; GSList* apply_to; GConfValueType type; GConfValueType list_type; GConfValueType car_type; GConfValueType cdr_type; GConfValue* global_default; GHashTable* hash; }; static int fill_default_from_string(SchemaInfo* info, const gchar* default_value, GConfValue** retloc) { g_return_val_if_fail(default_value != NULL, 1); switch (info->type) { case GCONF_VALUE_INVALID: g_printerr (_("WARNING: invalid or missing type for schema (%s)\n"), info->key); break; case GCONF_VALUE_LIST: { GError* error = NULL; if (info->list_type == GCONF_VALUE_INVALID) { g_printerr (_("WARNING: invalid or missing list_type for schema (%s)\n"), info->key); break; } *retloc = gconf_value_new_list_from_string(info->list_type, default_value, &error); if (*retloc == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } } break; case GCONF_VALUE_PAIR: { GError* error = NULL; if (info->car_type == GCONF_VALUE_INVALID || info->cdr_type == GCONF_VALUE_INVALID) { g_printerr (_("WARNING: invalid or missing car_type or cdr_type for schema (%s)\n"), info->key); break; } *retloc = gconf_value_new_pair_from_string(info->car_type, info->cdr_type, default_value, &error); if (*retloc == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } } break; case GCONF_VALUE_SCHEMA: g_printerr (_("WARNING: You cannot set a default value for a schema\n")); break; case GCONF_VALUE_STRING: case GCONF_VALUE_INT: case GCONF_VALUE_BOOL: case GCONF_VALUE_FLOAT: { GError* error = NULL; *retloc = gconf_value_new_from_string(info->type, default_value, &error); if (*retloc == NULL) { g_assert(error != NULL); g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key); g_error_free(error); error = NULL; } else { g_assert(error == NULL); } } break; default: g_printerr (_("WARNING: gconftool internal error, unknown GConfValueType\n")); break; } return 0; } static int extract_global_info(xmlNodePtr node, SchemaInfo* info) { xmlNodePtr iter; xmlNodePtr default_value_node = NULL; char* default_value = NULL; iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { char* tmp; if (strcmp((char *)iter->name, "key") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->key = g_strdup(tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "owner") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->owner = g_strdup(tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "type") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->type = gconf_value_type_from_string(tmp); if (info->type == GCONF_VALUE_INVALID) g_printerr (_("WARNING: failed to parse type name `%s'\n"), tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "list_type") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->list_type = gconf_value_type_from_string(tmp); if (info->list_type != GCONF_VALUE_INT && info->list_type != GCONF_VALUE_FLOAT && info->list_type != GCONF_VALUE_STRING && info->list_type != GCONF_VALUE_BOOL) { info->list_type = GCONF_VALUE_INVALID; g_printerr (_("WARNING: list_type can only be int, float, string or bool and not `%s'\n"), tmp); } else if (info->list_type == GCONF_VALUE_INVALID) g_printerr (_("WARNING: failed to parse type name `%s'\n"), tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "car_type") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->car_type = gconf_value_type_from_string(tmp); if (info->car_type != GCONF_VALUE_INT && info->car_type != GCONF_VALUE_FLOAT && info->car_type != GCONF_VALUE_STRING && info->car_type != GCONF_VALUE_BOOL) { info->car_type = GCONF_VALUE_INVALID; g_printerr (_("WARNING: car_type can only be int, float, string or bool and not `%s'\n"), tmp); } else if (info->car_type == GCONF_VALUE_INVALID) g_printerr (_("WARNING: failed to parse type name `%s'\n"), tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "cdr_type") == 0) { tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->cdr_type = gconf_value_type_from_string(tmp); if (info->cdr_type != GCONF_VALUE_INT && info->cdr_type != GCONF_VALUE_FLOAT && info->cdr_type != GCONF_VALUE_STRING && info->cdr_type != GCONF_VALUE_BOOL) { info->cdr_type = GCONF_VALUE_INVALID; g_printerr (_("WARNING: cdr_type can only be int, float, string or bool and not `%s'\n"), tmp); } else if (info->cdr_type == GCONF_VALUE_INVALID) g_printerr (_("WARNING: failed to parse type name `%s'\n"), tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "default") == 0) { default_value = (char *)xmlNodeGetContent(iter); } else if (strcmp((char *)iter->name, "default_value") == 0) { xmlNodePtr tmp_node = iter->xmlChildrenNode; while (tmp_node) { if (strcmp((char *)tmp_node->name, "value") == 0) default_value_node = tmp_node; tmp_node = tmp_node->next; } } else if (strcmp((char *)iter->name, "locale") == 0) { ; /* ignore, this is parsed later after we have the global info */ } else if (strcmp((char *)iter->name, "applyto") == 0) { /* Add the contents to the list of nodes to apply to */ tmp = (char *)xmlNodeGetContent(iter); if (tmp) { info->apply_to = g_slist_prepend(info->apply_to, g_strdup(tmp)); xmlFree(tmp); } else g_printerr (_("WARNING: empty node")); } else g_printerr (_("WARNING: node <%s> not understood below \n"), iter->name); } iter = iter->next; } if (info->type == GCONF_VALUE_LIST && info->list_type == GCONF_VALUE_INVALID) { g_printerr (_("WARNING: no specified for schema of type list\n")); } if (info->type == GCONF_VALUE_PAIR && info->car_type == GCONF_VALUE_INVALID) { g_printerr (_("WARNING: no specified for schema of type pair\n")); } if (info->type == GCONF_VALUE_PAIR && info->cdr_type == GCONF_VALUE_INVALID) { g_printerr (_("WARNING: no specified for schema of type pair\n")); } if (default_value_node != NULL) get_first_value_from_xml (default_value_node, &info->global_default); else if (default_value != NULL) /* Have to do this last, because the type may come after the default * value */ fill_default_from_string(info, default_value, &info->global_default); if (default_value) xmlFree(default_value); return 0; } static int process_locale_info(xmlNodePtr node, SchemaInfo* info) { char* name; GConfSchema* schema; xmlNodePtr iter; name = (char *)xmlGetProp(node, (xmlChar *)"name"); if (name == NULL) { g_printerr (_("WARNING: node has no `name=\"locale\"' attribute, ignoring\n")); return 1; } if (g_hash_table_lookup(info->hash, name) != NULL) { g_printerr (_("WARNING: multiple nodes for locale `%s', ignoring all past first\n"), name); xmlFree(name); return 1; } schema = gconf_schema_new(); gconf_schema_set_locale(schema, name); /* Only set the global default on the C locale */ if (strcmp(name, "C") == 0 && info->global_default != NULL) gconf_schema_set_default_value(schema, info->global_default); /* Fill in the global info */ if (info->type != GCONF_VALUE_INVALID) gconf_schema_set_type(schema, info->type); if (info->list_type != GCONF_VALUE_INVALID) gconf_schema_set_list_type(schema, info->list_type); if (info->car_type != GCONF_VALUE_INVALID) gconf_schema_set_car_type(schema, info->car_type); if (info->cdr_type != GCONF_VALUE_INVALID) gconf_schema_set_cdr_type(schema, info->cdr_type); if (info->owner != NULL) gconf_schema_set_owner(schema, info->owner); xmlFree(name); /* Locale-specific info */ iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (strcmp((char *)iter->name, "default_value") == 0) { GConfValue* val = NULL; xmlNodePtr tmp_node; tmp_node = iter->xmlChildrenNode; while (tmp_node) { if (strcmp((char *)tmp_node->name, "value") == 0) { get_first_value_from_xml(tmp_node, &val); if (val) gconf_schema_set_default_value_nocopy(schema, val); break; } tmp_node = tmp_node->next; } } else if (strcmp((char *)iter->name, "default") == 0) { GConfValue* val = NULL; char* tmp; tmp = (char *)xmlNodeGetContent(iter); if (tmp != NULL) { fill_default_from_string(info, tmp, &val); if (val) gconf_schema_set_default_value_nocopy(schema, val); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "short") == 0) { char* tmp; tmp = (char *)xmlNodeGetContent(iter); if (tmp != NULL) { gconf_schema_set_short_desc(schema, tmp); xmlFree(tmp); } } else if (strcmp((char *)iter->name, "long") == 0) { char* tmp; tmp = (char *)xmlNodeGetContent(iter); if (tmp != NULL) { gconf_schema_set_long_desc(schema, tmp); xmlFree(tmp); } } else { g_printerr (_("WARNING: Invalid node <%s> in a node\n"), iter->name); } } iter = iter->next; } g_hash_table_insert(info->hash, (gchar*)gconf_schema_get_locale(schema), /* cheat to save copying this string */ schema); return 0; } static int process_key_list(GConfEngine* conf, gboolean unload, const gchar* schema_name, GSList* keylist) { GSList* tmp; tmp = keylist; while (tmp != NULL) { GError* error = NULL; if (!gconf_engine_associate_schema(conf, tmp->data, !unload ? schema_name : NULL, &error)) { g_assert(error != NULL); g_printerr (_("WARNING: failed to associate schema `%s' with key `%s': %s\n"), schema_name, (gchar*)tmp->data, error->message); g_error_free(error); error = NULL; } else { g_assert(error == NULL); g_print (_("Attached schema `%s' to key `%s'\n"), schema_name, (gchar*)tmp->data); } tmp = g_slist_next(tmp); } return 0; } static int get_schema_from_xml(xmlNodePtr node, gchar **schema_key, GHashTable** schemas_hash, GSList **applyto_list) { xmlNodePtr iter; SchemaInfo info; info.key = NULL; info.type = GCONF_VALUE_INVALID; info.list_type = GCONF_VALUE_INVALID; info.car_type = GCONF_VALUE_INVALID; info.cdr_type = GCONF_VALUE_INVALID; info.apply_to = NULL; info.owner = NULL; info.global_default = NULL; info.hash = g_hash_table_new(g_str_hash, g_str_equal); extract_global_info(node, &info); if (info.type == GCONF_VALUE_INVALID) { g_free(info.owner); if (info.global_default) gconf_value_free(info.global_default); return 1; } iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (strcmp((char *)iter->name, "key") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "owner") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "type") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "list_type") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "car_type") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "cdr_type") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "default") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "applyto") == 0) ; /* nothing */ else if (strcmp((char *)iter->name, "locale") == 0) { process_locale_info(iter, &info); } else g_printerr (_("WARNING: node <%s> not understood below \n"), iter->name); } iter = iter->next; } if (g_hash_table_size(info.hash) == 0) { g_printerr (_("You must have at least one entry in a \n")); return 1; } *schema_key = info.key; *schemas_hash = info.hash; *applyto_list = info.apply_to; g_free(info.owner); if (info.global_default) gconf_value_free(info.global_default); return 0; } static void hash_install_foreach(gpointer key, gpointer value, gpointer user_data) { struct { GConfEngine* conf; gboolean unload; char* key; } *info; GConfSchema* schema; GError* error = NULL; info = user_data; schema = value; if (!info->unload) { if (!gconf_engine_set_schema(info->conf, info->key, schema, &error)) { g_assert(error != NULL); g_printerr (_("WARNING: failed to install schema `%s', locale `%s': %s\n"), info->key, gconf_schema_get_locale(schema), error->message); g_error_free(error); error = NULL; } else { g_assert(error == NULL); g_print (_("Installed schema `%s' for locale `%s'\n"), info->key, gconf_schema_get_locale(schema)); } } else { if (!gconf_engine_unset (info->conf, info->key, &error)) { g_assert(error != NULL); g_printerr (_("WARNING: failed to uninstall schema `%s', locale `%s': %s\n"), info->key, gconf_schema_get_locale(schema), error->message); g_error_free(error); error = NULL; } else { g_assert(error == NULL); g_print (_("Uninstalled schema `%s' from locale `%s'\n"), info->key, gconf_schema_get_locale(schema)); } } gconf_schema_free(schema); } static int process_schema(GConfEngine* conf, gboolean unload, xmlNodePtr node) { struct { GConfEngine* conf; gboolean unload; char* key; } hash_foreach_info; GHashTable* schemas_hash = NULL; GSList* applyto_list = NULL; GSList* tmp; gchar* schema_key = NULL; int retval = 0; if (get_schema_from_xml(node, &schema_key, &schemas_hash, &applyto_list) == 1) return 1; g_assert(schemas_hash != NULL); if (schema_key != NULL) { process_key_list(conf, unload, schema_key, applyto_list); hash_foreach_info.conf = conf; hash_foreach_info.unload = unload; hash_foreach_info.key = schema_key; g_hash_table_foreach(schemas_hash, hash_install_foreach, &hash_foreach_info); } else { g_printerr (_("WARNING: no key specified for schema\n")); retval = 1; } g_hash_table_destroy(schemas_hash); tmp = applyto_list; while (tmp != NULL) { g_free(tmp->data); tmp = tmp->next; } g_slist_free(applyto_list); g_free(schema_key); return retval; } static int process_list(GConfEngine* conf, LoadType load_type, gboolean unload, xmlNodePtr node, const gchar** base_dirs) { #define LOAD_TYPE_TO_LIST(t) ((t == LOAD_SCHEMA_FILE) ? "schemalist" : "entrylist") xmlNodePtr iter; char* orig_base = NULL; iter = node->xmlChildrenNode; if (load_type == LOAD_ENTRY_FILE) orig_base = (char *)xmlGetProp(node, (xmlChar *)"base"); while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (load_type == LOAD_SCHEMA_FILE && strcmp((char *)iter->name, "schema") == 0) process_schema(conf, unload, iter); else if (load_type == LOAD_ENTRY_FILE && strcmp((char *)iter->name, "entry") == 0) process_entry(conf, unload, iter, base_dirs, orig_base); else g_printerr (_("WARNING: node <%s> not understood below <%s>\n"), iter->name, LOAD_TYPE_TO_LIST(load_type)); } iter = iter->next; } if (orig_base) xmlFree(orig_base); return 0; #undef LOAD_TYPE_TO_LIST } static int do_load_file(GConfEngine* conf, LoadType load_type, gboolean unload, const gchar* file, const gchar** base_dirs) { #define LOAD_TYPE_TO_ROOT(t) ((t == LOAD_SCHEMA_FILE) ? "gconfschemafile" : "gconfentryfile") #define LOAD_TYPE_TO_LIST(t) ((t == LOAD_SCHEMA_FILE) ? "schemalist" : "entrylist") xmlDocPtr doc; xmlNodePtr iter; /* file comes from the command line, is thus in locale charset */ gchar *utf8_file = g_locale_to_utf8 (file, -1, NULL, NULL, NULL);; errno = 0; doc = xmlParseFile(file); if (doc == NULL) { if (errno != 0) g_printerr (_("Failed to open `%s': %s\n"), utf8_file, g_strerror(errno)); return 1; } if (doc->xmlRootNode == NULL) { g_printerr (_("Document `%s' is empty?\n"), utf8_file); return 1; } iter = doc->xmlRootNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (strcmp((char *)iter->name, LOAD_TYPE_TO_ROOT(load_type)) != 0) { g_printerr (_("Document `%s' has the wrong type of root node (<%s>, should be <%s>)\n"), utf8_file, iter->name, LOAD_TYPE_TO_ROOT(load_type)); return 1; } else break; } iter = iter->next; } if (iter == NULL) { g_printerr (_("Document `%s' has no top level <%s> node\n"), utf8_file, LOAD_TYPE_TO_ROOT(load_type)); return 1; } iter = iter->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (strcmp((char *)iter->name, LOAD_TYPE_TO_LIST(load_type)) == 0) process_list(conf, load_type, unload, iter, base_dirs); else g_printerr (_("WARNING: node <%s> below <%s> not understood\n"), iter->name, LOAD_TYPE_TO_ROOT(load_type)); } iter = iter->next; } return 0; #undef LOAD_TYPE_TO_LIST #undef LOAD_TYPE_TO_ROOT } static int do_sync(GConfEngine* conf) { GError *err = NULL; gconf_engine_suggest_sync(conf, &err); if (err != NULL) { g_printerr (_("Error syncing configuration data: %s"), err->message); g_error_free(err); return 1; } return 0; } static int do_makefile_install(GConfEngine* conf, const gchar** args, gboolean unload) { int retval = 0; if (args == NULL) { g_printerr (_("Must specify some schema files to install\n")); return 1; } while (*args) { if (do_load_file(conf, LOAD_SCHEMA_FILE, unload, *args, NULL) != 0) retval |= 1; ++args; } retval |= do_sync (conf); return retval; } typedef enum { BreakageSetBadValues, BreakageCleanup } BreakagePhase; static gboolean check_err(GError** err) { g_print ("."); if (*err != NULL) { g_printerr (_("\n%s\n"), (*err)->message); g_error_free(*err); *err = NULL; return TRUE; } else return FALSE; } static gboolean key_breakage(GConfEngine* conf, const gchar* key, BreakagePhase phase) { GError* error = NULL; if (phase == BreakageCleanup) { gconf_engine_unset(conf, key, &error); if (error != NULL) { g_printerr (_("Failed to unset breakage key %s: %s\n"), key, error->message); g_error_free(error); return FALSE; } } else if (phase == BreakageSetBadValues) { gint an_int = 43; gboolean a_bool = TRUE; gdouble a_float = 43695.435; const gchar* a_string = "Hello"; GConfValue* val; GSList* list = NULL; g_print (" +"); gconf_engine_set_string(conf, key, "", &error); if (check_err(&error)) return FALSE; gconf_engine_set_string(conf, key, "blah blah blah 93475028934670 @%^%$&%$&^% ", &error); if (check_err(&error)) return FALSE; gconf_engine_set_bool(conf, key, TRUE, &error); if (check_err(&error)) return FALSE; gconf_engine_set_bool(conf, key, FALSE, &error); if (check_err(&error)) return FALSE; gconf_engine_set_float(conf, key, 100.0, &error); if (check_err(&error)) return FALSE; gconf_engine_set_float(conf, key, -100.0, &error); if (check_err(&error)) return FALSE; gconf_engine_set_float(conf, key, 0.0, &error); if (check_err(&error)) return FALSE; gconf_engine_set_int(conf, key, 0, &error); if (check_err(&error)) return FALSE; gconf_engine_set_int(conf, key, 5384750, &error); if (check_err(&error)) return FALSE; gconf_engine_set_int(conf, key, -11, &error); if (check_err(&error)) return FALSE; gconf_engine_set_list(conf, key, GCONF_VALUE_BOOL, list, &error); if (check_err(&error)) return FALSE; gconf_engine_set_pair(conf, key, GCONF_VALUE_INT, GCONF_VALUE_BOOL, &an_int, &a_bool, &error); if (check_err(&error)) return FALSE; gconf_engine_set_pair(conf, key, GCONF_VALUE_FLOAT, GCONF_VALUE_STRING, &a_float, &a_string, &error); if (check_err(&error)) return FALSE; /* empty pair */ val = gconf_value_new(GCONF_VALUE_PAIR); gconf_engine_set (conf, key, val, &error); gconf_value_free(val); if (check_err(&error)) return FALSE; list = NULL; gconf_engine_set_list(conf, key, GCONF_VALUE_STRING, list, &error); if (check_err(&error)) return FALSE; gconf_engine_set_list(conf, key, GCONF_VALUE_INT, list, &error); if (check_err(&error)) return FALSE; gconf_engine_set_list(conf, key, GCONF_VALUE_BOOL, list, &error); if (check_err(&error)) return FALSE; list = g_slist_prepend(list, GINT_TO_POINTER(10)); list = g_slist_prepend(list, GINT_TO_POINTER(14)); list = g_slist_prepend(list, GINT_TO_POINTER(-93)); list = g_slist_prepend(list, GINT_TO_POINTER(1000000)); list = g_slist_prepend(list, GINT_TO_POINTER(32)); gconf_engine_set_list(conf, key, GCONF_VALUE_INT, list, &error); if (check_err(&error)) return FALSE; g_slist_free(list); list = NULL; list = g_slist_prepend(list, ""); list = g_slist_prepend(list, "blah"); list = g_slist_prepend(list, " "); list = g_slist_prepend(list, "\n\t\r\n \n"); list = g_slist_prepend(list, "woo fooo s^%*^%&@^$@%&@%$"); gconf_engine_set_list(conf, key, GCONF_VALUE_STRING, list, &error); if (check_err(&error)) return FALSE; g_slist_free(list); list = NULL; g_print ("\n"); } else g_assert_not_reached(); return TRUE; } static int do_break_key(GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify some keys to break\n")); return 1; } while (*args) { g_print (_("Trying to break your application by setting bad values for key:\n %s\n"), *args); if (!key_breakage(conf, *args, BreakageSetBadValues)) return 1; if (!key_breakage(conf, *args, BreakageCleanup)) return 1; ++args; } return 0; } static int do_break_directory(GConfEngine* conf, const gchar** args) { if (args == NULL) { g_printerr (_("Must specify some directories to break\n")); return 1; } while (*args) { gchar* keys[10] = { NULL }; gchar* full_keys[10] = { NULL }; int i; i = 0; while (i < 10) { keys[i] = gconf_unique_key(); full_keys[i] = gconf_concat_dir_and_key(*args, keys[i]); ++i; } g_print (_("Trying to break your application by setting bad values for keys in directory:\n %s\n"), *args); i = 0; while (i < 10) { if (!key_breakage(conf, full_keys[i], BreakageSetBadValues)) return 1; ++i; } i = 0; while (i < 10) { if (!key_breakage(conf, full_keys[i], BreakageCleanup)) return 1; ++i; } i = 0; while (i < 10) { g_free(keys[i]); g_free(full_keys[i]); ++i; } ++args; } return 0; } static int do_get_default_source (const gchar** args) { gchar *filename; gchar *source; gchar buf[512]; FILE *f; /* Try with $sysgconfdir/schema-install-source */ filename = g_build_filename (GCONF_ETCDIR, "schema-install-source", NULL); f = g_fopen(filename, "r"); g_free (filename); if (f != NULL) { source = fgets(buf, 512, f); fclose(f); if (source) { g_strchomp(source); if (*source != '\0') { g_print ("%s\n", source); return 0; } } } /* Use default database */ source = g_strconcat("xml:merged:", GCONF_ETCDIR, "/gconf.xml.defaults", NULL); g_print ("%s\n", source); g_free(source); return 0; }