1 /* GConf
2  * Copyright (C) 1999, 2000 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #include <config.h>
21 #include "gconf.h"
22 #include "gconf-internals.h"
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <libxml/tree.h>
27 #include <libxml/parser.h>
28 #include <libxml/globals.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <locale.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <glib.h>
35 
36 typedef enum {
37   LOAD_SCHEMA_FILE,
38   LOAD_ENTRY_FILE
39 } LoadType;
40 
41 static int set_mode = FALSE;
42 static int get_mode = FALSE;
43 static int unset_mode = FALSE;
44 static int toggle_mode = FALSE;
45 static int all_entries_mode = FALSE;
46 static int all_subdirs_mode = FALSE;
47 static char* dir_exists = NULL;
48 static int recursive_list = FALSE;
49 static int search_key = FALSE;
50 static int search_key_regex = FALSE;
51 static int dump_values = FALSE;
52 static int set_schema_mode = FALSE;
53 static char* value_type = NULL;
54 static int get_type_mode = FALSE;
55 static int get_list_size_mode = FALSE;
56 static int get_list_element_mode = FALSE;
57 static char* value_list_type = NULL;
58 static char* value_car_type = NULL;
59 static char* value_cdr_type = NULL;
60 static int shutdown_gconfd = FALSE;
61 static int ping_gconfd = FALSE;
62 static int spawn_gconfd = FALSE;
63 static char* short_desc = NULL;
64 static char* long_desc = NULL;
65 static char* owner = NULL;
66 static char* schema_file = NULL;
67 static char* entry_file = NULL;
68 static char* unload_entry_file = NULL;
69 static const char* config_source = NULL;
70 static int use_local_source = FALSE;
71 static int makefile_install_mode = FALSE;
72 static int makefile_uninstall_mode = FALSE;
73 static int break_key_mode = FALSE;
74 static int break_dir_mode = FALSE;
75 static int short_docs_mode = FALSE;
76 static int long_docs_mode = FALSE;
77 static int schema_name_mode = FALSE;
78 static int associate_schema_mode = FALSE;
79 static int dissociate_schema_mode = FALSE;
80 static int ignore_schema_defaults = FALSE;
81 static int default_source_mode = FALSE;
82 static int recursive_unset_mode = FALSE;
83 static int do_version = FALSE;
84 static const gchar **args = NULL;
85 
86 static const GOptionEntry client_entries[] = {
87   {
88     "set",
89     's',
90     0,
91     G_OPTION_ARG_NONE,
92     &set_mode,
93     N_("Set a key to a value and sync. Use with --type."),
94     NULL
95   },
96   {
97     "get",
98     'g',
99     0,
100     G_OPTION_ARG_NONE,
101     &get_mode,
102     N_("Print the value of a key to standard output."),
103     NULL
104   },
105   {
106 
107     "unset",
108     'u',
109     0,
110     G_OPTION_ARG_NONE,
111     &unset_mode,
112     N_("Unset the keys on the command line"),
113     NULL
114   },
115   {
116     "recursive-unset",
117     '\0',
118     0,
119     G_OPTION_ARG_NONE,
120     &recursive_unset_mode,
121     N_("Recursively unset all keys at or below the key/directory names on the command line"),
122     NULL
123   },
124   {
125     "toggle",
126     '\0',
127     0,
128     G_OPTION_ARG_NONE,
129     &toggle_mode,
130     N_("Toggles a boolean key."),
131     NULL
132   },
133   {
134     "all-entries",
135     'a',
136     0,
137     G_OPTION_ARG_NONE,
138     &all_entries_mode,
139     N_("Print all key/value pairs in a directory."),
140     NULL
141   },
142   {
143     "all-dirs",
144     '\0',
145     0,
146     G_OPTION_ARG_NONE,
147     &all_subdirs_mode,
148     N_("Print all subdirectories in a directory."),
149     NULL
150   },
151   {
152     "recursive-list",
153     'R',
154     0,
155     G_OPTION_ARG_NONE,
156     &recursive_list,
157     N_("Print all subdirectories and entries under a directory, recursively."),
158     NULL
159   },
160   {
161     "search-key",
162     'S',
163     0,
164     G_OPTION_ARG_NONE,
165     &search_key,
166     N_("Search for a key, recursively."),
167     NULL
168   },
169   {
170     "search-key-regex",
171     0,
172     0,
173     G_OPTION_ARG_NONE,
174     &search_key_regex,
175     N_("Search for a key, recursively."),
176     NULL
177   },
178   {
179     "short-docs",
180     '\0',
181     0,
182     G_OPTION_ARG_NONE,
183     &short_docs_mode,
184     N_("Get the short doc string for a key"),
185     NULL
186   },
187   {
188     "long-docs",
189     '\0',
190     0,
191     G_OPTION_ARG_NONE,
192     &long_docs_mode,
193     N_("Get the long doc string for a key"),
194     NULL
195   },
196   {
197     "dir-exists",
198     '\0',
199     0,
200     G_OPTION_ARG_STRING,
201     &dir_exists,
202     N_("Return 0 if the directory exists, 2 if it does not."),
203     NULL
204   },
205   {
206     "ignore-schema-defaults",
207     '\0',
208     0,
209     G_OPTION_ARG_NONE,
210     &ignore_schema_defaults,
211     N_("Ignore schema defaults when reading values."),
212     NULL
213   },
214   {
215     NULL
216   }
217 };
218 
219 static const GOptionEntry load_entries[] = {
220   {
221     "dump",
222     '\0',
223     0,
224     G_OPTION_ARG_NONE,
225     &dump_values,
226     N_("Dump to standard output an XML description of all entries under a directory, recursively."),
227     NULL
228   },
229   {
230     "load",
231     '\0',
232     0,
233     G_OPTION_ARG_FILENAME,
234     &entry_file,
235     N_("Load from the specified file an XML description of values and set them relative to a directory."),
236     NULL
237   },
238   {
239     "unload",
240     '\0',
241     0,
242     G_OPTION_ARG_FILENAME,
243     &unload_entry_file,
244     N_("Unload a set of values described in an XML file."),
245     NULL
246   },
247   {
248     NULL
249   }
250 };
251 
252 static const GOptionEntry server_entries[] = {
253   {
254     "get-default-source",
255     '\0',
256     0,
257     G_OPTION_ARG_NONE,
258     &default_source_mode,
259     N_("Get the name of the default source"),
260     NULL
261   },
262   {
263     "shutdown",
264     '\0',
265     0,
266     G_OPTION_ARG_NONE,
267     &shutdown_gconfd,
268     N_("Shut down gconfd. DON'T USE THIS OPTION WITHOUT GOOD REASON."),
269     NULL
270   },
271   {
272     "ping",
273     'p',
274     0,
275     G_OPTION_ARG_NONE,
276     &ping_gconfd,
277     N_("Return 0 if gconfd is running, 2 if not."),
278     NULL
279   },
280   {
281     "spawn",
282     '\0',
283     0,
284     G_OPTION_ARG_NONE,
285     &spawn_gconfd,
286     N_("Launch the configuration server (gconfd). (Normally happens automatically when needed.)"),
287     NULL
288   },
289   {
290     NULL
291   }
292 };
293 
294 static const GOptionEntry type_entries[] = {
295   {
296     "type",
297     't',
298     0,
299     G_OPTION_ARG_STRING,
300     &value_type,
301     N_("Specify the type of the value being set, or the type of the value a schema describes. Unique abbreviations OK."),
302     N_("int|bool|float|string|list|pair")
303   },
304   {
305     "get-type",
306     'T',
307     0,
308     G_OPTION_ARG_NONE,
309     &get_type_mode,
310     N_("Print the data type of a key to standard output."),
311     NULL
312   },
313   {
314     "get-list-size",
315     '\0',
316     0,
317     G_OPTION_ARG_NONE,
318     &get_list_size_mode,
319     N_("Get the number of elements in a list key."),
320     NULL
321   },
322   {
323     "get-list-element",
324     '\0',
325     0,
326     G_OPTION_ARG_NONE,
327     &get_list_element_mode,
328     N_("Get a specific element from a list key, numerically indexed."),
329     NULL
330   },
331   {
332     "list-type",
333     '\0',
334     0,
335     G_OPTION_ARG_STRING,
336     &value_list_type,
337     N_("Specify the type of the list value being set, or the type of the value a schema describes. Unique abbreviations OK."),
338     N_("int|bool|float|string")
339   },
340   {
341     "car-type",
342     '\0',
343     0,
344     G_OPTION_ARG_STRING,
345     &value_car_type,
346     N_("Specify the type of the car pair value being set, or the type of the value a schema describes. Unique abbreviations OK."),
347     N_("int|bool|float|string")
348   },
349   {
350     "cdr-type",
351     '\0',
352     0,
353     G_OPTION_ARG_STRING,
354     &value_cdr_type,
355     N_("Specify the type of the cdr pair value being set, or the type of the value a schema describes. Unique abbreviations OK."),
356     N_("int|bool|float|string")
357   },
358   {
359     NULL
360   }
361 };
362 
363 static const GOptionEntry install_entries[] = {
364   {
365     "install-schema-file",
366     '\0',
367     0,
368     G_OPTION_ARG_FILENAME,
369     &schema_file,
370     N_("Specify a schema file to be installed"),
371     N_("FILENAME")
372   },
373   {
374     "config-source",
375     '\0',
376     0,
377     G_OPTION_ARG_STRING,
378     &config_source,
379     N_("Specify a configuration source to use rather than the default path"),
380     N_("SOURCE")
381   },
382   {
383     "direct",
384     '\0',
385     0,
386     G_OPTION_ARG_NONE,
387     &use_local_source,
388     N_("Bypass server, and access the configuration database directly. Requires that gconfd is not running."),
389     NULL
390   },
391   {
392     "makefile-install-rule",
393     '\0',
394     0,
395     G_OPTION_ARG_NONE,
396     &makefile_install_mode,
397     N_("Properly installs schema files on the command line into the database. Specify a custom configuration source in the GCONF_CONFIG_SOURCE environment variable, or set set the variable to an empty string to use the default configuration source."),
398     NULL
399   },
400   {
401     "makefile-uninstall-rule",
402     '\0',
403     0,
404     G_OPTION_ARG_NONE,
405     &makefile_uninstall_mode,
406     N_("Properly uninstalls schema files on the command line from the database. GCONF_CONFIG_SOURCE environment variable should be set to a non-default configuration source or set to the empty string to use the default."),
407     NULL
408   },
409   {
410     NULL
411   }
412 };
413 
414 static const GOptionEntry test_entries[] = {
415   {
416     "break-key",
417     '\0',
418     0,
419     G_OPTION_ARG_NONE,
420     &break_key_mode,
421     N_("Torture-test an application by setting and unsetting a bunch of values of different types for keys on the command line."),
422     NULL
423   },
424   {
425     "break-directory",
426     '\0',
427     0,
428     G_OPTION_ARG_NONE,
429     &break_dir_mode,
430     N_("Torture-test an application by setting and unsetting a bunch of keys inside the directories on the command line."),
431     NULL
432   },
433   {
434     NULL
435   }
436 };
437 
438 static const GOptionEntry schema_entries[] = {
439   {
440     "set-schema",
441     '\0',
442     0,
443     G_OPTION_ARG_NONE,
444     &set_schema_mode,
445     N_("Set a schema and sync. Use with --short-desc, --long-desc, --owner, and --type."),
446     NULL
447   },
448   {
449     "short-desc",
450     '\0',
451     0,
452     G_OPTION_ARG_STRING,
453     &short_desc,
454     N_("Specify a short half-line description to go in a schema."),
455     N_("DESCRIPTION")
456   },
457   {
458     "long-desc",
459     '\0',
460     0,
461     G_OPTION_ARG_STRING,
462     &long_desc,
463     N_("Specify a several-line description to go in a schema."),
464     N_("DESCRIPTION")
465   },
466   {
467     "owner",
468     '\0',
469     0,
470     G_OPTION_ARG_STRING,
471     &owner,
472     N_("Specify the owner of a schema"),
473     N_("OWNER")
474   },
475   {
476     "get-schema-name",
477     '\0',
478     0,
479     G_OPTION_ARG_NONE,
480     &schema_name_mode,
481     N_("Get the name of the schema applied to this key"),
482     NULL
483   },
484   {
485     "apply-schema",
486     '\0',
487     0,
488     G_OPTION_ARG_NONE,
489     &associate_schema_mode,
490     N_("Specify the schema name followed by the key to apply the schema name to"),
491     NULL
492   },
493   {
494     "unapply-schema",
495     '\0',
496     0,
497     G_OPTION_ARG_NONE,
498     &dissociate_schema_mode,
499     N_("Remove any schema name applied to the given keys"),
500     NULL
501   },
502   {
503     NULL
504   }
505 };
506 
507 static const GOptionEntry main_entries[] = {
508   {
509     "version",
510     'v',
511     0,
512     G_OPTION_ARG_NONE,
513     &do_version,
514     N_("Print version"),
515     NULL
516   },
517   {
518     G_OPTION_REMAINING,
519     '\0',
520     0,
521     G_OPTION_ARG_STRING_ARRAY,
522     &args,
523     N_("[FILE...]|[KEY...]|[DIR...]"),
524     NULL
525   },
526   {
527     NULL
528   }
529 };
530 
531 static int do_break_key(GConfEngine* conf, const gchar** args);
532 static int do_break_directory(GConfEngine* conf, const gchar** args);
533 static int do_makefile_install(GConfEngine* conf, const gchar** args, gboolean unload);
534 static int do_recursive_list(GConfEngine* conf, const gchar** args);
535 static int do_search_key(GConfEngine* conf, const gchar** args);
536 static int do_search_key_regex(GConfEngine* conf, const gchar** args);
537 static int do_dump_values(GConfEngine* conf, const gchar** args);
538 static int do_all_pairs(GConfEngine* conf, const gchar** args);
539 static void list_pairs_in_dir(GConfEngine* conf, const gchar* dir, guint depth);
540 static int get_schema_from_xml(xmlNodePtr node, gchar **schema_key, GHashTable** schemas_hash, GSList **applyto_list);
541 static int get_first_value_from_xml(xmlNodePtr node, GConfValue** ret_value);
542 static void print_value_in_xml(GConfValue* value, int indent);
543 static void dump_entries_in_dir(GConfEngine* conf, const gchar* dir, const gchar *base_dir);
544 static gboolean do_dir_exists(GConfEngine* conf, const gchar* dir);
545 static void do_spawn_daemon(GConfEngine* conf);
546 static int do_get(GConfEngine* conf, const gchar** args);
547 static int do_set(GConfEngine* conf, const gchar** args);
548 static int do_toggle(GConfEngine* conf, const gchar** args);
549 static int do_get_type(GConfEngine* conf, const gchar** args);
550 static int do_get_list_size(GConfEngine* conf, const gchar** args);
551 static int do_get_list_element(GConfEngine* conf, const gchar** args);
552 static int do_set_schema(GConfEngine* conf, const gchar** args);
553 static int do_all_entries(GConfEngine* conf, const gchar** args);
554 static int do_unset(GConfEngine* conf, const gchar** args);
555 static int do_recursive_unset (GConfEngine* conf, const gchar** args);
556 static int do_all_subdirs(GConfEngine* conf, const gchar** args);
557 static int do_load_file(GConfEngine* conf, LoadType load_type, gboolean unload, const gchar* file, const gchar** base_dirs);
558 static int do_sync(GConfEngine* conf);
559 static int do_short_docs (GConfEngine *conf, const gchar **args);
560 static int do_long_docs (GConfEngine *conf, const gchar **args);
561 static int do_get_schema_name (GConfEngine *conf, const gchar **args);
562 static int do_associate_schema (GConfEngine *conf, const gchar **args);
563 static int do_dissociate_schema (GConfEngine *conf, const gchar **args);
564 static int do_get_default_source (const gchar **args);
565 
566 int
main(int argc,char ** argv)567 main (int argc, char** argv)
568 {
569   GConfEngine* conf;
570   GOptionContext *context;
571   GOptionGroup *group;
572   GError* err = NULL;
573 
574   LIBXML_TEST_VERSION;
575   xmlKeepBlanksDefault(1);
576 
577   setlocale (LC_ALL, "");
578   bindtextdomain (GETTEXT_PACKAGE,GCONF_LOCALE_DIR);
579   textdomain (GETTEXT_PACKAGE);
580 
581   g_thread_init (NULL);
582 
583   _gconf_init_i18n ();
584 
585   context = g_option_context_new (N_("- Tool to manipulate a GConf configuration"));
586 #if GLIB_CHECK_VERSION (2, 12, 0)
587   g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
588 #endif
589 
590   group = g_option_group_new ("client", N_("Client options:"), N_("Show client options"), NULL, NULL);
591   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
592   g_option_group_add_entries (group, client_entries);
593   g_option_context_add_group (context, group);
594 
595   group = g_option_group_new ("key-type", N_("Key type options:"), N_("Show key type options"), NULL, NULL);
596   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
597   g_option_group_add_entries (group, type_entries);
598   g_option_context_add_group (context, group);
599 
600   group = g_option_group_new ("load", N_("Load/Save options:"), N_("Show load/save options"), NULL, NULL);
601   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
602   g_option_group_add_entries (group, load_entries);
603   g_option_context_add_group (context, group);
604 
605   group = g_option_group_new ("server", N_("Server options:"), N_("Show server options"), NULL, NULL);
606   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
607   g_option_group_add_entries (group, server_entries);
608   g_option_context_add_group (context, group);
609 
610   group = g_option_group_new ("install", N_("Installation options:"), N_("Show installation options"), NULL, NULL);
611   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
612   g_option_group_add_entries (group, install_entries);
613   g_option_context_add_group (context, group);
614 
615   group = g_option_group_new ("test", N_("Test options:"), N_("Show test options"), NULL, NULL);
616   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
617   g_option_group_add_entries (group, test_entries);
618   g_option_context_add_group (context, group);
619 
620   group = g_option_group_new ("schema", N_("Schema options:"), N_("Show schema options"), NULL, NULL);
621   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
622   g_option_group_add_entries (group, schema_entries);
623   g_option_context_add_group (context, group);
624 
625   g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE);
626 
627   if (argc < 2)
628     {
629       g_printerr (_("Run '%s --help' to see a full list of available command line options.\n"),
630                   argv[0]);
631       return 1;
632     }
633 
634   g_option_context_parse (context, &argc, &argv, &err);
635   g_option_context_free (context);
636 
637   if (err)
638     {
639       g_printerr (_("Error while parsing options: %s.\nRun '%s --help' to see a full list of available command line options.\n"),
640                   err->message,
641                   argv[0]);
642       g_error_free (err);
643       return 1;
644     }
645 
646   /* Um, this is a mess. Not using compatible options? */
647 
648   if (do_version)
649     {
650       g_print ("%s\n", VERSION);
651       return 0;
652     }
653 
654   if ((get_mode && set_mode) ||
655       (get_mode && unset_mode))
656     {
657       g_printerr (_("Can't get and set/unset simultaneously\n"));
658       return 1;
659     }
660 
661   if ((set_mode && get_mode) ||
662       (set_mode && unset_mode) ||
663       (set_mode && get_type_mode) ||
664       (set_mode && get_list_size_mode) ||
665       (set_mode && get_list_element_mode))
666     {
667       g_printerr (_("Can't set and get/unset simultaneously\n"));
668       return 1;
669     }
670 
671   if ((get_type_mode && set_mode) ||
672       (get_type_mode && unset_mode))
673     {
674       g_printerr (_("Can't get type and set/unset simultaneously\n"));
675       return 1;
676     }
677 
678   if ((toggle_mode && set_mode) ||
679       (toggle_mode && get_mode) ||
680       (toggle_mode && unset_mode))
681     {
682       g_printerr (_("Can't toggle and get/set/unset simultaneously\n"));
683       return 1;
684     }
685 
686   if ((all_entries_mode && get_mode) ||
687       (all_entries_mode && set_mode) ||
688       (all_entries_mode && get_type_mode) ||
689       (all_entries_mode && unset_mode) ||
690       (all_entries_mode && get_list_size_mode) ||
691       (all_entries_mode && get_list_element_mode))
692     {
693       g_printerr (_("Can't use --all-entries with --get or --set\n"));
694       return 1;
695     }
696 
697   if ((all_subdirs_mode && get_mode) ||
698       (all_subdirs_mode && set_mode) ||
699       (all_subdirs_mode && get_type_mode) ||
700       (all_subdirs_mode && unset_mode) ||
701       (all_subdirs_mode && get_list_size_mode) ||
702       (all_subdirs_mode && get_list_element_mode))
703     {
704       g_printerr (_("Can't use --all-dirs with --get or --set\n"));
705       return 1;
706     }
707 
708   if ((recursive_list && get_mode) ||
709       (recursive_list && set_mode) ||
710       (recursive_list && unset_mode) ||
711       (recursive_list && get_type_mode) ||
712       (recursive_list && get_list_size_mode) ||
713       (recursive_list && get_list_element_mode) ||
714       (recursive_list && all_entries_mode) ||
715       (recursive_list && all_subdirs_mode) ||
716       (recursive_list && (search_key || search_key_regex)))
717     {
718       g_printerr (_("--recursive-list should not be used with --get, --set, --unset, --all-entries, --all-dirs, or --search-key\n"));
719       return 1;
720     }
721 
722   if ((set_schema_mode && get_mode) ||
723       (set_schema_mode && set_mode) ||
724       (set_schema_mode && unset_mode) ||
725       (set_schema_mode && get_type_mode) ||
726       (set_schema_mode && get_list_size_mode) ||
727       (set_schema_mode && get_list_element_mode) ||
728       (set_schema_mode && all_entries_mode) ||
729       (set_schema_mode && all_subdirs_mode) ||
730       (set_schema_mode && (search_key || search_key_regex)))
731     {
732       g_printerr (_("--set_schema should not be used with --get, --set, --unset, --all-entries, --all-dirs, or --search-key\n"));
733       return 1;
734     }
735 
736   if ((value_type != NULL) && !(set_mode || set_schema_mode))
737     {
738       g_printerr (_("Value type is only relevant when setting a value\n"));
739       return 1;
740     }
741 
742   if (set_mode && (value_type == NULL))
743     {
744       g_printerr (_("Must specify a type when setting a value\n"));
745       return 1;
746     }
747 
748   if (ignore_schema_defaults && !(get_mode || all_entries_mode ||
749 				  dump_values || recursive_list ||
750 				  get_list_size_mode || get_list_element_mode))
751     {
752       g_printerr (_("--ignore-schema-defaults is only relevant with --get, --all-entries, --dump, --recursive-list, --get-list-size or --get-list-element\n"));
753       return 1;
754     }
755 
756   if (ping_gconfd && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
757                       all_subdirs_mode || all_entries_mode || recursive_list ||
758                       get_type_mode || get_list_size_mode || get_list_element_mode ||
759                       spawn_gconfd || dir_exists || schema_file ||
760                       makefile_install_mode || makefile_uninstall_mode ||
761                       break_key_mode || break_dir_mode || short_docs_mode ||
762                          long_docs_mode || schema_name_mode))
763     {
764       g_printerr (_("%s option must be used by itself.\n"),
765 		      "-p/--ping");
766       return 1;
767     }
768 
769   if (dir_exists && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
770                      all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex ||
771                      get_type_mode || get_list_size_mode || get_list_element_mode ||
772                      spawn_gconfd || schema_file ||
773                      makefile_install_mode || makefile_uninstall_mode ||
774                      break_key_mode || break_dir_mode || short_docs_mode ||
775                          long_docs_mode || schema_name_mode))
776     {
777       g_printerr (_("%s option must be used by itself.\n"),
778 		      "--dir-exists");
779       return 1;
780     }
781 
782   if (schema_file && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
783                       all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex ||
784                       get_type_mode || get_list_size_mode || get_list_element_mode ||
785                       spawn_gconfd || dir_exists ||
786                       makefile_install_mode || makefile_uninstall_mode ||
787                       break_key_mode || break_dir_mode || short_docs_mode ||
788                          long_docs_mode || schema_name_mode))
789     {
790       g_printerr (_("%s option must be used by itself.\n"),
791 		      "--install-schema-file");
792       return 1;
793     }
794 
795 
796   if (makefile_install_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
797                                 all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex ||
798                                 get_type_mode || get_list_size_mode || get_list_element_mode ||
799                                 makefile_uninstall_mode ||
800                                 spawn_gconfd || dir_exists || schema_file ||
801                                 break_key_mode || break_dir_mode || short_docs_mode ||
802                          long_docs_mode || schema_name_mode))
803     {
804       g_printerr (_("%s option must be used by itself.\n"),
805 		      "--makefile-install-rule");
806       return 1;
807     }
808 
809   if (makefile_uninstall_mode && (shutdown_gconfd || set_mode || get_mode ||
810                                   unset_mode || all_subdirs_mode ||
811                                   all_entries_mode || recursive_list || search_key || search_key_regex ||
812                                   makefile_install_mode ||
813                                   spawn_gconfd || dir_exists || schema_file ||
814                                   break_key_mode || break_dir_mode || short_docs_mode ||
815                                   long_docs_mode || schema_name_mode))
816     {
817       g_printerr (_("%s option must be used by itself.\n"),
818 		      "--makefile-uninstall-rule");
819       return 1;
820     }
821 
822   if (break_key_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
823                                 all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex ||
824                                 get_type_mode || get_list_size_mode || get_list_element_mode ||
825                                 spawn_gconfd || dir_exists || schema_file ||
826                                 makefile_install_mode || makefile_uninstall_mode ||
827                                 break_dir_mode || short_docs_mode ||
828                          long_docs_mode || schema_name_mode))
829     {
830       g_printerr (_("%s option must be used by itself.\n"),
831 		      "--break-key");
832       return 1;
833     }
834 
835 
836   if (break_dir_mode && (shutdown_gconfd || set_mode || get_mode || unset_mode ||
837                                 all_subdirs_mode || all_entries_mode || recursive_list || search_key || search_key_regex ||
838                                 get_type_mode || get_list_size_mode || get_list_element_mode ||
839                                 spawn_gconfd || dir_exists || schema_file ||
840                                 break_key_mode || makefile_install_mode ||
841                                 makefile_uninstall_mode || short_docs_mode ||
842                          long_docs_mode || schema_name_mode))
843     {
844       g_printerr (_("%s option must be used by itself.\n"),
845 		      "--break-directory");
846       return 1;
847     }
848 
849   /* FIXME not checking that --recursive-unset, --dump or --load are used alone */
850 
851   if (use_local_source && config_source == NULL)
852     {
853       g_printerr (_("You must specify a configuration source with --config-source when using --direct\n"));
854       return 1;
855     }
856 
857   if (!gconf_init(argc, argv, &err))
858     {
859       g_printerr (_("Failed to init GConf: %s\n"), err->message);
860       g_error_free(err);
861       err = NULL;
862       return 1;
863     }
864 
865   /* Do this first, since we want to do only this if the user selected
866      it. */
867   if (ping_gconfd)
868     {
869       if (gconf_ping_daemon())
870         return 0;
871       else
872         return 2;
873     }
874 
875   /* Before creating engine */
876   if (default_source_mode)
877     {
878       if (do_get_default_source (args)  == 1)
879         return 1;
880       else
881         return 0;
882     }
883 
884   if (makefile_install_mode &&
885       g_getenv ("GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL"))
886     {
887       g_print (_("GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL is set, not installing schemas\n"));
888       makefile_install_mode = FALSE;
889     }
890 
891   if (makefile_uninstall_mode &&
892       g_getenv ("GCONF_DISABLE_MAKEFILE_SCHEMA_UNINSTALL"))
893     {
894       g_print (_("GCONF_DISABLE_MAKEFILE_SCHEMA_UNINSTALL is set, not uninstalling schemas\n"));
895       makefile_uninstall_mode = FALSE;
896     }
897 
898   if (makefile_install_mode || makefile_uninstall_mode)
899     {
900       g_assert (config_source == NULL);
901 
902       /* Try the environment variable */
903       config_source = g_getenv ("GCONF_CONFIG_SOURCE");
904 
905       if (config_source == NULL)
906         {
907           g_printerr (_("Must set the GCONF_CONFIG_SOURCE environment variable\n"));
908           return 1;
909         }
910 
911       if (*config_source == '\0')
912         {
913           /* Properly set, but set to nothing (use default source) */
914           config_source = NULL;
915         }
916 
917       use_local_source = TRUE;
918 
919       /* shut down daemon, this is a race condition, but will usually work. */
920       gconf_shutdown_daemon (NULL);
921     }
922 
923   if (config_source == NULL)
924     {
925         /* If we aren't running from within a session,
926          * assume we'll be touching the database locally
927          */
928       conf = NULL;
929       if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
930         {
931           char *conffile;
932           GSList *addresses;
933 
934           conffile = g_strconcat (GCONF_CONFDIR, "/path", NULL);
935           addresses = gconf_load_source_path (conffile, NULL);
936           g_free(conffile);
937 
938           conf = gconf_engine_get_local_for_addresses (addresses, &err);
939           gconf_address_list_free (addresses);
940         }
941 
942       if (conf == NULL)
943         conf = gconf_engine_get_default();
944     }
945   else
946     {
947       GSList *addresses;
948 
949       addresses = gconf_persistent_name_get_address_list (config_source);
950 
951       if (use_local_source)
952         conf = gconf_engine_get_local_for_addresses (addresses, &err);
953       else
954         conf = gconf_engine_get_for_addresses (addresses, &err);
955 
956       gconf_address_list_free (addresses);
957     }
958 
959   if (conf == NULL)
960     {
961       g_assert(err != NULL);
962       g_printerr (_("Failed to access configuration source(s): %s\n"), err->message);
963       g_error_free(err);
964       err = NULL;
965       return 1;
966     }
967   else
968     {
969       g_assert(err == NULL);
970     }
971 
972   g_assert(conf != NULL);
973 
974   if (dir_exists != NULL)
975     {
976       gboolean success;
977 
978       success = do_dir_exists(conf, dir_exists);
979 
980       gconf_engine_unref(conf);
981 
982       if (success)
983         return 0; /* TRUE */
984       else
985         return 2; /* FALSE */
986     }
987 
988   if (schema_file != NULL)
989     {
990       gint retval;
991 
992       retval = do_load_file(conf, LOAD_SCHEMA_FILE, FALSE, schema_file, NULL);
993       if (!retval)
994 	retval = do_sync(conf);
995 
996       gconf_engine_unref(conf);
997 
998       return retval;
999     }
1000 
1001   if (entry_file != NULL)
1002     {
1003       gint retval;
1004 
1005       retval = do_load_file(conf, LOAD_ENTRY_FILE, FALSE, entry_file, args);
1006       if (!retval)
1007 	retval = do_sync(conf);
1008 
1009       gconf_engine_unref(conf);
1010 
1011       return retval;
1012     }
1013 
1014   if (unload_entry_file != NULL)
1015     {
1016       gint retval;
1017 
1018       retval = do_load_file(conf, LOAD_ENTRY_FILE, TRUE, unload_entry_file, args);
1019       if (!retval)
1020 	retval = do_sync(conf);
1021 
1022       gconf_engine_unref(conf);
1023 
1024       return retval;
1025     }
1026 
1027   if (spawn_gconfd)
1028     {
1029       do_spawn_daemon(conf);
1030       /* don't exit, it's OK to have this along with other options
1031          (however, it's probably pointless) */
1032     }
1033 
1034   if (makefile_install_mode)
1035     {
1036       gint retval;
1037 
1038       umask (022);
1039       retval = do_makefile_install (conf, args, FALSE);
1040 
1041       gconf_engine_unref (conf);
1042 
1043       return retval;
1044     }
1045 
1046   if (makefile_uninstall_mode)
1047     {
1048       gint retval;
1049 
1050       umask (022);
1051       retval = do_makefile_install (conf, args, TRUE);
1052 
1053       gconf_engine_unref (conf);
1054 
1055       return retval;
1056     }
1057 
1058   if (break_key_mode)
1059     {
1060       gint retval = do_break_key(conf, args);
1061 
1062       gconf_engine_unref(conf);
1063 
1064       return retval;
1065     }
1066 
1067   if (break_dir_mode)
1068     {
1069       gint retval = do_break_directory(conf, args);
1070 
1071       gconf_engine_unref(conf);
1072 
1073       return retval;
1074     }
1075 
1076   if (get_mode)
1077     {
1078       if (do_get(conf, args)  == 1)
1079         {
1080           gconf_engine_unref(conf);
1081           return 1;
1082         }
1083     }
1084 
1085 
1086   if (set_mode)
1087     {
1088       if (do_set(conf, args) == 1)
1089         {
1090           gconf_engine_unref(conf);
1091           return 1;
1092         }
1093     }
1094 
1095   if (toggle_mode)
1096     {
1097       if (do_toggle(conf, args) == 1)
1098         {
1099           gconf_engine_unref(conf);
1100           return 1;
1101         }
1102     }
1103 
1104   if (get_type_mode)
1105     {
1106       if (do_get_type (conf, args) == 1)
1107         {
1108           gconf_engine_unref (conf);
1109           return 1;
1110         }
1111     }
1112 
1113   if (get_list_size_mode)
1114     {
1115       if (do_get_list_size (conf, args) == 1)
1116         {
1117           gconf_engine_unref (conf);
1118           return 1;
1119         }
1120     }
1121 
1122   if (get_list_element_mode)
1123     {
1124       if (do_get_list_element (conf, args) == 1)
1125         {
1126           gconf_engine_unref (conf);
1127           return 1;
1128         }
1129     }
1130 
1131   if (set_schema_mode)
1132     {
1133       if (do_set_schema(conf, args) == 1)
1134         {
1135           gconf_engine_unref(conf);
1136           return 1;
1137         }
1138     }
1139 
1140   if (short_docs_mode)
1141     {
1142       if (do_short_docs(conf, args)  == 1)
1143         {
1144           gconf_engine_unref(conf);
1145           return 1;
1146         }
1147     }
1148 
1149   if (long_docs_mode)
1150     {
1151       if (do_long_docs(conf, args)  == 1)
1152         {
1153           gconf_engine_unref(conf);
1154           return 1;
1155         }
1156     }
1157 
1158   if (schema_name_mode)
1159     {
1160       if (do_get_schema_name(conf, args)  == 1)
1161         {
1162           gconf_engine_unref(conf);
1163           return 1;
1164         }
1165     }
1166 
1167   if (associate_schema_mode)
1168     {
1169       if (do_associate_schema(conf, args)  == 1)
1170         {
1171           gconf_engine_unref(conf);
1172           return 1;
1173         }
1174     }
1175 
1176   if (dissociate_schema_mode)
1177     {
1178       if (do_dissociate_schema (conf, args)  == 1)
1179         {
1180           gconf_engine_unref (conf);
1181           return 1;
1182         }
1183     }
1184 
1185   if (all_entries_mode)
1186     {
1187       if (do_all_entries(conf, args) == 1)
1188         {
1189           gconf_engine_unref(conf);
1190           return 1;
1191         }
1192     }
1193 
1194   if (unset_mode)
1195     {
1196       if (do_unset(conf, args) == 1)
1197         {
1198           gconf_engine_unref(conf);
1199           return 1;
1200         }
1201     }
1202 
1203   if (recursive_unset_mode)
1204     {
1205       if (do_recursive_unset(conf, args) == 1)
1206         {
1207           gconf_engine_unref(conf);
1208           return 1;
1209         }
1210     }
1211 
1212   if (all_subdirs_mode)
1213     {
1214       if (do_all_subdirs(conf, args) == 1)
1215         {
1216           gconf_engine_unref(conf);
1217           return 1;
1218         }
1219     }
1220 
1221   if (recursive_list)
1222     {
1223       if (do_recursive_list(conf, args) == 1)
1224         {
1225           gconf_engine_unref(conf);
1226           return 1;
1227         }
1228     }
1229 
1230     if (search_key)
1231     {
1232       if (do_search_key(conf, args) == 1)
1233         {
1234           gconf_engine_unref(conf);
1235           return 1;
1236         }
1237     }
1238 
1239     if (search_key_regex)
1240     {
1241       if (do_search_key_regex(conf, args) == 1)
1242         {
1243           gconf_engine_unref(conf);
1244           return 1;
1245         }
1246     }
1247 
1248   if (dump_values)
1249     {
1250       if (do_dump_values(conf, args) == 1)
1251         {
1252           gconf_engine_unref(conf);
1253           return 1;
1254         }
1255     }
1256 
1257   gconf_engine_unref(conf);
1258 
1259   if (shutdown_gconfd)
1260     {
1261       err = NULL;
1262       gconf_shutdown_daemon(&err);
1263     }
1264 
1265   if (err != NULL)
1266     {
1267       g_printerr (_("Shutdown error: %s\n"),
1268 		  err->message);
1269       g_error_free(err);
1270       err = NULL;
1271     }
1272 
1273   return 0;
1274 }
1275 
1276 static void
recurse_subdir_list(GConfEngine * conf,GSList * subdirs,const gchar * parent,guint depth)1277 recurse_subdir_list(GConfEngine* conf, GSList* subdirs, const gchar* parent, guint depth)
1278 {
1279   GSList* tmp;
1280   gchar* whitespace;
1281 
1282   whitespace = g_strnfill(depth, ' ');
1283 
1284   tmp = subdirs;
1285 
1286   while (tmp != NULL)
1287     {
1288       gchar* s = tmp->data;
1289 
1290       g_print ("%s%s:\n", whitespace, s);
1291 
1292       list_pairs_in_dir(conf, s, depth);
1293 
1294       recurse_subdir_list(conf, gconf_engine_all_dirs(conf, s, NULL), s, depth+1);
1295 
1296       g_free(s);
1297 
1298       tmp = g_slist_next(tmp);
1299     }
1300 
1301   g_slist_free(subdirs);
1302   g_free(whitespace);
1303 }
1304 
1305 static int
do_recursive_list(GConfEngine * conf,const gchar ** args)1306 do_recursive_list(GConfEngine* conf, const gchar** args)
1307 {
1308   if (args == NULL)
1309     {
1310       g_printerr (_("Must specify one or more directories to recursively list.\n"));
1311       return 1;
1312     }
1313 
1314   while (*args)
1315     {
1316       GSList* subdirs;
1317 
1318       subdirs = gconf_engine_all_dirs(conf, *args, NULL);
1319 
1320       list_pairs_in_dir(conf, *args, 0);
1321 
1322       recurse_subdir_list(conf, subdirs, *args, 1);
1323 
1324       ++args;
1325     }
1326 
1327   return 0;
1328 }
1329 
1330 static gboolean
match_pattern(gpointer pattern,const char * key)1331 match_pattern (gpointer pattern, const char *key)
1332 {
1333   return g_pattern_match_string((GPatternSpec*) pattern, key);
1334 }
1335 
1336 static gboolean
match_regex(gpointer regex,const char * key)1337 match_regex (gpointer regex, const char *key)
1338 {
1339   return g_regex_match((GRegex*) regex, key, 0, NULL);
1340 }
1341 
1342 typedef gboolean (* MatchFunc) (gpointer match_data, const char *key);
1343 
1344 static void
search_key_in_dir(GConfEngine * conf,const gchar * dir,MatchFunc match_func,gpointer match_data)1345 search_key_in_dir(GConfEngine* conf, const gchar* dir, MatchFunc match_func, gpointer match_data)
1346 {
1347   GSList* pairs;
1348   GSList* tmp;
1349   GError* err = NULL;
1350 
1351   pairs = gconf_engine_all_entries(conf, dir, &err);
1352 
1353   if (err != NULL)
1354     {
1355       g_printerr (_("Failure listing entries in `%s': %s\n"),
1356               dir, err->message);
1357       g_error_free(err);
1358       err = NULL;
1359     }
1360 
1361   if (pairs != NULL)
1362     {
1363       tmp = pairs;
1364 
1365       while (tmp != NULL)
1366         {
1367           GConfEntry* pair = tmp->data;
1368           gchar* s;
1369 	  const gchar *k;
1370 
1371           if (gconf_entry_get_value (pair) &&
1372 	      (!ignore_schema_defaults || !gconf_entry_get_is_default (pair)))
1373             s = gconf_value_to_string (gconf_entry_get_value (pair));
1374           else
1375             s = g_strdup(_("(no value set)"));
1376 
1377 	  k = gconf_key_key (gconf_entry_get_key (pair));
1378 
1379 	  if (match_func(match_data, k))
1380 	    g_print (" %s/%s = %s\n", dir, k, s);
1381 
1382           g_free(s);
1383 
1384           gconf_entry_free(pair);
1385 
1386           tmp = g_slist_next(tmp);
1387         }
1388 
1389       g_slist_free(pairs);
1390     }
1391 }
1392 
1393 static void
recurse_subdir_search(GConfEngine * conf,GSList * subdirs,const gchar * parent,MatchFunc match_func,gpointer match_data)1394 recurse_subdir_search(GConfEngine* conf, GSList* subdirs, const gchar* parent,
1395 		      MatchFunc match_func, gpointer match_data)
1396 {
1397   GSList* tmp;
1398 
1399   tmp = subdirs;
1400 
1401   while (tmp != NULL)
1402     {
1403       gchar* s = tmp->data;
1404 
1405       search_key_in_dir(conf, s, match_func, match_data);
1406 
1407       recurse_subdir_search(conf, gconf_engine_all_dirs(conf, s, NULL), s, match_func, match_data);
1408 
1409       g_free(s);
1410 
1411       tmp = g_slist_next(tmp);
1412     }
1413 
1414   g_slist_free(subdirs);
1415 }
1416 
1417 static int
do_search(GConfEngine * conf,MatchFunc match_func,gpointer match_data)1418 do_search(GConfEngine* conf, MatchFunc match_func, gpointer match_data)
1419 {
1420   GSList* subdirs;
1421 
1422   subdirs = gconf_engine_all_dirs(conf, "/", NULL);
1423 
1424   search_key_in_dir(conf, "/", match_func, match_data);
1425 
1426   recurse_subdir_search(conf, subdirs, "/", match_func, match_data);
1427 
1428   return 0;
1429 }
1430 
1431 static int
do_search_key(GConfEngine * conf,const gchar ** args)1432 do_search_key(GConfEngine* conf, const gchar** args)
1433 {
1434   GPatternSpec* pattern;
1435 
1436   if (args == NULL)
1437     {
1438       g_printerr (_("Must specify a key pattern to search for.\n"));
1439       return 1;
1440     }
1441 
1442   pattern = g_pattern_spec_new (*args);
1443   do_search(conf, match_pattern, pattern);
1444   g_pattern_spec_free (pattern);
1445 
1446   return 0;
1447 }
1448 
1449 static int
do_search_key_regex(GConfEngine * conf,const gchar ** args)1450 do_search_key_regex(GConfEngine* conf, const gchar** args)
1451 {
1452   GRegex* regex;
1453   GError *error = NULL;
1454 
1455   if (args == NULL)
1456     {
1457       g_printerr(_("Must specify a PCRE regex to search for.\n"));
1458       return 1;
1459     }
1460 
1461   regex = g_regex_new(args[0], G_REGEX_OPTIMIZE, 0, &error);
1462   if (!regex)
1463     {
1464       g_printerr(_("Error compiling regex: %s\n"), error->message);
1465       g_error_free(error);
1466       return 1;
1467     }
1468 
1469   do_search(conf, match_regex, regex);
1470   g_regex_unref(regex);
1471 
1472   return 0;
1473 }
1474 
1475 static void
recurse_subdir_dump(GConfEngine * conf,GSList * dirs,const gchar * base_dir)1476 recurse_subdir_dump(GConfEngine* conf, GSList* dirs, const gchar* base_dir)
1477 {
1478   GSList* tmp;
1479 
1480   tmp = dirs;
1481 
1482   while (tmp != NULL)
1483     {
1484       gchar* s = tmp->data;
1485       GSList* subdirs;
1486 
1487       dump_entries_in_dir(conf, s, base_dir);
1488 
1489       subdirs = g_slist_sort(gconf_engine_all_dirs(conf, s, NULL),
1490 			     (GCompareFunc)strcmp);
1491 
1492       recurse_subdir_dump(conf, subdirs, base_dir);
1493 
1494       g_free(s);
1495 
1496       tmp = tmp->next;
1497     }
1498 
1499   g_slist_free(dirs);
1500 }
1501 
1502 static int
do_dump_values(GConfEngine * conf,const gchar ** args)1503 do_dump_values(GConfEngine* conf, const gchar** args)
1504 {
1505   if (args == NULL)
1506     {
1507       g_printerr (_("Must specify one or more directories to dump.\n"));
1508       return 1;
1509     }
1510 
1511   g_print ("<gconfentryfile>\n");
1512 
1513   while (*args)
1514     {
1515       GSList* subdirs;
1516 
1517       g_print ("  <entrylist base=\"%s\">\n", *args);
1518 
1519       subdirs = g_slist_sort(gconf_engine_all_dirs(conf, *args, NULL),
1520 			     (GCompareFunc)strcmp);
1521 
1522       dump_entries_in_dir(conf, *args, *args);
1523 
1524       recurse_subdir_dump(conf, subdirs, *args);
1525 
1526       g_print ("  </entrylist>\n");
1527 
1528       ++args;
1529     }
1530 
1531   g_print ("</gconfentryfile>\n");
1532   return 0;
1533 }
1534 
1535 static void
list_pairs_in_dir(GConfEngine * conf,const gchar * dir,guint depth)1536 list_pairs_in_dir(GConfEngine* conf, const gchar* dir, guint depth)
1537 {
1538   GSList* pairs;
1539   GSList* tmp;
1540   gchar* whitespace;
1541   GError* err = NULL;
1542 
1543   whitespace = g_strnfill(depth, ' ');
1544 
1545   pairs = gconf_engine_all_entries(conf, dir, &err);
1546 
1547   if (err != NULL)
1548     {
1549       g_printerr (_("Failure listing entries in `%s': %s\n"),
1550               dir, err->message);
1551       g_error_free(err);
1552       err = NULL;
1553     }
1554 
1555   if (pairs != NULL)
1556     {
1557       tmp = pairs;
1558 
1559       while (tmp != NULL)
1560         {
1561           GConfEntry* pair = tmp->data;
1562           gchar* s;
1563 
1564           if (gconf_entry_get_value (pair) &&
1565 	      (!ignore_schema_defaults || !gconf_entry_get_is_default (pair)))
1566             s = gconf_value_to_string (gconf_entry_get_value (pair));
1567           else
1568             s = g_strdup(_("(no value set)"));
1569 
1570           g_print (" %s%s = %s\n", whitespace,
1571 		   gconf_key_key (gconf_entry_get_key (pair)),
1572 		   s);
1573 
1574           g_free(s);
1575 
1576           gconf_entry_free(pair);
1577 
1578           tmp = g_slist_next(tmp);
1579         }
1580 
1581       g_slist_free(pairs);
1582     }
1583 
1584   g_free(whitespace);
1585 }
1586 
1587 static int
do_all_pairs(GConfEngine * conf,const gchar ** args)1588 do_all_pairs(GConfEngine* conf, const gchar** args)
1589 {
1590   while (*args)
1591     {
1592       list_pairs_in_dir(conf, *args, 0);
1593       ++args;
1594     }
1595   return 0;
1596 }
1597 
1598 /* FIXME: only prints the schema for the current locale.
1599  *        Need some way of getting the schemas for all locales.
1600  */
1601 static void
print_schema_in_xml(GConfValue * value,int indent)1602 print_schema_in_xml(GConfValue* value, int indent)
1603 {
1604   GConfSchema* schema;
1605   GConfValueType type;
1606   GConfValueType list_type;
1607   GConfValueType car_type;
1608   GConfValueType cdr_type;
1609   GConfValue* default_value;
1610   const gchar* owner;
1611   const gchar* short_desc;
1612   const gchar* long_desc;
1613   gchar* whitespace;
1614 
1615   whitespace = g_strnfill(indent, ' ');
1616 
1617   schema = gconf_value_get_schema(value);
1618 
1619   type = gconf_schema_get_type(schema);
1620   list_type = gconf_schema_get_list_type(schema);
1621   car_type = gconf_schema_get_car_type(schema);
1622   cdr_type = gconf_schema_get_cdr_type(schema);
1623 
1624   owner = gconf_schema_get_owner(schema);
1625   default_value = gconf_schema_get_default_value(schema);
1626   short_desc = gconf_schema_get_short_desc(schema);
1627   long_desc = gconf_schema_get_long_desc(schema);
1628 
1629   g_print ("%s<schema>\n", whitespace);
1630 
1631   if (owner)
1632     g_print ("%s  <owner>%s</owner>\n", whitespace, owner);
1633 
1634   g_print ("%s  <type>%s</type>\n", whitespace, gconf_value_type_to_string(type));
1635 
1636   if (type == GCONF_VALUE_LIST)
1637     g_print ("%s  <list_type>%s</list_type>\n", whitespace, gconf_value_type_to_string(list_type));
1638   else if (type == GCONF_VALUE_PAIR)
1639     {
1640       g_print ("%s  <car_type>%s</car_type>\n", whitespace, gconf_value_type_to_string(car_type));
1641       g_print ("%s  <cdr_type>%s</cdr_type>\n", whitespace, gconf_value_type_to_string(cdr_type));
1642     }
1643 
1644   g_print ("%s  <locale name=\"%s\">\n", whitespace, gconf_schema_get_locale (schema));
1645 
1646   if (default_value)
1647     {
1648       g_print ("%s    <default_value>\n", whitespace);
1649       print_value_in_xml(default_value, indent + 6);
1650       g_print ("%s    </default_value>\n", whitespace);
1651     }
1652 
1653   if (short_desc)
1654     {
1655       gchar* tmp = g_markup_escape_text(short_desc, -1);
1656       g_print ("%s    <short>%s</short>\n", whitespace, tmp);
1657       g_free(tmp);
1658     }
1659 
1660   if (long_desc)
1661     {
1662       gchar* tmp = g_markup_escape_text(long_desc, -1);
1663       g_print ("%s    <long>%s</long>\n", whitespace, tmp);
1664       g_free(tmp);
1665     }
1666 
1667   g_print ("%s  </locale>\n", whitespace);
1668 
1669   g_print ("%s</schema>\n", whitespace);
1670 
1671   g_free(whitespace);
1672 }
1673 
1674 static void
print_pair_in_xml(GConfValue * value,int indent)1675 print_pair_in_xml(GConfValue* value, int indent)
1676 {
1677   gchar* whitespace;
1678 
1679   whitespace = g_strnfill(indent, ' ');
1680 
1681   g_print ("%s<pair>\n", whitespace);
1682 
1683   g_print ("%s  <car>\n", whitespace);
1684   print_value_in_xml(gconf_value_get_car(value), indent + 4);
1685   g_print ("%s  </car>\n", whitespace);
1686 
1687   g_print ("%s  <cdr>\n", whitespace);
1688   print_value_in_xml(gconf_value_get_cdr(value), indent + 4);
1689   g_print ("%s  </cdr>\n", whitespace);
1690 
1691   g_print ("%s</pair>\n", whitespace);
1692 
1693   g_free(whitespace);
1694 }
1695 
1696 static void
print_list_in_xml(GConfValue * value,int indent)1697 print_list_in_xml(GConfValue* value, int indent)
1698 {
1699   GConfValueType list_type;
1700   GSList* tmp;
1701   gchar* whitespace;
1702 
1703   whitespace = g_strnfill(indent, ' ');
1704 
1705   list_type = gconf_value_get_list_type(value);
1706 
1707   g_print ("%s<list type=\"%s\">\n", whitespace, gconf_value_type_to_string(list_type));
1708 
1709   tmp = gconf_value_get_list(value);
1710   while (tmp)
1711     {
1712       print_value_in_xml(tmp->data, indent + 4);
1713 
1714       tmp = tmp->next;
1715     }
1716 
1717   g_print ("%s</list>\n", whitespace);
1718 
1719   g_free(whitespace);
1720 }
1721 
1722 static void
print_value_in_xml(GConfValue * value,int indent)1723 print_value_in_xml(GConfValue* value, int indent)
1724 {
1725   gchar* whitespace;
1726   gchar* tmp;
1727 
1728   whitespace = g_strnfill(indent, ' ');
1729 
1730   g_print ("%s<value>\n", whitespace);
1731 
1732   switch (value->type)
1733     {
1734     case GCONF_VALUE_INT:
1735       tmp = gconf_value_to_string(value);
1736       g_print ("%s  <int>%s</int>\n", whitespace, tmp);
1737       g_free(tmp);
1738       break;
1739     case GCONF_VALUE_FLOAT:
1740       tmp = gconf_value_to_string(value);
1741       g_print ("%s  <float>%s</float>\n", whitespace, tmp);
1742       g_free(tmp);
1743       break;
1744     case GCONF_VALUE_STRING:
1745       tmp = g_markup_escape_text(gconf_value_get_string(value), -1);
1746       g_print ("%s  <string>%s</string>\n", whitespace, (tmp[0] == ' ' && tmp[1] == '\0') ? "" : tmp);
1747       g_free(tmp);
1748       break;
1749     case GCONF_VALUE_BOOL:
1750       tmp = gconf_value_to_string(value);
1751       g_print ("%s  <bool>%s</bool>\n", whitespace, tmp);
1752       g_free(tmp);
1753       break;
1754     case GCONF_VALUE_LIST:
1755       print_list_in_xml(value, indent + 2);
1756       break;
1757     case GCONF_VALUE_PAIR:
1758       print_pair_in_xml(value, indent + 2);
1759       break;
1760     case GCONF_VALUE_SCHEMA:
1761       print_schema_in_xml(value, indent + 2);
1762       break;
1763     default:
1764       g_assert_not_reached();
1765       break;
1766     }
1767 
1768   g_print ("%s</value>\n", whitespace);
1769 
1770   g_free(whitespace);
1771 }
1772 
1773 static inline const gchar*
get_key_relative(const gchar * key,const gchar * dir)1774 get_key_relative(const gchar* key, const gchar* dir)
1775 {
1776   int i;
1777 
1778   g_assert(key != NULL);
1779   g_assert(dir != NULL);
1780 
1781   i = 0;
1782   while (dir [i])
1783     {
1784       if (dir [i] != key [i])
1785         return key;
1786       ++i;
1787     }
1788 
1789   if (key [i] != '/' || key [i] == '\0')
1790     return key;
1791 
1792   ++i;
1793 
1794   return key + i;
1795 }
1796 
1797 static int
compare_entries(GConfEntry * a,GConfEntry * b)1798 compare_entries (GConfEntry* a, GConfEntry *b)
1799 {
1800   return strcmp(gconf_entry_get_key(a), gconf_entry_get_key(b));
1801 }
1802 
1803 static void
dump_entries_in_dir(GConfEngine * conf,const gchar * dir,const gchar * base_dir)1804 dump_entries_in_dir(GConfEngine* conf, const gchar* dir, const gchar* base_dir)
1805 {
1806   GSList* entries;
1807   GSList* tmp;
1808   GError* err = NULL;
1809 
1810   entries = g_slist_sort(gconf_engine_all_entries(conf, dir, &err),
1811 			 (GCompareFunc)compare_entries);
1812 
1813   if (err != NULL)
1814     {
1815       g_printerr (_("Failure listing entries in `%s': %s\n"),
1816 		  dir, err->message);
1817       g_error_free(err);
1818       err = NULL;
1819     }
1820 
1821   tmp = entries;
1822   while (tmp != NULL)
1823     {
1824       GConfEntry* entry = tmp->data;
1825 
1826       g_print ("    <entry>\n");
1827 
1828       g_print ("      <key>%s</key>\n",
1829 	       get_key_relative(gconf_entry_get_key(entry), base_dir));
1830 
1831       /* <schema_key> will only be relative if its under the base dir */
1832       if (gconf_entry_get_schema_name(entry))
1833         g_print ("      <schema_key>%s</schema_key>\n",
1834 		 get_key_relative(gconf_entry_get_schema_name(entry), base_dir));
1835 
1836       if (entry->value &&
1837 	  (!ignore_schema_defaults || !gconf_entry_get_is_default(entry)))
1838         print_value_in_xml(entry->value, 6);
1839 
1840       g_print ("    </entry>\n");
1841 
1842       gconf_entry_free(entry);
1843 
1844       tmp = tmp->next;
1845     }
1846   g_slist_free(entries);
1847 }
1848 
1849 static gboolean
do_dir_exists(GConfEngine * conf,const gchar * dir)1850 do_dir_exists(GConfEngine* conf, const gchar* dir)
1851 {
1852   GError* err = NULL;
1853   gboolean exists = FALSE;
1854 
1855   exists = gconf_engine_dir_exists(conf, dir_exists, &err);
1856 
1857   if (err != NULL)
1858     {
1859       g_printerr ("%s\n", err->message);
1860       g_error_free(err);
1861       err = NULL;
1862     }
1863 
1864   return exists;
1865 }
1866 
1867 static void
do_spawn_daemon(GConfEngine * conf)1868 do_spawn_daemon(GConfEngine* conf)
1869 {
1870   GError* err = NULL;
1871 
1872   if (!gconf_spawn_daemon(&err))
1873     {
1874       g_printerr (_("Failed to spawn the configuration server (gconfd): %s\n"),
1875 		  err->message);
1876       g_error_free(err);
1877       err = NULL;
1878     }
1879 }
1880 
1881 static inline GConfValue *
get_maybe_without_default(GConfEngine * conf,const gchar * key,GError ** err)1882 get_maybe_without_default (GConfEngine  *conf,
1883 			   const gchar  *key,
1884 			   GError      **err)
1885 {
1886   if (!ignore_schema_defaults)
1887     {
1888       return gconf_engine_get (conf, key, err);
1889     }
1890   else
1891     {
1892       return gconf_engine_get_without_default (conf, key, err);
1893     }
1894 }
1895 
1896 static int
do_get(GConfEngine * conf,const gchar ** args)1897 do_get(GConfEngine* conf, const gchar** args)
1898 {
1899   GError* err = NULL;
1900 
1901   if (args == NULL)
1902     {
1903       g_printerr (_("Must specify a key or keys to get\n"));
1904       return 1;
1905     }
1906 
1907   while (*args)
1908     {
1909       GConfValue* value;
1910       gchar* s;
1911 
1912       err = NULL;
1913 
1914       value = get_maybe_without_default (conf, *args, &err);
1915 
1916       if (value != NULL)
1917         {
1918           if (value->type != GCONF_VALUE_SCHEMA)
1919             {
1920               s = gconf_value_to_string(value);
1921 
1922               g_print ("%s\n", s);
1923 
1924               g_free(s);
1925             }
1926           else
1927             {
1928               GConfSchema* sc = gconf_value_get_schema(value);
1929               GConfValueType stype = gconf_schema_get_type(sc);
1930               GConfValueType slist_type = gconf_schema_get_list_type(sc);
1931               GConfValueType scar_type = gconf_schema_get_car_type(sc);
1932               GConfValueType scdr_type = gconf_schema_get_cdr_type(sc);
1933               const gchar* long_desc = gconf_schema_get_long_desc(sc);
1934               const gchar* short_desc = gconf_schema_get_short_desc(sc);
1935               const gchar* owner = gconf_schema_get_owner(sc);
1936               GConfValue* def_value = gconf_schema_get_default_value(sc);
1937 
1938               g_print (_("Type: %s\n"), gconf_value_type_to_string(stype));
1939               g_print (_("List Type: %s\n"), gconf_value_type_to_string(slist_type));
1940               g_print (_("Car Type: %s\n"), gconf_value_type_to_string(scar_type));
1941               g_print (_("Cdr Type: %s\n"), gconf_value_type_to_string(scdr_type));
1942               if (def_value)
1943                 s = gconf_value_to_string (def_value);
1944               else
1945                 s = NULL;
1946               g_print (_("Default Value: %s\n"), def_value ? s : _("Unset"));
1947               g_free (s);
1948               g_print (_("Owner: %s\n"), owner ? owner : _("Unset"));
1949               g_print (_("Short Desc: %s\n"), short_desc ? short_desc : _("Unset"));
1950               g_print (_("Long Desc: %s\n"), long_desc ? long_desc : _("Unset"));
1951             }
1952 
1953           gconf_value_free(value);
1954         }
1955       else
1956         {
1957           if (err == NULL)
1958             {
1959               g_printerr (_("No value set for `%s'\n"), *args);
1960             }
1961           else
1962             {
1963               g_printerr (_("Failed to get value for `%s': %s\n"),
1964                       *args, err->message);
1965               g_error_free(err);
1966               err = NULL;
1967             }
1968         }
1969 
1970       ++args;
1971     }
1972   return 0;
1973 }
1974 
1975 static GConfValueType
read_value_type(const char * string)1976 read_value_type(const char *string)
1977 {
1978   GConfValueType type = GCONF_VALUE_INVALID;
1979   switch (*string)
1980     {
1981     case 'i':
1982     case 'I':
1983       type = GCONF_VALUE_INT;
1984       break;
1985     case 'f':
1986     case 'F':
1987       type = GCONF_VALUE_FLOAT;
1988       break;
1989     case 'b':
1990     case 'B':
1991       type = GCONF_VALUE_BOOL;
1992       break;
1993     case 's':
1994     case 'S':
1995       switch (string[1])
1996 	{
1997 	case 't':
1998 	case 'T':
1999 	  type = GCONF_VALUE_STRING;
2000 	  break;
2001 	case 'c':
2002 	case 'C':
2003 	  type = GCONF_VALUE_SCHEMA;
2004 	  break;
2005 	default:
2006 	  g_printerr (_("Don't understand type `%s'\n"), string);
2007 	}
2008       break;
2009     case 'l':
2010     case 'L':
2011       type = GCONF_VALUE_LIST;
2012       break;
2013     case 'p':
2014     case 'P':
2015       type = GCONF_VALUE_PAIR;
2016       break;
2017     default:
2018       g_printerr (_("Don't understand type `%s'\n"), string);
2019     }
2020   return type;
2021 }
2022 
2023 static int
do_set(GConfEngine * conf,const gchar ** args)2024 do_set(GConfEngine* conf, const gchar** args)
2025 {
2026   GError* err = NULL;
2027 
2028   if (args == NULL)
2029     {
2030       g_printerr (_("Must specify alternating keys/values as arguments\n"));
2031       return 1;
2032     }
2033 
2034   while (*args)
2035     {
2036       const gchar* key;
2037       const gchar* value;
2038       GConfValueType type = GCONF_VALUE_INVALID;
2039       GConfValueType list_type = GCONF_VALUE_INVALID;
2040       GConfValueType car_type = GCONF_VALUE_INVALID;
2041       GConfValueType cdr_type = GCONF_VALUE_INVALID;
2042       GConfValue* gval;
2043 
2044       key = *args;
2045       ++args;
2046       value = *args;
2047 
2048       if (value == NULL)
2049         {
2050           g_printerr (_("No value to set for key: `%s'\n"), key);
2051           return 1;
2052         }
2053 
2054       type = read_value_type(value_type);
2055       if (type == GCONF_VALUE_INVALID)
2056         return 1;
2057       if (value_list_type != NULL)
2058         {
2059           list_type = read_value_type(value_list_type);
2060           if (list_type == GCONF_VALUE_INVALID)
2061             return 1;
2062 	}
2063       if (value_car_type != NULL)
2064         {
2065           car_type = read_value_type(value_car_type);
2066           if (car_type == GCONF_VALUE_INVALID)
2067             return 1;
2068 	}
2069       if (value_cdr_type != NULL)
2070         {
2071           cdr_type = read_value_type(value_cdr_type);
2072           if (cdr_type == GCONF_VALUE_INVALID)
2073             return 1;
2074 	}
2075 
2076       if (type == GCONF_VALUE_SCHEMA)
2077         {
2078           g_printerr (_("Cannot set schema as value\n"));
2079           return 1;
2080 	}
2081 
2082       if (type == GCONF_VALUE_LIST &&
2083           list_type != GCONF_VALUE_STRING &&
2084           list_type != GCONF_VALUE_INT &&
2085           list_type != GCONF_VALUE_FLOAT &&
2086           list_type != GCONF_VALUE_BOOL)
2087         {
2088           g_printerr (_("When setting a list you must specify a primitive list-type\n"));
2089           return 1;
2090 	}
2091 
2092       if (type == GCONF_VALUE_PAIR &&
2093           ((car_type != GCONF_VALUE_STRING &&
2094             car_type != GCONF_VALUE_INT &&
2095             car_type != GCONF_VALUE_FLOAT &&
2096             car_type != GCONF_VALUE_BOOL) ||
2097            (cdr_type != GCONF_VALUE_STRING &&
2098             cdr_type != GCONF_VALUE_INT &&
2099             cdr_type != GCONF_VALUE_FLOAT &&
2100             cdr_type != GCONF_VALUE_BOOL)))
2101         {
2102           g_printerr (_("When setting a pair you must specify a primitive car-type and cdr-type\n"));
2103           return 1;
2104 	}
2105 
2106       err = NULL;
2107 
2108       if (type == GCONF_VALUE_LIST)
2109 	gval = gconf_value_new_list_from_string(list_type, value, &err);
2110       else if (type == GCONF_VALUE_PAIR)
2111 	gval = gconf_value_new_pair_from_string(car_type, cdr_type, value, &err);
2112       else
2113         gval = gconf_value_new_from_string(type, value, &err);
2114 
2115       if (gval == NULL)
2116         {
2117           g_printerr (_("Error: %s\n"),
2118 		      err->message);
2119           g_error_free(err);
2120           err = NULL;
2121           return 1;
2122         }
2123 
2124       err = NULL;
2125 
2126       gconf_engine_set (conf, key, gval, &err);
2127 
2128       if (err != NULL)
2129         {
2130           g_printerr (_("Error setting value: %s\n"),
2131 		      err->message);
2132           g_error_free(err);
2133           err = NULL;
2134           return 1;
2135         }
2136 
2137       gconf_value_free(gval);
2138 
2139       ++args;
2140     }
2141 
2142   err = NULL;
2143 
2144   gconf_engine_suggest_sync(conf, &err);
2145 
2146   if (err != NULL)
2147     {
2148       g_printerr (_("Error syncing: %s\n"),
2149               err->message);
2150       return 1;
2151     }
2152 
2153   return 0;
2154 }
2155 
2156 static int
do_toggle(GConfEngine * conf,const gchar ** args)2157 do_toggle(GConfEngine* conf, const gchar** args)
2158 {
2159   GError* err = NULL;
2160 
2161   if (args == NULL)
2162     {
2163       g_printerr (_("Must specify one or more keys as arguments\n"));
2164       return 1;
2165     }
2166 
2167   while (*args)
2168     {
2169       const gchar* key;
2170       GConfValue* value;
2171 
2172       key = *args;
2173       err = NULL;
2174 
2175       value = get_maybe_without_default (conf, key, &err);
2176 
2177       if (value == NULL)
2178         {
2179           g_printerr (_("No value found for key %s\n"), key);
2180           return 1;
2181         }
2182 
2183       if (value->type != GCONF_VALUE_BOOL)
2184         {
2185           g_printerr (_("Not a boolean value: %s\n"), key);
2186           return 1;
2187         }
2188 
2189       gconf_value_set_bool (value, !gconf_value_get_bool (value));
2190 
2191       gconf_engine_set (conf, key, value, &err);
2192 
2193       if (err != NULL)
2194         {
2195           g_printerr (_("Error setting value: %s\n"), err->message);
2196           g_error_free(err);
2197           err = NULL;
2198           return 1;
2199         }
2200 
2201       gconf_value_free (value);
2202 
2203       ++args;
2204     }
2205 
2206   return 0;
2207 }
2208 
2209 static int
do_get_type(GConfEngine * conf,const gchar ** args)2210 do_get_type(GConfEngine* conf, const gchar** args)
2211 {
2212   GError* err = NULL;
2213 
2214   if (args == NULL)
2215     {
2216       g_printerr (_("Must specify a key or keys to get type\n"));
2217       return 1;
2218     }
2219 
2220   while (*args)
2221     {
2222       GConfValue* value;
2223 
2224       err = NULL;
2225 
2226       value = get_maybe_without_default (conf, *args, &err);
2227 
2228       if (value != NULL)
2229 	{
2230 	  g_print ("%s\n", gconf_value_type_to_string (value->type));
2231 	}
2232       else
2233         {
2234           if (err == NULL)
2235             {
2236               g_printerr (_("No value set for `%s'\n"), *args);
2237             }
2238           else
2239             {
2240               g_printerr (_("Failed to get value for `%s': %s\n"),
2241 			  *args, err->message);
2242               g_error_free (err);
2243               err = NULL;
2244             }
2245         }
2246 
2247       ++args;
2248     }
2249   return 0;
2250 }
2251 
2252 static int
do_get_list_size(GConfEngine * conf,const gchar ** args)2253 do_get_list_size(GConfEngine* conf, const gchar** args)
2254 {
2255   GError* err = NULL;
2256   GConfValue *list = NULL;
2257 
2258   if (args == NULL || *args == NULL)
2259     {
2260       g_printerr (_("Must specify a key to lookup size of.\n"));
2261       return 1;
2262     }
2263 
2264   list = get_maybe_without_default (conf, *args, &err);
2265 
2266   if (list == NULL)
2267     {
2268       if (err == NULL)
2269 	{
2270 	  g_printerr (_("No value set for `%s'\n"), *args);
2271 	}
2272       else
2273 	{
2274 	  g_printerr (_("Failed to get value for `%s': %s\n"),
2275 		      *args, err->message);
2276 	  g_error_free (err);
2277 	  err = NULL;
2278 	}
2279 
2280       return 1;
2281     }
2282 
2283   if (list->type != GCONF_VALUE_LIST)
2284     {
2285       g_printerr (_("Key %s is not a list.\n"), *args);
2286       return 1;
2287     }
2288 
2289   g_print ("%u\n", g_slist_length (gconf_value_get_list (list)));
2290 
2291   return 0;
2292 }
2293 
2294 static int
do_get_list_element(GConfEngine * conf,const gchar ** args)2295 do_get_list_element(GConfEngine* conf, const gchar** args)
2296 {
2297   GError* err = NULL;
2298   GConfValue *list = NULL, *element = NULL;
2299   GSList *iter = NULL;
2300   gchar* s = NULL;
2301   int idx = 0;
2302 
2303   if (args == NULL || *args == NULL)
2304     {
2305       g_printerr (_("Must specify a key from which to get list element.\n"));
2306       return 1;
2307     }
2308 
2309   list = get_maybe_without_default (conf, *args, &err);
2310 
2311   if (list == NULL)
2312     {
2313       if (err == NULL)
2314 	{
2315 	  g_printerr (_("No value set for `%s'\n"), *args);
2316 	}
2317       else
2318 	{
2319 	  g_printerr (_("Failed to get value for `%s': %s\n"),
2320 		      *args, err->message);
2321 	  g_error_free (err);
2322 	  err = NULL;
2323 	}
2324 
2325       return 1;
2326     }
2327 
2328   if (list->type != GCONF_VALUE_LIST)
2329     {
2330       g_printerr (_("Key %s is not a list.\n"), *args);
2331       return 1;
2332     }
2333 
2334   if (args[1] == NULL)
2335     {
2336       g_printerr (_("Must specify list index.\n"));
2337       return 1;
2338     }
2339 
2340   idx = atoi (args[1]);
2341   if (idx < 0)
2342     {
2343       g_printerr (_("List index must be non-negative.\n"));
2344       return 1;
2345     }
2346 
2347   iter = gconf_value_get_list (list);
2348   element = g_slist_nth_data (iter, idx);
2349 
2350   if (element == NULL)
2351     {
2352       g_printerr (_("List index is out of bounds.\n"));
2353       return 1;
2354     }
2355 
2356   s = gconf_value_to_string (element);
2357   g_print ("%s\n", s);
2358   g_free (s);
2359 
2360   return 0;
2361 }
2362 
2363 enum
2364 {
2365   SCHEMA_INFO_SHORT_DOCS,
2366   SCHEMA_INFO_LONG_DOCS,
2367   SCHEMA_INFO_SCHEMA_NAME
2368 };
2369 
2370 static int
do_schema_info(GConfEngine * conf,const gchar ** args,int info)2371 do_schema_info (GConfEngine *conf, const gchar **args,
2372                 int info)
2373 {
2374   GError* err = NULL;
2375 
2376   if (args == NULL)
2377     {
2378       g_printerr (_("Must specify a key or keys on the command line\n"));
2379       return 1;
2380     }
2381 
2382   while (*args)
2383     {
2384       GConfEntry* entry;
2385 
2386       err = NULL;
2387 
2388       entry = gconf_engine_get_entry (conf, *args, NULL, TRUE, &err);
2389 
2390       if (entry != NULL)
2391         {
2392           const char *s;
2393 
2394           s = gconf_entry_get_schema_name (entry);
2395 
2396           if (s == NULL)
2397             {
2398               g_printerr (_("No schema known for `%s'\n"), *args);
2399             }
2400           else if (info == SCHEMA_INFO_SCHEMA_NAME)
2401             {
2402               g_print ("%s\n", s);
2403             }
2404           else
2405             {
2406               GConfValue *val;
2407 
2408               err = NULL;
2409 
2410               val = gconf_engine_get (conf, s, &err);
2411 
2412               if (val != NULL && val->type == GCONF_VALUE_SCHEMA)
2413                 {
2414                   GConfSchema *schema;
2415                   const char *docs;
2416 
2417                   docs = NULL;
2418                   schema = gconf_value_get_schema (val);
2419 
2420                   if (schema)
2421                     {
2422                       if (info == SCHEMA_INFO_SHORT_DOCS)
2423                         docs = gconf_schema_get_short_desc (schema);
2424                       else if (info == SCHEMA_INFO_LONG_DOCS)
2425                         docs = gconf_schema_get_long_desc (schema);
2426                     }
2427 
2428                   if (docs)
2429                     g_print ("%s\n", docs);
2430                   else
2431                     g_printerr (_("No doc string stored in schema at '%s'\n"),
2432 				s);
2433                 }
2434               else if (err != NULL)
2435                 {
2436                   g_printerr (_("Error getting schema at '%s': %s\n"),
2437 			      s, err->message);
2438                   g_error_free (err);
2439                 }
2440               else
2441                 {
2442                   if (val == NULL)
2443                     g_printerr (_("No schema stored at '%s'\n"),
2444 				s);
2445                   else
2446                     g_printerr (_("Value at '%s' is not a schema\n"),
2447 				s);
2448                 }
2449 
2450               if (val)
2451                 gconf_value_free (val);
2452             }
2453 
2454           gconf_entry_free (entry);
2455         }
2456       else
2457         {
2458           if (err == NULL)
2459             {
2460               g_printerr (_("No value set for `%s'\n"), *args);
2461             }
2462           else
2463             {
2464               g_printerr (_("Failed to get value for `%s': %s\n"),
2465 			  *args, err->message);
2466               g_error_free(err);
2467               err = NULL;
2468             }
2469         }
2470 
2471       ++args;
2472     }
2473 
2474   return 0;
2475 }
2476 
2477 static int
do_short_docs(GConfEngine * conf,const gchar ** args)2478 do_short_docs (GConfEngine *conf, const gchar **args)
2479 {
2480   return do_schema_info (conf, args, SCHEMA_INFO_SHORT_DOCS);
2481 }
2482 
2483 static int
do_long_docs(GConfEngine * conf,const gchar ** args)2484 do_long_docs (GConfEngine *conf, const gchar **args)
2485 {
2486   return do_schema_info (conf, args, SCHEMA_INFO_LONG_DOCS);
2487 }
2488 
2489 static int
do_get_schema_name(GConfEngine * conf,const gchar ** args)2490 do_get_schema_name (GConfEngine *conf, const gchar **args)
2491 {
2492   return do_schema_info (conf, args, SCHEMA_INFO_SCHEMA_NAME);
2493 }
2494 
2495 static int
do_associate_schema(GConfEngine * conf,const gchar ** args)2496 do_associate_schema (GConfEngine *conf, const gchar **args)
2497 {
2498   GError *err;
2499 
2500   if (!args || args[0] == NULL || args[1] == NULL || args[2] != NULL)
2501     {
2502       g_printerr (_("Must specify a schema name followed by the key name to apply it to\n"));
2503       return 1;
2504     }
2505 
2506   err = NULL;
2507   if (!gconf_engine_associate_schema (conf, args[1], args[0], &err))
2508     {
2509       g_printerr (_("Error associating schema name '%s' with key name '%s': %s\n"),
2510 		  args[0], args[1], err->message);
2511       g_error_free (err);
2512 
2513       return 1;
2514     }
2515 
2516   return 0;
2517 }
2518 
2519 static int
do_dissociate_schema(GConfEngine * conf,const gchar ** args)2520 do_dissociate_schema (GConfEngine *conf, const gchar **args)
2521 {
2522   GError *err;
2523   gboolean failed;
2524 
2525   if (!args || args[0] == NULL)
2526     {
2527       g_printerr (_("Must specify keys to unapply schema from\n"));
2528       return 1;
2529     }
2530 
2531   failed = FALSE;
2532   while (*args)
2533     {
2534       err = NULL;
2535       if (!gconf_engine_associate_schema (conf, *args, NULL, &err))
2536         {
2537           g_printerr (_("Error removing schema name from '%s': %s\n"),
2538 		      *args, err->message);
2539           g_error_free (err);
2540           failed = TRUE;
2541         }
2542 
2543       ++args;
2544     }
2545 
2546   if (failed)
2547     return 1;
2548   else
2549     return 0;
2550 }
2551 
2552 static int
do_set_schema(GConfEngine * conf,const gchar ** args)2553 do_set_schema(GConfEngine* conf, const gchar** args)
2554 {
2555   GConfSchema* sc;
2556   GConfValue* val;
2557   const gchar* key;
2558   GError* err = NULL;
2559 
2560   if ((args == NULL) || (args[1] != NULL))
2561     {
2562       g_printerr (_("Must specify key (schema name) as the only argument\n"));
2563       return 1;
2564     }
2565 
2566   key = *args;
2567 
2568   val = gconf_value_new(GCONF_VALUE_SCHEMA);
2569 
2570   sc = gconf_schema_new();
2571 
2572   gconf_value_set_schema_nocopy(val, sc);
2573 
2574   if (short_desc)
2575     gconf_schema_set_short_desc(sc, short_desc);
2576 
2577   if (long_desc)
2578     gconf_schema_set_long_desc(sc, long_desc);
2579 
2580   if (owner)
2581     gconf_schema_set_owner(sc, owner);
2582 
2583   if (value_type)
2584     {
2585       GConfValueType type = GCONF_VALUE_INVALID;
2586 
2587       type = read_value_type(value_type);
2588 
2589       if (type != GCONF_VALUE_INVALID)
2590         gconf_schema_set_type(sc, type);
2591     }
2592 
2593   if (value_list_type)
2594     {
2595       GConfValueType type = GCONF_VALUE_INVALID;
2596 
2597       type = read_value_type(value_list_type);
2598 
2599       if (type != GCONF_VALUE_STRING &&
2600           type != GCONF_VALUE_INT &&
2601           type != GCONF_VALUE_FLOAT &&
2602           type != GCONF_VALUE_BOOL)
2603 	{
2604           g_printerr (_("List type must be a primitive type: string, int, float or bool\n"));
2605           return 1;
2606 
2607 	}
2608 
2609       if (type != GCONF_VALUE_INVALID)
2610         gconf_schema_set_list_type(sc, type);
2611     }
2612 
2613   if (value_car_type)
2614     {
2615       GConfValueType type = GCONF_VALUE_INVALID;
2616 
2617       type = read_value_type(value_car_type);
2618 
2619       if (type != GCONF_VALUE_STRING &&
2620           type != GCONF_VALUE_INT &&
2621           type != GCONF_VALUE_FLOAT &&
2622           type != GCONF_VALUE_BOOL)
2623 	{
2624           g_printerr (_("Pair car type must be a primitive type: string, int, float or bool\n"));
2625           return 1;
2626 
2627 	}
2628 
2629       if (type != GCONF_VALUE_INVALID)
2630         gconf_schema_set_car_type(sc, type);
2631     }
2632 
2633   if (value_cdr_type)
2634     {
2635       GConfValueType type = GCONF_VALUE_INVALID;
2636 
2637       type = read_value_type(value_cdr_type);
2638 
2639       if (type != GCONF_VALUE_STRING &&
2640           type != GCONF_VALUE_INT &&
2641           type != GCONF_VALUE_FLOAT &&
2642           type != GCONF_VALUE_BOOL)
2643 	{
2644           g_printerr (_("Pair cdr type must be a primitive type: string, int, float or bool\n"));
2645           return 1;
2646 
2647 	}
2648 
2649       if (type != GCONF_VALUE_INVALID)
2650         gconf_schema_set_cdr_type(sc, type);
2651     }
2652 
2653   err = NULL;
2654 
2655   gconf_engine_set (conf, key, val, &err);
2656 
2657   if (err != NULL)
2658     {
2659       g_printerr (_("Error setting value: %s"),
2660 		  err->message);
2661       g_error_free(err);
2662       err = NULL;
2663       return 1;
2664     }
2665 
2666   gconf_value_free(val);
2667 
2668   err = NULL;
2669   gconf_engine_suggest_sync(conf, &err);
2670 
2671   if (err != NULL)
2672     {
2673       g_printerr (_("Error syncing: %s"),
2674 		  err->message);
2675       g_error_free(err);
2676       err = NULL;
2677       return 1;
2678     }
2679 
2680   return 0;
2681 }
2682 
2683 static int
do_all_entries(GConfEngine * conf,const gchar ** args)2684 do_all_entries(GConfEngine* conf, const gchar** args)
2685 {
2686   if (args == NULL)
2687     {
2688       g_printerr (_("Must specify one or more directories to get key/value pairs from.\n"));
2689       return 1;
2690     }
2691 
2692   return do_all_pairs(conf, args);
2693 }
2694 
2695 static int
do_unset(GConfEngine * conf,const gchar ** args)2696 do_unset(GConfEngine* conf, const gchar** args)
2697 {
2698   GError* err = NULL;
2699 
2700   if (args == NULL)
2701     {
2702       g_printerr (_("Must specify one or more keys to unset.\n"));
2703       return 1;
2704     }
2705 
2706   while (*args)
2707     {
2708       err = NULL;
2709       gconf_engine_unset(conf, *args, &err);
2710 
2711       if (err != NULL)
2712         {
2713           g_printerr (_("Error unsetting `%s': %s\n"),
2714 		      *args, err->message);
2715           g_error_free(err);
2716           err = NULL;
2717         }
2718 
2719       ++args;
2720     }
2721 
2722   err = NULL;
2723   gconf_engine_suggest_sync(conf, NULL); /* ignore errors */
2724 
2725   return 0;
2726 }
2727 
2728 static int
do_recursive_unset(GConfEngine * conf,const gchar ** args)2729 do_recursive_unset (GConfEngine* conf, const gchar** args)
2730 {
2731   if (args == NULL)
2732     {
2733       g_printerr (_("Must specify one or more keys to recursively unset.\n"));
2734       return 1;
2735     }
2736 
2737   while (*args)
2738     {
2739       GError *err;
2740 
2741       err = NULL;
2742       gconf_engine_recursive_unset (conf, *args,
2743                                     GCONF_UNSET_INCLUDING_SCHEMA_NAMES,
2744                                     &err);
2745       if (err != NULL)
2746         {
2747           g_printerr (_("Failure during recursive unset of \"%s\": %s\n"),
2748 		      *args, err->message);
2749           g_error_free (err);
2750         }
2751 
2752       ++args;
2753     }
2754 
2755   gconf_engine_suggest_sync (conf, NULL); /* ignore errors */
2756 
2757   return 0;
2758 }
2759 
2760 static int
do_all_subdirs(GConfEngine * conf,const gchar ** args)2761 do_all_subdirs(GConfEngine* conf, const gchar** args)
2762 {
2763   GError* err = NULL;
2764 
2765   if (args == NULL)
2766     {
2767       g_printerr (_("Must specify one or more directories to get subdirs from.\n"));
2768       return 1;
2769     }
2770 
2771   while (*args)
2772     {
2773       GSList* subdirs;
2774       GSList* tmp;
2775 
2776       err = NULL;
2777 
2778       subdirs = gconf_engine_all_dirs(conf, *args, &err);
2779 
2780       if (subdirs != NULL)
2781         {
2782           tmp = subdirs;
2783 
2784           while (tmp != NULL)
2785             {
2786               gchar* s = tmp->data;
2787 
2788               g_print (" %s\n", s);
2789 
2790               g_free(s);
2791 
2792               tmp = g_slist_next(tmp);
2793             }
2794 
2795           g_slist_free(subdirs);
2796         }
2797       else
2798         {
2799           if (err != NULL)
2800             {
2801               g_printerr (_("Error listing dirs: %s\n"),
2802 			  err->message);
2803               g_error_free(err);
2804               err = NULL;
2805             }
2806         }
2807 
2808       ++args;
2809     }
2810 
2811   return 0;
2812 }
2813 
2814 static void
hash_listify_foreach(gpointer key,gpointer val,gpointer user_data)2815 hash_listify_foreach(gpointer key, gpointer val, gpointer user_data)
2816 {
2817   GSList** values;
2818   GConfSchema* schema;
2819   GConfValue* value;
2820 
2821   values = user_data;
2822   schema = val;
2823 
2824   value = gconf_value_new(GCONF_VALUE_SCHEMA);
2825 
2826   gconf_value_set_schema_nocopy(value, schema);
2827 
2828   *values = g_slist_prepend(*values, value);
2829 }
2830 
2831 static int
get_list_value_from_xml(xmlNodePtr node,GConfValue ** ret_value)2832 get_list_value_from_xml(xmlNodePtr node, GConfValue** ret_value)
2833 {
2834   xmlNodePtr iter;
2835   GConfValue* value = NULL;
2836   GConfValueType list_type;
2837   GSList* list = NULL;
2838   char* list_type_str;
2839 
2840   list_type_str = (char *)xmlGetProp(node, (xmlChar *)"type");
2841   if (!list_type_str)
2842     {
2843       g_printerr ("WARNING: must specify a list type for using <list type=\"type\">\n");
2844       return 1;
2845     }
2846 
2847   list_type = gconf_value_type_from_string(list_type_str);
2848 
2849   xmlFree(list_type_str);
2850 
2851   if (list_type == GCONF_VALUE_INVALID)
2852     {
2853       g_printerr ("WARNING: invalid list type '%s'\n", list_type_str);
2854       return 1;
2855     }
2856 
2857   iter = node->xmlChildrenNode;
2858 
2859   while (iter != NULL)
2860     {
2861       if (strcmp((char *)iter->name, "value") == 0)
2862         {
2863           GConfValue* element = NULL;
2864 
2865           if (get_first_value_from_xml(iter, &element) == 0)
2866             {
2867               if (element->type == list_type)
2868                 list = g_slist_prepend (list, element);
2869               else
2870                 g_printerr ("WARNING: list type and element type do not match: %s != %s\n",
2871 			    gconf_value_type_to_string (list_type),
2872 			    gconf_value_type_to_string (element->type));
2873             }
2874         }
2875 
2876       iter = iter->next;
2877     }
2878 
2879   list = g_slist_reverse(list);
2880 
2881   value = gconf_value_new(GCONF_VALUE_LIST);
2882 
2883   gconf_value_set_list_type(value, list_type);
2884   gconf_value_set_list_nocopy(value, list);
2885 
2886   *ret_value = value;
2887 
2888   return 0;
2889 }
2890 
2891 static inline void
get_car_cdr_value(xmlNodePtr node,GConfValue ** ret_value)2892 get_car_cdr_value(xmlNodePtr node, GConfValue** ret_value)
2893 {
2894   xmlNodePtr iter;
2895 
2896   iter = node->xmlChildrenNode;
2897   while (iter != NULL)
2898     {
2899       if (strcmp((char *)iter->name, "value") == 0)
2900         get_first_value_from_xml(iter, ret_value);
2901 
2902       iter = iter->next;
2903     }
2904 }
2905 
2906 static int
get_pair_value_from_xml(xmlNodePtr node,GConfValue ** ret_value)2907 get_pair_value_from_xml(xmlNodePtr node, GConfValue** ret_value)
2908 {
2909   xmlNodePtr iter;
2910   GConfValue* value = NULL;
2911   GConfValue* cdr = NULL;
2912   GConfValue* car = NULL;
2913   int retval = 0;
2914 
2915   iter = node->xmlChildrenNode;
2916 
2917   while (iter != NULL)
2918     {
2919       if (strcmp((char *)iter->name, "car") == 0)
2920         get_car_cdr_value(iter, &car);
2921 
2922       else if (strcmp((char *)iter->name, "cdr") == 0)
2923         get_car_cdr_value(iter, &cdr);
2924 
2925       iter = iter->next;
2926     }
2927 
2928   if (car && cdr)
2929     {
2930       value = gconf_value_new(GCONF_VALUE_PAIR);
2931 
2932       gconf_value_set_car(value, car);
2933       gconf_value_set_cdr(value, cdr);
2934     }
2935   else
2936     {
2937       g_printerr (_("WARNING: must specify both a <car> and a <cdr> in a <pair>\n"));
2938       retval = 1;
2939     }
2940 
2941   if (car)
2942     gconf_value_free(car);
2943   if (cdr)
2944     gconf_value_free(cdr);
2945 
2946   *ret_value = value;
2947 
2948   return retval;
2949 }
2950 
2951 static int
get_schema_values_from_xml(xmlNodePtr node,GSList ** ret_values)2952 get_schema_values_from_xml(xmlNodePtr node, GSList** ret_values)
2953 {
2954   GHashTable* schemas_hash;
2955   GSList* values = NULL;
2956   GSList* applyto_list;
2957   GSList* tmp;
2958   gchar* schema_key;
2959 
2960   if (get_schema_from_xml(node, &schema_key, &schemas_hash, &applyto_list) == 1)
2961     return 1;
2962 
2963   if (schema_key != NULL)
2964     g_printerr (_("WARNING: key specified (%s) for schema under a <value> - ignoring\n"),
2965             schema_key);
2966 
2967   g_hash_table_foreach(schemas_hash, hash_listify_foreach, &values);
2968 
2969   g_hash_table_destroy(schemas_hash);
2970 
2971   tmp = applyto_list;
2972   while (tmp != NULL)
2973     {
2974       g_free(tmp->data);
2975       tmp = tmp->next;
2976     }
2977   g_slist_free(applyto_list);
2978 
2979   g_free(schema_key);
2980 
2981   *ret_values = values;
2982 
2983   return 0;
2984 }
2985 
2986 static int
get_values_from_xml(xmlNodePtr node,GSList ** ret_values)2987 get_values_from_xml(xmlNodePtr node, GSList** ret_values)
2988 {
2989   xmlNodePtr iter;
2990   GSList* values = NULL;
2991   GConfValue* value = NULL;
2992 
2993   iter = node->xmlChildrenNode;
2994 
2995   if (!iter)
2996     {
2997       g_printerr (_("WARNING: must have a child node under <value>\n"));
2998       return 1;
2999     }
3000 
3001   if (strcmp((char *)node->name, "value") != 0)
3002     {
3003       g_printerr (_("WARNING: node <%s> not understood\n"), node->name);
3004       return 1;
3005     }
3006 
3007   while (iter)
3008     {
3009       GError* error = NULL;
3010       char* content;
3011 
3012       if (strcmp((char *)iter->name, "int") == 0)
3013         {
3014           if ((content = (char *)xmlNodeGetContent(iter)) != NULL)
3015             {
3016               value = gconf_value_new_from_string(GCONF_VALUE_INT, content, &error);
3017               if (value == NULL)
3018                 {
3019                   g_assert(error != NULL);
3020 
3021                   g_printerr (_("WARNING: Failed to parse int value `%s'\n"), content);
3022 
3023                   g_error_free(error);
3024                   error = NULL;
3025                 }
3026               else
3027                 {
3028                   g_assert(error == NULL);
3029                 }
3030               xmlFree(content);
3031             }
3032         }
3033       else if (strcmp((char *)iter->name, "float") == 0)
3034         {
3035           if ((content = (char *)xmlNodeGetContent(iter)) != NULL)
3036             {
3037               value = gconf_value_new_from_string(GCONF_VALUE_FLOAT, content, &error);
3038               if (value == NULL)
3039                 {
3040                   g_assert(error != NULL);
3041 
3042                   g_printerr (_("WARNING: Failed to parse float value `%s'\n"), content);
3043 
3044                   g_error_free(error);
3045                   error = NULL;
3046                 }
3047               else
3048                 {
3049                   g_assert(error == NULL);
3050                 }
3051               xmlFree(content);
3052             }
3053 
3054         }
3055       else if (strcmp((char *)iter->name, "string") == 0)
3056         {
3057           if ((content = (char *)xmlNodeGetContent(iter)) != NULL)
3058             {
3059               value = gconf_value_new_from_string(GCONF_VALUE_STRING, content, &error);
3060               if (value == NULL)
3061                 {
3062                   g_assert(error != NULL);
3063 
3064                   g_printerr (_("WARNING: Failed to parse string value `%s'\n"), content);
3065 
3066                   g_error_free(error);
3067                   error = NULL;
3068                 }
3069               else
3070                 {
3071                   g_assert(error == NULL);
3072                 }
3073               xmlFree(content);
3074             }
3075         }
3076       else if (strcmp((char *)iter->name, "bool") == 0)
3077         {
3078           if ((content = (char *)xmlNodeGetContent(iter)) != NULL)
3079             {
3080               value = gconf_value_new_from_string(GCONF_VALUE_BOOL, content, &error);
3081               if (value == NULL)
3082                 {
3083                   g_assert(error != NULL);
3084 
3085                   g_printerr (_("WARNING: Failed to parse boolean value `%s'\n"), content);
3086 
3087                   g_error_free(error);
3088                   error = NULL;
3089                 }
3090               else
3091                 {
3092                   g_assert(error == NULL);
3093                 }
3094               xmlFree(content);
3095             }
3096         }
3097       else if (strcmp((char *)iter->name, "list") == 0)
3098         get_list_value_from_xml(iter, &value);
3099 
3100       else if (strcmp((char *)iter->name, "pair") == 0)
3101         get_pair_value_from_xml(iter, &value);
3102 
3103       else if (strcmp((char *)iter->name, "schema") == 0)
3104         get_schema_values_from_xml(iter, &values);
3105 
3106       iter = iter->next;
3107     }
3108 
3109   /* common case */
3110   if (value)
3111     {
3112       g_assert (values == NULL);
3113       values = g_slist_prepend(values, value);
3114     }
3115 
3116   *ret_values = values;
3117 
3118   return 0;
3119 }
3120 
3121 /* Confusingly, parsing a <value> can give you multiple
3122  * values in the case of schemas. Use this if you're sure
3123  * there it can't be a schema.
3124  */
3125 static int
get_first_value_from_xml(xmlNodePtr node,GConfValue ** ret_value)3126 get_first_value_from_xml(xmlNodePtr node, GConfValue** ret_value)
3127 {
3128   GConfValue* value = NULL;
3129   GSList* values;
3130   GSList* tmp;
3131 
3132   if (get_values_from_xml(node, &values) == 1)
3133     return 1;
3134 
3135   g_assert (g_slist_length(values) <= 1);
3136 
3137   tmp = values;
3138   while (tmp)
3139     {
3140       if (!value)
3141         value = tmp->data;
3142       else
3143         gconf_value_free(tmp->data);
3144       tmp = tmp->next;
3145     }
3146   g_slist_free(values);
3147 
3148   *ret_value = value;
3149 
3150   return 0;
3151 }
3152 
3153 /*
3154  * Loading entries
3155  */
3156 
3157 typedef struct {
3158   gchar *key;
3159   GConfValueType type;
3160   GConfValueType list_type;
3161   GConfValueType car_type;
3162   GConfValueType cdr_type;
3163   GConfValue* value;
3164 } EntryInfo;
3165 
3166 static void
set_values(GConfEngine * conf,gboolean unload,const gchar * base_dir,const gchar * key,const char * schema_key,GSList * values)3167 set_values(GConfEngine* conf, gboolean unload, const gchar* base_dir, const gchar* key, const char* schema_key, GSList* values)
3168 {
3169   GSList* tmp;
3170   gchar* full_key;
3171 
3172   if (base_dir)
3173     full_key = gconf_concat_dir_and_key(base_dir, key);
3174   else
3175     full_key = g_strdup(key);
3176 
3177   if (unload || schema_key)
3178     {
3179       gchar* full_schema_key = NULL;
3180       GError* error = NULL;
3181 
3182       if (!unload)
3183         {
3184           if (base_dir && *schema_key != '/')
3185             full_schema_key = gconf_concat_dir_and_key(base_dir, schema_key);
3186           else
3187             full_schema_key = g_strdup(schema_key);
3188         }
3189 
3190       if (!gconf_engine_associate_schema(conf, full_key, full_schema_key,  &error))
3191         {
3192           g_assert(error != NULL);
3193 
3194           g_printerr (_("WARNING: failed to associate schema `%s' with key `%s': %s\n"),
3195                       full_schema_key, full_key, error->message);
3196           g_error_free(error);
3197         }
3198 
3199       g_free(full_schema_key);
3200     }
3201 
3202   tmp = values;
3203   while (tmp)
3204     {
3205       GConfValue* value = tmp->data;
3206       GError* error;
3207 
3208       error = NULL;
3209       if (!unload)
3210         gconf_engine_set(conf, full_key, value, &error);
3211       else
3212         gconf_engine_unset(conf, full_key, &error);
3213       if (error != NULL)
3214         {
3215           g_printerr (_("Error setting value: %s\n"), error->message);
3216           g_error_free(error);
3217           error = NULL;
3218         }
3219 
3220       tmp = tmp->next;
3221     }
3222 
3223   g_free(full_key);
3224 }
3225 
3226 static int
process_entry(GConfEngine * conf,gboolean unload,xmlNodePtr node,const gchar ** base_dirs,const char * orig_base)3227 process_entry(GConfEngine* conf, gboolean unload, xmlNodePtr node, const gchar** base_dirs, const char* orig_base)
3228 {
3229   xmlNodePtr iter;
3230   GSList* values = NULL;
3231   GSList* tmp;
3232   char* key = NULL;
3233   char* schema_key = NULL;
3234   int retval = 0;
3235 
3236   iter = node->xmlChildrenNode;
3237   while (iter)
3238     {
3239       if (strcmp((char *)iter->name, "key") == 0)
3240         key = (char *)xmlNodeGetContent(iter);
3241 
3242       else if (strcmp((char *)iter->name, "value") == 0)
3243         get_values_from_xml(iter, &values);
3244 
3245       else if (strcmp((char *)iter->name, "schema_key") == 0)
3246         schema_key = (char *)xmlNodeGetContent(iter);
3247 
3248       iter = iter->next;
3249     }
3250 
3251   if (key && (values || schema_key))
3252     {
3253       if (!base_dirs)
3254         set_values(conf, unload, orig_base, key, schema_key, values);
3255 
3256       else while (*base_dirs)
3257         {
3258           set_values(conf, unload, *base_dirs, key, schema_key, values);
3259           ++base_dirs;
3260         }
3261     }
3262   else
3263     retval = 1;
3264 
3265   tmp = values;
3266   while (tmp)
3267     {
3268       gconf_value_free(tmp->data);
3269       tmp = tmp->next;
3270     }
3271   g_slist_free(values);
3272 
3273   if (key)
3274     xmlFree(key);
3275 
3276   if (schema_key)
3277     xmlFree(schema_key);
3278 
3279   return retval;
3280 }
3281 
3282 /*
3283  * Schema stuff
3284  */
3285 
3286 typedef struct _SchemaInfo SchemaInfo;
3287 
3288 struct _SchemaInfo {
3289   gchar* key;
3290   gchar* owner;
3291   GSList* apply_to;
3292   GConfValueType type;
3293   GConfValueType list_type;
3294   GConfValueType car_type;
3295   GConfValueType cdr_type;
3296   GConfValue* global_default;
3297   GHashTable* hash;
3298 };
3299 
3300 static int
fill_default_from_string(SchemaInfo * info,const gchar * default_value,GConfValue ** retloc)3301 fill_default_from_string(SchemaInfo* info, const gchar* default_value,
3302                          GConfValue** retloc)
3303 {
3304   g_return_val_if_fail(default_value != NULL, 1);
3305 
3306   switch (info->type)
3307     {
3308     case GCONF_VALUE_INVALID:
3309       g_printerr (_("WARNING: invalid or missing type for schema (%s)\n"),
3310 		  info->key);
3311       break;
3312 
3313     case GCONF_VALUE_LIST:
3314       {
3315         GError* error = NULL;
3316         if (info->list_type == GCONF_VALUE_INVALID)
3317 	  {
3318             g_printerr (_("WARNING: invalid or missing list_type for schema (%s)\n"),
3319 			info->key);
3320             break;
3321 	  }
3322         *retloc = gconf_value_new_list_from_string(info->list_type,
3323 						   default_value,
3324 						   &error);
3325         if (*retloc == NULL)
3326           {
3327             g_assert(error != NULL);
3328 
3329             g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key);
3330 
3331             g_error_free(error);
3332             error = NULL;
3333           }
3334         else
3335           {
3336             g_assert(error == NULL);
3337           }
3338       }
3339       break;
3340 
3341     case GCONF_VALUE_PAIR:
3342       {
3343         GError* error = NULL;
3344         if (info->car_type == GCONF_VALUE_INVALID ||
3345 	    info->cdr_type == GCONF_VALUE_INVALID)
3346 	  {
3347             g_printerr (_("WARNING: invalid or missing car_type or cdr_type for schema (%s)\n"),
3348                     info->key);
3349             break;
3350 	  }
3351         *retloc = gconf_value_new_pair_from_string(info->car_type,
3352 						   info->cdr_type,
3353 						   default_value,
3354 						   &error);
3355         if (*retloc == NULL)
3356           {
3357             g_assert(error != NULL);
3358 
3359             g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key);
3360 
3361             g_error_free(error);
3362             error = NULL;
3363           }
3364         else
3365           {
3366             g_assert(error == NULL);
3367           }
3368       }
3369       break;
3370 
3371     case GCONF_VALUE_SCHEMA:
3372       g_printerr (_("WARNING: You cannot set a default value for a schema\n"));
3373       break;
3374 
3375     case GCONF_VALUE_STRING:
3376     case GCONF_VALUE_INT:
3377     case GCONF_VALUE_BOOL:
3378     case GCONF_VALUE_FLOAT:
3379       {
3380         GError* error = NULL;
3381         *retloc = gconf_value_new_from_string(info->type,
3382                                               default_value,
3383                                               &error);
3384         if (*retloc == NULL)
3385           {
3386             g_assert(error != NULL);
3387 
3388             g_printerr (_("WARNING: Failed to parse default value `%s' for schema (%s)\n"), default_value, info->key);
3389 
3390             g_error_free(error);
3391             error = NULL;
3392           }
3393         else
3394           {
3395             g_assert(error == NULL);
3396           }
3397       }
3398       break;
3399 
3400     default:
3401       g_printerr (_("WARNING: gconftool internal error, unknown GConfValueType\n"));
3402       break;
3403     }
3404 
3405   return 0;
3406 }
3407 
3408 static int
extract_global_info(xmlNodePtr node,SchemaInfo * info)3409 extract_global_info(xmlNodePtr node,
3410                     SchemaInfo* info)
3411 {
3412   xmlNodePtr iter;
3413   xmlNodePtr default_value_node = NULL;
3414   char* default_value = NULL;
3415 
3416   iter = node->xmlChildrenNode;
3417 
3418   while (iter != NULL)
3419     {
3420       if (iter->type == XML_ELEMENT_NODE)
3421         {
3422           char* tmp;
3423 
3424           if (strcmp((char *)iter->name, "key") == 0)
3425             {
3426               tmp = (char *)xmlNodeGetContent(iter);
3427               if (tmp)
3428                 {
3429                   info->key = g_strdup(tmp);
3430                   xmlFree(tmp);
3431                 }
3432             }
3433           else if (strcmp((char *)iter->name, "owner") == 0)
3434             {
3435               tmp = (char *)xmlNodeGetContent(iter);
3436               if (tmp)
3437                 {
3438                   info->owner = g_strdup(tmp);
3439                   xmlFree(tmp);
3440                 }
3441             }
3442           else if (strcmp((char *)iter->name, "type") == 0)
3443             {
3444               tmp = (char *)xmlNodeGetContent(iter);
3445               if (tmp)
3446                 {
3447                   info->type = gconf_value_type_from_string(tmp);
3448                   if (info->type == GCONF_VALUE_INVALID)
3449                     g_printerr (_("WARNING: failed to parse type name `%s'\n"),
3450 				tmp);
3451                   xmlFree(tmp);
3452                 }
3453             }
3454           else if (strcmp((char *)iter->name, "list_type") == 0)
3455             {
3456               tmp = (char *)xmlNodeGetContent(iter);
3457               if (tmp)
3458                 {
3459                   info->list_type = gconf_value_type_from_string(tmp);
3460                   if (info->list_type != GCONF_VALUE_INT &&
3461 		      info->list_type != GCONF_VALUE_FLOAT &&
3462 		      info->list_type != GCONF_VALUE_STRING &&
3463 		      info->list_type != GCONF_VALUE_BOOL)
3464 		    {
3465 		      info->list_type = GCONF_VALUE_INVALID;
3466                       g_printerr (_("WARNING: list_type can only be int, float, string or bool and not `%s'\n"),
3467 				  tmp);
3468 		    }
3469                   else if (info->list_type == GCONF_VALUE_INVALID)
3470                     g_printerr (_("WARNING: failed to parse type name `%s'\n"),
3471 				tmp);
3472     		  xmlFree(tmp);
3473                 }
3474             }
3475           else if (strcmp((char *)iter->name, "car_type") == 0)
3476             {
3477               tmp = (char *)xmlNodeGetContent(iter);
3478               if (tmp)
3479                 {
3480                   info->car_type = gconf_value_type_from_string(tmp);
3481                   if (info->car_type != GCONF_VALUE_INT &&
3482 		      info->car_type != GCONF_VALUE_FLOAT &&
3483 		      info->car_type != GCONF_VALUE_STRING &&
3484 		      info->car_type != GCONF_VALUE_BOOL)
3485 		    {
3486 		      info->car_type = GCONF_VALUE_INVALID;
3487                       g_printerr (_("WARNING: car_type can only be int, float, string or bool and not `%s'\n"),
3488 				  tmp);
3489 		    }
3490                   else if (info->car_type == GCONF_VALUE_INVALID)
3491                     g_printerr (_("WARNING: failed to parse type name `%s'\n"),
3492 				tmp);
3493                   xmlFree(tmp);
3494                 }
3495             }
3496           else if (strcmp((char *)iter->name, "cdr_type") == 0)
3497             {
3498               tmp = (char *)xmlNodeGetContent(iter);
3499               if (tmp)
3500                 {
3501                   info->cdr_type = gconf_value_type_from_string(tmp);
3502                   if (info->cdr_type != GCONF_VALUE_INT &&
3503 		      info->cdr_type != GCONF_VALUE_FLOAT &&
3504 		      info->cdr_type != GCONF_VALUE_STRING &&
3505 		      info->cdr_type != GCONF_VALUE_BOOL)
3506 		    {
3507 		      info->cdr_type = GCONF_VALUE_INVALID;
3508                       g_printerr (_("WARNING: cdr_type can only be int, float, string or bool and not `%s'\n"),
3509 				  tmp);
3510 		    }
3511                   else if (info->cdr_type == GCONF_VALUE_INVALID)
3512                     g_printerr (_("WARNING: failed to parse type name `%s'\n"),
3513 				tmp);
3514                   xmlFree(tmp);
3515                 }
3516             }
3517           else if (strcmp((char *)iter->name, "default") == 0)
3518             {
3519               default_value = (char *)xmlNodeGetContent(iter);
3520             }
3521           else if (strcmp((char *)iter->name, "default_value") == 0)
3522             {
3523               xmlNodePtr tmp_node = iter->xmlChildrenNode;
3524 
3525               while (tmp_node)
3526                 {
3527                   if (strcmp((char *)tmp_node->name, "value") == 0)
3528                     default_value_node = tmp_node;
3529 
3530                   tmp_node = tmp_node->next;
3531                 }
3532             }
3533           else if (strcmp((char *)iter->name, "locale") == 0)
3534             {
3535               ; /* ignore, this is parsed later after we have the global info */
3536             }
3537           else if (strcmp((char *)iter->name, "applyto") == 0)
3538             {
3539               /* Add the contents to the list of nodes to apply to */
3540               tmp = (char *)xmlNodeGetContent(iter);
3541 
3542               if (tmp)
3543                 {
3544                   info->apply_to = g_slist_prepend(info->apply_to, g_strdup(tmp));
3545                   xmlFree(tmp);
3546                 }
3547               else
3548                 g_printerr (_("WARNING: empty <applyto> node"));
3549             }
3550           else
3551             g_printerr (_("WARNING: node <%s> not understood below <schema>\n"),
3552 			iter->name);
3553 
3554         }
3555 
3556       iter = iter->next;
3557     }
3558 
3559   if (info->type == GCONF_VALUE_LIST &&
3560       info->list_type == GCONF_VALUE_INVALID)
3561     {
3562       g_printerr (_("WARNING: no <list_type> specified for schema of type list\n"));
3563     }
3564 
3565   if (info->type == GCONF_VALUE_PAIR &&
3566       info->car_type == GCONF_VALUE_INVALID)
3567     {
3568       g_printerr (_("WARNING: no <car_type> specified for schema of type pair\n"));
3569     }
3570 
3571   if (info->type == GCONF_VALUE_PAIR &&
3572       info->cdr_type == GCONF_VALUE_INVALID)
3573     {
3574       g_printerr (_("WARNING: no <cdr_type> specified for schema of type pair\n"));
3575     }
3576 
3577   if (default_value_node != NULL)
3578     get_first_value_from_xml (default_value_node, &info->global_default);
3579 
3580   else if (default_value != NULL)
3581     /* Have to do this last, because the type may come after the default
3582      * value
3583      */
3584     fill_default_from_string(info, default_value, &info->global_default);
3585 
3586   if (default_value)
3587     xmlFree(default_value);
3588 
3589   return 0;
3590 }
3591 
3592 static int
process_locale_info(xmlNodePtr node,SchemaInfo * info)3593 process_locale_info(xmlNodePtr node, SchemaInfo* info)
3594 {
3595   char* name;
3596   GConfSchema* schema;
3597   xmlNodePtr iter;
3598 
3599   name = (char *)xmlGetProp(node, (xmlChar *)"name");
3600 
3601   if (name == NULL)
3602     {
3603       g_printerr (_("WARNING: <locale> node has no `name=\"locale\"' attribute, ignoring\n"));
3604       return 1;
3605     }
3606 
3607   if (g_hash_table_lookup(info->hash, name) != NULL)
3608     {
3609       g_printerr (_("WARNING: multiple <locale> nodes for locale `%s', ignoring all past first\n"),
3610               name);
3611       xmlFree(name);
3612       return 1;
3613     }
3614 
3615   schema = gconf_schema_new();
3616 
3617   gconf_schema_set_locale(schema, name);
3618 
3619   /* Only set the global default on the C locale */
3620   if (strcmp(name, "C") == 0 && info->global_default != NULL)
3621     gconf_schema_set_default_value(schema, info->global_default);
3622 
3623   /* Fill in the global info */
3624   if (info->type != GCONF_VALUE_INVALID)
3625     gconf_schema_set_type(schema, info->type);
3626 
3627   if (info->list_type != GCONF_VALUE_INVALID)
3628     gconf_schema_set_list_type(schema, info->list_type);
3629 
3630   if (info->car_type != GCONF_VALUE_INVALID)
3631     gconf_schema_set_car_type(schema, info->car_type);
3632 
3633   if (info->cdr_type != GCONF_VALUE_INVALID)
3634     gconf_schema_set_cdr_type(schema, info->cdr_type);
3635 
3636   if (info->owner != NULL)
3637     gconf_schema_set_owner(schema, info->owner);
3638 
3639   xmlFree(name);
3640 
3641   /* Locale-specific info */
3642   iter = node->xmlChildrenNode;
3643 
3644   while (iter != NULL)
3645     {
3646       if (iter->type == XML_ELEMENT_NODE)
3647         {
3648           if (strcmp((char *)iter->name, "default_value") == 0)
3649             {
3650               GConfValue* val = NULL;
3651               xmlNodePtr tmp_node;
3652 
3653               tmp_node = iter->xmlChildrenNode;
3654               while (tmp_node)
3655                 {
3656                   if (strcmp((char *)tmp_node->name, "value") == 0)
3657                     {
3658                       get_first_value_from_xml(tmp_node, &val);
3659                       if (val)
3660                         gconf_schema_set_default_value_nocopy(schema, val);
3661                       break;
3662                     }
3663                   tmp_node = tmp_node->next;
3664                 }
3665             }
3666           else if (strcmp((char *)iter->name, "default") == 0)
3667             {
3668               GConfValue* val = NULL;
3669               char* tmp;
3670 
3671               tmp = (char *)xmlNodeGetContent(iter);
3672               if (tmp != NULL)
3673                 {
3674                   fill_default_from_string(info, tmp, &val);
3675                   if (val)
3676                     gconf_schema_set_default_value_nocopy(schema, val);
3677 
3678                   xmlFree(tmp);
3679                 }
3680             }
3681           else if (strcmp((char *)iter->name, "short") == 0)
3682             {
3683               char* tmp;
3684 
3685               tmp = (char *)xmlNodeGetContent(iter);
3686 
3687               if (tmp != NULL)
3688                 {
3689                   gconf_schema_set_short_desc(schema, tmp);
3690                   xmlFree(tmp);
3691                 }
3692             }
3693           else if (strcmp((char *)iter->name, "long") == 0)
3694             {
3695               char* tmp;
3696 
3697               tmp = (char *)xmlNodeGetContent(iter);
3698 
3699               if (tmp != NULL)
3700                 {
3701                   gconf_schema_set_long_desc(schema, tmp);
3702                   xmlFree(tmp);
3703                 }
3704             }
3705           else
3706             {
3707               g_printerr (_("WARNING: Invalid node <%s> in a <locale> node\n"),
3708 			  iter->name);
3709             }
3710         }
3711 
3712       iter = iter->next;
3713     }
3714 
3715   g_hash_table_insert(info->hash,
3716                       (gchar*)gconf_schema_get_locale(schema), /* cheat to save copying this string */
3717                       schema);
3718 
3719   return 0;
3720 }
3721 
3722 static int
process_key_list(GConfEngine * conf,gboolean unload,const gchar * schema_name,GSList * keylist)3723 process_key_list(GConfEngine* conf, gboolean unload, const gchar* schema_name, GSList* keylist)
3724 {
3725   GSList* tmp;
3726 
3727   tmp = keylist;
3728   while (tmp != NULL)
3729     {
3730       GError* error = NULL;
3731 
3732       if (!gconf_engine_associate_schema(conf, tmp->data, !unload ? schema_name : NULL, &error))
3733         {
3734           g_assert(error != NULL);
3735 
3736           g_printerr (_("WARNING: failed to associate schema `%s' with key `%s': %s\n"),
3737 		      schema_name, (gchar*)tmp->data, error->message);
3738           g_error_free(error);
3739           error = NULL;
3740         }
3741       else
3742         {
3743           g_assert(error == NULL);
3744           g_print (_("Attached schema `%s' to key `%s'\n"),
3745 		   schema_name, (gchar*)tmp->data);
3746         }
3747 
3748       tmp = g_slist_next(tmp);
3749     }
3750 
3751   return 0;
3752 }
3753 
3754 static int
get_schema_from_xml(xmlNodePtr node,gchar ** schema_key,GHashTable ** schemas_hash,GSList ** applyto_list)3755 get_schema_from_xml(xmlNodePtr node, gchar **schema_key, GHashTable** schemas_hash, GSList **applyto_list)
3756 {
3757   xmlNodePtr iter;
3758   SchemaInfo info;
3759 
3760   info.key = NULL;
3761   info.type = GCONF_VALUE_INVALID;
3762   info.list_type = GCONF_VALUE_INVALID;
3763   info.car_type = GCONF_VALUE_INVALID;
3764   info.cdr_type = GCONF_VALUE_INVALID;
3765   info.apply_to = NULL;
3766   info.owner = NULL;
3767   info.global_default = NULL;
3768   info.hash = g_hash_table_new(g_str_hash, g_str_equal);
3769 
3770   extract_global_info(node, &info);
3771 
3772   if (info.type == GCONF_VALUE_INVALID)
3773     {
3774       g_free(info.owner);
3775 
3776       if (info.global_default)
3777         gconf_value_free(info.global_default);
3778 
3779       return 1;
3780     }
3781 
3782   iter = node->xmlChildrenNode;
3783 
3784   while (iter != NULL)
3785     {
3786       if (iter->type == XML_ELEMENT_NODE)
3787         {
3788           if (strcmp((char *)iter->name, "key") == 0)
3789             ; /* nothing */
3790           else if (strcmp((char *)iter->name, "owner") == 0)
3791             ;  /* nothing */
3792           else if (strcmp((char *)iter->name, "type") == 0)
3793             ;  /* nothing */
3794           else if (strcmp((char *)iter->name, "list_type") == 0)
3795             ;  /* nothing */
3796           else if (strcmp((char *)iter->name, "car_type") == 0)
3797             ;  /* nothing */
3798           else if (strcmp((char *)iter->name, "cdr_type") == 0)
3799             ;  /* nothing */
3800           else if (strcmp((char *)iter->name, "default") == 0)
3801             ;  /* nothing */
3802           else if (strcmp((char *)iter->name, "applyto") == 0)
3803             ;  /* nothing */
3804           else if (strcmp((char *)iter->name, "locale") == 0)
3805             {
3806               process_locale_info(iter, &info);
3807             }
3808           else
3809             g_printerr (_("WARNING: node <%s> not understood below <schema>\n"),
3810 			iter->name);
3811         }
3812 
3813       iter = iter->next;
3814     }
3815 
3816   if (g_hash_table_size(info.hash) == 0)
3817     {
3818       g_printerr (_("You must have at least one <locale> entry in a <schema>\n"));
3819       return 1;
3820     }
3821 
3822   *schema_key = info.key;
3823   *schemas_hash = info.hash;
3824   *applyto_list = info.apply_to;
3825 
3826   g_free(info.owner);
3827   if (info.global_default)
3828     gconf_value_free(info.global_default);
3829 
3830   return 0;
3831 }
3832 
3833 static void
hash_install_foreach(gpointer key,gpointer value,gpointer user_data)3834 hash_install_foreach(gpointer key, gpointer value, gpointer user_data)
3835 {
3836   struct {
3837     GConfEngine* conf;
3838     gboolean unload;
3839     char* key;
3840   } *info;
3841   GConfSchema* schema;
3842   GError* error = NULL;
3843 
3844   info = user_data;
3845   schema = value;
3846 
3847   if (!info->unload)
3848     {
3849       if (!gconf_engine_set_schema(info->conf, info->key, schema, &error))
3850 	{
3851 	  g_assert(error != NULL);
3852 
3853 	  g_printerr (_("WARNING: failed to install schema `%s', locale `%s': %s\n"),
3854 		      info->key, gconf_schema_get_locale(schema), error->message);
3855 	  g_error_free(error);
3856 	  error = NULL;
3857 	}
3858       else
3859 	{
3860 	  g_assert(error == NULL);
3861 	  g_print (_("Installed schema `%s' for locale `%s'\n"),
3862 		   info->key, gconf_schema_get_locale(schema));
3863 	}
3864     }
3865   else
3866     {
3867       if (!gconf_engine_unset (info->conf, info->key, &error))
3868 	{
3869 	  g_assert(error != NULL);
3870 
3871 	  g_printerr (_("WARNING: failed to uninstall schema `%s', locale `%s': %s\n"),
3872 		      info->key, gconf_schema_get_locale(schema), error->message);
3873 	  g_error_free(error);
3874 	  error = NULL;
3875 	}
3876       else
3877 	{
3878 	  g_assert(error == NULL);
3879 	  g_print (_("Uninstalled schema `%s' from locale `%s'\n"),
3880 		   info->key, gconf_schema_get_locale(schema));
3881 	}
3882     }
3883 
3884   gconf_schema_free(schema);
3885 }
3886 
3887 static int
process_schema(GConfEngine * conf,gboolean unload,xmlNodePtr node)3888 process_schema(GConfEngine* conf, gboolean unload, xmlNodePtr node)
3889 {
3890   struct {
3891     GConfEngine* conf;
3892     gboolean unload;
3893     char* key;
3894   } hash_foreach_info;
3895   GHashTable* schemas_hash = NULL;
3896   GSList* applyto_list = NULL;
3897   GSList* tmp;
3898   gchar* schema_key = NULL;
3899   int retval = 0;
3900 
3901   if (get_schema_from_xml(node, &schema_key, &schemas_hash, &applyto_list) == 1)
3902     return 1;
3903 
3904   g_assert(schemas_hash != NULL);
3905 
3906   if (schema_key != NULL)
3907     {
3908       process_key_list(conf, unload, schema_key, applyto_list);
3909 
3910       hash_foreach_info.conf = conf;
3911       hash_foreach_info.unload = unload;
3912       hash_foreach_info.key = schema_key;
3913       g_hash_table_foreach(schemas_hash, hash_install_foreach, &hash_foreach_info);
3914     }
3915   else
3916     {
3917       g_printerr (_("WARNING: no key specified for schema\n"));
3918       retval = 1;
3919     }
3920 
3921   g_hash_table_destroy(schemas_hash);
3922 
3923   tmp = applyto_list;
3924   while (tmp != NULL)
3925     {
3926       g_free(tmp->data);
3927       tmp = tmp->next;
3928     }
3929   g_slist_free(applyto_list);
3930 
3931   g_free(schema_key);
3932 
3933   return retval;
3934 }
3935 
3936 static int
process_list(GConfEngine * conf,LoadType load_type,gboolean unload,xmlNodePtr node,const gchar ** base_dirs)3937 process_list(GConfEngine* conf, LoadType load_type, gboolean unload, xmlNodePtr node, const gchar** base_dirs)
3938 {
3939 #define LOAD_TYPE_TO_LIST(t) ((t == LOAD_SCHEMA_FILE) ? "schemalist" : "entrylist")
3940 
3941   xmlNodePtr iter;
3942   char* orig_base = NULL;
3943 
3944   iter = node->xmlChildrenNode;
3945 
3946   if (load_type == LOAD_ENTRY_FILE)
3947     orig_base = (char *)xmlGetProp(node, (xmlChar *)"base");
3948 
3949   while (iter != NULL)
3950     {
3951       if (iter->type == XML_ELEMENT_NODE)
3952         {
3953           if (load_type == LOAD_SCHEMA_FILE && strcmp((char *)iter->name, "schema") == 0)
3954             process_schema(conf, unload, iter);
3955           else if (load_type == LOAD_ENTRY_FILE && strcmp((char *)iter->name, "entry") == 0)
3956             process_entry(conf, unload, iter, base_dirs, orig_base);
3957           else
3958             g_printerr (_("WARNING: node <%s> not understood below <%s>\n"),
3959 			iter->name, LOAD_TYPE_TO_LIST(load_type));
3960         }
3961 
3962       iter = iter->next;
3963     }
3964 
3965   if (orig_base)
3966     xmlFree(orig_base);
3967 
3968   return 0;
3969 
3970 #undef LOAD_TYPE_TO_LIST
3971 }
3972 
3973 static int
do_load_file(GConfEngine * conf,LoadType load_type,gboolean unload,const gchar * file,const gchar ** base_dirs)3974 do_load_file(GConfEngine* conf, LoadType load_type, gboolean unload, const gchar* file, const gchar** base_dirs)
3975 {
3976 #define LOAD_TYPE_TO_ROOT(t) ((t == LOAD_SCHEMA_FILE) ? "gconfschemafile" : "gconfentryfile")
3977 #define LOAD_TYPE_TO_LIST(t) ((t == LOAD_SCHEMA_FILE) ? "schemalist" : "entrylist")
3978 
3979   xmlDocPtr doc;
3980   xmlNodePtr iter;
3981   /* file comes from the command line, is thus in locale charset */
3982   gchar *utf8_file = g_locale_to_utf8 (file, -1, NULL, NULL, NULL);;
3983 
3984   errno = 0;
3985   doc = xmlParseFile(file);
3986 
3987   if (doc == NULL)
3988     {
3989       if (errno != 0)
3990         g_printerr (_("Failed to open `%s': %s\n"),
3991 		    utf8_file, g_strerror(errno));
3992       return 1;
3993     }
3994 
3995   if (doc->xmlRootNode == NULL)
3996     {
3997       g_printerr (_("Document `%s' is empty?\n"),
3998 		  utf8_file);
3999       return 1;
4000     }
4001 
4002   iter = doc->xmlRootNode;
4003   while (iter != NULL)
4004     {
4005       if (iter->type == XML_ELEMENT_NODE)
4006         {
4007           if (strcmp((char *)iter->name, LOAD_TYPE_TO_ROOT(load_type)) != 0)
4008             {
4009               g_printerr (_("Document `%s' has the wrong type of root node (<%s>, should be <%s>)\n"),
4010 			  utf8_file, iter->name, LOAD_TYPE_TO_ROOT(load_type));
4011               return 1;
4012             }
4013           else
4014             break;
4015         }
4016 
4017       iter = iter->next;
4018     }
4019 
4020   if (iter == NULL)
4021     {
4022       g_printerr (_("Document `%s' has no top level <%s> node\n"),
4023 		  utf8_file, LOAD_TYPE_TO_ROOT(load_type));
4024       return 1;
4025     }
4026 
4027   iter = iter->xmlChildrenNode;
4028 
4029   while (iter != NULL)
4030     {
4031       if (iter->type == XML_ELEMENT_NODE)
4032         {
4033           if (strcmp((char *)iter->name, LOAD_TYPE_TO_LIST(load_type)) == 0)
4034             process_list(conf, load_type, unload, iter, base_dirs);
4035           else
4036             g_printerr (_("WARNING: node <%s> below <%s> not understood\n"),
4037 			iter->name, LOAD_TYPE_TO_ROOT(load_type));
4038         }
4039 
4040       iter = iter->next;
4041     }
4042 
4043   return 0;
4044 #undef LOAD_TYPE_TO_LIST
4045 #undef LOAD_TYPE_TO_ROOT
4046 }
4047 
4048 static int
do_sync(GConfEngine * conf)4049 do_sync(GConfEngine* conf)
4050 {
4051   GError *err = NULL;
4052 
4053   gconf_engine_suggest_sync(conf, &err);
4054 
4055   if (err != NULL)
4056     {
4057       g_printerr (_("Error syncing configuration data: %s"),
4058 		  err->message);
4059       g_error_free(err);
4060       return 1;
4061     }
4062 
4063   return 0;
4064 }
4065 
4066 static int
do_makefile_install(GConfEngine * conf,const gchar ** args,gboolean unload)4067 do_makefile_install(GConfEngine* conf, const gchar** args, gboolean unload)
4068 {
4069   int retval = 0;
4070 
4071   if (args == NULL)
4072     {
4073       g_printerr (_("Must specify some schema files to install\n"));
4074       return 1;
4075     }
4076 
4077   while (*args)
4078     {
4079       if (do_load_file(conf, LOAD_SCHEMA_FILE, unload, *args, NULL) != 0)
4080         retval |= 1;
4081 
4082       ++args;
4083     }
4084 
4085   retval |= do_sync (conf);
4086   return retval;
4087 }
4088 
4089 typedef enum {
4090   BreakageSetBadValues,
4091   BreakageCleanup
4092 } BreakagePhase;
4093 
4094 static gboolean
check_err(GError ** err)4095 check_err(GError** err)
4096 {
4097   g_print (".");
4098 
4099   if (*err != NULL)
4100     {
4101       g_printerr (_("\n%s\n"),
4102 		  (*err)->message);
4103       g_error_free(*err);
4104       *err = NULL;
4105       return TRUE;
4106     }
4107   else
4108     return FALSE;
4109 }
4110 
4111 static gboolean
key_breakage(GConfEngine * conf,const gchar * key,BreakagePhase phase)4112 key_breakage(GConfEngine* conf, const gchar* key, BreakagePhase phase)
4113 {
4114   GError* error = NULL;
4115 
4116   if (phase == BreakageCleanup)
4117     {
4118       gconf_engine_unset(conf, key, &error);
4119       if (error != NULL)
4120         {
4121           g_printerr (_("Failed to unset breakage key %s: %s\n"),
4122 		      key, error->message);
4123           g_error_free(error);
4124           return FALSE;
4125         }
4126     }
4127   else if (phase == BreakageSetBadValues)
4128     {
4129       gint an_int = 43;
4130       gboolean a_bool = TRUE;
4131       gdouble a_float = 43695.435;
4132       const gchar* a_string = "Hello";
4133       GConfValue* val;
4134       GSList* list = NULL;
4135 
4136       g_print ("  +");
4137 
4138       gconf_engine_set_string(conf, key, "", &error);
4139       if (check_err(&error))
4140         return FALSE;
4141 
4142       gconf_engine_set_string(conf, key, "blah blah blah 93475028934670 @%^%$&%$&^%", &error);
4143       if (check_err(&error))
4144         return FALSE;
4145 
4146       gconf_engine_set_bool(conf, key, TRUE, &error);
4147       if (check_err(&error))
4148         return FALSE;
4149 
4150       gconf_engine_set_bool(conf, key, FALSE, &error);
4151       if (check_err(&error))
4152         return FALSE;
4153 
4154       gconf_engine_set_float(conf, key, 100.0, &error);
4155       if (check_err(&error))
4156         return FALSE;
4157 
4158       gconf_engine_set_float(conf, key, -100.0, &error);
4159       if (check_err(&error))
4160         return FALSE;
4161 
4162       gconf_engine_set_float(conf, key, 0.0, &error);
4163       if (check_err(&error))
4164         return FALSE;
4165 
4166       gconf_engine_set_int(conf, key, 0, &error);
4167       if (check_err(&error))
4168         return FALSE;
4169 
4170       gconf_engine_set_int(conf, key, 5384750, &error);
4171       if (check_err(&error))
4172         return FALSE;
4173 
4174       gconf_engine_set_int(conf, key, -11, &error);
4175       if (check_err(&error))
4176         return FALSE;
4177 
4178       gconf_engine_set_list(conf, key, GCONF_VALUE_BOOL, list, &error);
4179       if (check_err(&error))
4180         return FALSE;
4181 
4182       gconf_engine_set_pair(conf, key, GCONF_VALUE_INT, GCONF_VALUE_BOOL,
4183                             &an_int, &a_bool, &error);
4184       if (check_err(&error))
4185         return FALSE;
4186 
4187       gconf_engine_set_pair(conf, key, GCONF_VALUE_FLOAT, GCONF_VALUE_STRING,
4188                             &a_float, &a_string, &error);
4189       if (check_err(&error))
4190         return FALSE;
4191 
4192       /* empty pair */
4193       val = gconf_value_new(GCONF_VALUE_PAIR);
4194       gconf_engine_set (conf, key, val, &error);
4195       gconf_value_free(val);
4196       if (check_err(&error))
4197         return FALSE;
4198 
4199       list = NULL;
4200       gconf_engine_set_list(conf, key, GCONF_VALUE_STRING, list, &error);
4201       if (check_err(&error))
4202         return FALSE;
4203       gconf_engine_set_list(conf, key, GCONF_VALUE_INT, list, &error);
4204       if (check_err(&error))
4205         return FALSE;
4206       gconf_engine_set_list(conf, key, GCONF_VALUE_BOOL, list, &error);
4207       if (check_err(&error))
4208         return FALSE;
4209 
4210       list = g_slist_prepend(list, GINT_TO_POINTER(10));
4211       list = g_slist_prepend(list, GINT_TO_POINTER(14));
4212       list = g_slist_prepend(list, GINT_TO_POINTER(-93));
4213       list = g_slist_prepend(list, GINT_TO_POINTER(1000000));
4214       list = g_slist_prepend(list, GINT_TO_POINTER(32));
4215       gconf_engine_set_list(conf, key, GCONF_VALUE_INT, list, &error);
4216       if (check_err(&error))
4217         return FALSE;
4218 
4219       g_slist_free(list);
4220       list = NULL;
4221 
4222       list = g_slist_prepend(list, "");
4223       list = g_slist_prepend(list, "blah");
4224       list = g_slist_prepend(list, "");
4225       list = g_slist_prepend(list, "\n\t\r\n     \n");
4226       list = g_slist_prepend(list, "woo fooo s^%*^%&@^$@%&@%$");
4227       gconf_engine_set_list(conf, key, GCONF_VALUE_STRING, list, &error);
4228       if (check_err(&error))
4229         return FALSE;
4230 
4231       g_slist_free(list);
4232       list = NULL;
4233 
4234       g_print ("\n");
4235     }
4236   else
4237     g_assert_not_reached();
4238 
4239   return TRUE;
4240 }
4241 
4242 static int
do_break_key(GConfEngine * conf,const gchar ** args)4243 do_break_key(GConfEngine* conf, const gchar** args)
4244 {
4245   if (args == NULL)
4246     {
4247       g_printerr (_("Must specify some keys to break\n"));
4248       return 1;
4249     }
4250 
4251   while (*args)
4252     {
4253       g_print (_("Trying to break your application by setting bad values for key:\n  %s\n"), *args);
4254 
4255       if (!key_breakage(conf, *args, BreakageSetBadValues))
4256         return 1;
4257       if (!key_breakage(conf, *args, BreakageCleanup))
4258         return 1;
4259 
4260       ++args;
4261     }
4262 
4263   return 0;
4264 }
4265 
4266 static int
do_break_directory(GConfEngine * conf,const gchar ** args)4267 do_break_directory(GConfEngine* conf, const gchar** args)
4268 {
4269   if (args == NULL)
4270     {
4271       g_printerr (_("Must specify some directories to break\n"));
4272       return 1;
4273     }
4274 
4275   while (*args)
4276     {
4277       gchar* keys[10] = { NULL };
4278       gchar* full_keys[10] = { NULL };
4279       int i;
4280 
4281       i = 0;
4282       while (i < 10)
4283         {
4284           keys[i] = gconf_unique_key();
4285           full_keys[i] = gconf_concat_dir_and_key(*args, keys[i]);
4286 
4287           ++i;
4288         }
4289 
4290       g_print (_("Trying to break your application by setting bad values for keys in directory:\n  %s\n"), *args);
4291 
4292       i = 0;
4293       while (i < 10)
4294         {
4295           if (!key_breakage(conf, full_keys[i], BreakageSetBadValues))
4296             return 1;
4297 
4298           ++i;
4299         }
4300 
4301       i = 0;
4302       while (i < 10)
4303         {
4304           if (!key_breakage(conf, full_keys[i], BreakageCleanup))
4305             return 1;
4306 
4307           ++i;
4308         }
4309 
4310       i = 0;
4311       while (i < 10)
4312         {
4313           g_free(keys[i]);
4314           g_free(full_keys[i]);
4315 
4316           ++i;
4317         }
4318 
4319       ++args;
4320     }
4321 
4322   return 0;
4323 }
4324 
4325 static int
do_get_default_source(const gchar ** args)4326 do_get_default_source (const gchar** args)
4327 {
4328   gchar *filename;
4329   gchar *source;
4330   gchar buf[512];
4331   FILE *f;
4332 
4333   /* Try with $sysgconfdir/schema-install-source */
4334   filename = g_build_filename (GCONF_ETCDIR, "schema-install-source", NULL);
4335   f = g_fopen(filename, "r");
4336   g_free (filename);
4337 
4338   if (f != NULL)
4339     {
4340       source = fgets(buf, 512, f);
4341       fclose(f);
4342       if (source)
4343 	{
4344 	  g_strchomp(source);
4345 	  if (*source != '\0')
4346 	    {
4347 	      g_print ("%s\n", source);
4348 	      return 0;
4349 	    }
4350 	}
4351     }
4352 
4353   /* Use default database */
4354   source = g_strconcat("xml:merged:", GCONF_ETCDIR, "/gconf.xml.defaults", NULL);
4355   g_print ("%s\n", source);
4356   g_free(source);
4357 
4358   return 0;
4359 }
4360