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