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