]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/commands.c
configd-42.tar.gz
[apple/configd.git] / scutil.tproj / commands.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * November 9, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/errno.h>
36
37 #include "scutil.h"
38 #include "commands.h"
39 #include "dictionary.h"
40 #include "session.h"
41 #include "cache.h"
42 #include "notify.h"
43 #include "tests.h"
44
45 #include <SystemConfiguration/SCPrivate.h>
46
47
48 const cmdInfo commands[] = {
49 /* cmd minArgs maxArgs func group ctype */
50 /* usage */
51
52 { "help", 0, 0, do_help, 0, 0,
53 " help : list available commands" },
54
55 { "f.read", 1, 1, do_readFile, 0, 0,
56 " f.read file : process commands from file" },
57
58 /* local dictionary manipulation commands */
59
60 { "d.init", 0, 0, do_dictInit, 1, 0,
61 " d.init : initialize (empty) dictionary" },
62
63 { "d.show", 0, 0, do_dictShow, 1, 0,
64 " d.show : show dictionary contents" },
65
66 { "d.add", 2, 101, do_dictSetKey, 1, 0,
67 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
68 " (*=array, #=number, ?=boolean)" },
69
70 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
71 " d.remove key : remove key from dictionary" },
72
73 /* data store manipulation commands */
74
75 { "open", 0, 0, do_open, 2, 0,
76 " open : open a session with \"configd\"" },
77
78 { "close", 0, 0, do_close, 2, 0,
79 " close : close current \"configd\" session" },
80
81 { "lock", 0, 0, do_lock, 3, 1,
82 " lock : secures write access to data store" },
83
84 { "unlock", 0, 0, do_unlock, 3, 1,
85 " unlock : secures write access to data store" },
86
87 { "list", 0, 2, do_list, 4, 0,
88 " list [pattern] : list keys in data store" },
89
90 { "add", 1, 2, do_add, 4, 0,
91 " add key [\"temporary\"] : add key in data store w/current dict" },
92
93 { "get", 1, 1, do_get, 4, 0,
94 " get key : get dict from data store w/key" },
95
96 { "set", 1, 1, do_set, 4, 0,
97 " set key : set key in data store w/current dict" },
98
99 { "show", 1, 1, do_show, 4, 1,
100 " show key : show dict in data store w/key" },
101
102 { "remove", 1, 1, do_remove, 4, 0,
103 " remove key : remove key from data store" },
104
105 { "notify", 1, 1, do_notify, 4, 0,
106 " notify key : notify key in data store" },
107
108 { "touch", 1, 1, do_touch, 4, 1,
109 " touch key : touch key in data store" },
110
111 { "n.list", 0, 1, do_notify_list, 5, 0,
112 " n.list [\"pattern\"] : list notification keys" },
113
114 { "n.add", 1, 2, do_notify_add, 5, 0,
115 " n.add key [\"pattern\"] : add notification key" },
116
117 { "n.remove", 1, 2, do_notify_remove, 5, 0,
118 " n.remove key [\"pattern\"] : remove notification key" },
119
120 { "n.changes", 0, 0, do_notify_changes, 5, 0,
121 " n.changes : list changed keys" },
122
123 { "n.watch", 0, 1, do_notify_watch, 5, 0,
124 " n.watch [verbose] : watch for changes" },
125
126 { "n.wait", 0, 0, do_notify_wait, 5, 2,
127 " n.wait : wait for changes" },
128
129 { "n.callback", 0, 1, do_notify_callback, 5, 2,
130 " n.callback [\"verbose\"] : watch for changes" },
131
132 { "n.signal", 1, 2, do_notify_signal, 5, 2,
133 " n.signal sig [pid] : signal changes" },
134
135 { "n.file", 0, 1, do_notify_file, 5, 2,
136 " n.file [identifier] : watch for changes via file" },
137
138 { "n.cancel", 0, 1, do_notify_cancel, 5, 0,
139 " n.cancel : cancel notification requests" },
140
141 { "snapshot", 0, 0, do_snapshot, 9, 2,
142 " snapshot : save snapshot of store and session data" },
143 };
144
145 const int nCommands = (sizeof(commands)/sizeof(cmdInfo));
146
147 Boolean enablePrivateAPI = FALSE;
148
149
150 void
151 do_command(int argc, char **argv)
152 {
153 int i;
154 char *cmd = argv[0];
155
156 for (i=0; i<nCommands; i++) {
157 if ((commands[i].ctype > 1) && !enablePrivateAPI) {
158 continue; /* if "private" API and access has not been enabled */
159 }
160
161 if (strcasecmp(cmd, commands[i].cmd) == 0) {
162 --argc;
163 argv++;
164 if (argc < commands[i].minArgs) {
165 SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd);
166 return;
167 } else if (argc > commands[i].maxArgs) {
168 SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
169 return;
170 }
171 commands[i].func(argc, argv);
172 return;
173 }
174 }
175
176 SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd);
177 return;
178 }
179
180
181 void
182 do_help(int argc, char **argv)
183 {
184 int g = -1; /* current group */
185 int i;
186
187 SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
188 for (i=0; i<nCommands; i++) {
189 if ((commands[i].ctype > 0) && !enablePrivateAPI) {
190 continue; /* if "private" API and access has not been enabled */
191 }
192
193 /* check if this is a new command group */
194 if (g != commands[i].group) {
195 SCPrint(TRUE, stdout, CFSTR("\n"));
196 g = commands[i].group;
197 }
198
199 /* display the command */
200 SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage);
201 }
202 SCPrint(TRUE, stdout, CFSTR("\n"));
203
204 return;
205 }
206
207
208 void
209 do_readFile(int argc, char **argv)
210 {
211 CFSocketContext context;
212 FILE *fp = fopen(argv[0], "r");
213 CFSocketRef in;
214 CFRunLoopSourceRef rls;
215
216 if (fp == NULL) {
217 SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno));
218 return;
219 }
220
221 /* open file, increase nesting level */
222 SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]);
223 nesting++;
224
225 /* create a "socket" reference with the file descriptor associated with stdin */
226 context.version = 0;
227 context.info = fp;
228 context.retain = NULL;
229 context.release = NULL;
230 context.copyDescription = NULL;
231 in = CFSocketCreateWithNative(NULL,
232 fileno(fp),
233 kCFSocketReadCallBack,
234 runLoopProcessInput,
235 &context);
236
237 /* Create and add a run loop source for the file descriptor */
238 rls = CFSocketCreateRunLoopSource(NULL, in, nesting);
239
240 /*
241 * Remove the current input file from the run loop sources. We
242 * will reactivate the current input file source when we are
243 * finished reading data from the new file.
244 */
245 CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
246 (CFRunLoopSourceRef) CFArrayGetValueAtIndex(sources, 0),
247 kCFRunLoopDefaultMode);
248
249 /* keep track of this new source */
250 CFArrayInsertValueAtIndex(sources, 0, rls);
251
252 /* add this source to the run loop */
253 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
254
255 CFRelease(rls);
256 CFRelease(in);
257
258 return;
259 }