]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/commands.c
configd-395.11.tar.gz
[apple/configd.git] / scutil.tproj / commands.c
CommitLineData
5958d7c0 1/*
6bb65964 2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
009ee3c6 5 *
009ee3c6
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
5958d7c0
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
009ee3c6
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
5958d7c0
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
0fae82ee
A
24/*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
5958d7c0
A
34#include <stdio.h>
35#include <string.h>
36#include <sys/errno.h>
37
38#include "scutil.h"
39#include "commands.h"
40#include "dictionary.h"
41#include "session.h"
42#include "cache.h"
dbf6a266 43#include "notifications.h"
5958d7c0 44#include "tests.h"
dbf6a266 45#include "net.h"
edebe297 46#include "prefs.h"
5958d7c0 47
5958d7c0 48
dbf6a266
A
49__private_extern__
50const cmdInfo commands_store[] = {
0fae82ee
A
51 /* cmd minArgs maxArgs func group ctype */
52 /* usage */
5958d7c0 53
0fae82ee
A
54 { "help", 0, 0, do_help, 0, 0,
55 " help : list available commands" },
5958d7c0 56
0fae82ee
A
57 { "f.read", 1, 1, do_readFile, 0, 0,
58 " f.read file : process commands from file" },
5958d7c0 59
dbf6a266
A
60 { "quit", 0, 0, do_quit, 0, 0,
61 " quit : quit" },
62
63 { "q", 0, 0, do_quit, 0, -1,
64 NULL },
65
66 { "exit", 0, 0, do_quit, 0, -1,
67 NULL },
68
5958d7c0
A
69 /* local dictionary manipulation commands */
70
0fae82ee
A
71 { "d.init", 0, 0, do_dictInit, 1, 0,
72 " d.init : initialize (empty) dictionary" },
5958d7c0 73
0fae82ee
A
74 { "d.show", 0, 0, do_dictShow, 1, 0,
75 " d.show : show dictionary contents" },
5958d7c0 76
0fae82ee
A
77 { "d.add", 2, 101, do_dictSetKey, 1, 0,
78 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
dbf6a266 79 " (*=array, #=number, ?=boolean)" },
5958d7c0 80
0fae82ee
A
81 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
82 " d.remove key : remove key from dictionary" },
5958d7c0 83
edebe297 84 /* dynamic store manipulation commands */
5958d7c0 85
dbf6a266
A
86 { "open", 0, 1, do_open, 2, 1,
87 " open [\"temporary\"] : open a session with \"configd\"" },
0fae82ee 88
dbf6a266 89 { "close", 0, 0, do_close, 2, 1,
0fae82ee
A
90 " close : close current \"configd\" session" },
91
92 { "lock", 0, 0, do_lock, 3, 1,
edebe297 93 " lock : locks write access to data store" },
5958d7c0 94
0fae82ee 95 { "unlock", 0, 0, do_unlock, 3, 1,
edebe297 96 " unlock : unlocks write access to data store" },
5958d7c0 97
0fae82ee
A
98 { "list", 0, 2, do_list, 4, 0,
99 " list [pattern] : list keys in data store" },
5958d7c0 100
0fae82ee 101 { "add", 1, 2, do_add, 4, 0,
dbf6a266 102 " add key [\"temporary\"] : add key in data store w/current dict" },
5958d7c0 103
0fae82ee
A
104 { "get", 1, 1, do_get, 4, 0,
105 " get key : get dict from data store w/key" },
5958d7c0 106
0fae82ee 107 { "set", 1, 1, do_set, 4, 0,
edebe297 108 " set key : set key in data store w/current dict" },
5958d7c0 109
009ee3c6
A
110 { "show", 1, 2, do_show, 4, 0,
111 " show key [\"pattern\"] : show values in data store w/key" },
5958d7c0 112
0fae82ee
A
113 { "remove", 1, 1, do_remove, 4, 0,
114 " remove key : remove key from data store" },
5958d7c0 115
0fae82ee
A
116 { "notify", 1, 1, do_notify, 4, 0,
117 " notify key : notify key in data store" },
5958d7c0 118
0fae82ee
A
119 { "touch", 1, 1, do_touch, 4, 1,
120 " touch key : touch key in data store" },
5958d7c0 121
0fae82ee
A
122 { "n.list", 0, 1, do_notify_list, 5, 0,
123 " n.list [\"pattern\"] : list notification keys" },
5958d7c0 124
0fae82ee 125 { "n.add", 1, 2, do_notify_add, 5, 0,
dbf6a266 126 " n.add key [\"pattern\"] : add notification key" },
5958d7c0 127
0fae82ee
A
128 { "n.remove", 1, 2, do_notify_remove, 5, 0,
129 " n.remove key [\"pattern\"] : remove notification key" },
5958d7c0 130
0fae82ee
A
131 { "n.changes", 0, 0, do_notify_changes, 5, 0,
132 " n.changes : list changed keys" },
5958d7c0 133
a40a14f8
A
134 { "n.watch", 0, 0, do_notify_watch, 5, 0,
135 " n.watch : watch for changes" },
5958d7c0 136
0fae82ee
A
137 { "n.wait", 0, 0, do_notify_wait, 5, 2,
138 " n.wait : wait for changes" },
5958d7c0 139
0fae82ee
A
140 { "n.callback", 0, 1, do_notify_callback, 5, 2,
141 " n.callback [\"verbose\"] : watch for changes" },
5958d7c0 142
0fae82ee
A
143 { "n.signal", 1, 2, do_notify_signal, 5, 2,
144 " n.signal sig [pid] : signal changes" },
5958d7c0 145
0fae82ee
A
146 { "n.file", 0, 1, do_notify_file, 5, 2,
147 " n.file [identifier] : watch for changes via file" },
5958d7c0 148
0fae82ee
A
149 { "n.cancel", 0, 1, do_notify_cancel, 5, 0,
150 " n.cancel : cancel notification requests" },
5958d7c0 151
dbf6a266
A
152 { "snapshot", 0, 0, do_snapshot, 99, 2,
153 " snapshot : save snapshot of store and session data" }
5958d7c0 154};
dbf6a266
A
155__private_extern__
156const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo));
157
158
159__private_extern__
edebe297 160const cmdInfo commands_net[] = {
dbf6a266
A
161 /* cmd minArgs maxArgs func group ctype */
162 /* usage */
163
164 { "help", 0, 0, do_help, 0, 0,
165 " help : list available commands" },
166
167 { "f.read", 1, 1, do_readFile, 0, 0,
168 " f.read file : process commands from file" },
169
170 { "quit", 0, 1, do_net_quit, 0, 0,
171 " quit [!] : quit" },
172
173 { "q", 0, 1, do_net_quit, 0, -1,
174 NULL },
175
176 { "exit", 0, 1, do_net_quit, 0, -1,
177 NULL },
178
179 /* network configuration manipulation commands */
180
181 { "open", 0, 1, do_net_open, 2, 1,
182 " open : open the network configuration" },
183
184 { "commit", 0, 0, do_net_commit, 2, 0,
185 " commit : commit any changes" },
186
187 { "apply", 0, 0, do_net_apply, 2, 0,
188 " apply : apply any changes" },
5958d7c0 189
dbf6a266
A
190 { "close", 0, 1, do_net_close, 2, 1,
191 " close [!] : close the network configuration" },
5958d7c0 192
dbf6a266
A
193 { "create", 1, 3, do_net_create, 3, 0,
194 " create interface <interfaceType> [ <interfaceName> | <interface#> ]\n"
195 " create protocol <protocolType>\n"
196 " create service [ <interfaceName> | <interface#> [ <serviceName> ]]\n"
197 " create set [setName]" },
0fae82ee 198
edebe297 199 { "disable", 1, 2, do_net_disable, 4, 0,
dbf6a266
A
200 " disable protocol [ <protocolType> ]\n"
201 " disable service [ <serviceName> | <service#> ]" },
5958d7c0 202
edebe297 203 { "enable", 1, 2, do_net_enable, 5, 0,
dbf6a266
A
204 " enable protocol [ <protocolType> ]\n"
205 " enable service [ <serviceName> | <service#> ]" },
206
207 { "remove", 1, 2, do_net_remove, 6, 0,
208 " remove protocol [ <protocolType> ]\n"
209 " remove service [ <serviceName> | <service#> ]\n"
210 " remove set [ <setName> | <set#> ]" },
211
a40a14f8 212 { "select", 2, 3, do_net_select, 7, 0,
6bb65964 213 " select interface <interfaceName> | <interface#> | $child | $service | $vlan | $bond <memberName> | $bridge <memberName>\n"
dbf6a266
A
214 " select protocol <protocolType>\n"
215 " select service <serviceName> | <service#>\n"
216 " select set <setName> | <set#>" },
217
218 { "set", 2, 101, do_net_set, 8, 0,
219 " set interface context-sensitive-arguments (or ? for help)\n"
220 " set protocol context-sensitive-arguments (or ? for help)\n"
a40a14f8 221 " set service [ name <serviceName> ] [ order new-order ] [ rank ("" | First | Last | Never) [temp] ]\n"
6bb65964 222 " set set [ name setName ] | [ current ]" },
dbf6a266
A
223
224 { "show", 1, 2, do_net_show, 9, 0,
225 " show interfaces\n"
226 " show interface [ <interfaceName> | <interface#> ]\n"
227 " show protocols\n"
228 " show protocol [ <protocolType> ]\n"
229 " show services [ all ]\n"
230 " show service [ <serviceName> | <service#> ]\n"
231 " show sets\n\n"
232 " show set [ <setName> | <set#> ]" },
233
edebe297
A
234 { "update", 0, 1, do_net_update, 10, 0,
235 " update : update the network configuration" },
236
dbf6a266
A
237 { "snapshot", 0, 0, do_net_snapshot, 99, 2,
238 " snapshot" }
239
240};
241__private_extern__
edebe297
A
242const int nCommands_net = (sizeof(commands_net)/sizeof(cmdInfo));
243
244
245__private_extern__
246const cmdInfo commands_prefs[] = {
247 /* cmd minArgs maxArgs func group ctype */
248 /* usage */
249
250 { "help", 0, 0, do_help, 0, 0,
251 " help : list available commands" },
252
253 { "f.read", 1, 1, do_readFile, 0, 0,
254 " f.read file : process commands from file" },
255
256 { "quit", 0, 1, do_prefs_quit, 0, 0,
257 " quit [!] : quit" },
258
259 { "q", 0, 1, do_prefs_quit, 0, -1,
260 NULL },
261
262 { "exit", 0, 1, do_prefs_quit, 0, -1,
263 NULL },
264
265 /* local dictionary manipulation commands */
266
267 { "d.init", 0, 0, do_dictInit, 1, 0,
268 " d.init : initialize (empty) dictionary" },
269
270 { "d.show", 0, 0, do_dictShow, 1, 0,
271 " d.show : show dictionary contents" },
272
273 { "d.add", 2, 101, do_dictSetKey, 1, 0,
274 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
275 " (*=array, #=number, ?=boolean)" },
276
277 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
278 " d.remove key : remove key from dictionary" },
279
280 /* data store manipulation commands */
281
282 { "open", 0, 1, do_prefs_open, 2, 1,
a40a14f8 283 " open [\"prefsID\"] : open a \"preferences\" session" },
edebe297
A
284
285 { "lock", 0, 1, do_prefs_lock, 3, 1,
286 " lock [wait] : locks write access to preferences" },
287
288 { "commit", 0, 0, do_prefs_commit, 2, 0,
289 " commit : commit any changes" },
290
291 { "apply", 0, 0, do_prefs_apply, 2, 0,
292 " apply : apply any changes" },
293
294 { "unlock", 0, 0, do_prefs_unlock, 3, 1,
295 " unlock : unlocks write access to preferences" },
296
297 { "close", 0, 1, do_prefs_close, 2, 1,
298 " close [!] : close current \"preference\" session" },
299
6d034b4e
A
300 { "synchronize",0, 1, do_prefs_synchronize, 2, 0,
301 " synchronize : synchronize a \"preferences\" session" },
a40a14f8 302
edebe297
A
303 { "list", 0, 1, do_prefs_list, 4, 0,
304 " list [path] : list preference paths" },
305
306 { "get", 1, 1, do_prefs_get, 4, 0,
307 " get path : get dict from preferences w/path" },
308
309 { "set", 1, 2, do_prefs_set, 4, 0,
310 " set path : set path in preferences w/current dict\n"
311 " set path link : set path in preferences w/link" },
312
313 { "remove", 1, 1, do_prefs_remove, 4, 0,
314 " remove path : remove path from preferences" }
315};
316__private_extern__
dbf6a266
A
317const int nCommands_prefs = (sizeof(commands_prefs)/sizeof(cmdInfo));
318
319
320__private_extern__ cmdInfo *commands = NULL;
321__private_extern__ int nCommands = 0;
322__private_extern__ Boolean enablePrivateAPI = FALSE;
323__private_extern__ Boolean termRequested = FALSE;
324
325
326__private_extern__
5958d7c0
A
327void
328do_command(int argc, char **argv)
329{
330 int i;
331 char *cmd = argv[0];
332
009ee3c6 333 for (i = 0; i < nCommands; i++) {
0fae82ee
A
334 if ((commands[i].ctype > 1) && !enablePrivateAPI) {
335 continue; /* if "private" API and access has not been enabled */
336 }
337
5958d7c0
A
338 if (strcasecmp(cmd, commands[i].cmd) == 0) {
339 --argc;
340 argv++;
341 if (argc < commands[i].minArgs) {
0fae82ee 342 SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd);
5958d7c0
A
343 return;
344 } else if (argc > commands[i].maxArgs) {
0fae82ee 345 SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
5958d7c0
A
346 return;
347 }
dbf6a266 348 (*commands[i].func)(argc, argv);
5958d7c0
A
349 return;
350 }
351 }
352
0fae82ee 353 SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd);
5958d7c0
A
354 return;
355}
356
357
dbf6a266 358__private_extern__
5958d7c0
A
359void
360do_help(int argc, char **argv)
361{
362 int g = -1; /* current group */
363 int i;
364
0fae82ee 365 SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
009ee3c6 366 for (i = 0; i < nCommands; i++) {
dbf6a266
A
367 if (commands[i].ctype < 0) {
368 continue; /* if "hidden" */
369 }
370
0fae82ee
A
371 if ((commands[i].ctype > 0) && !enablePrivateAPI) {
372 continue; /* if "private" API and access has not been enabled */
373 }
374
375 /* check if this is a new command group */
5958d7c0 376 if (g != commands[i].group) {
0fae82ee 377 SCPrint(TRUE, stdout, CFSTR("\n"));
5958d7c0
A
378 g = commands[i].group;
379 }
0fae82ee
A
380
381 /* display the command */
382 SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage);
5958d7c0 383 }
0fae82ee 384 SCPrint(TRUE, stdout, CFSTR("\n"));
5958d7c0
A
385
386 return;
387}
388
389
dbf6a266 390__private_extern__
5958d7c0
A
391void
392do_readFile(int argc, char **argv)
393{
009ee3c6 394 InputRef src;
5958d7c0 395
009ee3c6
A
396 /* allocate command input stream */
397 src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
398 src->el = NULL;
6bb65964 399 src->h = NULL;
009ee3c6
A
400 src->fp = fopen(argv[0], "r");
401
402 if (src->fp == NULL) {
0fae82ee 403 SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno));
009ee3c6 404 CFAllocatorDeallocate(NULL, src);
5958d7c0
A
405 return;
406 }
407
408 /* open file, increase nesting level */
0fae82ee 409 SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]);
5958d7c0
A
410 nesting++;
411
a40a14f8
A
412 while (TRUE) {
413 Boolean ok;
414
415 ok = process_line(src);
416 if (!ok) {
417 break;
418 }
009ee3c6
A
419 }
420
421 (void)fclose(src->fp);
422 CFAllocatorDeallocate(NULL, src);
5958d7c0
A
423
424 return;
425}
dbf6a266
A
426
427
428__private_extern__
429void
430do_quit(int argc, char **argv)
431{
432 termRequested = TRUE;
433 return;
434}