Fix gsettings tool crash, part 2
[platform/upstream/glib.git] / gio / gsettings-tool.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 2010 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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Matthias Clasen
20  */
21
22 #include "config.h"
23
24 #include <locale.h>
25 #include <gi18n.h>
26 #include <gio.h>
27
28 static gint
29 usage (gint      *argc,
30        gchar    **argv[],
31        gboolean   use_stdout)
32 {
33   GOptionContext *context;
34   gchar *s;
35
36   g_set_prgname (g_path_get_basename ((*argv)[0]));
37
38   context = g_option_context_new (_("COMMAND"));
39   g_option_context_set_help_enabled (context, FALSE);
40   s = g_strdup_printf (
41     _("Commands:\n"
42       "  help        Show this information\n"
43       "  get         Get the value of a key\n"
44       "  set         Set the value of a key\n"
45       "  monitor     Monitor a key for changes\n"
46       "  writable    Check if a key is writable\n"
47       "\n"
48       "Use '%s COMMAND --help' to get help for individual commands.\n"),
49       g_get_prgname ());
50   g_option_context_set_description (context, s);
51   g_free (s);
52   s = g_option_context_get_help (context, FALSE, NULL);
53   if (use_stdout)
54     g_print ("%s", s);
55   else
56     g_printerr ("%s", s);
57   g_free (s);
58   g_option_context_free (context);
59
60   return use_stdout ? 0 : 1;
61 }
62
63 static void
64 remove_arg (gint num, gint *argc, gchar **argv[])
65 {
66   gint n;
67
68   g_assert (num <= (*argc));
69
70   for (n = num; (*argv)[n] != NULL; n++)
71     (*argv)[n] = (*argv)[n+1];
72   (*argv)[n] = NULL;
73   (*argc) = (*argc) - 1;
74 }
75
76 static void
77 modify_argv0_for_command (gint         *argc,
78                           gchar       **argv[],
79                           const gchar  *command)
80 {
81   gchar *s;
82
83   g_assert (g_strcmp0 ((*argv)[1], command) == 0);
84   remove_arg (1, argc, argv);
85
86   s = g_strdup_printf ("%s %s", (*argv)[0], command);
87   (*argv)[0] = s;
88 }
89
90
91 static gint
92 handle_get (gint   *argc,
93             gchar **argv[])
94 {
95   gchar *schema;
96   gchar *path;
97   gchar *key;
98   GSettings *settings;
99   GVariant *v;
100   GOptionContext *context;
101   GOptionEntry entries[] = {
102     { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") },
103     { NULL }
104   };
105   GError *error;
106   gint ret = 1;
107
108   modify_argv0_for_command (argc, argv, "get");
109
110   context = g_option_context_new (_("SCHEMA KEY"));
111   g_option_context_set_help_enabled (context, FALSE);
112   g_option_context_set_summary (context, _("Get the value of KEY"));
113   g_option_context_set_description (context,
114     _("Arguments:\n"
115       "  SCHEMA      The id of the schema\n"
116       "  KEY         The name of the key\n"));
117   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
118
119   path = NULL;
120
121   error = NULL;
122   if (!g_option_context_parse (context, argc, argv, NULL) || *argc != 3)
123     {
124       gchar *s;
125       s = g_option_context_get_help (context, FALSE, NULL);
126       g_printerr ("%s", s);
127       g_free (s);
128
129       goto out;
130     }
131
132   schema = (*argv)[1];
133   key = (*argv)[2];
134
135   if (path)
136     settings = g_settings_new_with_path (schema, path);
137   else
138     settings = g_settings_new (schema);
139
140   v = g_settings_get_value (settings, key);
141   g_print ("%s\n", g_variant_print (v, FALSE));
142   g_variant_unref (v);
143   ret = 0;
144
145  out:
146   g_option_context_free (context);
147
148   return ret;
149 }
150
151 static gint
152 handle_set (gint   *argc,
153             gchar **argv[])
154 {
155   gchar *schema;
156   gchar *path;
157   gchar *key;
158   gchar *value;
159   GSettings *settings;
160   GVariant *v;
161   const GVariantType *type;
162   GOptionContext *context;
163   GOptionEntry entries[] = {
164     { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") },
165     { NULL }
166   };
167   GError *error;
168   gint ret = 1;
169
170   modify_argv0_for_command (argc, argv, "set");
171
172   context = g_option_context_new (_("SCHEMA KEY VALUE"));
173   g_option_context_set_help_enabled (context, FALSE);
174   g_option_context_set_summary (context, _("Set the value of KEY"));
175   g_option_context_set_description (context,
176     _("Arguments:\n"
177       "  SCHEMA      The id of the schema\n"
178       "  KEY         The name of the key\n"
179       "  VALUE       The value to set key to, as a serialized GVariant\n"));
180   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
181
182   path = NULL;
183
184   error = NULL;
185   if (!g_option_context_parse (context, argc, argv, NULL) || *argc != 4)
186     {
187       gchar *s;
188       s = g_option_context_get_help (context, FALSE, NULL);
189       g_printerr ("%s", s);
190       g_free (s);
191
192       goto out;
193     }
194
195   schema = (*argv)[1];
196   key = (*argv)[2];
197   value = (*argv)[3];
198
199   if (path)
200     settings = g_settings_new_with_path (schema, path);
201   else
202     settings = g_settings_new (schema);
203
204   v = g_settings_get_value (settings, key);
205   type = g_variant_get_type (v);
206   g_variant_unref (v);
207
208   error = NULL;
209   v = g_variant_parse (type, value, NULL, NULL, &error);
210   if (v == NULL)
211     {
212       g_printerr ("%s\n", error->message);
213       goto out;
214     }
215
216   if (!g_settings_set_value (settings, key, v))
217     {
218       g_printerr (_("Key %s is not writable\n"), key);
219       goto out;
220     }
221
222   g_settings_sync ();
223   ret = 0;
224
225  out:
226   g_option_context_free (context);
227
228   return ret;
229 }
230
231 static gint
232 handle_writable (gint   *argc,
233                  gchar **argv[])
234 {
235   gchar *schema;
236   gchar *path;
237   gchar *key;
238   GSettings *settings;
239   GOptionContext *context;
240   GOptionEntry entries[] = {
241     { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") },
242     { NULL }
243   };
244   GError *error;
245   gint ret = 1;
246
247   modify_argv0_for_command (argc, argv, "writable");
248
249   context = g_option_context_new (_("SCHEMA KEY"));
250   g_option_context_set_help_enabled (context, FALSE);
251   g_option_context_set_summary (context, _("Find out whether KEY is writable"));
252   g_option_context_set_description (context,
253     _("Arguments:\n"
254       "  SCHEMA      The id of the schema\n"
255       "  KEY         The name of the key\n"));
256   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
257
258   path = NULL;
259
260   error = NULL;
261   if (!g_option_context_parse (context, argc, argv, NULL) || *argc != 3)
262     {
263       gchar *s;
264       s = g_option_context_get_help (context, FALSE, NULL);
265       g_printerr ("%s", s);
266       g_free (s);
267
268       goto out;
269     }
270
271   schema = (*argv)[1];
272   key = (*argv)[2];
273
274   if (path)
275     settings = g_settings_new_with_path (schema, path);
276   else
277     settings = g_settings_new (schema);
278
279   if (g_settings_is_writable (settings, key))
280     g_print ("true\n");
281   else
282     g_print ("false\n");
283   ret = 0;
284
285  out:
286   g_option_context_free (context);
287
288   return ret;
289 }
290
291 static void
292 key_changed (GSettings   *settings,
293              const gchar *key)
294 {
295   GVariant *v;
296   gchar *value;
297
298   v = g_settings_get_value (settings, key);
299   value = g_variant_print (v, FALSE);
300   g_print ("%s\n", value);
301   g_free (value);
302   g_variant_unref (v);
303 }
304
305 static gint
306 handle_monitor (gint   *argc,
307                 gchar **argv[])
308 {
309   gchar *schema;
310   gchar *path;
311   gchar *key;
312   GSettings *settings;
313   gchar *detailed_signal;
314   GMainLoop *loop;
315   GOptionContext *context;
316   GOptionEntry entries[] = {
317     { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") },
318     { NULL }
319   };
320   GError *error;
321   gint ret = 1;
322
323   modify_argv0_for_command (argc, argv, "monitor");
324
325   context = g_option_context_new (_("SCHEMA KEY"));
326   g_option_context_set_help_enabled (context, FALSE);
327   g_option_context_set_summary (context,
328     _("Monitor KEY for changes and print the changed values.\n"
329       "Monitoring will continue until the process is terminated."));
330
331   g_option_context_set_description (context,
332     _("Arguments:\n"
333       "  SCHEMA      The id of the schema\n"
334       "  KEY         The name of the key\n"));
335   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
336
337   path = NULL;
338
339   error = NULL;
340   if (!g_option_context_parse (context, argc, argv, NULL) || *argc != 3)
341     {
342       gchar *s;
343       s = g_option_context_get_help (context, FALSE, NULL);
344       g_printerr ("%s", s);
345       g_free (s);
346
347       goto out;
348     }
349
350   schema = (*argv)[1];
351   key = (*argv)[2];
352
353   if (path)
354     settings = g_settings_new_with_path (schema, path);
355   else
356     settings = g_settings_new (schema);
357
358   detailed_signal = g_strdup_printf ("changed::%s", key);
359   g_signal_connect (settings, detailed_signal,
360                     G_CALLBACK (key_changed), NULL);
361
362   loop = g_main_loop_new (NULL, FALSE);
363   g_main_loop_run (loop);
364   g_main_loop_unref (loop);
365
366  out:
367   g_option_context_free (context);
368
369   return ret;
370 }
371 int
372 main (int argc, char *argv[])
373 {
374   gboolean ret = 1;
375
376   setlocale (LC_ALL, "");
377
378   g_type_init ();
379
380   if (argc < 2)
381     ret = usage (&argc, &argv, FALSE);
382   else if (g_strcmp0 (argv[1], "help") == 0)
383     ret = usage (&argc, &argv, TRUE);
384   else if (g_strcmp0 (argv[1], "get") == 0)
385     ret = handle_get (&argc, &argv);
386   else if (g_strcmp0 (argv[1], "set") == 0)
387     ret = handle_set (&argc, &argv);
388   else if (g_strcmp0 (argv[1], "monitor") == 0)
389     ret = handle_monitor (&argc, &argv);
390   else if (g_strcmp0 (argv[1], "writable") == 0)
391     ret = handle_writable (&argc, &argv);
392   else
393     {
394       g_printerr (_("Unknown command '%s'\n"), argv[1]);
395       ret = usage (&argc, &argv, FALSE);
396     }
397
398   return ret;
399 }