]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/notify.c
configd-53.1.tar.gz
[apple/configd.git] / scutil.tproj / notify.c
CommitLineData
5958d7c0 1/*
a5f60add 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
5958d7c0
A
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
0fae82ee
A
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
5958d7c0
A
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <sys/un.h>
36#include <unistd.h>
37
38#include "scutil.h"
39
0fae82ee
A
40#include <SystemConfiguration/SCPrivate.h>
41#include "v1Compatibility.h"
42
43
44static int osig;
45static struct sigaction *oact = NULL;
46
47
48static CFComparisonResult
49sort_keys(const void *p1, const void *p2, void *context) {
50 CFStringRef key1 = (CFStringRef)p1;
51 CFStringRef key2 = (CFStringRef)p2;
52 return CFStringCompare(key1, key2, 0);
53}
54
5958d7c0
A
55
56void
0fae82ee 57storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
5958d7c0 58{
5958d7c0 59 int i;
0fae82ee
A
60 CFIndex n;
61
62 SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
63
64 n = CFArrayGetCount(changedKeys);
65 if (n > 0) {
66 for (i=0; i<n; i++) {
67 SCPrint(TRUE,
68 stdout,
a5f60add 69 CFSTR(" changed key [%d] = %@\n"),
0fae82ee
A
70 i,
71 CFArrayGetValueAtIndex(changedKeys, i));
72 }
73 } else {
a5f60add 74 SCPrint(TRUE, stdout, CFSTR(" no changed key's.\n"));
0fae82ee
A
75 }
76
77 return;
78}
79
80
81void
82do_notify_list(int argc, char **argv)
83{
84 int i;
85 CFArrayRef list;
86 CFIndex listCnt;
87 Boolean isRegex = FALSE;
88 CFMutableArrayRef sortedList;
5958d7c0
A
89
90 if (argc == 1)
0fae82ee 91 isRegex = TRUE;
5958d7c0 92
0fae82ee
A
93 list = SCDynamicStoreCopyWatchedKeyList(store, isRegex);
94 if (!list) {
a5f60add
A
95 if (SCError() != kSCStatusOK) {
96 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
97 } else {
98 SCPrint(TRUE,
99 stdout,
100 CFSTR(" no notifier %s.\n"),
101 isRegex ? "patterns" : "keys");
102 }
5958d7c0
A
103 return;
104 }
105
106 listCnt = CFArrayGetCount(list);
0fae82ee
A
107 sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
108 CFRelease(list);
109 CFArraySortValues(sortedList,
110 CFRangeMake(0, listCnt),
111 sort_keys,
112 NULL);
113
5958d7c0
A
114 if (listCnt > 0) {
115 for (i=0; i<listCnt; i++) {
0fae82ee
A
116 SCPrint(TRUE,
117 stdout,
a5f60add
A
118 CFSTR(" notifier %s [%d] = %@\n"),
119 isRegex ? "pattern" : "key",
0fae82ee
A
120 i,
121 CFArrayGetValueAtIndex(sortedList, i));
5958d7c0
A
122 }
123 } else {
a5f60add
A
124 SCPrint(TRUE,
125 stdout,
126 CFSTR(" no notifier %s.\n"),
127 isRegex ? "patterns" : "keys");
5958d7c0 128 }
0fae82ee 129 CFRelease(sortedList);
5958d7c0
A
130
131 return;
132}
133
134
135void
136do_notify_add(int argc, char **argv)
137{
138 CFStringRef key;
0fae82ee 139 Boolean isRegex = FALSE;
5958d7c0
A
140
141 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
142
143 if (argc == 2)
0fae82ee 144 isRegex = TRUE;
5958d7c0 145
0fae82ee
A
146 if (!SCDynamicStoreAddWatchedKey(store, key, isRegex)) {
147 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0 148 }
0fae82ee 149 CFRelease(key);
5958d7c0
A
150 return;
151}
152
153
154void
155do_notify_remove(int argc, char **argv)
156{
5958d7c0 157 CFStringRef key;
0fae82ee 158 Boolean isRegex = FALSE;
5958d7c0
A
159
160 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
161
162 if (argc == 2)
0fae82ee 163 isRegex = TRUE;
5958d7c0 164
0fae82ee
A
165 if (!SCDynamicStoreRemoveWatchedKey(store, key, isRegex)) {
166 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0 167 }
0fae82ee 168 CFRelease(key);
5958d7c0
A
169 return;
170}
171
172
173void
174do_notify_changes(int argc, char **argv)
175{
176 CFArrayRef list;
177 CFIndex listCnt;
5958d7c0
A
178 int i;
179
0fae82ee
A
180 list = SCDynamicStoreCopyNotifiedKeys(store);
181 if (!list) {
182 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
183 return;
184 }
185
186 listCnt = CFArrayGetCount(list);
187 if (listCnt > 0) {
188 for (i=0; i<listCnt; i++) {
0fae82ee
A
189 SCPrint(TRUE,
190 stdout,
191 CFSTR(" changedKey [%d] = %@\n"),
192 i,
193 CFArrayGetValueAtIndex(list, i));
5958d7c0
A
194 }
195 } else {
0fae82ee 196 SCPrint(TRUE, stdout, CFSTR(" no changedKey's.\n"));
5958d7c0
A
197 }
198 CFRelease(list);
199
200 return;
201}
202
203
204void
0fae82ee 205do_notify_watch(int argc, char **argv)
5958d7c0 206{
0fae82ee
A
207 notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
208 if (!notifyRls) {
209 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
210 return;
211 }
5958d7c0 212
0fae82ee
A
213 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
214 return;
215}
216
217
218void
219do_notify_wait(int argc, char **argv)
220{
221 if (!SCDynamicStoreNotifyWait(store)) {
222 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
223 return;
224 }
225
5958d7c0
A
226 return;
227}
228
229
230static boolean_t
0fae82ee 231notificationWatcher(SCDynamicStoreRef store, void *arg)
5958d7c0 232{
0fae82ee
A
233 SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
234 SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
5958d7c0
A
235 return TRUE;
236}
237
238
239static boolean_t
0fae82ee 240notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
5958d7c0 241{
0fae82ee
A
242 SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
243 SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
5958d7c0
A
244 do_notify_changes(0, NULL); /* report the keys which changed */
245 return TRUE;
246}
247
248
249void
250do_notify_callback(int argc, char **argv)
251{
0fae82ee 252 SCDynamicStoreCallBack_v1 func = notificationWatcher;
5958d7c0
A
253
254 if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
255 func = notificationWatcherVerbose;
256 }
257
0fae82ee
A
258 if (!SCDynamicStoreNotifyCallback(store, CFRunLoopGetCurrent(), func, "Changed detected by callback handler!")) {
259 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
260 return;
261 }
262
263 return;
264}
265
266
267void
268do_notify_file(int argc, char **argv)
269{
270 int32_t reqID = 0;
5958d7c0
A
271 int fd;
272 union {
273 char data[4];
274 int32_t gotID;
275 } buf;
276 char *bufPtr;
277 int needed;
278
279 if (argc == 1) {
280 if ((sscanf(argv[0], "%d", &reqID) != 1)) {
0fae82ee 281 SCPrint(TRUE, stdout, CFSTR("invalid identifier.\n"));
5958d7c0
A
282 return;
283 }
284 }
285
0fae82ee
A
286 if (!SCDynamicStoreNotifyFileDescriptor(store, reqID, &fd)) {
287 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
288 return;
289 }
290
291 bzero(buf.data, sizeof(buf.data));
292 bufPtr = &buf.data[0];
293 needed = sizeof(buf.gotID);
294 while (needed > 0) {
295 int got;
296
297 got = read(fd, bufPtr, needed);
298 if (got == -1) {
299 /* if error detected */
0fae82ee 300 SCPrint(TRUE, stdout, CFSTR("read() failed: %s.\n"), strerror(errno));
5958d7c0
A
301 break;
302 }
303
304 if (got == 0) {
305 /* if end of file detected */
0fae82ee 306 SCPrint(TRUE, stdout, CFSTR("read(): detected end of file.\n"));
5958d7c0
A
307 break;
308 }
309
0fae82ee 310 SCPrint(TRUE, stdout, CFSTR("Received %d bytes.\n"), got);
5958d7c0
A
311 bufPtr += got;
312 needed -= got;
313 }
314
315 if (needed != sizeof(buf.gotID)) {
0fae82ee 316 SCPrint(TRUE, stdout, CFSTR(" Received notification, identifier = %d.\n"), buf.gotID);
5958d7c0
A
317 }
318
319 /* this utility only allows processes one notification per "n.file" request */
0fae82ee 320 (void) SCDynamicStoreNotifyCancel(store);
5958d7c0
A
321
322 (void) close(fd); /* close my side of the file descriptor */
323
324 return;
325}
326
327
5958d7c0
A
328static void
329signalCatcher(int signum)
330{
331 static int n = 0;
332
a5f60add 333 SCPrint(TRUE, stdout, CFSTR("Received sig%s (#%d).\n"), sys_signame[signum], n++);
5958d7c0
A
334 return;
335}
336
337
338void
339do_notify_signal(int argc, char **argv)
340{
341 int sig;
342 pid_t pid;
343 struct sigaction nact;
344 int ret;
5958d7c0
A
345
346 if (isdigit(*argv[0])) {
347 if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
0fae82ee 348 SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1);
5958d7c0
A
349 return;
350 }
351 } else {
352 for (sig=1; sig<NSIG; sig++) {
a5f60add 353 if (strcasecmp(argv[0], sys_signame[sig]) == 0)
5958d7c0
A
354 break;
355 }
356 if (sig >= NSIG) {
0fae82ee
A
357 CFMutableStringRef str;
358
359 SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n"));
360
361 str = CFStringCreateMutable(NULL, 0);
5958d7c0 362 for (sig=1; sig<NSIG; sig++) {
a5f60add 363 CFStringAppendFormat(str, NULL, CFSTR(" %-6s"), sys_signame[sig]);
0fae82ee
A
364 if ((sig % 10) == 0) {
365 CFStringAppendFormat(str, NULL, CFSTR("\n"));
366 }
367 }
368 if ((sig % 10) != 0) {
369 CFStringAppendFormat(str, NULL, CFSTR("\n"));
5958d7c0 370 }
0fae82ee
A
371 SCPrint(TRUE, stdout, CFSTR("%@"), str);
372 CFRelease(str);
5958d7c0
A
373 return;
374 }
375
376 }
377
378 if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
379 pid = getpid();
380 }
381
382 if (oact != NULL) {
383 ret = sigaction(osig, oact, NULL); /* restore original signal handler */
384 } else {
385 oact = malloc(sizeof(struct sigaction));
386 }
387
388 nact.sa_handler = signalCatcher;
389 sigemptyset(&nact.sa_mask);
390 nact.sa_flags = SA_RESTART;
391 ret = sigaction(sig, &nact, oact);
392 osig = sig;
0fae82ee 393 SCPrint(TRUE, stdout, CFSTR("signal handler started.\n"));
5958d7c0 394
0fae82ee
A
395 if (!SCDynamicStoreNotifySignal(store, pid, sig)) {
396 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
397 return;
398 }
399
400 return;
401}
402
403
404void
405do_notify_cancel(int argc, char **argv)
406{
5958d7c0
A
407 int ret;
408
0fae82ee
A
409 if (notifyRls) {
410 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
411 CFRelease(notifyRls);
412 notifyRls = NULL;
413 }
414
415 if (!SCDynamicStoreNotifyCancel(store)) {
416 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
5958d7c0
A
417 return;
418 }
419
420 if (oact != NULL) {
421 ret = sigaction(osig, oact, NULL); /* restore original signal handler */
422 free(oact);
423 oact = NULL;
424 }
425
426 return;
427}