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