X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsettings-tool.c;h=cf3ef19137f1b8c4f969b7a80baa5a7e32fcea24;hb=51fac05d73f8363de821eb0d6940dedca13a8c0f;hp=3771a1798eafa0c31ca2d1d0e0d03deb8505b30d;hpb=bedf4c3259756caec97d5aa4cd32d501de2be82e;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsettings-tool.c b/gio/gsettings-tool.c index 3771a17..cf3ef19 100644 --- a/gio/gsettings-tool.c +++ b/gio/gsettings-tool.c @@ -1,10 +1,10 @@ -/* GLIB - Library of useful routines for C programming - * Copyright (C) 2010 Red Hat, Inc. +/* + * Copyright © 2010 Codethink Limited * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2 of the licence, 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 @@ -12,159 +12,820 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . * - * Author: Matthias Clasen + * Author: Ryan Lortie */ -#include -#include +#include "config.h" + +#include #include -#include +#include +#include +#include + +#ifdef G_OS_WIN32 +#include "glib/glib-private.h" +#endif + +static GSettingsSchemaSource *global_schema_source; +static GSettings *global_settings; +static GSettingsSchema *global_schema; +static GSettingsSchemaKey *global_schema_key; +const gchar *global_key; +const gchar *global_value; + +static gboolean +is_relocatable_schema (GSettingsSchema *schema) +{ + return g_settings_schema_get_path (schema) == NULL; +} + +static gboolean +check_relocatable_schema (GSettingsSchema *schema, + const gchar *schema_id) +{ + if (schema == NULL) + { + g_printerr (_("No such schema '%s'\n"), schema_id); + return FALSE; + } + + if (!is_relocatable_schema (schema)) + { + g_printerr (_("Schema '%s' is not relocatable " + "(path must not be specified)\n"), + schema_id); + return FALSE; + } + + return TRUE; +} + +static gboolean +check_schema (GSettingsSchema *schema, + const gchar *schema_id) +{ + if (schema == NULL) + { + g_printerr (_("No such schema '%s'\n"), schema_id); + return FALSE; + } + + if (is_relocatable_schema (schema)) + { + g_printerr (_("Schema '%s' is relocatable " + "(path must be specified)\n"), + schema_id); + return FALSE; + } + + return TRUE; +} + +static gboolean +check_path (const gchar *path) +{ + if (path[0] == '\0') + { + g_printerr (_("Empty path given.\n")); + return FALSE; + } + + if (path[0] != '/') + { + g_printerr (_("Path must begin with a slash (/)\n")); + return FALSE; + } + + if (!g_str_has_suffix (path, "/")) + { + g_printerr (_("Path must end with a slash (/)\n")); + return FALSE; + } + + if (strstr (path, "//")) + { + g_printerr (_("Path must not contain two adjacent slashes (//)\n")); + return FALSE; + } + + return TRUE; +} static void -key_changed (GSettings *settings, - const gchar *key) +output_list (gchar **list) { - GVariant *v; - gchar *value; + gint i; - v = g_settings_get_value (settings, key); - value = g_variant_print (v, FALSE); - g_print ("%s\n", value); - g_free (value); - g_variant_unref (v); + for (i = 0; list[i]; i++) + g_print ("%s\n", list[i]); } -int -main (int argc, char *argv[]) +static void +gsettings_print_version (void) { - gboolean do_get = FALSE; - gboolean do_set = FALSE; - gboolean do_writable = FALSE; - gboolean do_monitor = FALSE; + g_print ("%d.%d.%d\n", glib_major_version, glib_minor_version, + glib_micro_version); +} - gchar *path = NULL; - gchar *schema; - gchar *key; - gchar *value; - - GSettings *settings; - GVariant *v; - - GOptionContext *context; - GOptionEntry entries[] = { - { "get", 'g', 0, G_OPTION_ARG_NONE, &do_get, N_("Get the value of KEY"), NULL }, - { "set", 's', 0, G_OPTION_ARG_NONE, &do_set, N_("Set the value of KEY"), NULL }, - { "writable", 'w', 0, G_OPTION_ARG_NONE, &do_writable, N_("Check if KEY is writable"), NULL }, - { "monitor", 'm', 0, G_OPTION_ARG_NONE, &do_monitor, N_("Monitor KEY for changes"), NULL }, - { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") }, - { NULL } - }; - GError *error; +static void +gsettings_list_schemas (void) +{ + gchar **schemas; - setlocale (LC_ALL, ""); + g_settings_schema_source_list_schemas (global_schema_source, TRUE, &schemas, NULL); + output_list (schemas); + g_strfreev (schemas); +} + +static void +gsettings_list_relocatable_schemas (void) +{ + gchar **schemas; + + g_settings_schema_source_list_schemas (global_schema_source, TRUE, NULL, &schemas); + output_list (schemas); + g_strfreev (schemas); +} - g_type_init (); +static void +gsettings_list_keys (void) +{ + gchar **keys; - context = g_option_context_new (N_("SCHEMA KEY [VALUE]")); - g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); - g_option_context_set_summary (context, N_("Manipulate GSettings configuration")); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + keys = g_settings_list_keys (global_settings); + output_list (keys); + g_strfreev (keys); +} - error = NULL; - if (!g_option_context_parse (context, &argc, &argv, &error)) +static void +gsettings_list_children (void) +{ + gchar **children; + gint max = 0; + gint i; + + children = g_settings_list_children (global_settings); + for (i = 0; children[i]; i++) + if (strlen (children[i]) > max) + max = strlen (children[i]); + + for (i = 0; children[i]; i++) { - g_printerr ("%s\n", error->message); - return 1; + GSettings *child; + GSettingsSchema *schema; + gchar *path; + + child = g_settings_get_child (global_settings, children[i]); + g_object_get (child, + "settings-schema", &schema, + "path", &path, + NULL); + + if (g_settings_schema_get_path (schema) != NULL) + g_print ("%-*s %s\n", max, children[i], g_settings_schema_get_id (schema)); + else + g_print ("%-*s %s:%s\n", max, children[i], g_settings_schema_get_id (schema), path); + + g_object_unref (child); + g_settings_schema_unref (schema); + g_free (path); } - if (do_get + do_set + do_writable + do_monitor != 1) + g_strfreev (children); +} + +static void +enumerate (GSettings *settings) +{ + gchar **keys; + gchar *schema; + gint i; + + g_object_get (settings, "schema-id", &schema, NULL); + + keys = g_settings_list_keys (settings); + for (i = 0; keys[i]; i++) { - g_printerr (_("You must specify exactly one of --get, --set, --writable or --monitor\n")); - return 1; + GVariant *value; + gchar *printed; + + value = g_settings_get_value (settings, keys[i]); + printed = g_variant_print (value, TRUE); + g_print ("%s %s %s\n", schema, keys[i], printed); + g_variant_unref (value); + g_free (printed); + } + + g_free (schema); + g_strfreev (keys); +} + +static void +list_recursively (GSettings *settings) +{ + gchar **children; + gint i; + + enumerate (settings); + children = g_settings_list_children (settings); + for (i = 0; children[i]; i++) + { + GSettings *child; + + child = g_settings_get_child (settings, children[i]); + list_recursively (child); + g_object_unref (child); } - if (do_get || do_writable || do_monitor) + g_strfreev (children); +} + +static void +gsettings_list_recursively (void) +{ + if (global_settings) { - if (argc != 3) + list_recursively (global_settings); + } + else + { + gchar **schemas; + gint i; + + g_settings_schema_source_list_schemas (global_schema_source, TRUE, &schemas, NULL); + + for (i = 0; schemas[i]; i++) { - g_printerr (_("You must specify a schema and a key\n")); - return 1; + GSettings *settings; + + settings = g_settings_new (schemas[i]); + list_recursively (settings); + g_object_unref (settings); } - schema = argv[1]; - key = argv[2]; + g_strfreev (schemas); + } +} + +static void +gsettings_range (void) +{ + GVariant *range, *detail; + const gchar *type; + + range = g_settings_schema_key_get_range (global_schema_key); + g_variant_get (range, "(&sv)", &type, &detail); + + if (strcmp (type, "type") == 0) + g_print ("type %s\n", g_variant_get_type_string (detail) + 1); + + else if (strcmp (type, "range") == 0) + { + GVariant *min, *max; + gchar *smin, *smax; + + g_variant_get (detail, "(**)", &min, &max); + smin = g_variant_print (min, FALSE); + smax = g_variant_print (max, FALSE); + + g_print ("range %s %s %s\n", + g_variant_get_type_string (min), smin, smax); + g_variant_unref (min); + g_variant_unref (max); + g_free (smin); + g_free (smax); } - else if (do_set) + + else if (strcmp (type, "enum") == 0 || strcmp (type, "flags") == 0) { - if (argc != 4) + GVariantIter iter; + GVariant *item; + + g_print ("%s\n", type); + + g_variant_iter_init (&iter, detail); + while (g_variant_iter_loop (&iter, "*", &item)) { - g_printerr (_("You must specify a schema, a key and a value\n")); - return 1; + gchar *printed; + + printed = g_variant_print (item, FALSE); + g_print ("%s\n", printed); + g_free (printed); } + } + + g_variant_unref (detail); + g_variant_unref (range); +} + +static void +gsettings_get (void) +{ + GVariant *value; + gchar *printed; + + value = g_settings_get_value (global_settings, global_key); + printed = g_variant_print (value, TRUE); + g_print ("%s\n", printed); + g_variant_unref (value); + g_free (printed); +} + +static void +gsettings_reset (void) +{ + g_settings_reset (global_settings, global_key); + g_settings_sync (); +} + +static void +reset_all_keys (GSettings *settings) +{ + gchar **keys; + gint i; + + keys = g_settings_list_keys (settings); + for (i = 0; keys[i]; i++) + { + g_settings_reset (settings, keys[i]); + } + + g_strfreev (keys); +} + +static void +gsettings_reset_recursively (void) +{ + gchar **children; + gint i; + + g_settings_delay (global_settings); + + reset_all_keys (global_settings); + children = g_settings_list_children (global_settings); + for (i = 0; children[i]; i++) + { + GSettings *child; + child = g_settings_get_child (global_settings, children[i]); + + reset_all_keys (child); + + g_object_unref (child); + } + + g_strfreev (children); + + g_settings_apply (global_settings); + g_settings_sync (); +} + +static void +gsettings_writable (void) +{ + g_print ("%s\n", + g_settings_is_writable (global_settings, global_key) ? + "true" : "false"); +} + +static void +value_changed (GSettings *settings, + const gchar *key, + gpointer user_data) +{ + GVariant *value; + gchar *printed; + + value = g_settings_get_value (settings, key); + printed = g_variant_print (value, TRUE); + g_print ("%s: %s\n", key, printed); + g_variant_unref (value); + g_free (printed); +} + +static void +gsettings_monitor (void) +{ + gchar **keys; - schema = argv[1]; - key = argv[2]; - value = argv[3]; + if (global_key) + { + gchar *name; + + name = g_strdup_printf ("changed::%s", global_key); + g_signal_connect (global_settings, name, G_CALLBACK (value_changed), NULL); } + else + g_signal_connect (global_settings, "changed", G_CALLBACK (value_changed), NULL); + + /* We have to read a value from GSettings before we start receiving + * signals... + * + * If the schema has zero keys then we won't be displaying any + * notifications anyway. + */ + keys = g_settings_list_keys (global_settings); + if (keys[0]) + g_variant_unref (g_settings_get_value (global_settings, keys[0])); + g_strfreev (keys); + + for (;;) + g_main_context_iteration (NULL, TRUE); +} + +static void +gsettings_set (void) +{ + const GVariantType *type; + GError *error = NULL; + GVariant *new; + gchar *freeme = NULL; + + type = g_settings_schema_key_get_value_type (global_schema_key); - settings = g_settings_new_with_path (schema, path); + new = g_variant_parse (type, global_value, NULL, NULL, &error); - if (do_get) + /* If that didn't work and the type is string then we should assume + * that the user is just trying to set a string directly and forgot + * the quotes (or had them consumed by the shell). + * + * If the user started with a quote then we assume that some deeper + * problem is at play and we want the failure in that case. + * + * Consider: + * + * gsettings set x.y.z key "'i don't expect this to work'" + * + * Note that we should not just add quotes and try parsing again, but + * rather assume that the user is providing us with a bare string. + * Assume we added single quotes, then consider this case: + * + * gsettings set x.y.z key "i'd expect this to work" + * + * A similar example could be given for double quotes. + * + * Avoid that whole mess by just using g_variant_new_string(). + */ + if (new == NULL && + g_variant_type_equal (type, G_VARIANT_TYPE_STRING) && + global_value[0] != '\'' && global_value[0] != '"') { - v = g_settings_get_value (settings, key); + g_clear_error (&error); + new = g_variant_new_string (global_value); + } - g_print ("%s\n", g_variant_print (v, FALSE)); + if (new == NULL) + { + gchar *context; - return 0; + context = g_variant_parse_error_print_context (error, global_value); + g_printerr ("%s", context); + exit (1); } - else if (do_writable) + + if (!g_settings_schema_key_range_check (global_schema_key, new)) { - if (g_settings_is_writable (settings, key)) - g_print ("true\n"); - else - g_print ("false\n"); + g_printerr (_("The provided value is outside of the valid range\n")); + g_variant_unref (new); + exit (1); + } + + if (!g_settings_set_value (global_settings, global_key, new)) + { + g_printerr (_("The key is not writable\n")); + exit (1); + } + + g_settings_sync (); + + g_free (freeme); +} + +static int +gsettings_help (gboolean requested, + const gchar *command) +{ + const gchar *description; + const gchar *synopsis; + GString *string; + + string = g_string_new (NULL); + + if (command == NULL) + ; + + else if (strcmp (command, "help") == 0) + { + description = _("Print help"); + synopsis = "[COMMAND]"; + } - return 0; + else if (strcmp (command, "--version") == 0) + { + description = _("Print version information and exit"); + synopsis = ""; + } + + else if (strcmp (command, "list-schemas") == 0) + { + description = _("List the installed (non-relocatable) schemas"); + synopsis = ""; + } + + else if (strcmp (command, "list-relocatable-schemas") == 0) + { + description = _("List the installed relocatable schemas"); + synopsis = ""; + } + + else if (strcmp (command, "list-keys") == 0) + { + description = _("List the keys in SCHEMA"); + synopsis = N_("SCHEMA[:PATH]"); + } + + else if (strcmp (command, "list-children") == 0) + { + description = _("List the children of SCHEMA"); + synopsis = N_("SCHEMA[:PATH]"); + } + + else if (strcmp (command, "list-recursively") == 0) + { + description = _("List keys and values, recursively\n" + "If no SCHEMA is given, list all keys\n"); + synopsis = N_("[SCHEMA[:PATH]]"); + } + + else if (strcmp (command, "get") == 0) + { + description = _("Get the value of KEY"); + synopsis = N_("SCHEMA[:PATH] KEY"); + } + + else if (strcmp (command, "range") == 0) + { + description = _("Query the range of valid values for KEY"); + synopsis = N_("SCHEMA[:PATH] KEY"); + } + + else if (strcmp (command, "set") == 0) + { + description = _("Set the value of KEY to VALUE"); + synopsis = N_("SCHEMA[:PATH] KEY VALUE"); + } + + else if (strcmp (command, "reset") == 0) + { + description = _("Reset KEY to its default value"); + synopsis = N_("SCHEMA[:PATH] KEY"); } - else if (do_set) + + else if (strcmp (command, "reset-recursively") == 0) { - const GVariantType *type; - GError *error; + description = _("Reset all keys in SCHEMA to their defaults"); + synopsis = N_("SCHEMA[:PATH]"); + } - v = g_settings_get_value (settings, key); - type = g_variant_get_type (v); - g_variant_unref (v); + else if (strcmp (command, "writable") == 0) + { + description = _("Check if KEY is writable"); + synopsis = N_("SCHEMA[:PATH] KEY"); + } - error = NULL; - v = g_variant_parse (type, value, NULL, NULL, &error); - if (v == NULL) + else if (strcmp (command, "monitor") == 0) + { + description = _("Monitor KEY for changes.\n" + "If no KEY is specified, monitor all keys in SCHEMA.\n" + "Use ^C to stop monitoring.\n"); + synopsis = N_("SCHEMA[:PATH] [KEY]"); + } + else + { + g_string_printf (string, _("Unknown command %s\n\n"), command); + requested = FALSE; + command = NULL; + } + + if (command == NULL) + { + g_string_append (string, + _("Usage:\n" + " gsettings --version\n" + " gsettings [--schemadir SCHEMADIR] COMMAND [ARGS...]\n" + "\n" + "Commands:\n" + " help Show this information\n" + " list-schemas List installed schemas\n" + " list-relocatable-schemas List relocatable schemas\n" + " list-keys List keys in a schema\n" + " list-children List children of a schema\n" + " list-recursively List keys and values, recursively\n" + " range Queries the range of a key\n" + " get Get the value of a key\n" + " set Set the value of a key\n" + " reset Reset the value of a key\n" + " reset-recursively Reset all values in a given schema\n" + " writable Check if a key is writable\n" + " monitor Watch for changes\n" + "\n" + "Use 'gsettings help COMMAND' to get detailed help.\n\n")); + } + else + { + g_string_append_printf (string, _("Usage:\n gsettings [--schemadir SCHEMADIR] %s %s\n\n%s\n\n"), + command, synopsis[0] ? _(synopsis) : "", description); + + g_string_append (string, _("Arguments:\n")); + + g_string_append (string, + _(" SCHEMADIR A directory to search for additional schemas\n")); + + if (strstr (synopsis, "[COMMAND]")) + g_string_append (string, + _(" COMMAND The (optional) command to explain\n")); + + else if (strstr (synopsis, "SCHEMA")) + g_string_append (string, + _(" SCHEMA The name of the schema\n" + " PATH The path, for relocatable schemas\n")); + + if (strstr (synopsis, "[KEY]")) + g_string_append (string, + _(" KEY The (optional) key within the schema\n")); + + else if (strstr (synopsis, "KEY")) + g_string_append (string, + _(" KEY The key within the schema\n")); + + if (strstr (synopsis, "VALUE")) + g_string_append (string, + _(" VALUE The value to set\n")); + + g_string_append (string, "\n"); + } + + if (requested) + g_print ("%s", string->str); + else + g_printerr ("%s\n", string->str); + + g_string_free (string, TRUE); + + return requested ? 0 : 1; +} + + +int +main (int argc, char **argv) +{ + void (* function) (void); + +#ifdef G_OS_WIN32 + gchar *tmp; +#endif + + setlocale (LC_ALL, ""); + textdomain (GETTEXT_PACKAGE); + +#ifdef G_OS_WIN32 + tmp = _glib_get_locale_dir (); + bindtextdomain (GETTEXT_PACKAGE, tmp); + g_free (tmp); +#else + bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR); +#endif + +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + if (argc < 2) + return gsettings_help (FALSE, NULL); + + global_schema_source = g_settings_schema_source_ref (g_settings_schema_source_get_default ()); + + if (argc > 3 && g_str_equal (argv[1], "--schemadir")) + { + GSettingsSchemaSource *parent = global_schema_source; + GError *error = NULL; + + global_schema_source = g_settings_schema_source_new_from_directory (argv[2], parent, FALSE, &error); + g_settings_schema_source_unref (parent); + + if (global_schema_source == NULL) { - g_printerr ("%s\n", error->message); + g_printerr (_("Could not load schemas from %s: %s\n"), argv[2], error->message); + g_clear_error (&error); + return 1; } - if (!g_settings_set_value (settings, key, v)) + /* shift remaining arguments (not correct wrt argv[0], but doesn't matter) */ + argv = argv + 2; + argc -= 2; + } + + if (strcmp (argv[1], "help") == 0) + return gsettings_help (TRUE, argv[2]); + + else if (argc == 2 && strcmp (argv[1], "--version") == 0) + function = gsettings_print_version; + + else if (argc == 2 && strcmp (argv[1], "list-schemas") == 0) + function = gsettings_list_schemas; + + else if (argc == 2 && strcmp (argv[1], "list-relocatable-schemas") == 0) + function = gsettings_list_relocatable_schemas; + + else if (argc == 3 && strcmp (argv[1], "list-keys") == 0) + function = gsettings_list_keys; + + else if (argc == 3 && strcmp (argv[1], "list-children") == 0) + function = gsettings_list_children; + + else if ((argc == 2 || argc == 3) && strcmp (argv[1], "list-recursively") == 0) + function = gsettings_list_recursively; + + else if (argc == 4 && strcmp (argv[1], "range") == 0) + function = gsettings_range; + + else if (argc == 4 && strcmp (argv[1], "get") == 0) + function = gsettings_get; + + else if (argc == 5 && strcmp (argv[1], "set") == 0) + function = gsettings_set; + + else if (argc == 4 && strcmp (argv[1], "reset") == 0) + function = gsettings_reset; + + else if (argc == 3 && strcmp (argv[1], "reset-recursively") == 0) + function = gsettings_reset_recursively; + + else if (argc == 4 && strcmp (argv[1], "writable") == 0) + function = gsettings_writable; + + else if ((argc == 3 || argc == 4) && strcmp (argv[1], "monitor") == 0) + function = gsettings_monitor; + + else + return gsettings_help (FALSE, argv[1]); + + if (argc > 2) + { + gchar **parts; + + if (argv[2][0] == '\0') { - g_printerr (_("Key %s is not writable\n"), key); + g_printerr (_("Empty schema name given\n")); return 1; } + + parts = g_strsplit (argv[2], ":", 2); + + global_schema = g_settings_schema_source_lookup (global_schema_source, parts[0], TRUE); + if (parts[1]) + { + if (!check_relocatable_schema (global_schema, parts[0]) || !check_path (parts[1])) + return 1; + + global_settings = g_settings_new_full (global_schema, NULL, parts[1]); + } + else + { + if (!check_schema (global_schema, parts[0])) + return 1; + + global_settings = g_settings_new_full (global_schema, NULL, NULL); + } + + g_strfreev (parts); } - else if (do_monitor) - { - gchar *detailed_signal; - GMainLoop *loop; - detailed_signal = g_strdup_printf ("changed::%s", key); - g_signal_connect (settings, detailed_signal, - G_CALLBACK (key_changed), NULL); + if (argc > 3) + { + if (!g_settings_schema_has_key (global_schema, argv[3])) + { + g_printerr (_("No such key '%s'\n"), argv[3]); + return 1; + } - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); + global_key = argv[3]; + global_schema_key = g_settings_schema_get_key (global_schema, global_key); } + if (argc > 4) + global_value = argv[4]; + + (* function) (); + + + g_clear_pointer (&global_schema_source, g_settings_schema_source_unref); + g_clear_pointer (&global_schema_key, g_settings_schema_key_unref); + g_clear_pointer (&global_schema, g_settings_schema_unref); + g_clear_object (&global_settings); + return 0; }