]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/notify.c
configd-24.1.tar.gz
[apple/configd.git] / scutil.tproj / notify.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 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27
28 #include "scutil.h"
29
30 static int osig;
31 static struct sigaction *oact = NULL;
32
33 void
34 do_notify_list(int argc, char **argv)
35 {
36 int regexOptions = 0;
37 SCDStatus status;
38 CFArrayRef list;
39 CFIndex listCnt;
40 int i;
41
42 if (argc == 1)
43 regexOptions = kSCDRegexKey;
44
45 status = SCDNotifierList(session, regexOptions, &list);
46 if (status != SCD_OK) {
47 printf("SCDNotifierList: %s\n", SCDError(status));
48 return;
49 }
50
51 listCnt = CFArrayGetCount(list);
52 if (listCnt > 0) {
53 for (i=0; i<listCnt; i++) {
54 SCDLog(LOG_NOTICE, CFSTR(" notifierKey [%d] = %@"), i, CFArrayGetValueAtIndex(list, i));
55 }
56 } else {
57 SCDLog(LOG_NOTICE, CFSTR(" no notifierKey's"));
58 }
59 CFRelease(list);
60
61 return;
62 }
63
64
65 void
66 do_notify_add(int argc, char **argv)
67 {
68 CFStringRef key;
69 int regexOptions = 0;
70 SCDStatus status;
71
72 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
73
74 if (argc == 2)
75 regexOptions = kSCDRegexKey;
76
77 status = SCDNotifierAdd(session, key, regexOptions);
78 CFRelease(key);
79 if (status != SCD_OK) {
80 printf("SCDNotifierAdd: %s\n", SCDError(status));
81 }
82 return;
83 }
84
85
86 void
87 do_notify_remove(int argc, char **argv)
88 {
89 SCDStatus status;
90 CFStringRef key;
91 int regexOptions = 0;
92
93 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
94
95 if (argc == 2)
96 regexOptions = kSCDRegexKey;
97
98 status = SCDNotifierRemove(session, key, regexOptions);
99 CFRelease(key);
100 if (status != SCD_OK) {
101 printf("SCDNotifierRemove: %s\n", SCDError(status));
102 }
103 return;
104 }
105
106
107 void
108 do_notify_changes(int argc, char **argv)
109 {
110 CFArrayRef list;
111 CFIndex listCnt;
112 SCDStatus status;
113 int i;
114
115 status = SCDNotifierGetChanges(session, &list);
116 if (status != SCD_OK) {
117 printf("SCDNotifierGetChanges: %s\n", SCDError(status));
118 return;
119 }
120
121 listCnt = CFArrayGetCount(list);
122 if (listCnt > 0) {
123 for (i=0; i<listCnt; i++) {
124 SCDLog(LOG_NOTICE, CFSTR(" changedKey [%d] = %@"), i, CFArrayGetValueAtIndex(list, i));
125 }
126 } else {
127 SCDLog(LOG_NOTICE, CFSTR(" no changedKey's"));
128 }
129 CFRelease(list);
130
131 return;
132 }
133
134
135 void
136 do_notify_wait(int argc, char **argv)
137 {
138 SCDStatus status;
139
140 status = SCDNotifierWait(session);
141 if (status != SCD_OK) {
142 printf("SCDNotifierWait: %s\n", SCDError(status));
143 return;
144 }
145
146 printf("OK, something changed!\n");
147 return;
148 }
149
150
151 static boolean_t
152 notificationWatcher(SCDSessionRef session, void *arg)
153 {
154 printf("notification callback (session address = %p)\n", session);
155 printf(" arg = %s\n", (char *)arg);
156 return TRUE;
157 }
158
159
160 static boolean_t
161 notificationWatcherVerbose(SCDSessionRef session, void *arg)
162 {
163 printf("notification callback (session address = %p)\n", session);
164 printf(" arg = %s\n", (char *)arg);
165 do_notify_changes(0, NULL); /* report the keys which changed */
166 return TRUE;
167 }
168
169
170 void
171 do_notify_callback(int argc, char **argv)
172 {
173 SCDStatus status;
174 SCDCallbackRoutine_t func = notificationWatcher;
175
176 if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
177 func = notificationWatcherVerbose;
178 }
179
180 status = SCDNotifierInformViaCallback(session,
181 func,
182 "Changed detected by callback handler!");
183 if (status != SCD_OK) {
184 printf("SCDNotifierInformViaCallback: %s\n", SCDError(status));
185 return;
186 }
187
188 return;
189 }
190
191
192 void
193 do_notify_file(int argc, char **argv)
194 {
195 int32_t reqID = 0;
196 SCDStatus status;
197 int fd;
198 union {
199 char data[4];
200 int32_t gotID;
201 } buf;
202 char *bufPtr;
203 int needed;
204
205 if (argc == 1) {
206 if ((sscanf(argv[0], "%d", &reqID) != 1)) {
207 printf("invalid identifier\n");
208 return;
209 }
210 }
211
212 status = SCDNotifierInformViaFD(session, reqID, &fd);
213 if (status != SCD_OK) {
214 printf("SCDNotifierInformViaFD: %s\n", SCDError(status));
215 return;
216 }
217
218 bzero(buf.data, sizeof(buf.data));
219 bufPtr = &buf.data[0];
220 needed = sizeof(buf.gotID);
221 while (needed > 0) {
222 int got;
223
224 got = read(fd, bufPtr, needed);
225 if (got == -1) {
226 /* if error detected */
227 printf("read() failed: %s\n", strerror(errno));
228 break;
229 }
230
231 if (got == 0) {
232 /* if end of file detected */
233 printf("read(): detected end of file\n");
234 break;
235 }
236
237 printf("Received %d bytes\n", got);
238 bufPtr += got;
239 needed -= got;
240 }
241
242 if (needed != sizeof(buf.gotID)) {
243 printf(" Received notification, identifier = %d\n", buf.gotID);
244 }
245
246 /* this utility only allows processes one notification per "n.file" request */
247 (void)SCDNotifierCancel(session);
248
249 (void) close(fd); /* close my side of the file descriptor */
250
251 return;
252 }
253
254
255 static char *signames[] = {
256 "" , "HUP" , "INT" , "QUIT", "ILL" , "TRAP", "ABRT", "EMT" ,
257 "FPE" , "KILL", "BUS" , "SEGV", "SYS" , "PIPE", "ALRM", "TERM",
258 "URG" , "STOP", "TSTP" , "CONT", "CHLD" , "TTIN", "TTOU", "IO" ,
259 "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1",
260 "USR2"
261 };
262
263
264 static void
265 signalCatcher(int signum)
266 {
267 static int n = 0;
268
269 printf("Received SIG%s (#%d)\n", signames[signum], n++);
270 return;
271 }
272
273
274 void
275 do_notify_signal(int argc, char **argv)
276 {
277 int sig;
278 pid_t pid;
279 struct sigaction nact;
280 int ret;
281 SCDStatus status;
282
283 if (isdigit(*argv[0])) {
284 if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
285 printf("signal must be in the range of 1 .. %d\n", NSIG-1);
286 return;
287 }
288 } else {
289 for (sig=1; sig<NSIG; sig++) {
290 if (strcasecmp(argv[0], signames[sig]) == 0)
291 break;
292 }
293 if (sig >= NSIG) {
294 printf("Signal must be one of the following:");
295 for (sig=1; sig<NSIG; sig++) {
296 if ((sig % 10) == 1)
297 printf("\n ");
298 printf(" %-6s", signames[sig]);
299 }
300 printf("\n");
301 return;
302 }
303
304 }
305
306 if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
307 pid = getpid();
308 }
309
310 if (oact != NULL) {
311 ret = sigaction(osig, oact, NULL); /* restore original signal handler */
312 } else {
313 oact = malloc(sizeof(struct sigaction));
314 }
315
316 nact.sa_handler = signalCatcher;
317 sigemptyset(&nact.sa_mask);
318 nact.sa_flags = SA_RESTART;
319 ret = sigaction(sig, &nact, oact);
320 osig = sig;
321 printf("signal handler started\n");
322
323 status = SCDNotifierInformViaSignal(session, pid, sig);
324 if (status != SCD_OK) {
325 printf("SCDNotifierInformViaSignal: %s\n", SCDError(status));
326 return;
327 }
328
329 return;
330 }
331
332
333 void
334 do_notify_cancel(int argc, char **argv)
335 {
336 SCDStatus status;
337 int ret;
338
339 status = SCDNotifierCancel(session);
340 if (status != SCD_OK) {
341 printf("SCDNotifierCancel: %s\n", SCDError(status));
342 return;
343 }
344
345 if (oact != NULL) {
346 ret = sigaction(osig, oact, NULL); /* restore original signal handler */
347 free(oact);
348 oact = NULL;
349 }
350
351 return;
352 }