/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * * June 1, 2001 Allan Nathanson * - public API conversion * * November 9, 2000 Allan Nathanson * - initial revision */ #include #include #include #include "scutil.h" #include "commands.h" #include "dictionary.h" #include "session.h" #include "cache.h" #include "notify.h" #include "tests.h" #include const cmdInfo commands[] = { /* cmd minArgs maxArgs func group ctype */ /* usage */ { "help", 0, 0, do_help, 0, 0, " help : list available commands" }, { "f.read", 1, 1, do_readFile, 0, 0, " f.read file : process commands from file" }, /* local dictionary manipulation commands */ { "d.init", 0, 0, do_dictInit, 1, 0, " d.init : initialize (empty) dictionary" }, { "d.show", 0, 0, do_dictShow, 1, 0, " d.show : show dictionary contents" }, { "d.add", 2, 101, do_dictSetKey, 1, 0, " d.add key [*#?] val [v2 ...] : add information to dictionary\n" " (*=array, #=number, ?=boolean)" }, { "d.remove", 1, 1, do_dictRemoveKey, 1, 0, " d.remove key : remove key from dictionary" }, /* data store manipulation commands */ { "open", 0, 0, do_open, 2, 0, " open : open a session with \"configd\"" }, { "close", 0, 0, do_close, 2, 0, " close : close current \"configd\" session" }, { "lock", 0, 0, do_lock, 3, 1, " lock : secures write access to data store" }, { "unlock", 0, 0, do_unlock, 3, 1, " unlock : secures write access to data store" }, { "list", 0, 2, do_list, 4, 0, " list [pattern] : list keys in data store" }, { "add", 1, 2, do_add, 4, 0, " add key [\"temporary\"] : add key in data store w/current dict" }, { "get", 1, 1, do_get, 4, 0, " get key : get dict from data store w/key" }, { "set", 1, 1, do_set, 4, 0, " set key : set key in data store w/current dict" }, { "show", 1, 1, do_show, 4, 1, " show key : show dict in data store w/key" }, { "remove", 1, 1, do_remove, 4, 0, " remove key : remove key from data store" }, { "notify", 1, 1, do_notify, 4, 0, " notify key : notify key in data store" }, { "touch", 1, 1, do_touch, 4, 1, " touch key : touch key in data store" }, { "n.list", 0, 1, do_notify_list, 5, 0, " n.list [\"pattern\"] : list notification keys" }, { "n.add", 1, 2, do_notify_add, 5, 0, " n.add key [\"pattern\"] : add notification key" }, { "n.remove", 1, 2, do_notify_remove, 5, 0, " n.remove key [\"pattern\"] : remove notification key" }, { "n.changes", 0, 0, do_notify_changes, 5, 0, " n.changes : list changed keys" }, { "n.watch", 0, 1, do_notify_watch, 5, 0, " n.watch [verbose] : watch for changes" }, { "n.wait", 0, 0, do_notify_wait, 5, 2, " n.wait : wait for changes" }, { "n.callback", 0, 1, do_notify_callback, 5, 2, " n.callback [\"verbose\"] : watch for changes" }, { "n.signal", 1, 2, do_notify_signal, 5, 2, " n.signal sig [pid] : signal changes" }, { "n.file", 0, 1, do_notify_file, 5, 2, " n.file [identifier] : watch for changes via file" }, { "n.cancel", 0, 1, do_notify_cancel, 5, 0, " n.cancel : cancel notification requests" }, { "snapshot", 0, 0, do_snapshot, 9, 2, " snapshot : save snapshot of store and session data" }, }; const int nCommands = (sizeof(commands)/sizeof(cmdInfo)); Boolean enablePrivateAPI = FALSE; void do_command(int argc, char **argv) { int i; char *cmd = argv[0]; for (i=0; i 1) && !enablePrivateAPI) { continue; /* if "private" API and access has not been enabled */ } if (strcasecmp(cmd, commands[i].cmd) == 0) { --argc; argv++; if (argc < commands[i].minArgs) { SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd); return; } else if (argc > commands[i].maxArgs) { SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd); return; } commands[i].func(argc, argv); return; } } SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd); return; } void do_help(int argc, char **argv) { int g = -1; /* current group */ int i; SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n")); for (i=0; i 0) && !enablePrivateAPI) { continue; /* if "private" API and access has not been enabled */ } /* check if this is a new command group */ if (g != commands[i].group) { SCPrint(TRUE, stdout, CFSTR("\n")); g = commands[i].group; } /* display the command */ SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage); } SCPrint(TRUE, stdout, CFSTR("\n")); return; } void do_readFile(int argc, char **argv) { CFSocketContext context; FILE *fp = fopen(argv[0], "r"); CFSocketRef in; CFRunLoopSourceRef rls; if (fp == NULL) { SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno)); return; } /* open file, increase nesting level */ SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]); nesting++; /* create a "socket" reference with the file descriptor associated with stdin */ context.version = 0; context.info = fp; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; in = CFSocketCreateWithNative(NULL, fileno(fp), kCFSocketReadCallBack, runLoopProcessInput, &context); /* Create and add a run loop source for the file descriptor */ rls = CFSocketCreateRunLoopSource(NULL, in, nesting); /* * Remove the current input file from the run loop sources. We * will reactivate the current input file source when we are * finished reading data from the new file. */ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), (CFRunLoopSourceRef) CFArrayGetValueAtIndex(sources, 0), kCFRunLoopDefaultMode); /* keep track of this new source */ CFArrayInsertValueAtIndex(sources, 0, rls); /* add this source to the run loop */ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); CFRelease(in); return; }