2 * Copyright (c) 2000-2011, 2013, 2014, 2017 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
36 #include <sys/errno.h>
40 #include "dictionary.h"
43 #include "notifications.h"
50 const cmdInfo commands_store
[] = {
51 /* cmd minArgs maxArgs func group ctype */
54 { "help", 0, 0, do_help
, 0, 0,
55 " help : list available commands" },
57 { "f.read", 1, 1, do_readFile
, 0, 0,
58 " f.read file : process commands from file" },
60 { "quit", 0, 0, do_quit
, 0, 0,
63 { "q", 0, 0, do_quit
, 0, -1,
66 { "exit", 0, 0, do_quit
, 0, -1,
69 /* local dictionary manipulation commands */
71 { "d.init", 0, 0, do_dictInit
, 1, 0,
72 " d.init : initialize (empty) dictionary" },
74 { "d.show", 0, 0, do_dictShow
, 1, 0,
75 " d.show : show dictionary contents" },
77 { "d.add", 2, 101, do_dictSetKey
, 1, 0,
78 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
79 " (*=array, #=number, ?=boolean, %=hex data)" },
81 { "d.remove", 1, 1, do_dictRemoveKey
, 1, 0,
82 " d.remove key : remove key from dictionary" },
84 /* dynamic store manipulation commands */
86 { "open", 0, 1, do_open
, 2, 1,
87 " open [\"temporary\"] : open a session with \"configd\"" },
89 { "close", 0, 0, do_close
, 2, 1,
90 " close : close current \"configd\" session" },
92 { "block", 0, 1, do_block
, 3, 1,
93 " block [\"begin\" | \"end\"] : block multiple data store transactions" },
95 { "list", 0, 2, do_list
, 4, 0,
96 " list [pattern] : list keys in data store" },
98 { "add", 1, 2, do_add
, 4, 0,
99 " add key [\"temporary\"] : add key in data store w/current dict" },
101 { "get", 1, 1, do_get
, 4, 0,
102 " get key : get dict from data store w/key" },
104 { "set", 1, 1, do_set
, 4, 0,
105 " set key : set key in data store w/current dict" },
107 { "show", 1, 2, do_show
, 4, 0,
108 " show key [\"pattern\"] : show values in data store w/key" },
110 { "remove", 1, 1, do_remove
, 4, 0,
111 " remove key : remove key from data store" },
113 { "notify", 1, 1, do_notify
, 4, 0,
114 " notify key : notify key in data store" },
116 { "n.list", 0, 1, do_notify_list
, 5, 0,
117 " n.list [\"pattern\"] : list notification keys" },
119 { "n.add", 1, 2, do_notify_add
, 5, 0,
120 " n.add key [\"pattern\"] : add notification key" },
122 { "n.remove", 1, 2, do_notify_remove
, 5, 0,
123 " n.remove key [\"pattern\"] : remove notification key" },
125 { "n.changes", 0, 0, do_notify_changes
, 5, 0,
126 " n.changes : list changed keys" },
128 { "n.watch", 0, 0, do_notify_watch
, 5, 0,
129 " n.watch : watch for changes" },
131 { "n.wait", 0, 0, do_notify_wait
, 5, 2,
132 " n.wait : wait for changes" },
134 { "n.signal", 1, 2, do_notify_signal
, 5, 2,
135 " n.signal sig [pid] : signal changes" },
137 { "n.file", 0, 1, do_notify_file
, 5, 2,
138 " n.file [identifier] : watch for changes via file" },
140 { "n.cancel", 0, 1, do_notify_cancel
, 5, 0,
141 " n.cancel : cancel notification requests" },
143 { "snapshot", 0, 1, do_snapshot
, 99, 2,
144 " snapshot [file] : save snapshot of store and session data" }
147 const int nCommands_store
= (sizeof(commands_store
)/sizeof(cmdInfo
));
151 const cmdInfo commands_net
[] = {
152 /* cmd minArgs maxArgs func group ctype */
155 { "help", 0, 0, do_help
, 0, 0,
156 " help : list available commands" },
158 { "f.read", 1, 1, do_readFile
, 0, 0,
159 " f.read file : process commands from file" },
161 { "quit", 0, 1, do_net_quit
, 0, 0,
162 " quit [!] : quit" },
164 { "q", 0, 1, do_net_quit
, 0, -1,
167 { "exit", 0, 1, do_net_quit
, 0, -1,
170 /* network configuration manipulation commands */
172 { "open", 0, 1, do_net_open
, 2, 1,
173 " open : open the network configuration" },
175 { "commit", 0, 0, do_net_commit
, 2, 0,
176 " commit : commit any changes" },
178 { "apply", 0, 0, do_net_apply
, 2, 0,
179 " apply : apply any changes" },
181 { "close", 0, 1, do_net_close
, 2, 1,
182 " close [!] : close the network configuration" },
184 { "create", 1, 3, do_net_create
, 3, 0,
185 " create interface <interfaceType> [ <interfaceName> | <interface#> ]\n"
186 " create protocol <protocolType>\n"
187 " create service [ <interfaceName> | <interface#> [ <serviceName> ]]\n"
188 " create set [setName]" },
190 { "disable", 1, 2, do_net_disable
, 4, 0,
191 " disable protocol [ <protocolType> ]\n"
192 " disable service [ <serviceName> | <service#> ]" },
194 { "enable", 1, 2, do_net_enable
, 5, 0,
195 " enable protocol [ <protocolType> ]\n"
196 " enable service [ <serviceName> | <service#> ]" },
198 { "migrate", 2, 5, do_net_migrate
, 11, 0,
199 " migrate perform <old-configuration> <new-configuration> [<current-configuration>]\n"
200 " migrate validate <configuration> <expected-configuration>"},
202 { "remove", 1, 2, do_net_remove
, 6, 0,
203 " remove protocol [ <protocolType> ]\n"
204 " remove service [ <serviceName> | <service#> ]\n"
205 " remove set [ <setName> | <set#> ]" },
207 { "select", 2, 3, do_net_select
, 7, 0,
208 " select interface <interfaceName> | <interface#> | $child | $service | $vlan | $bond <memberName> | $bridge <memberName>\n"
209 " select protocol <protocolType>\n"
210 " select service <serviceName> | <service#>\n"
211 " select set <setName> | <set#>" },
213 { "set", 2, 101, do_net_set
, 8, 0,
214 " set interface context-sensitive-arguments (or ? for help)\n"
215 " set protocol context-sensitive-arguments (or ? for help)\n"
216 " set service [ name <serviceName> ] [ order new-order ] [ rank ("" | First | Last | Never | Scoped ) [temp] ] [ id <serviceID> ]\n"
217 " set set [ name setName ] | [ current ] [ id <setID> ]" },
219 { "show", 1, 2, do_net_show
, 9, 0,
221 " show interface [ <interfaceName> | <interface#> ]\n"
223 " show protocol [ <protocolType> ]\n"
224 " show services [ all ]\n"
225 " show service [ <serviceName> | <service#> ]\n"
227 " show set [ <setName> | <set#> ]" },
229 { "update", 0, 1, do_net_update
, 10, 0,
230 " update : update the network configuration" },
232 { "snapshot", 0, 0, do_net_snapshot
, 99, 2,
237 const int nCommands_net
= (sizeof(commands_net
)/sizeof(cmdInfo
));
241 const cmdInfo commands_prefs
[] = {
242 /* cmd minArgs maxArgs func group ctype */
245 { "help", 0, 0, do_help
, 0, 0,
246 " help : list available commands" },
248 { "f.read", 1, 1, do_readFile
, 0, 0,
249 " f.read file : process commands from file" },
251 { "quit", 0, 1, do_prefs_quit
, 0, 0,
252 " quit [!] : quit" },
254 { "q", 0, 1, do_prefs_quit
, 0, -1,
257 { "exit", 0, 1, do_prefs_quit
, 0, -1,
260 /* local dictionary manipulation commands */
262 { "d.init", 0, 0, do_dictInit
, 1, 0,
263 " d.init : initialize (empty) dictionary" },
265 { "d.show", 0, 0, do_dictShow
, 1, 0,
266 " d.show : show dictionary contents" },
268 { "d.add", 2, 101, do_dictSetKey
, 1, 0,
269 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
270 " (*=array, #=number, ?=boolean, %=hex data)" },
272 { "d.remove", 1, 1, do_dictRemoveKey
, 1, 0,
273 " d.remove key : remove key from dictionary" },
275 /* data store manipulation commands */
277 { "open", 0, 1, do_prefs_open
, 2, 1,
278 " open [\"prefsID\"] : open a \"preferences\" session" },
280 { "lock", 0, 1, do_prefs_lock
, 3, 1,
281 " lock [wait] : locks write access to preferences" },
283 { "commit", 0, 0, do_prefs_commit
, 2, 0,
284 " commit : commit any changes" },
286 { "apply", 0, 0, do_prefs_apply
, 2, 0,
287 " apply : apply any changes" },
289 { "unlock", 0, 0, do_prefs_unlock
, 3, 1,
290 " unlock : unlocks write access to preferences" },
292 { "close", 0, 1, do_prefs_close
, 2, 1,
293 " close [!] : close current \"preference\" session" },
295 { "synchronize",0, 1, do_prefs_synchronize
, 2, 0,
296 " synchronize : synchronize a \"preferences\" session" },
298 { "list", 0, 1, do_prefs_list
, 4, 0,
299 " list [path] : list preference paths" },
301 { "get", 1, 1, do_prefs_get
, 4, 0,
302 " get path : get dict from preferences w/path" },
304 { "set", 1, 2, do_prefs_set
, 4, 0,
305 " set path : set path in preferences w/current dict\n"
306 " set path link : set path in preferences w/link" },
308 { "remove", 1, 1, do_prefs_remove
, 4, 0,
309 " remove path : remove path from preferences" }
312 const int nCommands_prefs
= (sizeof(commands_prefs
)/sizeof(cmdInfo
));
315 __private_extern__ cmdInfo
*commands
= NULL
;
316 __private_extern__
int nCommands
= 0;
317 __private_extern__ Boolean enablePrivateAPI
= FALSE
;
318 __private_extern__ Boolean termRequested
= FALSE
;
323 do_command(int argc
, char **argv
)
328 for (i
= 0; i
< nCommands
; i
++) {
329 if ((commands
[i
].ctype
> 1) && !enablePrivateAPI
) {
330 continue; /* if "private" API and access has not been enabled */
333 if (strcasecmp(cmd
, commands
[i
].cmd
) == 0) {
336 if (argc
< commands
[i
].minArgs
) {
337 SCPrint(TRUE
, stdout
, CFSTR("%s: too few arguments\n"), cmd
);
339 } else if (argc
> commands
[i
].maxArgs
) {
340 SCPrint(TRUE
, stdout
, CFSTR("%s: too many arguments\n"), cmd
);
343 (*commands
[i
].func
)(argc
, argv
);
348 SCPrint(TRUE
, stdout
, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd
);
355 do_help(int argc
, char **argv
)
359 int g
= -1; /* current group */
362 SCPrint(TRUE
, stdout
, CFSTR("\nAvailable commands:\n"));
363 for (i
= 0; i
< nCommands
; i
++) {
364 if (commands
[i
].ctype
< 0) {
365 continue; /* if "hidden" */
368 if ((commands
[i
].ctype
> 0) && !enablePrivateAPI
) {
369 continue; /* if "private" API and access has not been enabled */
372 /* check if this is a new command group */
373 if (g
!= commands
[i
].group
) {
374 SCPrint(TRUE
, stdout
, CFSTR("\n"));
375 g
= commands
[i
].group
;
378 /* display the command */
379 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), commands
[i
].usage
);
381 SCPrint(TRUE
, stdout
, CFSTR("\n"));
389 do_readFile(int argc
, char **argv
)
394 /* allocate command input stream */
395 src
= (InputRef
)CFAllocatorAllocate(NULL
, sizeof(Input
), 0);
398 src
->fp
= fopen(argv
[0], "r");
400 if (src
->fp
== NULL
) {
401 SCPrint(TRUE
, stdout
, CFSTR("f.read: could not open file (%s).\n"), strerror(errno
));
402 CFAllocatorDeallocate(NULL
, src
);
406 /* open file, increase nesting level */
407 SCPrint(TRUE
, stdout
, CFSTR("f.read: reading file (%s).\n"), argv
[0]);
413 ok
= process_line(src
);
419 (void)fclose(src
->fp
);
420 CFAllocatorDeallocate(NULL
, src
);
428 do_quit(int argc
, char **argv
)
432 termRequested
= TRUE
;