Fix gsettings tool crash
[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   settings = g_settings_new_with_path (schema, path);
275
276   if (g_settings_is_writable (settings, key))
277     g_print ("true\n");
278   else
279     g_print ("false\n");
280   ret = 0;
281
282  out:
283   g_option_context_free (context);
284
285   return ret;
286 }
287
288 static void
289 key_changed (GSettings   *settings,
290              const gchar *key)
291 {
292   GVariant *v;
293   gchar *value;
294
295   v = g_settings_get_value (settings, key);
296   value = g_variant_print (v, FALSE);
297   g_print ("%s\n", value);
298   g_free (value);
299   g_variant_unref (v);
300 }
301
302 static gint
303 handle_monitor (gint   *argc,
304                 gchar **argv[])
305 {
306   gchar *schema;
307   gchar *path;
308   gchar *key;
309   GSettings *settings;
310   gchar *detailed_signal;
311   GMainLoop *loop;
312   GOptionContext *context;
313   GOptionEntry entries[] = {
314     { "path", 'p', 0, G_OPTION_ARG_STRING, &path, N_("Specify the path for the schema"), N_("PATH") },
315     { NULL }
316   };
317   GError *error;
318   gint ret = 1;
319
320   modify_argv0_for_command (argc, argv, "monitor");
321
322   context = g_option_context_new (_("SCHEMA KEY"));
323   g_option_context_set_help_enabled (context, FALSE);
324   g_option_context_set_summary (context,
325     _("Monitor KEY for changes and print the changed values.\n"
326       "Monitoring will continue until the process is terminated."));
327
328   g_option_context_set_description (context,
329     _("Arguments:\n"
330       "  SCHEMA      The id of the schema\n"
331       "  KEY         The name of the key\n"));
332   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
333
334   path = NULL;
335
336   error = NULL;
337   if (!g_option_context_parse (context, argc, argv, NULL) || *argc != 3)
338     {
339       gchar *s;
340       s = g_option_context_get_help (context, FALSE, NULL);
341       g_printerr ("%s", s);
342       g_free (s);
343
344       goto out;
345     }
346
347   schema = (*argv)[1];
348   key = (*argv)[2];
349
350   settings = g_settings_new_with_path (schema, path);
351
352   detailed_signal = g_strdup_printf ("changed::%s", key);
353   g_signal_connect (settings, detailed_signal,
354                     G_CALLBACK (key_changed), NULL);
355
356   loop = g_main_loop_new (NULL, FALSE);
357   g_main_loop_run (loop);
358   g_main_loop_unref (loop);
359
360  out:
361   g_option_context_free (context);
362
363   return ret;
364 }
365 int
366 main (int argc, char *argv[])
367 {
368   gboolean ret = 1;
369
370   setlocale (LC_ALL, "");
371
372   g_type_init ();
373
374   if (argc < 2)
375     ret = usage (&argc, &argv, FALSE);
376   else if (g_strcmp0 (argv[1], "help") == 0)
377     ret = usage (&argc, &argv, TRUE);
378   else if (g_strcmp0 (argv[1], "get") == 0)
379     ret = handle_get (&argc, &argv);
380   else if (g_strcmp0 (argv[1], "set") == 0)
381     ret = handle_set (&argc, &argv);
382   else if (g_strcmp0 (argv[1], "monitor") == 0)
383     ret = handle_monitor (&argc, &argv);
384   else if (g_strcmp0 (argv[1], "writable") == 0)
385     ret = handle_writable (&argc, &argv);
386   else
387     {
388       g_printerr (_("Unknown command '%s'\n"), argv[1]);
389       ret = usage (&argc, &argv, FALSE);
390     }
391
392   return ret;
393 }