2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * November 9, 2000 Allan Nathanson <ajn@apple.com>
33 #include <sys/types.h>
34 #include <sys/socket.h>
40 #include <SystemConfiguration/SCPrivate.h>
41 #include "v1Compatibility.h"
45 static struct sigaction
*oact
= NULL
;
48 static CFComparisonResult
49 sort_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);
57 storeCallback(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *info
)
62 SCPrint(TRUE
, stdout
, CFSTR("notification callback (store address = %p).\n"), store
);
64 n
= CFArrayGetCount(changedKeys
);
69 CFSTR(" changedKey [%d] = %@\n"),
71 CFArrayGetValueAtIndex(changedKeys
, i
));
74 SCPrint(TRUE
, stdout
, CFSTR(" no changedKey's.\n"));
82 do_notify_list(int argc
, char **argv
)
87 Boolean isRegex
= FALSE
;
88 CFMutableArrayRef sortedList
;
93 list
= SCDynamicStoreCopyWatchedKeyList(store
, isRegex
);
95 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
99 listCnt
= CFArrayGetCount(list
);
100 sortedList
= CFArrayCreateMutableCopy(NULL
, listCnt
, list
);
102 CFArraySortValues(sortedList
,
103 CFRangeMake(0, listCnt
),
108 for (i
=0; i
<listCnt
; i
++) {
111 CFSTR(" notifierKey [%d] = %@\n"),
113 CFArrayGetValueAtIndex(sortedList
, i
));
116 SCPrint(TRUE
, stdout
, CFSTR(" no notifierKey's.\n"));
118 CFRelease(sortedList
);
125 do_notify_add(int argc
, char **argv
)
128 Boolean isRegex
= FALSE
;
130 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingMacRoman
);
135 if (!SCDynamicStoreAddWatchedKey(store
, key
, isRegex
)) {
136 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
144 do_notify_remove(int argc
, char **argv
)
147 Boolean isRegex
= FALSE
;
149 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingMacRoman
);
154 if (!SCDynamicStoreRemoveWatchedKey(store
, key
, isRegex
)) {
155 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
163 do_notify_changes(int argc
, char **argv
)
169 list
= SCDynamicStoreCopyNotifiedKeys(store
);
171 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
175 listCnt
= CFArrayGetCount(list
);
177 for (i
=0; i
<listCnt
; i
++) {
180 CFSTR(" changedKey [%d] = %@\n"),
182 CFArrayGetValueAtIndex(list
, i
));
185 SCPrint(TRUE
, stdout
, CFSTR(" no changedKey's.\n"));
194 do_notify_watch(int argc
, char **argv
)
196 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
198 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
202 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
208 do_notify_wait(int argc
, char **argv
)
210 if (!SCDynamicStoreNotifyWait(store
)) {
211 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
220 notificationWatcher(SCDynamicStoreRef store
, void *arg
)
222 SCPrint(TRUE
, stdout
, CFSTR("notification callback (store address = %p).\n"), store
);
223 SCPrint(TRUE
, stdout
, CFSTR(" arg = %s.\n"), (char *)arg
);
229 notificationWatcherVerbose(SCDynamicStoreRef store
, void *arg
)
231 SCPrint(TRUE
, stdout
, CFSTR("notification callback (store address = %p).\n"), store
);
232 SCPrint(TRUE
, stdout
, CFSTR(" arg = %s.\n"), (char *)arg
);
233 do_notify_changes(0, NULL
); /* report the keys which changed */
239 do_notify_callback(int argc
, char **argv
)
241 SCDynamicStoreCallBack_v1 func
= notificationWatcher
;
243 if ((argc
== 1) && (strcmp(argv
[0], "verbose") == 0)) {
244 func
= notificationWatcherVerbose
;
247 if (!SCDynamicStoreNotifyCallback(store
, CFRunLoopGetCurrent(), func
, "Changed detected by callback handler!")) {
248 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
257 do_notify_file(int argc
, char **argv
)
269 if ((sscanf(argv
[0], "%d", &reqID
) != 1)) {
270 SCPrint(TRUE
, stdout
, CFSTR("invalid identifier.\n"));
275 if (!SCDynamicStoreNotifyFileDescriptor(store
, reqID
, &fd
)) {
276 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
280 bzero(buf
.data
, sizeof(buf
.data
));
281 bufPtr
= &buf
.data
[0];
282 needed
= sizeof(buf
.gotID
);
286 got
= read(fd
, bufPtr
, needed
);
288 /* if error detected */
289 SCPrint(TRUE
, stdout
, CFSTR("read() failed: %s.\n"), strerror(errno
));
294 /* if end of file detected */
295 SCPrint(TRUE
, stdout
, CFSTR("read(): detected end of file.\n"));
299 SCPrint(TRUE
, stdout
, CFSTR("Received %d bytes.\n"), got
);
304 if (needed
!= sizeof(buf
.gotID
)) {
305 SCPrint(TRUE
, stdout
, CFSTR(" Received notification, identifier = %d.\n"), buf
.gotID
);
308 /* this utility only allows processes one notification per "n.file" request */
309 (void) SCDynamicStoreNotifyCancel(store
);
311 (void) close(fd
); /* close my side of the file descriptor */
317 static char *signames
[] = {
318 "" , "HUP" , "INT" , "QUIT", "ILL" , "TRAP", "ABRT", "EMT" ,
319 "FPE" , "KILL", "BUS" , "SEGV", "SYS" , "PIPE", "ALRM", "TERM",
320 "URG" , "STOP", "TSTP" , "CONT", "CHLD" , "TTIN", "TTOU", "IO" ,
321 "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1",
327 signalCatcher(int signum
)
331 SCPrint(TRUE
, stdout
, CFSTR("Received SIG%s (#%d).\n"), signames
[signum
], n
++);
337 do_notify_signal(int argc
, char **argv
)
341 struct sigaction nact
;
344 if (isdigit(*argv
[0])) {
345 if ((sscanf(argv
[0], "%d", &sig
) != 1) || (sig
<= 0) || (sig
>= NSIG
)) {
346 SCPrint(TRUE
, stdout
, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG
-1);
350 for (sig
=1; sig
<NSIG
; sig
++) {
351 if (strcasecmp(argv
[0], signames
[sig
]) == 0)
355 CFMutableStringRef str
;
357 SCPrint(TRUE
, stdout
, CFSTR("Signal must be one of the following:\n"));
359 str
= CFStringCreateMutable(NULL
, 0);
360 for (sig
=1; sig
<NSIG
; sig
++) {
361 CFStringAppendFormat(str
, NULL
, CFSTR(" %-6s"), signames
[sig
]);
362 if ((sig
% 10) == 0) {
363 CFStringAppendFormat(str
, NULL
, CFSTR("\n"));
366 if ((sig
% 10) != 0) {
367 CFStringAppendFormat(str
, NULL
, CFSTR("\n"));
369 SCPrint(TRUE
, stdout
, CFSTR("%@"), str
);
376 if ((argc
!= 2) || (sscanf(argv
[1], "%d", &pid
) != 1)) {
381 ret
= sigaction(osig
, oact
, NULL
); /* restore original signal handler */
383 oact
= malloc(sizeof(struct sigaction
));
386 nact
.sa_handler
= signalCatcher
;
387 sigemptyset(&nact
.sa_mask
);
388 nact
.sa_flags
= SA_RESTART
;
389 ret
= sigaction(sig
, &nact
, oact
);
391 SCPrint(TRUE
, stdout
, CFSTR("signal handler started.\n"));
393 if (!SCDynamicStoreNotifySignal(store
, pid
, sig
)) {
394 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
403 do_notify_cancel(int argc
, char **argv
)
408 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
409 CFRelease(notifyRls
);
413 if (!SCDynamicStoreNotifyCancel(store
)) {
414 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
419 ret
= sigaction(osig
, oact
, NULL
); /* restore original signal handler */