1/* 2 * Copyright (c) 2000-2011 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__ 50const 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.signal", 1, 2, do_notify_signal, 5, 2, 135 " n.signal sig [pid] : signal changes" }, 136 137 { "n.file", 0, 1, do_notify_file, 5, 2, 138 " n.file [identifier] : watch for changes via file" }, 139 140 { "n.cancel", 0, 1, do_notify_cancel, 5, 0, 141 " n.cancel : cancel notification requests" }, 142 143 { "snapshot", 0, 0, do_snapshot, 99, 2, 144 " snapshot : save snapshot of store and session data" } 145}; 146__private_extern__ 147const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo)); 148 149 150__private_extern__ 151const cmdInfo commands_net[] = { 152 /* cmd minArgs maxArgs func group ctype */ 153 /* usage */ 154 155 { "help", 0, 0, do_help, 0, 0, 156 " help : list available commands" }, 157 158 { "f.read", 1, 1, do_readFile, 0, 0, 159 " f.read file : process commands from file" }, 160 161 { "quit", 0, 1, do_net_quit, 0, 0, 162 " quit [!] : quit" }, 163 164 { "q", 0, 1, do_net_quit, 0, -1, 165 NULL }, 166 167 { "exit", 0, 1, do_net_quit, 0, -1, 168 NULL }, 169 170 /* network configuration manipulation commands */ 171 172 { "open", 0, 1, do_net_open, 2, 1, 173 " open : open the network configuration" }, 174 175 { "commit", 0, 0, do_net_commit, 2, 0, 176 " commit : commit any changes" }, 177 178 { "apply", 0, 0, do_net_apply, 2, 0, 179 " apply : apply any changes" }, 180 181 { "close", 0, 1, do_net_close, 2, 1, 182 " close [!] : close the network configuration" }, 183 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]" }, 189 190 { "disable", 1, 2, do_net_disable, 4, 0, 191 " disable protocol [ <protocolType> ]\n" 192 " disable service [ <serviceName> | <service#> ]" }, 193 194 { "enable", 1, 2, do_net_enable, 5, 0, 195 " enable protocol [ <protocolType> ]\n" 196 " enable service [ <serviceName> | <service#> ]" }, 197 198 { "remove", 1, 2, do_net_remove, 6, 0, 199 " remove protocol [ <protocolType> ]\n" 200 " remove service [ <serviceName> | <service#> ]\n" 201 " remove set [ <setName> | <set#> ]" }, 202 203 { "select", 2, 3, do_net_select, 7, 0, 204 " select interface <interfaceName> | <interface#> | $child | $service | $vlan | $bond <memberName> | $bridge <memberName>\n" 205 " select protocol <protocolType>\n" 206 " select service <serviceName> | <service#>\n" 207 " select set <setName> | <set#>" }, 208 209 { "set", 2, 101, do_net_set, 8, 0, 210 " set interface context-sensitive-arguments (or ? for help)\n" 211 " set protocol context-sensitive-arguments (or ? for help)\n" 212 " set service [ name <serviceName> ] [ order new-order ] [ rank ("" | First | Last | Never) [temp] ]\n" 213 " set set [ name setName ] | [ current ]" }, 214 215 { "show", 1, 2, do_net_show, 9, 0, 216 " show interfaces\n" 217 " show interface [ <interfaceName> | <interface#> ]\n" 218 " show protocols\n" 219 " show protocol [ <protocolType> ]\n" 220 " show services [ all ]\n" 221 " show service [ <serviceName> | <service#> ]\n" 222 " show sets\n\n" 223 " show set [ <setName> | <set#> ]" }, 224 225 { "update", 0, 1, do_net_update, 10, 0, 226 " update : update the network configuration" }, 227 228 { "snapshot", 0, 0, do_net_snapshot, 99, 2, 229 " snapshot" } 230 231}; 232__private_extern__ 233const int nCommands_net = (sizeof(commands_net)/sizeof(cmdInfo)); 234 235 236__private_extern__ 237const cmdInfo commands_prefs[] = { 238 /* cmd minArgs maxArgs func group ctype */ 239 /* usage */ 240 241 { "help", 0, 0, do_help, 0, 0, 242 " help : list available commands" }, 243 244 { "f.read", 1, 1, do_readFile, 0, 0, 245 " f.read file : process commands from file" }, 246 247 { "quit", 0, 1, do_prefs_quit, 0, 0, 248 " quit [!] : quit" }, 249 250 { "q", 0, 1, do_prefs_quit, 0, -1, 251 NULL }, 252 253 { "exit", 0, 1, do_prefs_quit, 0, -1, 254 NULL }, 255 256 /* local dictionary manipulation commands */ 257 258 { "d.init", 0, 0, do_dictInit, 1, 0, 259 " d.init : initialize (empty) dictionary" }, 260 261 { "d.show", 0, 0, do_dictShow, 1, 0, 262 " d.show : show dictionary contents" }, 263 264 { "d.add", 2, 101, do_dictSetKey, 1, 0, 265 " d.add key [*#?] val [v2 ...] : add information to dictionary\n" 266 " (*=array, #=number, ?=boolean, %=hex data)" }, 267 268 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0, 269 " d.remove key : remove key from dictionary" }, 270 271 /* data store manipulation commands */ 272 273 { "open", 0, 1, do_prefs_open, 2, 1, 274 " open [\"prefsID\"] : open a \"preferences\" session" }, 275 276 { "lock", 0, 1, do_prefs_lock, 3, 1, 277 " lock [wait] : locks write access to preferences" }, 278 279 { "commit", 0, 0, do_prefs_commit, 2, 0, 280 " commit : commit any changes" }, 281 282 { "apply", 0, 0, do_prefs_apply, 2, 0, 283 " apply : apply any changes" }, 284 285 { "unlock", 0, 0, do_prefs_unlock, 3, 1, 286 " unlock : unlocks write access to preferences" }, 287 288 { "close", 0, 1, do_prefs_close, 2, 1, 289 " close [!] : close current \"preference\" session" }, 290 291 { "synchronize",0, 1, do_prefs_synchronize, 2, 0, 292 " synchronize : synchronize a \"preferences\" session" }, 293 294 { "list", 0, 1, do_prefs_list, 4, 0, 295 " list [path] : list preference paths" }, 296 297 { "get", 1, 1, do_prefs_get, 4, 0, 298 " get path : get dict from preferences w/path" }, 299 300 { "set", 1, 2, do_prefs_set, 4, 0, 301 " set path : set path in preferences w/current dict\n" 302 " set path link : set path in preferences w/link" }, 303 304 { "remove", 1, 1, do_prefs_remove, 4, 0, 305 " remove path : remove path from preferences" } 306}; 307__private_extern__ 308const int nCommands_prefs = (sizeof(commands_prefs)/sizeof(cmdInfo)); 309 310 311__private_extern__ cmdInfo *commands = NULL; 312__private_extern__ int nCommands = 0; 313__private_extern__ Boolean enablePrivateAPI = FALSE; 314__private_extern__ Boolean termRequested = FALSE; 315 316 317__private_extern__ 318void 319do_command(int argc, char **argv) 320{ 321 int i; 322 char *cmd = argv[0]; 323 324 for (i = 0; i < nCommands; i++) { 325 if ((commands[i].ctype > 1) && !enablePrivateAPI) { 326 continue; /* if "private" API and access has not been enabled */ 327 } 328 329 if (strcasecmp(cmd, commands[i].cmd) == 0) { 330 --argc; 331 argv++; 332 if (argc < commands[i].minArgs) { 333 SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd); 334 return; 335 } else if (argc > commands[i].maxArgs) { 336 SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd); 337 return; 338 } 339 (*commands[i].func)(argc, argv); 340 return; 341 } 342 } 343 344 SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd); 345 return; 346} 347 348 349__private_extern__ 350void 351do_help(int argc, char **argv) 352{ 353 int g = -1; /* current group */ 354 int i; 355 356 SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n")); 357 for (i = 0; i < nCommands; i++) { 358 if (commands[i].ctype < 0) { 359 continue; /* if "hidden" */ 360 } 361 362 if ((commands[i].ctype > 0) && !enablePrivateAPI) { 363 continue; /* if "private" API and access has not been enabled */ 364 } 365 366 /* check if this is a new command group */ 367 if (g != commands[i].group) { 368 SCPrint(TRUE, stdout, CFSTR("\n")); 369 g = commands[i].group; 370 } 371 372 /* display the command */ 373 SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage); 374 } 375 SCPrint(TRUE, stdout, CFSTR("\n")); 376 377 return; 378} 379 380 381__private_extern__ 382void 383do_readFile(int argc, char **argv) 384{ 385 InputRef src; 386 387 /* allocate command input stream */ 388 src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); 389 src->el = NULL; 390 src->h = NULL; 391 src->fp = fopen(argv[0], "r"); 392 393 if (src->fp == NULL) { 394 SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno)); 395 CFAllocatorDeallocate(NULL, src); 396 return; 397 } 398 399 /* open file, increase nesting level */ 400 SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]); 401 nesting++; 402 403 while (TRUE) { 404 Boolean ok; 405 406 ok = process_line(src); 407 if (!ok) { 408 break; 409 } 410 } 411 412 (void)fclose(src->fp); 413 CFAllocatorDeallocate(NULL, src); 414 415 return; 416} 417 418 419__private_extern__ 420void 421do_quit(int argc, char **argv) 422{ 423 termRequested = TRUE; 424 return; 425} 426