Trivial: fix a typo
[platform/upstream/glib.git] / gio / gsettings-tool.c
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 of the licence, 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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include <gio/gio.h>
25 #include <gi18n.h>
26 #include <locale.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 static gboolean
31 contained (const gchar * const *items,
32            const gchar         *item)
33 {
34   while (*items)
35     if (strcmp (*items++, item) == 0)
36       return TRUE;
37
38   return FALSE;
39 }
40
41 static gboolean
42 is_schema (const gchar *schema)
43 {
44   return contained (g_settings_list_schemas (), schema);
45 }
46
47 static gboolean
48 is_relocatable_schema (const gchar *schema)
49 {
50   return contained (g_settings_list_relocatable_schemas (), schema);
51 }
52
53 static gboolean
54 check_relocatable_schema (const gchar *schema)
55 {
56   if (is_relocatable_schema (schema))
57     return TRUE;
58
59   if (is_schema (schema))
60     g_printerr (_("Schema '%s' is not relocatable "
61                   "(path must not be specified)\n"),
62                 schema);
63
64   else
65     g_printerr (_("No such schema '%s'\n"), schema);
66
67   return FALSE;
68 }
69
70 static gboolean
71 check_schema (const gchar *schema)
72 {
73   if (is_schema (schema))
74     return TRUE;
75
76   if (is_relocatable_schema (schema))
77     g_printerr (_("Schema '%s' is relocatable "
78                   "(path must be specified)\n"),
79                 schema);
80
81   else
82     g_printerr (_("No such schema '%s'\n"), schema);
83
84   return FALSE;
85 }
86
87 static gboolean
88 check_path (const gchar *path)
89 {
90   if (path[0] == '\0')
91     {
92       g_printerr (_("Empty path given.\n"));
93       return FALSE;
94     }
95
96   if (path[0] != '/')
97     {
98       g_printerr (_("Path must begin with a slash (/)\n"));
99       return FALSE;
100     }
101
102   if (!g_str_has_suffix (path, "/"))
103     {
104       g_printerr (_("Path must end with a slash (/)\n"));
105       return FALSE;
106     }
107
108   if (strstr (path, "//"))
109     {
110       g_printerr (_("Path must not contain two adjacent slashes (//)\n"));
111       return FALSE;
112     }
113
114   return TRUE;
115 }
116
117 static gboolean
118 check_key (GSettings   *settings,
119            const gchar *key)
120 {
121   gboolean good;
122   gchar **keys;
123
124   keys = g_settings_list_keys (settings);
125   good = contained ((const gchar **) keys, key);
126   g_strfreev (keys);
127
128   if (good)
129     return TRUE;
130
131   g_printerr (_("No such key '%s'\n"), key);
132
133   return FALSE;
134 }
135
136 static void
137 output_list (const gchar * const *list)
138 {
139   gint i;
140
141   for (i = 0; list[i]; i++)
142     g_print ("%s\n", list[i]);
143 }
144
145 static void
146 gsettings_list_schemas (GSettings   *settings,
147                         const gchar *key,
148                         const gchar *value)
149 {
150   output_list (g_settings_list_schemas ());
151 }
152
153 static void
154 gsettings_list_relocatable_schemas (GSettings   *settings,
155                                     const gchar *key,
156                                     const gchar *value)
157 {
158   output_list (g_settings_list_relocatable_schemas ());
159 }
160
161 static void
162 gsettings_list_keys (GSettings   *settings,
163                      const gchar *key,
164                      const gchar *value)
165 {
166   gchar **keys;
167
168   keys = g_settings_list_keys (settings);
169   output_list ((const gchar **) keys);
170   g_strfreev (keys);
171 }
172
173 static void
174 gsettings_list_children (GSettings   *settings,
175                          const gchar *key,
176                          const gchar *value)
177 {
178   gchar **children;
179   gint max = 0;
180   gint i;
181
182   children = g_settings_list_children (settings);
183   for (i = 0; children[i]; i++)
184     if (strlen (children[i]) > max)
185       max = strlen (children[i]);
186
187   for (i = 0; children[i]; i++)
188     {
189       GSettings *child;
190       gchar *schema;
191       gchar *path;
192
193       child = g_settings_get_child (settings, children[i]);
194       g_object_get (child,
195                     "schema", &schema,
196                     "path", &path,
197                     NULL);
198
199       if (is_schema (schema))
200         g_print ("%-*s   %s\n", max, children[i], schema);
201       else
202         g_print ("%-*s   %s:%s\n", max, children[i], schema, path);
203
204       g_object_unref (child);
205       g_free (schema);
206       g_free (path);
207     }
208
209   g_strfreev (children);
210 }
211
212 static void
213 enumerate (GSettings *settings)
214 {
215   gchar **keys;
216   gchar *schema;
217   gint i;
218
219   g_object_get (settings, "schema", &schema, NULL);
220
221   keys = g_settings_list_keys (settings);
222   for (i = 0; keys[i]; i++)
223     {
224       GVariant *value;
225       gchar *printed;
226
227       value = g_settings_get_value (settings, keys[i]);
228       printed = g_variant_print (value, TRUE);
229       g_print ("%s %s %s\n", schema, keys[i], printed);
230       g_variant_unref (value);
231       g_free (printed);
232     }
233
234   g_free (schema);
235   g_strfreev (keys);
236 }
237
238 static void
239 gsettings_list_recursively (GSettings   *settings,
240                             const gchar *key,
241                             const gchar *value)
242 {
243   if (settings)
244     {
245       gchar **children;
246       gint i;
247
248       enumerate (settings);
249       children = g_settings_list_children (settings);
250       for (i = 0; children[i]; i++)
251         {
252           GSettings *child;
253           gchar *schema;
254
255           child = g_settings_get_child (settings, children[i]);
256           g_object_get (child, "schema", &schema, NULL);
257
258           if (is_schema (schema))
259             enumerate (child);
260
261           g_object_unref (child);
262           g_free (schema);
263         }
264
265       g_strfreev (children);
266     }
267   else
268     {
269       const gchar * const *schemas;
270       gint i;
271
272       schemas = g_settings_list_schemas ();
273
274       for (i = 0; schemas[i]; i++)
275         {
276           settings = g_settings_new (schemas[i]);
277           enumerate (settings);
278           g_object_unref (settings);
279         }
280     }
281 }
282
283 static void
284 gsettings_range (GSettings   *settings,
285                  const gchar *key,
286                  const gchar *value)
287 {
288   GVariant *range, *detail;
289   const gchar *type;
290
291   range = g_settings_get_range (settings, key);
292   g_variant_get (range, "(&sv)", &type, &detail);
293
294   if (strcmp (type, "type") == 0)
295     g_print ("type %s\n", g_variant_get_type_string (detail) + 1);
296
297   else if (strcmp (type, "range") == 0)
298     {
299       GVariant *min, *max;
300       gchar *smin, *smax;
301
302       g_variant_get (detail, "(**)", &min, &max);
303       smin = g_variant_print (min, FALSE);
304       smax = g_variant_print (max, FALSE);
305
306       g_print ("range %s %s %s\n",
307                g_variant_get_type_string (min), smin, smax);
308       g_variant_unref (min);
309       g_variant_unref (max);
310       g_free (smin);
311       g_free (smax);
312     }
313
314   else if (strcmp (type, "enum") == 0 || strcmp (type, "flags") == 0)
315     {
316       GVariantIter iter;
317       GVariant *item;
318
319       g_print ("%s\n", type);
320
321       g_variant_iter_init (&iter, detail);
322       while (g_variant_iter_loop (&iter, "*", &item))
323         {
324           gchar *printed;
325
326           printed = g_variant_print (item, FALSE);
327           g_print ("%s\n", printed);
328           g_free (printed);
329         }
330     }
331
332   g_variant_unref (detail);
333   g_variant_unref (range);
334 }
335
336 static void
337 gsettings_get (GSettings   *settings,
338                const gchar *key,
339                const gchar *value_)
340 {
341   GVariant *value;
342   gchar *printed;
343
344   value = g_settings_get_value (settings, key);
345   printed = g_variant_print (value, TRUE);
346   g_print ("%s\n", printed);
347   g_variant_unref (value);
348   g_free (printed);
349 }
350
351 static void
352 gsettings_reset (GSettings   *settings,
353                  const gchar *key,
354                  const gchar *value)
355 {
356   g_settings_reset (settings, key);
357   g_settings_sync ();
358 }
359
360 static void
361 reset_all_keys (GSettings   *settings)
362 {
363   gchar **keys;
364   gint i;
365
366   keys = g_settings_list_keys (settings);
367   for (i = 0; keys[i]; i++)
368     {
369       g_settings_reset (settings, keys[i]);
370     }
371
372   g_strfreev (keys);
373 }
374
375 static void
376 gsettings_reset_recursively (GSettings   *settings,
377                              const gchar *key,
378                              const gchar *value)
379 {
380   gchar **children;
381   gint i;
382
383   g_settings_delay (settings);
384
385   reset_all_keys (settings);
386   children = g_settings_list_children (settings);
387   for (i = 0; children[i]; i++)
388     {
389       GSettings *child;
390       gchar *schema;
391
392       child = g_settings_get_child (settings, children[i]);
393       g_object_get (child, "schema", &schema, NULL);
394
395       if (is_schema (schema))
396         reset_all_keys (child);
397
398       g_object_unref (child);
399       g_free (schema);
400     }
401
402   g_strfreev (children);
403
404   g_settings_apply (settings);
405   g_settings_sync ();
406 }
407
408 static void
409 gsettings_writable (GSettings   *settings,
410                     const gchar *key,
411                     const gchar *value)
412 {
413   g_print ("%s\n",
414            g_settings_is_writable (settings, key) ?
415            "true" : "false");
416 }
417
418 static void
419 value_changed (GSettings   *settings,
420                const gchar *key,
421                gpointer     user_data)
422 {
423   GVariant *value;
424   gchar *printed;
425
426   value = g_settings_get_value (settings, key);
427   printed = g_variant_print (value, TRUE);
428   g_print ("%s: %s\n", key, printed);
429   g_variant_unref (value);
430   g_free (printed);
431 }
432
433 static void
434 gsettings_monitor (GSettings   *settings,
435                    const gchar *key,
436                    const gchar *value)
437 {
438   if (key)
439     {
440       gchar *name;
441
442       name = g_strdup_printf ("changed::%s", key);
443       g_signal_connect (settings, name, G_CALLBACK (value_changed), NULL);
444     }
445   else
446     g_signal_connect (settings, "changed", G_CALLBACK (value_changed), NULL);
447
448   g_main_loop_run (g_main_loop_new (NULL, FALSE));
449 }
450
451 static void
452 gsettings_set (GSettings   *settings,
453                const gchar *key,
454                const gchar *value)
455 {
456   const GVariantType *type;
457   GError *error = NULL;
458   GVariant *existing;
459   GVariant *new;
460   GVariant *stored;
461   gchar *freeme = NULL;
462
463   existing = g_settings_get_value (settings, key);
464   type = g_variant_get_type (existing);
465
466   new = g_variant_parse (type, value, NULL, NULL, &error);
467
468   /* If that didn't work and the type is string then we should assume
469    * that the user is just trying to set a string directly and forgot
470    * the quotes (or had them consumed by the shell).
471    *
472    * If the user started with a quote then we assume that some deeper
473    * problem is at play and we want the failure in that case.
474    *
475    * Consider:
476    *
477    *   gsettings set x.y.z key "'i don't expect this to work'"
478    *
479    * Note that we should not just add quotes and try parsing again, but
480    * rather assume that the user is providing us with a bare string.
481    * Assume we added single quotes, then consider this case:
482    *
483    *   gsettings set x.y.z key "i'd expect this to work"
484    *
485    * A similar example could be given for double quotes.
486    *
487    * Avoid that whole mess by just using g_variant_new_string().
488    */
489   if (new == NULL &&
490       g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
491       value[0] != '\'' && value[0] != '"')
492     {
493       g_clear_error (&error);
494       new = g_variant_new_string (value);
495     }
496
497   if (new == NULL)
498     {
499       g_printerr ("%s\n", error->message);
500       exit (1);
501     }
502
503   if (!g_settings_range_check (settings, key, new))
504     {
505       g_printerr (_("The provided value is outside of the valid range\n"));
506       exit (1);
507     }
508
509   g_settings_set_value (settings, key, new);
510   g_settings_sync ();
511
512   stored = g_settings_get_value (settings, key);
513   if (g_variant_equal (stored, existing))
514     {
515       g_printerr (_("Failed to set value\n"));
516       exit (1);
517     }
518
519   g_variant_unref (stored);
520   g_variant_unref (existing);
521   g_variant_unref (new);
522
523   g_free (freeme);
524 }
525
526 static int
527 gsettings_help (gboolean     requested,
528                 const gchar *command)
529 {
530   const gchar *description;
531   const gchar *synopsis;
532   GString *string;
533
534   string = g_string_new (NULL);
535
536   if (command == NULL)
537     ;
538
539   else if (strcmp (command, "help") == 0)
540     {
541       description = _("Print help");
542       synopsis = "[COMMAND]";
543     }
544
545   else if (strcmp (command, "list-schemas") == 0)
546     {
547       description = _("List the installed (non-relocatable) schemas");
548       synopsis = "";
549     }
550
551   else if (strcmp (command, "list-relocatable-schemas") == 0)
552     {
553       description = _("List the installed relocatable schemas");
554       synopsis = "";
555     }
556
557   else if (strcmp (command, "list-keys") == 0)
558     {
559       description = _("List the keys in SCHEMA");
560       synopsis = N_("SCHEMA[:PATH]");
561     }
562
563   else if (strcmp (command, "list-children") == 0)
564     {
565       description = _("List the children of SCHEMA");
566       synopsis = N_("SCHEMA[:PATH]");
567     }
568
569   else if (strcmp (command, "list-recursively") == 0)
570     {
571       description = _("List keys and values, recursively\n"
572                       "If no SCHEMA is given, list all keys\n");
573       synopsis = N_("[SCHEMA[:PATH]]");
574     }
575
576   else if (strcmp (command, "get") == 0)
577     {
578       description = _("Get the value of KEY");
579       synopsis = N_("SCHEMA[:PATH] KEY");
580     }
581
582   else if (strcmp (command, "range") == 0)
583     {
584       description = _("Query the range of valid values for KEY");
585       synopsis = N_("SCHEMA[:PATH] KEY");
586     }
587
588   else if (strcmp (command, "set") == 0)
589     {
590       description = _("Set the value of KEY to VALUE");
591       synopsis = N_("SCHEMA[:PATH] KEY VALUE");
592     }
593
594   else if (strcmp (command, "reset") == 0)
595     {
596       description = _("Reset KEY to its default value");
597       synopsis = N_("SCHEMA[:PATH] KEY");
598     }
599
600   else if (strcmp (command, "reset-recursively") == 0)
601     {
602       description = _("Reset all keys in SCHEMA to their defaults");
603       synopsis = N_("SCHEMA[:PATH]");
604     }
605
606   else if (strcmp (command, "writable") == 0)
607     {
608       description = _("Check if KEY is writable");
609       synopsis = N_("SCHEMA[:PATH] KEY");
610     }
611
612   else if (strcmp (command, "monitor") == 0)
613     {
614       description = _("Monitor KEY for changes.\n"
615                     "If no KEY is specified, monitor all keys in SCHEMA.\n"
616                     "Use ^C to stop monitoring.\n");
617       synopsis = N_("SCHEMA[:PATH] [KEY]");
618     }
619   else
620     {
621       g_string_printf (string, _("Unknown command %s\n\n"), command);
622       requested = FALSE;
623       command = NULL;
624     }
625
626   if (command == NULL)
627     {
628       g_string_append (string,
629       _("Usage:\n"
630         "  gsettings COMMAND [ARGS...]\n"
631         "\n"
632         "Commands:\n"
633         "  help                      Show this information\n"
634         "  list-schemas              List installed schemas\n"
635         "  list-relocatable-schemas  List relocatable schemas\n"
636         "  list-keys                 List keys in a schema\n"
637         "  list-children             List children of a schema\n"
638         "  list-recursively          List keys and values, recursively\n"
639         "  range                     Queries the range of a key\n"
640         "  get                       Get the value of a key\n"
641         "  set                       Set the value of a key\n"
642         "  reset                     Reset the value of a key\n"
643         "  reset-recursively         Reset all values in a given schema\n"
644         "  writable                  Check if a key is writable\n"
645         "  monitor                   Watch for changes\n"
646         "\n"
647         "Use 'gsettings help COMMAND' to get detailed help.\n\n"));
648     }
649   else
650     {
651       g_string_append_printf (string, _("Usage:\n  gsettings %s %s\n\n%s\n\n"),
652                               command, synopsis[0] ? _(synopsis) : "", description);
653
654       if (synopsis[0])
655         {
656           g_string_append (string, _("Arguments:\n"));
657
658           if (strstr (synopsis, "[COMMAND]"))
659             g_string_append (string,
660                            _("  COMMAND   The (optional) command to explain\n"));
661
662           else if (strstr (synopsis, "SCHEMA"))
663             g_string_append (string,
664                            _("  SCHEMA    The name of the schema\n"
665                              "  PATH      The path, for relocatable schemas\n"));
666
667           if (strstr (synopsis, "[KEY]"))
668             g_string_append (string,
669                            _("  KEY       The (optional) key within the schema\n"));
670
671           else if (strstr (synopsis, "KEY"))
672             g_string_append (string,
673                            _("  KEY       The key within the schema\n"));
674
675           if (strstr (synopsis, "VALUE"))
676             g_string_append (string,
677                            _("  VALUE     The value to set\n"));
678
679           g_string_append (string, "\n");
680         }
681     }
682
683   if (requested)
684     g_print ("%s", string->str);
685   else
686     g_printerr ("%s\n", string->str);
687
688   g_string_free (string, TRUE);
689
690   return requested ? 0 : 1;
691 }
692
693
694 int
695 main (int argc, char **argv)
696 {
697   void (* function) (GSettings *, const gchar *, const gchar *);
698   GSettings *settings;
699   const gchar *key;
700
701   setlocale (LC_ALL, "");
702   textdomain (GETTEXT_PACKAGE);
703
704 #ifdef G_OS_WIN32
705   gchar *tmp = _glib_get_locale_dir ();
706   bindtextdomain (GETTEXT_PACKAGE, tmp);
707   g_free (tmp);
708 #else
709   bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
710 #endif
711
712 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
713   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
714 #endif
715
716   if (argc < 2)
717     return gsettings_help (FALSE, NULL);
718
719   else if (strcmp (argv[1], "help") == 0)
720     return gsettings_help (TRUE, argv[2]);
721
722   else if (argc == 2 && strcmp (argv[1], "list-schemas") == 0)
723     function = gsettings_list_schemas;
724
725   else if (argc == 2 && strcmp (argv[1], "list-relocatable-schemas") == 0)
726     function = gsettings_list_relocatable_schemas;
727
728   else if (argc == 3 && strcmp (argv[1], "list-keys") == 0)
729     function = gsettings_list_keys;
730
731   else if (argc == 3 && strcmp (argv[1], "list-children") == 0)
732     function = gsettings_list_children;
733
734   else if ((argc == 2 || argc == 3) && strcmp (argv[1], "list-recursively") == 0)
735     function = gsettings_list_recursively;
736
737   else if (argc == 4 && strcmp (argv[1], "range") == 0)
738     function = gsettings_range;
739
740   else if (argc == 4 && strcmp (argv[1], "get") == 0)
741     function = gsettings_get;
742
743   else if (argc == 5 && strcmp (argv[1], "set") == 0)
744     function = gsettings_set;
745
746   else if (argc == 4 && strcmp (argv[1], "reset") == 0)
747     function = gsettings_reset;
748
749   else if (argc == 3 && strcmp (argv[1], "reset-recursively") == 0)
750     function = gsettings_reset_recursively;
751
752   else if (argc == 4 && strcmp (argv[1], "writable") == 0)
753     function = gsettings_writable;
754
755   else if ((argc == 3 || argc == 4) && strcmp (argv[1], "monitor") == 0)
756     function = gsettings_monitor;
757
758   else
759     return gsettings_help (FALSE, argv[1]);
760
761   g_type_init ();
762
763   if (argc > 2)
764     {
765       gchar **parts;
766
767       if (argv[2][0] == '\0')
768         {
769           g_printerr (_("Empty schema name given\n"));
770           return 1;
771         }
772
773       parts = g_strsplit (argv[2], ":", 2);
774
775       if (parts[1])
776         {
777           if (!check_relocatable_schema (parts[0]) || !check_path (parts[1]))
778             return 1;
779
780           settings = g_settings_new_with_path (parts[0], parts[1]);
781         }
782       else
783         {
784           if (!check_schema (parts[0]))
785             return 1;
786
787           settings = g_settings_new (parts[0]);
788         }
789
790       g_strfreev (parts);
791     }
792   else
793     settings = NULL;
794
795   if (argc > 3)
796     {
797       if (!check_key (settings, argv[3]))
798         return 1;
799
800       key = argv[3];
801     }
802   else
803     key = NULL;
804
805   (* function) (settings, key, argc > 4 ? argv[4] : NULL);
806
807   if (settings != NULL)
808     g_object_unref (settings);
809
810   return 0;
811 }