561f15c1e5d13f55bc4b679b071f6920373f519a
[apple/configd.git] / scutil.tproj / commands.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, 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 "notify.h"
44 #include "tests.h"
45
46 #include "SCDynamicStoreInternal.h"
47
48
49 const cmdInfo commands[] = {
50 /* cmd minArgs maxArgs func group ctype */
51 /* usage */
52
53 { "help", 0, 0, do_help, 0, 0,
54 " help : list available commands" },
55
56 { "f.read", 1, 1, do_readFile, 0, 0,
57 " f.read file : process commands from file" },
58
59 /* local dictionary manipulation commands */
60
61 { "d.init", 0, 0, do_dictInit, 1, 0,
62 " d.init : initialize (empty) dictionary" },
63
64 { "d.show", 0, 0, do_dictShow, 1, 0,
65 " d.show : show dictionary contents" },
66
67 { "d.add", 2, 101, do_dictSetKey, 1, 0,
68 " d.add key [*#?] val [v2 ...] : add information to dictionary\n"
69 " (*=array, #=number, ?=boolean)" },
70
71 { "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
72 " d.remove key : remove key from dictionary" },
73
74 /* data store manipulation commands */
75
76 { "open", 0, 0, do_open, 2, 0,
77 " open : open a session with \"configd\"" },
78
79 { "close", 0, 0, do_close, 2, 0,
80 " close : close current \"configd\" session" },
81
82 { "lock", 0, 0, do_lock, 3, 1,
83 " lock : secures write access to data store" },
84
85 { "unlock", 0, 0, do_unlock, 3, 1,
86 " unlock : secures write access to data store" },
87
88 { "list", 0, 2, do_list, 4, 0,
89 " list [pattern] : list keys in data store" },
90
91 { "add", 1, 2, do_add, 4, 0,
92 " add key [\"temporary\"] : add key in data store w/current dict" },
93
94 { "get", 1, 1, do_get, 4, 0,
95 " get key : get dict from data store w/key" },
96
97 { "set", 1, 1, do_set, 4, 0,
98 " set key : set key in data store w/current dict" },
99
100 { "show", 1, 2, do_show, 4, 0,
101 " show key [\"pattern\"] : show values in data store w/key" },
102
103 { "remove", 1, 1, do_remove, 4, 0,
104 " remove key : remove key from data store" },
105
106 { "notify", 1, 1, do_notify, 4, 0,
107 " notify key : notify key in data store" },
108
109 { "touch", 1, 1, do_touch, 4, 1,
110 " touch key : touch key in data store" },
111
112 { "n.list", 0, 1, do_notify_list, 5, 0,
113 " n.list [\"pattern\"] : list notification keys" },
114
115 { "n.add", 1, 2, do_notify_add, 5, 0,
116 " n.add key [\"pattern\"] : add notification key" },
117
118 { "n.remove", 1, 2, do_notify_remove, 5, 0,
119 " n.remove key [\"pattern\"] : remove notification key" },
120
121 { "n.changes", 0, 0, do_notify_changes, 5, 0,
122 " n.changes : list changed keys" },
123
124 { "n.watch", 0, 1, do_notify_watch, 5, 0,
125 " n.watch [verbose] : watch for changes" },
126
127 { "n.wait", 0, 0, do_notify_wait, 5, 2,
128 " n.wait : wait for changes" },
129
130 { "n.callback", 0, 1, do_notify_callback, 5, 2,
131 " n.callback [\"verbose\"] : watch for changes" },
132
133 { "n.signal", 1, 2, do_notify_signal, 5, 2,
134 " n.signal sig [pid] : signal changes" },
135
136 { "n.file", 0, 1, do_notify_file, 5, 2,
137 " n.file [identifier] : watch for changes via file" },
138
139 { "n.cancel", 0, 1, do_notify_cancel, 5, 0,
140 " n.cancel : cancel notification requests" },
141
142 { "snapshot", 0, 0, do_snapshot, 9, 2,
143 " snapshot : save snapshot of store and session data" },
144 };
145
146 const int nCommands = (sizeof(commands)/sizeof(cmdInfo));
147
148 Boolean enablePrivateAPI = FALSE;
149
150
151 void
152 do_command(int argc, char **argv)
153 {
154 int i;
155 char *cmd = argv[0];
156
157 for (i = 0; i < nCommands; i++) {
158 if ((commands[i].ctype > 1) && !enablePrivateAPI) {
159 continue; /* if "private" API and access has not been enabled */
160 }
161
162 if (strcasecmp(cmd, commands[i].cmd) == 0) {
163 --argc;
164 argv++;
165 if (argc < commands[i].minArgs) {
166 SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd);
167 return;
168 } else if (argc > commands[i].maxArgs) {
169 SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
170 return;
171 }
172 commands[i].func(argc, argv);
173 return;
174 }
175 }
176
177 SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd);
178 return;
179 }
180
181
182 void
183 do_help(int argc, char **argv)
184 {
185 int g = -1; /* current group */
186 int i;
187
188 SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
189 for (i = 0; i < nCommands; i++) {
190 if ((commands[i].ctype > 0) && !enablePrivateAPI) {
191 continue; /* if "private" API and access has not been enabled */
192 }
193
194 /* check if this is a new command group */
195 if (g != commands[i].group) {
196 SCPrint(TRUE, stdout, CFSTR("\n"));
197 g = commands[i].group;
198 }
199
200 /* display the command */
201 SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage);
202 }
203 SCPrint(TRUE, stdout, CFSTR("\n"));
204
205 return;
206 }
207
208
209 void
210 do_readFile(int argc, char **argv)
211 {
212 InputRef src;
213
214 /* allocate command input stream */
215 src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
216 src->el = NULL;
217 src->fp = fopen(argv[0], "r");
218
219 if (src->fp == NULL) {
220 SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno));
221 CFAllocatorDeallocate(NULL, src);
222 return;
223 }
224
225 /* open file, increase nesting level */
226 SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]);
227 nesting++;
228
229 while (process_line(src) == TRUE) {
230 /* debug information, diagnostics */
231 __showMachPortStatus();
232 }
233
234 (void)fclose(src->fp);
235 CFAllocatorDeallocate(NULL, src);
236
237 return;
238 }