mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 19:36:18 +01:00
8ff5668a45
GSettings objects begin watching for changes as soon as they are created in order that they can emit the "changed" signal. In the case of dconf, if we want to be able to emit the changed signal, we need to go on the bus and add some match rules. This requires creating the dconf helper thread and also requires initialising GDBus (which creates another thread). Some users of GSettings are never interested in the "changed" signal. One of these users is the glib-networking code that gets run every time a new network connection is created. Some users are reporting that they are annoyed that simply establishing a network connection would spawn two extra threads and create a D-Bus connection. In order to avoid doing unnecessary work for these simple uses, delay the subscription until we know that we will actually need to do it. We do this in a simple way, using a simple argument: in order for the user to care that a value changed then they must have: 1) watched for a change signal; and then 2) actually read a value If the user didn't actually read a value then they cannot possibly be interested in if the value changed or not (since they never knew the old value to begin with and therefore would be unable to observe that it ever changed, since they have nothing to compare the new value with). This really is a behaviour change, however, and it does impact at least one user: the 'monitor' functionality of the GSettings commandline tool, which is interested in reporting changes without ever having known the original values. We add a workaround to the commandline tool in order to ensure that it continues to function properly. It's also possible to argue that it is completely valid to have read a value and _then_ established a change signal connection under the (correct) assumption that it would not have been possible to miss a change signal by virtue of not having returned to the mainloop. Although this argument is true, this pattern is extremely non-idiomatic, and the problem is easily avoided by doing things in the usual order. We never really talked about change notification in the overview documentation for GSettings, so it seems like now is a good time to add some discussion, including the new rules for when one can expect change signals to be emitted. https://bugzilla.gnome.org/show_bug.cgi?id=733791
832 lines
20 KiB
C
832 lines
20 KiB
C
/*
|
|
* 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 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
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Ryan Lortie <desrt@desrt.ca>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gio/gio.h>
|
|
#include <gi18n.h>
|
|
#include <locale.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#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
|
|
output_list (gchar **list)
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; list[i]; i++)
|
|
g_print ("%s\n", list[i]);
|
|
}
|
|
|
|
static void
|
|
gsettings_print_version (void)
|
|
{
|
|
g_print ("%d.%d.%d\n", glib_major_version, glib_minor_version,
|
|
glib_micro_version);
|
|
}
|
|
|
|
static void
|
|
gsettings_list_schemas (void)
|
|
{
|
|
gchar **schemas;
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
gsettings_list_keys (void)
|
|
{
|
|
gchar **keys;
|
|
|
|
keys = g_settings_list_keys (global_settings);
|
|
output_list (keys);
|
|
g_strfreev (keys);
|
|
}
|
|
|
|
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++)
|
|
{
|
|
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);
|
|
}
|
|
|
|
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++)
|
|
{
|
|
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);
|
|
}
|
|
|
|
g_strfreev (children);
|
|
}
|
|
|
|
static void
|
|
gsettings_list_recursively (void)
|
|
{
|
|
if (global_settings)
|
|
{
|
|
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++)
|
|
{
|
|
GSettings *settings;
|
|
|
|
settings = g_settings_new (schemas[i]);
|
|
list_recursively (settings);
|
|
g_object_unref (settings);
|
|
}
|
|
|
|
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 (strcmp (type, "enum") == 0 || strcmp (type, "flags") == 0)
|
|
{
|
|
GVariantIter iter;
|
|
GVariant *item;
|
|
|
|
g_print ("%s\n", type);
|
|
|
|
g_variant_iter_init (&iter, detail);
|
|
while (g_variant_iter_loop (&iter, "*", &item))
|
|
{
|
|
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;
|
|
|
|
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);
|
|
|
|
new = g_variant_parse (type, global_value, NULL, NULL, &error);
|
|
|
|
/* 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] != '"')
|
|
{
|
|
g_clear_error (&error);
|
|
new = g_variant_new_string (global_value);
|
|
}
|
|
|
|
if (new == NULL)
|
|
{
|
|
gchar *context;
|
|
|
|
context = g_variant_parse_error_print_context (error, global_value);
|
|
g_printerr ("%s", context);
|
|
exit (1);
|
|
}
|
|
|
|
if (!g_settings_schema_key_range_check (global_schema_key, new))
|
|
{
|
|
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]";
|
|
}
|
|
|
|
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 (strcmp (command, "reset-recursively") == 0)
|
|
{
|
|
description = _("Reset all keys in SCHEMA to their defaults");
|
|
synopsis = N_("SCHEMA[:PATH]");
|
|
}
|
|
|
|
else if (strcmp (command, "writable") == 0)
|
|
{
|
|
description = _("Check if KEY is writable");
|
|
synopsis = N_("SCHEMA[:PATH] KEY");
|
|
}
|
|
|
|
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 (_("Could not load schemas from %s: %s\n"), argv[2], error->message);
|
|
g_clear_error (&error);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* 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 (_("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);
|
|
}
|
|
|
|
if (argc > 3)
|
|
{
|
|
if (!g_settings_schema_has_key (global_schema, argv[3]))
|
|
{
|
|
g_printerr (_("No such key '%s'\n"), argv[3]);
|
|
return 1;
|
|
}
|
|
|
|
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;
|
|
}
|