2 * Copyright © 2010, 2011 Codethink Limited
3 * Copyright © 2011 Canonical Limited
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the licence, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Ryan Lortie <desrt@desrt.ca>
21 void show_help (bool requested
, string? command
) {
22 var str
= new
StringBuilder ();
23 string? description
= null;
24 string? synopsis
= null;
31 description
= "Print help";
32 synopsis
= " COMMAND ";
36 description
= "Read the value of a key. -d to read default values.";
37 synopsis
= " [-d] KEY ";
41 description
= "List the sub-keys and sub-dirs of a dir";
46 description
= "List the locks under a dir";
51 description
= "Write a new value to a key";
52 synopsis
= " KEY VALUE ";
56 description
= "Reset a key or dir. -f is required for dirs.";
57 synopsis
= " [-f] PATH ";
61 description
= "Compile a binary database from keyfiles";
62 synopsis
= " OUTPUT KEYFILEDIR ";
66 description
= "Update the system dconf databases";
71 description
= "Watch a path for key changes";
76 description
= "Dump an entire subpath to stdout";
81 description
= "Populate a subpath from stdin";
86 str
.append_printf ("Unknown command '%s'\n\n", command
);
91 if (command
== null) {
94 dconf COMMAND [ARGS...]
97 help Show this information
98 read Read the value of a key
99 list List the contents of a dir
100 write Change the value of a key
101 reset Reset the value of a key or dir
102 compile Compile a binary database from keyfiles
103 update Update the system databases
104 watch Watch a path for changes
105 dump Dump an entire subpath to stdout
106 load Populate a subpath from stdin
108 Use 'dconf help COMMAND' to get detailed help.
112 str
.append ("Usage:\n");
113 str
.append_printf (" dconf %s%s\n\n", command
, synopsis
);
114 str
.append_printf ("%s\n\n", description
);
116 if (synopsis
!= "") {
117 str
.append ("Arguments:\n");
119 if (" COMMAND " in synopsis
) {
120 str
.append (" COMMAND The (optional) command to explain\n");
123 if (" PATH " in synopsis
) {
124 str
.append (" PATH Either a KEY or DIR\n");
127 if (" PATH " in synopsis
|| " KEY " in synopsis
) {
128 str
.append (" KEY A key path (starting, but not ending with '/')\n");
131 if (" PATH " in synopsis
|| " DIR " in synopsis
) {
132 str
.append (" DIR A directory path (starting and ending with '/')\n");
135 if (" VALUE " in synopsis
) {
136 str
.append (" VALUE The value to write (in GVariant format)\n");
139 if (" OUTPUT " in synopsis
) {
140 str
.append (" OUTPUT The filename of the (binary) output\n");
143 if (" KEYFILEDIR " in synopsis
) {
144 str
.append (" KEYFILEDIR The path to the .d directory containing keyfiles\n");
152 print ("%s", str
.str
);
154 printerr ("%s", str
.str
);
158 void dconf_help (string[] args
) throws Error
{
159 show_help (true, args
[2]);
162 void dconf_read (string?
[] args
) throws Error
{
163 var client
= new DConf
.Client ();
164 var flags
= DConf
.ReadFlags
.NONE
;
167 if (args
[index
] == "-d") {
168 flags
= DConf
.ReadFlags
.DEFAULT_VALUE
;
172 var key
= args
[index
];
174 DConf
.verify_key (key
);
176 var result
= client
.read_full (key
, flags
, null);
178 if (result
!= null) {
179 print ("%s\n", result
.print (true));
183 void dconf_list (string?
[] args
) throws Error
{
184 var client
= new DConf
.Client ();
187 DConf
.verify_dir (dir
);
189 foreach (var item
in client
.list (dir
)) {
190 print ("%s\n", item
);
194 void dconf_list_locks (string?
[] args
) throws Error
{
195 var client
= new DConf
.Client ();
198 DConf
.verify_dir (dir
);
200 foreach (var item
in client
.list_locks (dir
)) {
201 print ("%s\n", item
);
205 void dconf_write (string?
[] args
) throws Error
{
206 var client
= new DConf
.Client ();
210 DConf
.verify_key (key
);
212 client
.write_sync (key
, Variant
.parse (null, val
));
215 void dconf_reset (string?
[] args
) throws Error
{
216 var client
= new DConf
.Client ();
220 if (args
[index
] == "-f") {
225 var path
= args
[index
];
227 DConf
.verify_path (path
);
229 if (DConf
.is_dir (path
) && !force
) {
230 throw new OptionError
.FAILED ("-f must be given to (recursively) reset entire dirs");
233 client
.write_sync (path
, null);
236 void show_path (DConf
.Client client
, string path
) {
237 if (DConf
.is_key (path
)) {
238 var value
= client
.read (path
);
240 print (" %s\n", value
!= null ? value
.print (true) : "unset");
244 void watch_function (DConf
.Client client
, string path
, string[] items
, string? tag
) {
245 foreach (var item
in items
) {
246 var full
= path
+ item
;
247 print ("%s\n", full
);
248 show_path (client
, full
);
253 void dconf_watch (string?
[] args
) throws Error
{
254 var client
= new DConf
.Client ();
257 DConf
.verify_path (path
);
259 client
.changed
.connect (watch_function
);
260 client
.watch_sync (path
);
262 new
MainLoop (null, false).run ();
265 void dconf_blame (string?
[] args
) throws Error
{
266 var connection
= Bus
.get_sync (BusType
.SESSION
, null);
267 var reply
= connection
.call_sync ("ca.desrt.dconf", "/ca/desrt/dconf", "ca.desrt.dconf.ServiceInfo", "Blame",
268 null, new
VariantType ("(s)"), DBusCallFlags
.NONE
, -1, null);
269 print ("%s", reply
.get_child_value (0).get_string (null));
272 void dconf_complete (string[] args
) throws Error
{
273 var suffix
= args
[2];
281 if (path
[0] == '/') {
282 var client
= new DConf
.Client ();
285 for (var i
= 1; path
[i
] != '\0'; i
++) {
286 if (path
[i
] == '/') {
291 var dir
= path
.substring (0, last
+ 1);
292 foreach (var item
in client
.list (dir
)) {
293 var full_item
= dir
+ item
;
295 if (full_item
.has_prefix (path
) && item
.has_suffix (suffix
)) {
296 print ("%s%s\n", full_item
, full_item
.has_suffix ("/") ?
"" : " ");
302 delegate
void Command (string[] args
) throws Error
;
304 struct CommandMapping
{
305 unowned Command func
;
308 public CommandMapping (string name
, Command func
) {
314 int main (string[] args
) {
315 assert (args
.length
!= 0);
316 Environment
.set_prgname (args
[0]);
318 Intl
.setlocale (LocaleCategory
.ALL
, "");
320 var map
= new CommandMapping
[] {
321 CommandMapping ("help", dconf_help
),
322 CommandMapping ("read", dconf_read
),
323 CommandMapping ("list", dconf_list
),
324 CommandMapping ("list-locks", dconf_list_locks
),
325 CommandMapping ("write", dconf_write
),
326 CommandMapping ("reset", dconf_reset
),
327 CommandMapping ("compile", dconf_compile
),
328 CommandMapping ("update", dconf_update
),
329 CommandMapping ("watch", dconf_watch
),
330 CommandMapping ("dump", dconf_dump
),
331 CommandMapping ("load", dconf_load
),
332 CommandMapping ("blame", dconf_blame
),
333 CommandMapping ("_complete", dconf_complete
)
337 if (args
[1] == null) {
338 throw new OptionError
.FAILED ("no command specified");
341 foreach (var mapping
in map
) {
342 if (mapping
.name
== args
[1]) {
348 throw new OptionError
.FAILED ("unknown command %s", args
[1]);
350 stderr
.printf ("error: %s\n\n", e
.message
);
351 show_help (false, args
[1]);