]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/commands.c
configd-1109.40.9.tar.gz
[apple/configd.git] / scutil.tproj / commands.c
1 /*
2 * Copyright (c) 2000-2011, 2013, 2014, 2017-2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
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
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"
43 #include "notifications.h"
44 #include "tests.h"
45 #include "net.h"
46 #include "prefs.h"
47
48
49 __private_extern__
50 const cmdInfo commands_store[] = {
51 /* cmd minArgs maxArgs func group ctype */
52 /* usage */
53
54 { "help", 0, 0, do_help, 0, 0,
55 " help : list available commands" },
56
57 { "f.read", 1, 1, do_readFile, 0, 0,
58 " f.read file : process commands from file" },
59
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
69 /* local dictionary manipulation commands */
70
71 { "d.init", 0, 0, do_dictInit, 1, 0,
72 " d.init : initialize (empty) dictionary" },
73
74 { "d.show", 0, 0, do_dictShow, 1, 0,
75 " d.show : show dictionary contents" },
76
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)" },
80
81 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
82 " d.remove key : remove key from dictionary" },
83
84 /* dynamic store manipulation commands */
85
86 { "open", 0, 1, do_open, 2, 1,
87 " open [\"temporary\"] : open a session with \"configd\"" },
88
89 { "close", 0, 0, do_close, 2, 1,
90 " close : close current \"configd\" session" },
91
92 { "block", 0, 1, do_block, 3, 1,
93 " block [\"begin\" | \"end\"] : block multiple data store transactions" },
94
95 { "list", 0, 2, do_list, 4, 0,
96 " list [pattern] : list keys in data store" },
97
98 { "add", 1, 2, do_add, 4, 0,
99 " add key [\"temporary\"] : add key in data store w/current dict" },
100
101 { "get", 1, 1, do_get, 4, 0,
102 " get key : get dict from data store w/key" },
103
104 { "set", 1, 1, do_set, 4, 0,
105 " set key : set key in data store w/current dict" },
106
107 { "show", 1, 2, do_show, 4, 0,
108 " show key [\"pattern\"] : show values in data store w/key" },
109
110 { "remove", 1, 1, do_remove, 4, 0,
111 " remove key : remove key from data store" },
112
113 { "notify", 1, 1, do_notify, 4, 0,
114 " notify key : notify key in data store" },
115
116 { "n.list", 0, 1, do_notify_list, 5, 0,
117 " n.list [\"pattern\"] : list notification keys" },
118
119 { "n.add", 1, 2, do_notify_add, 5, 0,
120 " n.add key [\"pattern\"] : add notification key" },
121
122 { "n.remove", 1, 2, do_notify_remove, 5, 0,
123 " n.remove key [\"pattern\"] : remove notification key" },
124
125 { "n.changes", 0, 0, do_notify_changes, 5, 0,
126 " n.changes : list changed keys" },
127
128 { "n.watch", 0, 0, do_notify_watch, 5, 0,
129 " n.watch : watch for changes" },
130
131 { "n.wait", 0, 0, do_notify_wait, 5, 2,
132 " n.wait : wait for changes" },
133
134 { "n.file", 0, 1, do_notify_file, 5, 2,
135 " n.file [identifier] : watch for changes via file" },
136
137 { "n.cancel", 0, 1, do_notify_cancel, 5, 0,
138 " n.cancel : cancel notification requests" },
139
140 { "snapshot", 0, 1, do_snapshot, 99, 2,
141 " snapshot [file] : save snapshot of store and session data" }
142 };
143 __private_extern__
144 const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo));
145
146
147 __private_extern__
148 const cmdInfo commands_net[] = {
149 /* cmd minArgs maxArgs func group ctype */
150 /* usage */
151
152 { "help", 0, 0, do_help, 0, 0,
153 " help : list available commands" },
154
155 { "f.read", 1, 1, do_readFile, 0, 0,
156 " f.read file : process commands from file" },
157
158 { "quit", 0, 1, do_net_quit, 0, 0,
159 " quit [!] : quit" },
160
161 { "q", 0, 1, do_net_quit, 0, -1,
162 NULL },
163
164 { "exit", 0, 1, do_net_quit, 0, -1,
165 NULL },
166
167 /* network configuration manipulation commands */
168
169 { "open", 0, 1, do_net_open, 2, 1,
170 " open : open the network configuration" },
171
172 { "commit", 0, 0, do_net_commit, 2, 0,
173 " commit : commit any changes" },
174
175 { "apply", 0, 0, do_net_apply, 2, 0,
176 " apply : apply any changes" },
177
178 { "close", 0, 1, do_net_close, 2, 1,
179 " close [!] : close the network configuration" },
180
181 { "create", 1, 3, do_net_create, 3, 0,
182 " create interface <interfaceType> [ <interfaceName> | <interface#> ]\n"
183 " create protocol <protocolType>\n"
184 " create service [ <interfaceName> | <interface#> [ <serviceName> ]]\n"
185 " create set [setName]" },
186
187 { "disable", 1, 2, do_net_disable, 4, 0,
188 " disable protocol [ <protocolType> ]\n"
189 " disable service [ <serviceName> | <service#> ]" },
190
191 { "enable", 1, 2, do_net_enable, 5, 0,
192 " enable protocol [ <protocolType> ]\n"
193 " enable service [ <serviceName> | <service#> ]" },
194
195 { "remove", 1, 2, do_net_remove, 6, 0,
196 " remove protocol [ <protocolType> ]\n"
197 " remove service [ <serviceName> | <service#> ]\n"
198 " remove set [ <setName> | <set#> ]" },
199
200 { "select", 2, 3, do_net_select, 7, 0,
201 " select interface <interfaceName> | <interface#> | $child | $service | $vlan | $bond <memberName> | $bridge <memberName>\n"
202 " select protocol <protocolType>\n"
203 " select service <serviceName> | <service#>\n"
204 " select set <setName> | <set#>" },
205
206 { "set", 2, 101, do_net_set, 8, 0,
207 " set interface context-sensitive-arguments (or ? for help)\n"
208 " set protocol context-sensitive-arguments (or ? for help)\n"
209 " set service [ name <serviceName> ] [ order new-order ] [ rank ("" | First | Last | Never | Scoped ) [temp] ] [ id <serviceID> ]\n"
210 " set set [ name setName ] | [ current ] [ id <setID> ]" },
211
212 { "show", 1, 2, do_net_show, 9, 0,
213 " show interfaces\n"
214 " show interface [ <interfaceName> | <interface#> ]\n"
215 " show protocols\n"
216 " show protocol [ <protocolType> ]\n"
217 " show services [ all ]\n"
218 " show service [ <serviceName> | <service#> ]\n"
219 " show sets\n\n"
220 " show set [ <setName> | <set#> ]" },
221
222 { "migrate", 2, 5, do_net_migrate, 10, 0,
223 " migrate perform <old-configuration> <new-configuration> [<current-configuration>]\n"
224 " migrate validate <configuration> <expected-configuration>"},
225
226 { "clean", 0, 0, do_net_clean, 11, 0,
227 " clean : clean the network configuration" },
228
229 { "update", 0, 0, do_net_update, 11, 0,
230 " update : update the network configuration" },
231
232 { "upgrade", 0, 1, do_net_upgrade, 11, 0,
233 " upgrade [ <plist-name> ] : upgrade the network configuration" },
234
235 { "snapshot", 0, 0, do_net_snapshot, 99, 2,
236 " snapshot" }
237
238 };
239 __private_extern__
240 const int nCommands_net = (sizeof(commands_net)/sizeof(cmdInfo));
241
242
243 __private_extern__
244 const cmdInfo commands_prefs[] = {
245 /* cmd minArgs maxArgs func group ctype */
246 /* usage */
247
248 { "help", 0, 0, do_help, 0, 0,
249 " help : list available commands" },
250
251 { "f.read", 1, 1, do_readFile, 0, 0,
252 " f.read file : process commands from file" },
253
254 { "quit", 0, 1, do_prefs_quit, 0, 0,
255 " quit [!] : quit" },
256
257 { "q", 0, 1, do_prefs_quit, 0, -1,
258 NULL },
259
260 { "exit", 0, 1, do_prefs_quit, 0, -1,
261 NULL },
262
263 /* local dictionary manipulation commands */
264
265 { "d.init", 0, 0, do_dictInit, 1, 0,
266 " d.init : initialize (empty) dictionary" },
267
268 { "d.show", 0, 0, do_dictShow, 1, 0,
269 " d.show : show dictionary contents" },
270
271 { "d.add", 2, 101, do_dictSetKey, 1, 0,
272 " d.add key [*#?%] val [v2 ...] : add information to dictionary\n"
273 " (*=array, #=number, ?=boolean, %=hex data)" },
274
275 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
276 " d.remove key : remove key from dictionary" },
277
278 /* data store manipulation commands */
279
280 { "open", 0, 1, do_prefs_open, 2, 1,
281 " open [\"prefsID\"] : open a \"preferences\" session" },
282
283 { "lock", 0, 1, do_prefs_lock, 3, 1,
284 " lock [wait] : locks write access to preferences" },
285
286 { "commit", 0, 0, do_prefs_commit, 2, 0,
287 " commit : commit any changes" },
288
289 { "apply", 0, 0, do_prefs_apply, 2, 0,
290 " apply : apply any changes" },
291
292 { "unlock", 0, 0, do_prefs_unlock, 3, 1,
293 " unlock : unlocks write access to preferences" },
294
295 { "close", 0, 1, do_prefs_close, 2, 1,
296 " close [!] : close current \"preference\" session" },
297
298 { "synchronize",0, 1, do_prefs_synchronize, 2, 0,
299 " synchronize : synchronize a \"preferences\" session" },
300
301 { "list", 0, 1, do_prefs_list, 4, 0,
302 " list [path] : list preference paths" },
303
304 { "get", 1, 1, do_prefs_get, 4, 0,
305 " get path : get dict from preferences w/path" },
306
307 { "set", 1, 2, do_prefs_set, 4, 0,
308 " set path : set path in preferences w/current dict\n"
309 " set path link : set path in preferences w/link" },
310
311 { "remove", 1, 1, do_prefs_remove, 4, 0,
312 " remove path : remove path from preferences" }
313 };
314 __private_extern__
315 const int nCommands_prefs = (sizeof(commands_prefs)/sizeof(cmdInfo));
316
317
318 __private_extern__ cmdInfo *commands = NULL;
319 __private_extern__ int nCommands = 0;
320 __private_extern__ Boolean enablePrivateAPI = FALSE;
321 __private_extern__ Boolean termRequested = FALSE;
322
323
324 __private_extern__
325 void
326 do_command(int argc, char **argv)
327 {
328 int i;
329 char *cmd = argv[0];
330
331 for (i = 0; i < nCommands; i++) {
332 if ((commands[i].ctype > 1) && !enablePrivateAPI) {
333 continue; /* if "private" API and access has not been enabled */
334 }
335
336 if (strcasecmp(cmd, commands[i].cmd) == 0) {
337 --argc;
338 argv++;
339 if (argc < commands[i].minArgs) {
340 SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd);
341 return;
342 } else if (argc > commands[i].maxArgs) {
343 SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
344 return;
345 }
346 (*commands[i].func)(argc, argv);
347 return;
348 }
349 }
350
351 SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd);
352 return;
353 }
354
355
356 __private_extern__
357 void
358 do_help(int argc, char **argv)
359 {
360 #pragma unused(argc)
361 #pragma unused(argv)
362 int g = -1; /* current group */
363 int i;
364
365 SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
366 for (i = 0; i < nCommands; i++) {
367 if (commands[i].ctype < 0) {
368 continue; /* if "hidden" */
369 }
370
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 */
376 if (g != commands[i].group) {
377 SCPrint(TRUE, stdout, CFSTR("\n"));
378 g = commands[i].group;
379 }
380
381 /* display the command */
382 SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage);
383 }
384 SCPrint(TRUE, stdout, CFSTR("\n"));
385
386 return;
387 }
388
389
390 __private_extern__
391 void
392 do_readFile(int argc, char **argv)
393 {
394 #pragma unused(argc)
395 InputRef src;
396
397 /* allocate command input stream */
398 src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
399 src->el = NULL;
400 src->h = NULL;
401 src->fp = fopen(argv[0], "r");
402
403 if (src->fp == NULL) {
404 SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno));
405 CFAllocatorDeallocate(NULL, src);
406 return;
407 }
408
409 /* open file, increase nesting level */
410 SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]);
411 nesting++;
412
413 while (TRUE) {
414 Boolean ok;
415
416 ok = process_line(src);
417 if (!ok) {
418 break;
419 }
420 }
421
422 (void)fclose(src->fp);
423 CFAllocatorDeallocate(NULL, src);
424
425 return;
426 }
427
428
429 __private_extern__
430 void
431 do_quit(int argc, char **argv)
432 {
433 #pragma unused(argc)
434 #pragma unused(argv)
435 termRequested = TRUE;
436 return;
437 }