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