]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/prefs.c
configd-596.12.tar.gz
[apple/configd.git] / scutil.tproj / prefs.c
1 /*
2 * Copyright (c) 2003-2008, 2011-2013 Apple 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 * May 29, 2003 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <unistd.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dlfcn.h>
36
37 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
38 #if !TARGET_OS_IPHONE
39 #include <Security/Authorization.h>
40 #endif /* !TARGET_OS_IPHONE */
41
42 #include "scutil.h"
43 #include "commands.h"
44 #include "prefs.h"
45
46
47 /* -------------------- */
48
49
50 #if !TARGET_OS_IPHONE
51 static void *
52 __loadSecurity(void) {
53 static void *image = NULL;
54 if (NULL == image) {
55 const char *framework = "/System/Library/Frameworks/Security.framework/Security";
56 struct stat statbuf;
57 const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
58 char path[MAXPATHLEN];
59
60 strlcpy(path, framework, sizeof(path));
61 if (suffix) strlcat(path, suffix, sizeof(path));
62 if (0 <= stat(path, &statbuf)) {
63 image = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
64 } else {
65 image = dlopen(framework, RTLD_LAZY | RTLD_LOCAL);
66 }
67 }
68 return (void *)image;
69 }
70
71
72 static OSStatus
73 _AuthorizationCreate(const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, AuthorizationRef *authorization)
74 {
75 #undef AuthorizationCreate
76 static typeof (AuthorizationCreate) *dyfunc = NULL;
77 if (dyfunc == NULL) {
78 void *image = __loadSecurity();
79 if (image) dyfunc = dlsym(image, "AuthorizationCreate");
80 }
81 return dyfunc ? dyfunc(rights, environment, flags, authorization) : -1;
82 }
83 #define AuthorizationCreate _AuthorizationCreate
84
85
86 static OSStatus
87 _AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
88 {
89 #undef AuthorizationFree
90 static typeof (AuthorizationFree) *dyfunc = NULL;
91 if (dyfunc == NULL) {
92 void *image = __loadSecurity();
93 if (image) dyfunc = dlsym(image, "AuthorizationFree");
94 }
95 return dyfunc ? dyfunc(authorization, flags) : -1;
96 }
97 #define AuthorizationFree _AuthorizationFree
98
99
100 /* -------------------- */
101
102 __private_extern__
103 AuthorizationRef
104 _prefs_AuthorizationCreate()
105 {
106 AuthorizationRef authorization = NULL;
107
108 if (getenv("SCPREFERENCES_USE_ENTITLEMENTS") != NULL) {
109 authorization = kSCPreferencesUseEntitlementAuthorization;
110 } else {
111 AuthorizationFlags flags = kAuthorizationFlagDefaults;
112 OSStatus status;
113
114 status = AuthorizationCreate(NULL,
115 kAuthorizationEmptyEnvironment,
116 flags,
117 &authorization);
118 if (status != errAuthorizationSuccess) {
119 SCPrint(TRUE,
120 stdout,
121 CFSTR("AuthorizationCreate() failed: status = %d\n"),
122 status);
123 return NULL;
124 }
125 }
126
127 return authorization;
128 }
129
130
131 __private_extern__
132 void
133 _prefs_AuthorizationFree(AuthorizationRef authorization)
134 {
135 if (authorization != kSCPreferencesUseEntitlementAuthorization) {
136 AuthorizationFree(authorization, kAuthorizationFlagDefaults);
137 // AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
138 }
139
140 return;
141 }
142
143 #endif /* !TARGET_OS_IPHONE */
144
145 /* -------------------- */
146
147
148 __private_extern__ Boolean _prefs_changed = FALSE;
149
150
151 __private_extern__
152 Boolean
153 _prefs_open(CFStringRef name, CFStringRef prefsID)
154 {
155 CFMutableDictionaryRef options = NULL;
156 Boolean useHelper = FALSE;
157 Boolean useOptions = FALSE;
158
159 authorization = NULL;
160
161 if (geteuid() != 0) {
162 // if we need to use a helper
163 useHelper = TRUE;
164
165 #if !TARGET_OS_IPHONE
166 authorization = _prefs_AuthorizationCreate();
167 #else
168 authorization = kSCPreferencesUseEntitlementAuthorization;
169 #endif /* !TARGET_OS_IPHONE */
170 }
171
172 if (getenv("SCPREFERENCES_REMOVE_WHEN_EMPTY") != NULL) {
173 // if we have options
174 useOptions = TRUE;
175
176 if (options == NULL) {
177 options = CFDictionaryCreateMutable(NULL,
178 0,
179 &kCFTypeDictionaryKeyCallBacks,
180 &kCFTypeDictionaryValueCallBacks);
181 }
182 CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue);
183 }
184
185 if (!useHelper && !useOptions) {
186 // if no helper/options needed
187 prefs = SCPreferencesCreate(NULL, name, prefsID);
188 } else if (!useOptions) {
189 // if no options needed
190 prefs = SCPreferencesCreateWithAuthorization(NULL, name, prefsID, authorization);
191 } else {
192 prefs = SCPreferencesCreateWithOptions(NULL, name, prefsID, authorization, options);
193 CFRelease(options);
194 }
195
196 if (prefs == NULL) {
197 return FALSE;
198 }
199
200 _prefs_changed = FALSE;
201 return TRUE;
202 }
203
204
205 __private_extern__
206 void
207 _prefs_save()
208 {
209 if (!SCPreferencesCommitChanges(prefs)) {
210 switch (SCError()) {
211 case kSCStatusAccessError :
212 SCPrint(TRUE, stderr, CFSTR("Permission denied.\n"));
213 break;
214 default :
215 SCPrint(TRUE,
216 stdout,
217 CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
218 SCErrorString(SCError()));
219 break;
220 }
221 exit (1);
222 }
223
224 _prefs_changed = FALSE;
225
226 if (!SCPreferencesApplyChanges(prefs)) {
227 SCPrint(TRUE,
228 stdout,
229 CFSTR("SCPreferencesApplyChanges() failed: %s\n"),
230 SCErrorString(SCError()));
231 exit (1);
232 }
233
234 return;
235 }
236
237
238 __private_extern__
239 void
240 _prefs_close()
241 {
242 if (prefs != NULL) {
243 CFRelease(prefs);
244 prefs = NULL;
245 _prefs_changed = FALSE;
246 }
247
248 if (authorization != NULL) {
249 #if !TARGET_OS_IPHONE
250 _prefs_AuthorizationFree(authorization);
251 #else /* !TARGET_OS_IPHONE */
252 // Uh...if authorization isn't NULL, something went horribly wrong.
253 #endif /* !TARGET_OS_IPHONE */
254 authorization = NULL;
255 }
256
257 return;
258 }
259
260
261 __private_extern__
262 Boolean
263 _prefs_commitRequired(int argc, char **argv, const char *command)
264 {
265 if (_prefs_changed) {
266 if ((currentInput != NULL) &&
267 isatty(fileno(currentInput->fp)) &&
268 ((argc < 1) || (strcmp(argv[0], "!") != 0))
269 ) {
270 SCPrint(TRUE, stdout,
271 CFSTR("preference changes have not been committed\n"
272 "use \"commit\" to save changes"));
273 if (command != NULL) {
274 SCPrint(TRUE, stdout,
275 CFSTR(" or \"%s !\" to abandon changes"),
276 command);
277 }
278 SCPrint(TRUE, stdout, CFSTR("\n"));
279 return TRUE;
280 }
281
282 SCPrint(TRUE, stdout, CFSTR("preference changes abandoned\n"));
283 }
284
285 return FALSE;
286 }
287
288
289 /* -------------------- */
290
291
292 static void
293 get_ComputerName(int argc, char **argv)
294 {
295 CFStringEncoding encoding;
296 CFStringRef hostname;
297
298 hostname = SCDynamicStoreCopyComputerName(NULL, &encoding);
299 if (hostname == NULL) {
300 int sc_status = SCError();
301
302 switch (sc_status) {
303 case kSCStatusNoKey :
304 SCPrint(TRUE,
305 stderr,
306 CFSTR("ComputerName: not set\n"));
307 break;
308 default :
309 SCPrint(TRUE,
310 stderr,
311 CFSTR("SCDynamicStoreCopyComputerName() failed: %s\n"),
312 SCErrorString(SCError()));
313 break;
314 }
315 exit (1);
316 }
317
318 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
319 CFRelease(hostname);
320
321 exit(0);
322 }
323
324
325 static void
326 set_ComputerName(int argc, char **argv)
327 {
328 CFStringRef hostname;
329 Boolean ok;
330
331 ok = _prefs_open(CFSTR("scutil --set ComputerName"), NULL);
332 if (!ok) {
333 SCPrint(TRUE,
334 stdout,
335 CFSTR("Could not open prefs: %s\n"),
336 SCErrorString(SCError()));
337 exit(1);
338 }
339
340 if (argc == 0) {
341 CFStringEncoding old_encoding;
342 CFStringRef old_hostname;
343
344 old_hostname = SCDynamicStoreCopyComputerName(NULL, &old_encoding);
345 hostname = _copyStringFromSTDIN(CFSTR("ComputerName"), old_hostname);
346 if (old_hostname) CFRelease(old_hostname);
347 } else {
348 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
349 }
350
351 ok = SCPreferencesSetComputerName(prefs, hostname, kCFStringEncodingUTF8);
352 if (hostname != NULL) CFRelease(hostname);
353 if (!ok) {
354 SCPrint(TRUE,
355 stdout,
356 CFSTR("Could not open prefs: %s\n"),
357 SCErrorString(SCError()));
358 _prefs_close();
359 exit (1);
360 }
361
362 _prefs_save();
363 _prefs_close();
364 exit(0);
365 }
366
367
368 static void
369 get_HostName(int argc, char **argv)
370 {
371 CFStringRef hostname;
372 Boolean ok;
373
374 ok = _prefs_open(CFSTR("scutil --get HostName"), NULL);
375 if (!ok) {
376 SCPrint(TRUE,
377 stdout,
378 CFSTR("SCPreferencesCreate() failed: %s\n"),
379 SCErrorString(SCError()));
380 exit(1);
381 }
382
383 hostname = SCPreferencesGetHostName(prefs);
384 if (hostname == NULL) {
385 int sc_status = SCError();
386
387 switch (sc_status) {
388 case kSCStatusNoKey :
389 SCPrint(TRUE,
390 stderr,
391 CFSTR("HostName: not set\n"));
392 break;
393 default :
394 SCPrint(TRUE,
395 stderr,
396 CFSTR("SCPreferencesGetHostName() failed: %s\n"),
397 SCErrorString(SCError()));
398 break;
399 }
400 _prefs_close();
401 exit (1);
402 }
403
404 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
405 _prefs_close();
406 exit(0);
407 }
408
409
410 static void
411 set_HostName(int argc, char **argv)
412 {
413 CFStringRef hostname = NULL;
414 Boolean ok;
415
416 ok = _prefs_open(CFSTR("scutil --set HostName"), NULL);
417 if (!ok) {
418 SCPrint(TRUE,
419 stdout,
420 CFSTR("Could not open prefs: %s\n"),
421 SCErrorString(SCError()));
422 exit(1);
423 }
424
425 if (argc == 0) {
426 hostname = _copyStringFromSTDIN(CFSTR("HostName"), SCPreferencesGetHostName(prefs));
427 } else {
428 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
429 }
430
431 ok = SCPreferencesSetHostName(prefs, hostname);
432 if (hostname != NULL) CFRelease(hostname);
433 if (!ok) {
434 SCPrint(TRUE,
435 stderr,
436 CFSTR("SCPreferencesSetHostName() failed: %s\n"),
437 SCErrorString(SCError()));
438 _prefs_close();
439 exit (1);
440 }
441
442 _prefs_save();
443 _prefs_close();
444 exit(0);
445 }
446
447
448 static void
449 get_LocalHostName(int argc, char **argv)
450 {
451 CFStringRef hostname;
452
453 hostname = SCDynamicStoreCopyLocalHostName(NULL);
454 if (hostname == NULL) {
455 int sc_status = SCError();
456
457 switch (sc_status) {
458 case kSCStatusNoKey :
459 SCPrint(TRUE,
460 stderr,
461 CFSTR("LocalHostName: not set\n"));
462 break;
463 default :
464 SCPrint(TRUE,
465 stderr,
466 CFSTR("SCDynamicStoreCopyLocalHostName() failed: %s\n"),
467 SCErrorString(SCError()));
468 break;
469 }
470 exit (1);
471 }
472
473 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
474 CFRelease(hostname);
475
476 exit(0);
477 }
478
479
480 static void
481 set_LocalHostName(int argc, char **argv)
482 {
483 CFStringRef hostname = NULL;
484 Boolean ok;
485
486 ok = _prefs_open(CFSTR("scutil --set LocalHostName"), NULL);
487 if (!ok) {
488 SCPrint(TRUE,
489 stdout,
490 CFSTR("Could not open prefs: %s\n"),
491 SCErrorString(SCError()));
492 exit(1);
493 }
494
495 if (argc == 0) {
496 CFStringRef old_hostname;
497
498 old_hostname = SCDynamicStoreCopyLocalHostName(NULL);
499 hostname = _copyStringFromSTDIN(CFSTR("LocalHostName"), old_hostname);
500 if (old_hostname) CFRelease(old_hostname);
501 } else {
502 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
503 }
504
505 ok = SCPreferencesSetLocalHostName(prefs, hostname);
506 if (hostname != NULL) CFRelease(hostname);
507 if (!ok) {
508 SCPrint(TRUE,
509 stderr,
510 CFSTR("SCPreferencesSetLocalHostName() failed: %s\n"),
511 SCErrorString(SCError()));
512 _prefs_close();
513 exit (1);
514 }
515
516 _prefs_save();
517 _prefs_close();
518 exit(0);
519 }
520
521
522 /* -------------------- */
523
524
525 typedef void (*pref_func) (int argc, char **argv);
526
527 static const struct {
528 char *pref;
529 pref_func get;
530 pref_func set;
531 } pref_keys[] = {
532 { "ComputerName", get_ComputerName, set_ComputerName },
533 { "HostName", get_HostName, set_HostName },
534 { "LocalHostName", get_LocalHostName, set_LocalHostName }
535 };
536 #define N_PREF_KEYS (sizeof(pref_keys) / sizeof(pref_keys[0]))
537
538
539 __private_extern__
540 int
541 findPref(char *pref)
542 {
543 int i;
544
545 for (i = 0; i < (int)N_PREF_KEYS; i++) {
546 if (strcmp(pref, pref_keys[i].pref) == 0) {
547 return i;
548 }
549 }
550
551 return -1;
552 }
553
554
555 __private_extern__
556 void
557 do_getPref(char *pref, int argc, char **argv)
558 {
559 int i;
560
561 if (argc == 0) {
562 i = findPref(pref);
563 if (i >= 0) {
564 (*pref_keys[i].get)(argc, argv);
565 }
566 return;
567 }
568
569 // Add support to parse out extended get
570 // ie. scutil --get <filename> <prefs path> <key>
571 do_prefs_init();
572 do_prefs_open(argc, argv);
573 do_prefs_get(--argc, ++argv);
574
575 if (value != NULL) {
576 CFStringRef key;
577 CFStringRef prefs_val;
578
579 key = CFStringCreateWithCString(NULL, *(++argv), kCFStringEncodingUTF8);
580 prefs_val = CFDictionaryGetValue(value, key);
581 CFRelease(key);
582
583 if (prefs_val != NULL) {
584 SCPrint(TRUE, stdout, CFSTR("%@\n"), prefs_val);
585 } else {
586 _prefs_close();
587 exit(1);
588 }
589 }
590 _prefs_close();
591 exit(0);
592 }
593
594
595 __private_extern__
596 void
597 do_setPref(char *pref, int argc, char **argv)
598 {
599 int i;
600
601 i = findPref(pref);
602 if (i >= 0) {
603 (*pref_keys[i].set)(argc, argv);
604 }
605 return;
606 }
607
608
609 /* -------------------- */
610
611
612 __private_extern__
613 void
614 do_prefs_init()
615 {
616 return;
617 }
618
619
620 __private_extern__
621 void
622 do_prefs_open(int argc, char **argv)
623 {
624 Boolean ok;
625 CFStringRef prefsID = NULL;
626
627 if (prefs != NULL) {
628 if (_prefs_commitRequired(argc, argv, "close")) {
629 return;
630 }
631
632 do_prefs_close(0, NULL);
633 }
634
635 if (argc > 0) {
636 prefsID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
637 }
638
639 ok = _prefs_open(CFSTR("scutil --prefs"), prefsID);
640 if (prefsID != NULL) CFRelease(prefsID);
641 if (!ok) {
642 SCPrint(TRUE,
643 stdout,
644 CFSTR("Could not open prefs: %s\n"),
645 SCErrorString(SCError()));
646 return;
647 }
648
649 return;
650 }
651
652
653 __private_extern__
654 void
655 do_prefs_lock(int argc, char **argv)
656 {
657 Boolean wait = (argc > 0) ? TRUE : FALSE;
658
659 if (!SCPreferencesLock(prefs, wait)) {
660 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
661 return;
662 }
663
664 return;
665 }
666
667
668 __private_extern__
669 void
670 do_prefs_unlock(int argc, char **argv)
671 {
672 if (!SCPreferencesUnlock(prefs)) {
673 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
674 return;
675 }
676
677 return;
678 }
679
680
681 __private_extern__
682 void
683 do_prefs_commit(int argc, char **argv)
684 {
685 if (!SCPreferencesCommitChanges(prefs)) {
686 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
687 return;
688 }
689
690 _prefs_changed = FALSE;
691 return;
692 }
693
694
695 __private_extern__
696 void
697 do_prefs_apply(int argc, char **argv)
698 {
699 if (!SCPreferencesApplyChanges(prefs)) {
700 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
701 }
702
703 return;
704 }
705
706
707 __private_extern__
708 void
709 do_prefs_close(int argc, char **argv)
710 {
711 if (_prefs_commitRequired(argc, argv, "close")) {
712 return;
713 }
714
715 _prefs_close();
716 return;
717 }
718
719
720 __private_extern__
721 void
722 do_prefs_quit(int argc, char **argv)
723 {
724 if (_prefs_commitRequired(argc, argv, "quit")) {
725 return;
726 }
727
728 _prefs_close();
729
730 termRequested = TRUE;
731 return;
732 }
733
734
735 __private_extern__
736 void
737 do_prefs_synchronize(int argc, char **argv)
738 {
739 SCPreferencesSynchronize(prefs);
740 return;
741 }
742
743
744 static CFComparisonResult
745 sort_paths(const void *p1, const void *p2, void *context) {
746 CFStringRef path1 = (CFStringRef)p1;
747 CFStringRef path2 = (CFStringRef)p2;
748 return CFStringCompare(path1, path2, 0);
749 }
750
751
752 __private_extern__
753 void
754 do_prefs_list(int argc, char **argv)
755 {
756 int i;
757 CFIndex n;
758 CFMutableArrayRef paths = NULL;
759 CFStringRef prefix;
760 CFDictionaryRef entity;
761
762 prefix = CFStringCreateWithCString(NULL,
763 (argc >= 1) ? argv[0] : "/",
764 kCFStringEncodingUTF8);
765
766 entity = SCPreferencesPathGetValue(prefs, prefix);
767 if (entity == NULL) {
768 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
769 goto done;
770 }
771
772 paths = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
773
774 n = isA_CFDictionary(entity) ? CFDictionaryGetCount(entity) : 0;
775 if (n > 0) {
776 CFIndex i;
777 const void ** keys;
778 const void ** vals;
779
780 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
781 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
782 CFDictionaryGetKeysAndValues(entity, keys, vals);
783 for (i = 0; i < n; i++) {
784 if (isA_CFDictionary(vals[i])) {
785 CFArrayAppendValue(paths, keys[i]);
786 }
787 }
788 CFAllocatorDeallocate(NULL, keys);
789 CFAllocatorDeallocate(NULL, vals);
790 }
791
792 n = CFArrayGetCount(paths);
793 CFArraySortValues(paths,
794 CFRangeMake(0, n),
795 sort_paths,
796 NULL);
797
798 if (n > 0) {
799 for (i = 0; i < n; i++) {
800 SCPrint(TRUE,
801 stdout,
802 CFSTR(" path [%d] = %@/%@\n"),
803 i,
804 CFEqual(prefix, CFSTR("/")) ? CFSTR("") : prefix,
805 CFArrayGetValueAtIndex(paths, i));
806 }
807 } else {
808 SCPrint(TRUE, stdout, CFSTR(" no paths.\n"));
809 }
810
811 CFRelease(paths);
812
813 done :
814
815 CFRelease(prefix);
816 return;
817 }
818
819
820 __private_extern__
821 void
822 do_prefs_get(int argc, char **argv)
823 {
824 CFDictionaryRef dict;
825 CFStringRef link;
826 CFIndex n;
827 CFMutableDictionaryRef newDict;
828 CFStringRef path;
829
830 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
831
832 link = SCPreferencesPathGetLink(prefs, path);
833 if (link != NULL) {
834 SCPrint(TRUE, stdout, CFSTR(" --> %@\n"), link);
835 }
836
837 dict = SCPreferencesPathGetValue(prefs, path);
838 CFRelease(path);
839 if (dict == NULL) {
840 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
841 return;
842 }
843
844 newDict = CFDictionaryCreateMutable(NULL,
845 0,
846 &kCFTypeDictionaryKeyCallBacks,
847 &kCFTypeDictionaryValueCallBacks);
848
849 // remove [path] children
850 n = isA_CFDictionary(dict) ? CFDictionaryGetCount(dict) : 0;
851 if (n > 0) {
852 CFIndex i;
853 const void ** keys;
854 const void ** vals;
855
856 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
857 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
858 CFDictionaryGetKeysAndValues(dict, keys, vals);
859 for (i = 0; i < n; i++) {
860 if (!isA_CFDictionary(vals[i])) {
861 CFDictionaryAddValue(newDict, keys[i], vals[i]);
862 }
863 }
864 CFAllocatorDeallocate(NULL, keys);
865 CFAllocatorDeallocate(NULL, vals);
866 }
867
868 if (value != NULL) {
869 CFRelease(value); /* we have new information, release the old */
870 }
871
872 value = newDict;
873
874 return;
875 }
876
877
878 __private_extern__
879 void
880 do_prefs_set(int argc, char **argv)
881 {
882 CFDictionaryRef dict;
883 CFMutableDictionaryRef newDict = NULL;
884 CFStringRef path;
885
886 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
887 newDict = CFDictionaryCreateMutableCopy(NULL, 0, value);
888
889 dict = SCPreferencesPathGetValue(prefs, path);
890 if (dict != NULL) {
891 CFIndex n;
892
893 // retain [path] children
894 n = CFDictionaryGetCount(dict);
895 if (n > 0) {
896 CFIndex i;
897 const void ** keys;
898 const void ** vals;
899
900 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
901 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
902 CFDictionaryGetKeysAndValues(dict, keys, vals);
903 for (i = 0; i < n; i++) {
904 if (isA_CFDictionary(vals[i])) {
905 if (CFDictionaryContainsKey(newDict, keys[i])) {
906 SCPrint(TRUE, stdout, CFSTR(" key %@ is already a path component and cannot be replaced\n"), keys[i]);
907 goto done;
908 }
909 CFDictionaryAddValue(newDict, keys[i], vals[i]);
910 }
911 }
912 CFAllocatorDeallocate(NULL, keys);
913 CFAllocatorDeallocate(NULL, vals);
914 }
915 } else if (SCError() == kSCStatusInvalidArgument) {
916 SCPrint(TRUE, stdout, CFSTR(" a path component is not a dictionary\n"));
917 goto done;
918 } else if (SCError() != kSCStatusNoKey) {
919 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
920 goto done;
921 }
922
923 if (argc > 1) {
924 CFStringRef link;
925 Boolean ok;
926
927 // set link
928 link = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
929 ok = SCPreferencesPathSetLink(prefs, path, link);
930 CFRelease(link);
931 if (!ok) {
932 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
933 goto done;
934 }
935 } else {
936 // set value
937 if (!SCPreferencesPathSetValue(prefs, path, newDict)) {
938 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
939 goto done;
940 }
941 }
942
943 _prefs_changed = TRUE;
944
945 done :
946
947 CFRelease(newDict);
948 CFRelease(path);
949 return;
950 }
951
952
953 __private_extern__
954 void
955 do_prefs_remove(int argc, char **argv)
956 {
957 CFStringRef path;
958
959 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
960
961 if (!SCPreferencesPathRemoveValue(prefs, path)) {
962 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
963 goto done;
964 }
965
966 _prefs_changed = TRUE;
967
968 done :
969
970 CFRelease(path);
971 return;
972 }
973
974 /* -------------------- */
975
976 #include "IPMonitorControlPrefs.h"
977
978 __private_extern__
979 void
980 do_log(char * log, int argc, char **argv)
981 {
982 if (strcmp(log, "IPMonitor")) {
983 exit(0);
984 }
985 if (argc == 0) {
986 printf("IPMonitor log is %s\n",
987 IPMonitorControlPrefsIsVerbose() ? "on" : "off");
988 }
989 else {
990 Boolean verbose = FALSE;
991
992 if (strcasecmp(argv[0], "on") == 0) {
993 verbose = TRUE;
994 }
995 else if (strcasecmp(argv[0], "off") == 0) {
996 verbose = FALSE;
997 }
998 else {
999 fprintf(stderr, "%s invalid, must be 'on' or 'off'\n",
1000 argv[0]);
1001 exit(1);
1002 }
1003 if (IPMonitorControlPrefsSetVerbose(verbose) == FALSE) {
1004 fprintf(stderr, "failed to set preferences\n");
1005 exit(2);
1006 }
1007 }
1008 exit(0);
1009 return;
1010 }
1011
1012