1 /*
2 * Copyright © 2010 Codethink Limited
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Ryan Lortie <desrt@desrt.ca>
18 */
19
20 #include "config.h"
21
22 #include <gio/gio.h>
23 #include <gi18n.h>
24 #include <locale.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "glib/glib-private.h"
29
30 static GSettingsSchemaSource *global_schema_source;
31 static GSettings *global_settings;
32 static GSettingsSchema *global_schema;
33 static GSettingsSchemaKey *global_schema_key;
34 const gchar *global_key;
35 const gchar *global_value;
36
37 static gboolean
is_relocatable_schema(GSettingsSchema * schema)38 is_relocatable_schema (GSettingsSchema *schema)
39 {
40 return g_settings_schema_get_path (schema) == NULL;
41 }
42
43 static gboolean
check_relocatable_schema(GSettingsSchema * schema,const gchar * schema_id)44 check_relocatable_schema (GSettingsSchema *schema,
45 const gchar *schema_id)
46 {
47 if (schema == NULL)
48 {
49 g_printerr (_("No such schema “%s”\n"), schema_id);
50 return FALSE;
51 }
52
53 if (!is_relocatable_schema (schema))
54 {
55 g_printerr (_("Schema “%s” is not relocatable "
56 "(path must not be specified)\n"),
57 schema_id);
58 return FALSE;
59 }
60
61 return TRUE;
62 }
63
64 static gboolean
check_schema(GSettingsSchema * schema,const gchar * schema_id)65 check_schema (GSettingsSchema *schema,
66 const gchar *schema_id)
67 {
68 if (schema == NULL)
69 {
70 g_printerr (_("No such schema “%s”\n"), schema_id);
71 return FALSE;
72 }
73
74 if (is_relocatable_schema (schema))
75 {
76 g_printerr (_("Schema “%s” is relocatable "
77 "(path must be specified)\n"),
78 schema_id);
79 return FALSE;
80 }
81
82 return TRUE;
83 }
84
85 static gboolean
check_path(const gchar * path)86 check_path (const gchar *path)
87 {
88 if (path[0] == '\0')
89 {
90 g_printerr (_("Empty path given.\n"));
91 return FALSE;
92 }
93
94 if (path[0] != '/')
95 {
96 g_printerr (_("Path must begin with a slash (/)\n"));
97 return FALSE;
98 }
99
100 if (!g_str_has_suffix (path, "/"))
101 {
102 g_printerr (_("Path must end with a slash (/)\n"));
103 return FALSE;
104 }
105
106 if (strstr (path, "//"))
107 {
108 g_printerr (_("Path must not contain two adjacent slashes (//)\n"));
109 return FALSE;
110 }
111
112 return TRUE;
113 }
114
115 static void
output_list(gchar ** list)116 output_list (gchar **list)
117 {
118 gint i;
119
120 for (i = 0; list[i]; i++)
121 g_print ("%s\n", list[i]);
122 }
123
124 static void
gsettings_print_version(void)125 gsettings_print_version (void)
126 {
127 g_print ("%d.%d.%d\n", glib_major_version, glib_minor_version,
128 glib_micro_version);
129 }
130
131 static void
gsettings_list_schemas(void)132 gsettings_list_schemas (void)
133 {
134 gchar **schemas;
135
136 g_settings_schema_source_list_schemas (global_schema_source, TRUE, &schemas, NULL);
137 output_list (schemas);
138 g_strfreev (schemas);
139 }
140
141 static void
gsettings_list_schemas_with_paths(void)142 gsettings_list_schemas_with_paths (void)
143 {
144 gchar **schemas;
145 gsize i;
146
147 g_settings_schema_source_list_schemas (global_schema_source, TRUE, &schemas, NULL);
148
149 for (i = 0; schemas[i] != NULL; i++)
150 {
151 GSettingsSchema *schema;
152 gchar *schema_name;
153 const gchar *schema_path;
154
155 schema_name = g_steal_pointer (&schemas[i]);
156
157 schema = g_settings_schema_source_lookup (global_schema_source, schema_name, TRUE);
158 schema_path = g_settings_schema_get_path (schema);
159
160 schemas[i] = g_strconcat (schema_name, " ", schema_path, NULL);
161
162 g_settings_schema_unref (schema);
163 g_free (schema_name);
164 }
165
166 output_list (schemas);
167 g_strfreev (schemas);
168 }
169
170 static void
gsettings_list_relocatable_schemas(void)171 gsettings_list_relocatable_schemas (void)
172 {
173 gchar **schemas;
174
175 g_settings_schema_source_list_schemas (global_schema_source, TRUE, NULL, &schemas);
176 output_list (schemas);
177 g_strfreev (schemas);
178 }
179
180 static void
gsettings_list_keys(void)181 gsettings_list_keys (void)
182 {
183 gchar **keys;
184
185 keys = g_settings_schema_list_keys (global_schema);
186 output_list (keys);
187 g_strfreev (keys);
188 }
189
190 static void
gsettings_list_children(void)191 gsettings_list_children (void)
192 {
193 gchar **children;
194 gint max = 0;
195 gint i;
196
197 children = g_settings_list_children (global_settings);
198 for (i = 0; children[i]; i++)
199 if (strlen (children[i]) > max)
200 max = strlen (children[i]);
201
202 for (i = 0; children[i]; i++)
203 {
204 GSettings *child;
205 GSettingsSchema *schema;
206 gchar *path;
207
208 child = g_settings_get_child (global_settings, children[i]);
209 g_object_get (child,
210 "settings-schema", &schema,
211 "path", &path,
212 NULL);
213
214 if (g_settings_schema_get_path (schema) != NULL)
215 g_print ("%-*s %s\n", max, children[i], g_settings_schema_get_id (schema));
216 else
217 g_print ("%-*s %s:%s\n", max, children[i], g_settings_schema_get_id (schema), path);
218
219 g_object_unref (child);
220 g_settings_schema_unref (schema);
221 g_free (path);
222 }
223
224 g_strfreev (children);
225 }
226
227 static void
enumerate(GSettings * settings)228 enumerate (GSettings *settings)
229 {
230 gchar **keys;
231 GSettingsSchema *schema;
232 gint i;
233
234 g_object_get (settings, "settings-schema", &schema, NULL);
235
236 keys = g_settings_schema_list_keys (schema);
237 for (i = 0; keys[i]; i++)
238 {
239 GVariant *value;
240 gchar *printed;
241
242 value = g_settings_get_value (settings, keys[i]);
243 printed = g_variant_print (value, TRUE);
244 g_print ("%s %s %s\n", g_settings_schema_get_id (schema), keys[i], printed);
245 g_variant_unref (value);
246 g_free (printed);
247 }
248
249 g_settings_schema_unref (schema);
250 g_strfreev (keys);
251 }
252
253 static void
list_recursively(GSettings * settings)254 list_recursively (GSettings *settings)
255 {
256 gchar **children;
257 gint i;
258
259 enumerate (settings);
260 children = g_settings_list_children (settings);
261 for (i = 0; children[i]; i++)
262 {
263 gboolean will_see_elsewhere = FALSE;
264 GSettings *child;
265
266 child = g_settings_get_child (settings, children[i]);
267
268 if (global_settings == NULL)
269 {
270 /* we're listing all non-relocatable settings objects from the
271 * top-level, so if this one is non-relocatable, don't recurse,
272 * because we will pick it up later on.
273 */
274
275 GSettingsSchema *child_schema;
276
277 g_object_get (child, "settings-schema", &child_schema, NULL);
278 will_see_elsewhere = !is_relocatable_schema (child_schema);
279 g_settings_schema_unref (child_schema);
280 }
281
282 if (!will_see_elsewhere)
283 list_recursively (child);
284
285 g_object_unref (child);
286 }
287
288 g_strfreev (children);
289 }
290
291 static void
gsettings_list_recursively(void)292 gsettings_list_recursively (void)
293 {
294 if (global_settings)
295 {
296 list_recursively (global_settings);
297 }
298 else
299 {
300 gchar **schemas;
301 gint i;
302
303 g_settings_schema_source_list_schemas (global_schema_source, TRUE, &schemas, NULL);
304
305 for (i = 0; schemas[i]; i++)
306 {
307 GSettings *settings;
308
309 settings = g_settings_new (schemas[i]);
310 list_recursively (settings);
311 g_object_unref (settings);
312 }
313
314 g_strfreev (schemas);
315 }
316 }
317
318 static void
gsettings_description(void)319 gsettings_description (void)
320 {
321 const gchar *description;
322 description = g_settings_schema_key_get_description (global_schema_key);
323 if (description == NULL)
324 description = g_settings_schema_key_get_summary (global_schema_key);
325 g_print ("%s\n", description);
326 }
327
328 static void
gsettings_range(void)329 gsettings_range (void)
330 {
331 GVariant *range, *detail;
332 const gchar *type;
333
334 range = g_settings_schema_key_get_range (global_schema_key);
335 g_variant_get (range, "(&sv)", &type, &detail);
336
337 if (strcmp (type, "type") == 0)
338 g_print ("type %s\n", g_variant_get_type_string (detail) + 1);
339
340 else if (strcmp (type, "range") == 0)
341 {
342 GVariant *min, *max;
343 gchar *smin, *smax;
344
345 g_variant_get (detail, "(**)", &min, &max);
346 smin = g_variant_print (min, FALSE);
347 smax = g_variant_print (max, FALSE);
348
349 g_print ("range %s %s %s\n",
350 g_variant_get_type_string (min), smin, smax);
351 g_variant_unref (min);
352 g_variant_unref (max);
353 g_free (smin);
354 g_free (smax);
355 }
356
357 else if (strcmp (type, "enum") == 0 || strcmp (type, "flags") == 0)
358 {
359 GVariantIter iter;
360 GVariant *item;
361
362 g_print ("%s\n", type);
363
364 g_variant_iter_init (&iter, detail);
365 while (g_variant_iter_loop (&iter, "*", &item))
366 {
367 gchar *printed;
368
369 printed = g_variant_print (item, FALSE);
370 g_print ("%s\n", printed);
371 g_free (printed);
372 }
373 }
374
375 g_variant_unref (detail);
376 g_variant_unref (range);
377 }
378
379 static void
gsettings_get(void)380 gsettings_get (void)
381 {
382 GVariant *value;
383 gchar *printed;
384
385 value = g_settings_get_value (global_settings, global_key);
386 printed = g_variant_print (value, TRUE);
387 g_print ("%s\n", printed);
388 g_variant_unref (value);
389 g_free (printed);
390 }
391
392 static void
gsettings_reset(void)393 gsettings_reset (void)
394 {
395 g_settings_reset (global_settings, global_key);
396 g_settings_sync ();
397 }
398
399 static void
reset_all_keys(GSettings * settings)400 reset_all_keys (GSettings *settings)
401 {
402 GSettingsSchema *schema;
403 gchar **keys;
404 gint i;
405
406 g_object_get (settings, "settings-schema", &schema, NULL);
407
408 keys = g_settings_schema_list_keys (schema);
409 for (i = 0; keys[i]; i++)
410 {
411 g_settings_reset (settings, keys[i]);
412 }
413
414 g_settings_schema_unref (schema);
415 g_strfreev (keys);
416 }
417
418 static void
gsettings_reset_recursively(void)419 gsettings_reset_recursively (void)
420 {
421 gchar **children;
422 gint i;
423
424 g_settings_delay (global_settings);
425
426 reset_all_keys (global_settings);
427 children = g_settings_list_children (global_settings);
428 for (i = 0; children[i]; i++)
429 {
430 GSettings *child;
431 child = g_settings_get_child (global_settings, children[i]);
432
433 reset_all_keys (child);
434
435 g_object_unref (child);
436 }
437
438 g_strfreev (children);
439
440 g_settings_apply (global_settings);
441 g_settings_sync ();
442 }
443
444 static void
gsettings_writable(void)445 gsettings_writable (void)
446 {
447 g_print ("%s\n",
448 g_settings_is_writable (global_settings, global_key) ?
449 "true" : "false");
450 }
451
452 static void
value_changed(GSettings * settings,const gchar * key,gpointer user_data)453 value_changed (GSettings *settings,
454 const gchar *key,
455 gpointer user_data)
456 {
457 GVariant *value;
458 gchar *printed;
459
460 value = g_settings_get_value (settings, key);
461 printed = g_variant_print (value, TRUE);
462 g_print ("%s: %s\n", key, printed);
463 g_variant_unref (value);
464 g_free (printed);
465 }
466
467 static void
gsettings_monitor(void)468 gsettings_monitor (void)
469 {
470 if (global_key)
471 {
472 gchar *name;
473
474 name = g_strdup_printf ("changed::%s", global_key);
475 g_signal_connect (global_settings, name, G_CALLBACK (value_changed), NULL);
476 }
477 else
478 g_signal_connect (global_settings, "changed", G_CALLBACK (value_changed), NULL);
479
480 for (;;)
481 g_main_context_iteration (NULL, TRUE);
482 }
483
484 static void
gsettings_set(void)485 gsettings_set (void)
486 {
487 const GVariantType *type;
488 GError *error = NULL;
489 GVariant *new;
490 gchar *freeme = NULL;
491
492 type = g_settings_schema_key_get_value_type (global_schema_key);
493
494 new = g_variant_parse (type, global_value, NULL, NULL, &error);
495
496 /* If that didn't work and the type is string then we should assume
497 * that the user is just trying to set a string directly and forgot
498 * the quotes (or had them consumed by the shell).
499 *
500 * If the user started with a quote then we assume that some deeper
501 * problem is at play and we want the failure in that case.
502 *
503 * Consider:
504 *
505 * gsettings set x.y.z key "'i don't expect this to work'"
506 *
507 * Note that we should not just add quotes and try parsing again, but
508 * rather assume that the user is providing us with a bare string.
509 * Assume we added single quotes, then consider this case:
510 *
511 * gsettings set x.y.z key "i'd expect this to work"
512 *
513 * A similar example could be given for double quotes.
514 *
515 * Avoid that whole mess by just using g_variant_new_string().
516 */
517 if (new == NULL &&
518 g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
519 global_value[0] != '\'' && global_value[0] != '"')
520 {
521 g_clear_error (&error);
522 new = g_variant_new_string (global_value);
523 }
524
525 if (new == NULL)
526 {
527 gchar *context;
528
529 context = g_variant_parse_error_print_context (error, global_value);
530 g_printerr ("%s", context);
531 exit (1);
532 }
533
534 if (!g_settings_schema_key_range_check (global_schema_key, new))
535 {
536 g_printerr (_("The provided value is outside of the valid range\n"));
537 g_variant_unref (new);
538 exit (1);
539 }
540
541 if (!g_settings_set_value (global_settings, global_key, new))
542 {
543 g_printerr (_("The key is not writable\n"));
544 exit (1);
545 }
546
547 g_settings_sync ();
548
549 g_free (freeme);
550 }
551
552 static int
gsettings_help(gboolean requested,const gchar * command)553 gsettings_help (gboolean requested,
554 const gchar *command)
555 {
556 const gchar *description;
557 const gchar *synopsis;
558 GString *string;
559
560 string = g_string_new (NULL);
561
562 if (command == NULL)
563 ;
564
565 else if (strcmp (command, "help") == 0)
566 {
567 description = _("Print help");
568 synopsis = "[COMMAND]";
569 }
570
571 else if (strcmp (command, "--version") == 0)
572 {
573 description = _("Print version information and exit");
574 synopsis = "";
575 }
576
577 else if (strcmp (command, "list-schemas") == 0)
578 {
579 description = _("List the installed (non-relocatable) schemas");
580 synopsis = "[--print-paths]";
581 }
582
583 else if (strcmp (command, "list-relocatable-schemas") == 0)
584 {
585 description = _("List the installed relocatable schemas");
586 synopsis = "";
587 }
588
589 else if (strcmp (command, "list-keys") == 0)
590 {
591 description = _("List the keys in SCHEMA");
592 synopsis = N_("SCHEMA[:PATH]");
593 }
594
595 else if (strcmp (command, "list-children") == 0)
596 {
597 description = _("List the children of SCHEMA");
598 synopsis = N_("SCHEMA[:PATH]");
599 }
600
601 else if (strcmp (command, "list-recursively") == 0)
602 {
603 description = _("List keys and values, recursively\n"
604 "If no SCHEMA is given, list all keys\n");
605 synopsis = N_("[SCHEMA[:PATH]]");
606 }
607
608 else if (strcmp (command, "get") == 0)
609 {
610 description = _("Get the value of KEY");
611 synopsis = N_("SCHEMA[:PATH] KEY");
612 }
613
614 else if (strcmp (command, "range") == 0)
615 {
616 description = _("Query the range of valid values for KEY");
617 synopsis = N_("SCHEMA[:PATH] KEY");
618 }
619
620 else if (strcmp (command, "describe") == 0)
621 {
622 description = _("Query the description for KEY");
623 synopsis = N_("SCHEMA[:PATH] KEY");
624 }
625
626 else if (strcmp (command, "set") == 0)
627 {
628 description = _("Set the value of KEY to VALUE");
629 synopsis = N_("SCHEMA[:PATH] KEY VALUE");
630 }
631
632 else if (strcmp (command, "reset") == 0)
633 {
634 description = _("Reset KEY to its default value");
635 synopsis = N_("SCHEMA[:PATH] KEY");
636 }
637
638 else if (strcmp (command, "reset-recursively") == 0)
639 {
640 description = _("Reset all keys in SCHEMA to their defaults");
641 synopsis = N_("SCHEMA[:PATH]");
642 }
643
644 else if (strcmp (command, "writable") == 0)
645 {
646 description = _("Check if KEY is writable");
647 synopsis = N_("SCHEMA[:PATH] KEY");
648 }
649
650 else if (strcmp (command, "monitor") == 0)
651 {
652 description = _("Monitor KEY for changes.\n"
653 "If no KEY is specified, monitor all keys in SCHEMA.\n"
654 "Use ^C to stop monitoring.\n");
655 synopsis = N_("SCHEMA[:PATH] [KEY]");
656 }
657 else
658 {
659 g_string_printf (string, _("Unknown command %s\n\n"), command);
660 requested = FALSE;
661 command = NULL;
662 }
663
664 if (command == NULL)
665 {
666 g_string_append (string,
667 _("Usage:\n"
668 " gsettings --version\n"
669 " gsettings [--schemadir SCHEMADIR] COMMAND [ARGS…]\n"
670 "\n"
671 "Commands:\n"
672 " help Show this information\n"
673 " list-schemas List installed schemas\n"
674 " list-relocatable-schemas List relocatable schemas\n"
675 " list-keys List keys in a schema\n"
676 " list-children List children of a schema\n"
677 " list-recursively List keys and values, recursively\n"
678 " range Queries the range of a key\n"
679 " describe Queries the description of a key\n"
680 " get Get the value of a key\n"
681 " set Set the value of a key\n"
682 " reset Reset the value of a key\n"
683 " reset-recursively Reset all values in a given schema\n"
684 " writable Check if a key is writable\n"
685 " monitor Watch for changes\n"
686 "\n"
687 "Use “gsettings help COMMAND” to get detailed help.\n\n"));
688 }
689 else
690 {
691 g_string_append_printf (string, _("Usage:\n gsettings [--schemadir SCHEMADIR] %s %s\n\n%s\n\n"),
692 command, synopsis[0] ? _(synopsis) : "", description);
693
694 g_string_append (string, _("Arguments:\n"));
695
696 g_string_append (string,
697 _(" SCHEMADIR A directory to search for additional schemas\n"));
698
699 if (strstr (synopsis, "[COMMAND]"))
700 g_string_append (string,
701 _(" COMMAND The (optional) command to explain\n"));
702
703 else if (strstr (synopsis, "SCHEMA"))
704 g_string_append (string,
705 _(" SCHEMA The name of the schema\n"
706 " PATH The path, for relocatable schemas\n"));
707
708 if (strstr (synopsis, "[KEY]"))
709 g_string_append (string,
710 _(" KEY The (optional) key within the schema\n"));
711
712 else if (strstr (synopsis, "KEY"))
713 g_string_append (string,
714 _(" KEY The key within the schema\n"));
715
716 if (strstr (synopsis, "VALUE"))
717 g_string_append (string,
718 _(" VALUE The value to set\n"));
719
720 g_string_append (string, "\n");
721 }
722
723 if (requested)
724 g_print ("%s", string->str);
725 else
726 g_printerr ("%s\n", string->str);
727
728 g_string_free (string, TRUE);
729
730 return requested ? 0 : 1;
731 }
732
733
734 int
main(int argc,char ** argv)735 main (int argc, char **argv)
736 {
737 void (* function) (void);
738 gboolean need_settings, skip_third_arg_test;
739
740 #ifdef G_OS_WIN32
741 gchar *tmp;
742 #endif
743
744 setlocale (LC_ALL, GLIB_DEFAULT_LOCALE);
745 textdomain (GETTEXT_PACKAGE);
746
747 #ifdef G_OS_WIN32
748 tmp = _glib_get_locale_dir ();
749 bindtextdomain (GETTEXT_PACKAGE, tmp);
750 g_free (tmp);
751 #else
752 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
753 #endif
754
755 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
756 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
757 #endif
758
759 if (argc < 2)
760 return gsettings_help (FALSE, NULL);
761
762 global_schema_source = g_settings_schema_source_get_default ();
763
764 if (argc > 3 && g_str_equal (argv[1], "--schemadir"))
765 {
766 GSettingsSchemaSource *parent = global_schema_source;
767 GError *error = NULL;
768
769 global_schema_source = g_settings_schema_source_new_from_directory (argv[2], parent, FALSE, &error);
770
771 if (global_schema_source == NULL)
772 {
773 g_printerr (_("Could not load schemas from %s: %s\n"), argv[2], error->message);
774 g_clear_error (&error);
775
776 return 1;
777 }
778
779 /* shift remaining arguments (not correct wrt argv[0], but doesn't matter) */
780 argv = argv + 2;
781 argc -= 2;
782 }
783 else if (global_schema_source == NULL)
784 {
785 g_printerr (_("No schemas installed\n"));
786 return 1;
787 }
788 else
789 g_settings_schema_source_ref (global_schema_source);
790
791 need_settings = TRUE;
792 skip_third_arg_test = FALSE;
793
794 if (strcmp (argv[1], "help") == 0)
795 return gsettings_help (TRUE, argv[2]);
796
797 else if (argc == 2 && strcmp (argv[1], "--version") == 0)
798 function = gsettings_print_version;
799
800 else if (argc == 2 && strcmp (argv[1], "list-schemas") == 0)
801 function = gsettings_list_schemas;
802
803 else if (argc == 3 && strcmp (argv[1], "list-schemas") == 0
804 && strcmp (argv[2], "--print-paths") == 0)
805 {
806 skip_third_arg_test = TRUE;
807 function = gsettings_list_schemas_with_paths;
808 }
809
810 else if (argc == 2 && strcmp (argv[1], "list-relocatable-schemas") == 0)
811 function = gsettings_list_relocatable_schemas;
812
813 else if (argc == 3 && strcmp (argv[1], "list-keys") == 0)
814 {
815 need_settings = FALSE;
816 function = gsettings_list_keys;
817 }
818
819 else if (argc == 3 && strcmp (argv[1], "list-children") == 0)
820 function = gsettings_list_children;
821
822 else if ((argc == 2 || argc == 3) && strcmp (argv[1], "list-recursively") == 0)
823 function = gsettings_list_recursively;
824
825 else if (argc == 4 && strcmp (argv[1], "describe") == 0)
826 {
827 need_settings = FALSE;
828 function = gsettings_description;
829 }
830
831 else if (argc == 4 && strcmp (argv[1], "range") == 0)
832 {
833 need_settings = FALSE;
834 function = gsettings_range;
835 }
836
837 else if (argc == 4 && strcmp (argv[1], "get") == 0)
838 function = gsettings_get;
839
840 else if (argc == 5 && strcmp (argv[1], "set") == 0)
841 function = gsettings_set;
842
843 else if (argc == 4 && strcmp (argv[1], "reset") == 0)
844 function = gsettings_reset;
845
846 else if (argc == 3 && strcmp (argv[1], "reset-recursively") == 0)
847 function = gsettings_reset_recursively;
848
849 else if (argc == 4 && strcmp (argv[1], "writable") == 0)
850 function = gsettings_writable;
851
852 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "monitor") == 0)
853 function = gsettings_monitor;
854
855 else
856 return gsettings_help (FALSE, argv[1]);
857
858 if (argc > 2 && !skip_third_arg_test)
859 {
860 gchar **parts;
861
862 if (argv[2][0] == '\0')
863 {
864 g_printerr (_("Empty schema name given\n"));
865 return 1;
866 }
867
868 parts = g_strsplit (argv[2], ":", 2);
869
870 global_schema = g_settings_schema_source_lookup (global_schema_source, parts[0], TRUE);
871
872 if (need_settings)
873 {
874 if (parts[1])
875 {
876 if (!check_relocatable_schema (global_schema, parts[0]) || !check_path (parts[1]))
877 return 1;
878
879 global_settings = g_settings_new_full (global_schema, NULL, parts[1]);
880 }
881 else
882 {
883 if (!check_schema (global_schema, parts[0]))
884 return 1;
885
886 global_settings = g_settings_new_full (global_schema, NULL, NULL);
887 }
888 }
889 else
890 {
891 /* If the user has given a path then we enforce that we have a
892 * relocatable schema, but if they didn't give a path then it
893 * doesn't matter what type of schema we have (since it's
894 * reasonable to ask for introspection information on a
895 * relocatable schema without having to give the path).
896 */
897 if (parts[1])
898 {
899 if (!check_relocatable_schema (global_schema, parts[0]) || !check_path (parts[1]))
900 return 1;
901 }
902 else
903 {
904 if (global_schema == NULL)
905 {
906 g_printerr (_("No such schema “%s”\n"), parts[0]);
907 return 1;
908 }
909 }
910 }
911
912 g_strfreev (parts);
913 }
914
915 if (argc > 3)
916 {
917 if (!g_settings_schema_has_key (global_schema, argv[3]))
918 {
919 g_printerr (_("No such key “%s”\n"), argv[3]);
920 return 1;
921 }
922
923 global_key = argv[3];
924 global_schema_key = g_settings_schema_get_key (global_schema, global_key);
925 }
926
927 if (argc > 4)
928 global_value = argv[4];
929
930 (* function) ();
931
932
933 g_clear_pointer (&global_schema_source, g_settings_schema_source_unref);
934 g_clear_pointer (&global_schema_key, g_settings_schema_key_unref);
935 g_clear_pointer (&global_schema, g_settings_schema_unref);
936 g_clear_object (&global_settings);
937
938 return 0;
939 }
940