]> git.saurik.com Git - apple/configd.git/blob - Plugins/PreferencesMonitor/prefsmon.c
configd-699.30.1.tar.gz
[apple/configd.git] / Plugins / PreferencesMonitor / prefsmon.c
1 /*
2 * Copyright (c) 2000-2008, 2010, 2012-2014 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 * April 2, 2004 Allan Nathanson <ajn@apple.com>
28 * - use SCPreference notification APIs
29 *
30 * June 24, 2001 Allan Nathanson <ajn@apple.com>
31 * - update to public SystemConfiguration.framework APIs
32 *
33 * November 10, 2000 Allan Nathanson <ajn@apple.com>
34 * - initial revision
35 */
36
37
38 #include <TargetConditionals.h>
39 #include <fcntl.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43
44
45 #include <SystemConfiguration/SystemConfiguration.h>
46 #include <SystemConfiguration/SCPrivate.h>
47 #include <SystemConfiguration/SCValidation.h>
48
49
50
51
52 /* globals */
53 static SCPreferencesRef prefs = NULL;
54 static SCDynamicStoreRef store = NULL;
55
56 /* preferences "initialization" globals */
57 static CFStringRef initKey = NULL;
58 static CFRunLoopSourceRef initRls = NULL;
59
60 /* SCDynamicStore (Setup:) */
61 static CFMutableDictionaryRef currentPrefs; /* current prefs */
62 static CFMutableDictionaryRef newPrefs; /* new prefs */
63 static CFMutableArrayRef unchangedPrefsKeys; /* new prefs keys which match current */
64 static CFMutableArrayRef removedPrefsKeys; /* old prefs keys to be removed */
65
66 static Boolean rofs = FALSE;
67 static Boolean _verbose = FALSE;
68
69
70 static Boolean
71 establishNewPreferences()
72 {
73 CFBundleRef bundle;
74 SCNetworkSetRef current = NULL;
75 CFStringRef new_model;
76 Boolean ok = FALSE;
77 int sc_status = kSCStatusFailed;
78 SCNetworkSetRef set = NULL;
79 CFStringRef setName = NULL;
80 Boolean updated = FALSE;
81
82 while (TRUE) {
83 ok = SCPreferencesLock(prefs, TRUE);
84 if (ok) {
85 break;
86 }
87
88 sc_status = SCError();
89 if (sc_status == kSCStatusStale) {
90 SCPreferencesSynchronize(prefs);
91 } else {
92 SCLog(TRUE, LOG_ERR,
93 CFSTR("Could not acquire network configuration lock: %s"),
94 SCErrorString(sc_status));
95 return FALSE;
96 }
97 }
98
99 /* Ensure that the preferences has the new model */
100 new_model = _SC_hw_model(FALSE);
101
102 /* Need to regenerate the new configuration for new model */
103 if (new_model != NULL) {
104 CFStringRef old_model;
105
106 old_model = SCPreferencesGetValue(prefs, MODEL);
107 if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
108 CFIndex count;
109 CFIndex index;
110 CFArrayRef keys;
111
112 keys = SCPreferencesCopyKeyList(prefs);
113 count = (keys != NULL) ? CFArrayGetCount(keys) : 0;
114 // if new hardware
115 for (index = 0; index < count; index++) {
116 CFStringRef existing_key;
117
118 existing_key = CFArrayGetValueAtIndex(keys, index);
119 if (isA_CFString(existing_key) != NULL) {
120 CFStringRef new_key;
121 CFPropertyListRef value;
122
123 /* If it already contains a Model
124 or if it already contains a MODEL:KEY key skip it*/
125 if (CFEqual(existing_key, MODEL)
126 || CFStringFind(existing_key, CFSTR(":"), 0).location
127 != kCFNotFound) {
128 continue;
129 }
130
131 value = SCPreferencesGetValue(prefs, existing_key);
132
133 /* Create a new key as OLD_MODEL:OLD_KEY */
134 new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
135 old_model, existing_key);
136 SCPreferencesSetValue(prefs, new_key, value);
137 if (!CFEqual(existing_key, kSCPrefSystem)) {
138 /* preserve existing host names */
139 SCPreferencesRemoveValue(prefs, existing_key);
140 }
141 CFRelease(new_key);
142 }
143 }
144
145 if (keys != NULL) {
146 CFRelease(keys);
147 }
148 }
149 /* Set the new model */
150 SCPreferencesSetValue(prefs, MODEL, new_model);
151 }
152
153 current = SCNetworkSetCopyCurrent(prefs);
154 if (current != NULL) {
155 set = current;
156 }
157
158 if (set == NULL) {
159 set = SCNetworkSetCreate(prefs);
160 if (set == NULL) {
161 ok = FALSE;
162 sc_status = SCError();
163 goto done;
164 }
165
166 bundle = _SC_CFBundleGet();
167 if (bundle != NULL) {
168 setName = CFBundleCopyLocalizedString(bundle,
169 CFSTR("DEFAULT_SET_NAME"),
170 CFSTR("Automatic"),
171 NULL);
172 }
173
174 ok = SCNetworkSetSetName(set, (setName != NULL) ? setName : CFSTR("Automatic"));
175 if (!ok) {
176 sc_status = SCError();
177 goto done;
178 }
179
180 ok = SCNetworkSetSetCurrent(set);
181 if (!ok) {
182 sc_status = SCError();
183 goto done;
184 }
185 }
186
187 ok = SCNetworkSetEstablishDefaultConfiguration(set);
188 if (!ok) {
189 sc_status = SCError();
190 goto done;
191 }
192
193 done :
194
195 if (ok) {
196 ok = SCPreferencesCommitChanges(prefs);
197 if (ok) {
198 SCLog(TRUE, LOG_NOTICE, CFSTR("New network configuration saved"));
199 updated = TRUE;
200 } else {
201 sc_status = SCError();
202 if (sc_status == EROFS) {
203 /* a read-only fileysstem is OK */
204 ok = TRUE;
205
206 /* ... but we don't want to synchronize */
207 rofs = TRUE;
208 }
209 }
210
211 /* apply (committed or temporary/read-only) changes */
212 (void) SCPreferencesApplyChanges(prefs);
213 } else if ((current == NULL) && (set != NULL)) {
214 (void) SCNetworkSetRemove(set);
215 }
216
217 if (!ok) {
218 SCLog(TRUE, LOG_ERR,
219 CFSTR("Could not establish network configuration: %s"),
220 SCErrorString(sc_status));
221 }
222
223 (void)SCPreferencesUnlock(prefs);
224 if (setName != NULL) CFRelease(setName);
225 if (set != NULL) CFRelease(set);
226 return updated;
227 }
228
229
230 static Boolean
231 quiet(Boolean *timeout)
232 {
233 CFDictionaryRef dict;
234 Boolean _quiet = FALSE;
235 Boolean _timeout = FALSE;
236
237 // check if quiet
238 dict = SCDynamicStoreCopyValue(store, initKey);
239 if (dict != NULL) {
240 if (isA_CFDictionary(dict)) {
241 if (CFDictionaryContainsKey(dict, CFSTR("*QUIET*"))) {
242 _quiet = TRUE;
243 }
244 if (CFDictionaryContainsKey(dict, CFSTR("*TIMEOUT*"))) {
245 _timeout = TRUE;
246 }
247 }
248 CFRelease(dict);
249 }
250
251 if (timeout != NULL) {
252 *timeout = _timeout;
253 }
254 return _quiet;
255 }
256
257
258 static void
259 watchQuietDisable()
260 {
261 if ((initKey == NULL) || (initRls == NULL)) {
262 return;
263 }
264
265 (void) SCDynamicStoreSetNotificationKeys(store, NULL, NULL);
266
267 CFRunLoopSourceInvalidate(initRls);
268 CFRelease(initRls);
269 initRls = NULL;
270
271 CFRelease(initKey);
272 initKey = NULL;
273
274 return;
275 }
276
277
278 static void
279 watchQuietEnable()
280 {
281 CFArrayRef keys;
282 Boolean ok;
283
284 initKey = SCDynamicStoreKeyCreate(NULL,
285 CFSTR("%@" "InterfaceNamer"),
286 kSCDynamicStoreDomainPlugin);
287
288 initRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
289 CFRunLoopAddSource(CFRunLoopGetCurrent(), initRls, kCFRunLoopDefaultMode);
290
291 keys = CFArrayCreate(NULL, (const void **)&initKey, 1, &kCFTypeArrayCallBacks);
292 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
293 CFRelease(keys);
294 if (!ok) {
295 SCLog(TRUE, LOG_ERR,
296 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
297 watchQuietDisable();
298 }
299
300 return;
301 }
302
303
304
305
306 static void
307 watchQuietCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
308 {
309 Boolean _quiet;
310 Boolean _timeout = FALSE;
311
312 _quiet = quiet(&_timeout);
313 if (_quiet
314 #if !TARGET_OS_IPHONE
315 || _timeout
316 #endif /* !TARGET_OS_IPHONE */
317 ) {
318 watchQuietDisable();
319 }
320
321 if (_quiet || _timeout) {
322 static int logged = 0;
323
324 (void) establishNewPreferences();
325 if (_timeout && (logged++ == 0)) {
326 SCLog(TRUE, LOG_NOTICE,
327 CFSTR("Network configuration creation timed out waiting for IORegistry"));
328 }
329 }
330
331 return;
332 }
333
334
335 static void
336 updateCache(const void *key, const void *value, void *context)
337 {
338 CFStringRef configKey = (CFStringRef)key;
339 CFPropertyListRef configData = (CFPropertyListRef)value;
340 CFPropertyListRef cacheData;
341 CFIndex i;
342
343 cacheData = CFDictionaryGetValue(currentPrefs, configKey);
344 if (cacheData) {
345 /* key exists */
346 if (CFEqual(cacheData, configData)) {
347 /*
348 * if the old & new property list values have
349 * not changed then we don't need to update
350 * the preference.
351 */
352 CFArrayAppendValue(unchangedPrefsKeys, configKey);
353 }
354 }
355
356 /* in any case, this key should not be removed */
357 i = CFArrayGetFirstIndexOfValue(removedPrefsKeys,
358 CFRangeMake(0, CFArrayGetCount(removedPrefsKeys)),
359 configKey);
360 if (i != kCFNotFound) {
361 CFArrayRemoveValueAtIndex(removedPrefsKeys, i);
362 }
363
364 return;
365 }
366
367
368 static void
369 flatten(SCPreferencesRef prefs,
370 CFStringRef key,
371 CFDictionaryRef base)
372 {
373 CFDictionaryRef subset;
374 CFStringRef link;
375 CFMutableDictionaryRef myDict;
376 CFStringRef myKey;
377 CFIndex i;
378 CFIndex nKeys;
379 const void **keys;
380 const void **vals;
381
382 if (!CFDictionaryGetValueIfPresent(base, kSCResvLink, (const void **)&link)) {
383 /* if this dictionary is not linked */
384 subset = base;
385 } else {
386 /* if __LINK__ key is present */
387 subset = SCPreferencesPathGetValue(prefs, link);
388 if (!subset) {
389 /* if error with link */
390 SCLog(TRUE, LOG_ERR,
391 CFSTR("SCPreferencesPathGetValue(,%@,) failed: %s"),
392 link,
393 SCErrorString(SCError()));
394 return;
395 }
396 }
397
398 if (CFDictionaryContainsKey(subset, kSCResvInactive)) {
399 /* if __INACTIVE__ key is present */
400 return;
401 }
402
403 myKey = CFStringCreateWithFormat(NULL,
404 NULL,
405 CFSTR("%@%@"),
406 kSCDynamicStoreDomainSetup,
407 key);
408
409 myDict = (CFMutableDictionaryRef)CFDictionaryGetValue(newPrefs, myKey);
410 if (myDict) {
411 myDict = CFDictionaryCreateMutableCopy(NULL,
412 0,
413 (CFDictionaryRef)myDict);
414 } else {
415 myDict = CFDictionaryCreateMutable(NULL,
416 0,
417 &kCFTypeDictionaryKeyCallBacks,
418 &kCFTypeDictionaryValueCallBacks);
419 }
420
421 nKeys = CFDictionaryGetCount(subset);
422 if (nKeys > 0) {
423 keys = CFAllocatorAllocate(NULL, nKeys * sizeof(CFStringRef) , 0);
424 vals = CFAllocatorAllocate(NULL, nKeys * sizeof(CFPropertyListRef), 0);
425 CFDictionaryGetKeysAndValues(subset, keys, vals);
426 for (i = 0; i < nKeys; i++) {
427 if (CFGetTypeID((CFTypeRef)vals[i]) != CFDictionaryGetTypeID()) {
428 /* add this key/value to the current dictionary */
429 CFDictionarySetValue(myDict, keys[i], vals[i]);
430 } else {
431 CFStringRef subKey;
432
433 /* flatten [sub]dictionaries */
434 subKey = CFStringCreateWithFormat(NULL,
435 NULL,
436 CFSTR("%@%s%@"),
437 key,
438 CFEqual(key, CFSTR("/")) ? "" : "/",
439 keys[i]);
440 flatten(prefs, subKey, vals[i]);
441 CFRelease(subKey);
442 }
443 }
444 CFAllocatorDeallocate(NULL, keys);
445 CFAllocatorDeallocate(NULL, vals);
446 }
447
448 if (CFDictionaryGetCount(myDict) > 0) {
449 /* add this dictionary to the new preferences */
450 CFDictionarySetValue(newPrefs, myKey, myDict);
451 }
452
453 CFRelease(myDict);
454 CFRelease(myKey);
455
456 return;
457 }
458
459
460 static void
461 updateSCDynamicStore(SCPreferencesRef prefs)
462 {
463 CFStringRef current = NULL;
464 CFDateRef date = NULL;
465 CFMutableDictionaryRef dict = NULL;
466 CFDictionaryRef global = NULL;
467 CFIndex i;
468 CFArrayRef keys;
469 CFIndex n;
470 CFStringRef pattern;
471 CFMutableArrayRef patterns;
472 CFDictionaryRef set = NULL;
473
474 /*
475 * initialize old preferences, new preferences, an array
476 * of keys which have not changed, and an array of keys
477 * to be removed (cleaned up).
478 */
479
480 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
481 pattern = CFStringCreateWithFormat(NULL,
482 NULL,
483 CFSTR("^%@.*"),
484 kSCDynamicStoreDomainSetup);
485 CFArrayAppendValue(patterns, pattern);
486 dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns);
487 CFRelease(patterns);
488 CFRelease(pattern);
489 if (dict) {
490 currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict);
491 CFRelease(dict);
492 } else {
493 currentPrefs = CFDictionaryCreateMutable(NULL,
494 0,
495 &kCFTypeDictionaryKeyCallBacks,
496 &kCFTypeDictionaryValueCallBacks);
497 }
498
499 unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
500
501 i = CFDictionaryGetCount(currentPrefs);
502 if (i > 0) {
503 const void **currentKeys;
504 CFArrayRef array;
505
506 currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0);
507 CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL);
508 array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks);
509 removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array);
510 CFRelease(array);
511 CFAllocatorDeallocate(NULL, currentKeys);
512 } else {
513 removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
514 }
515
516 /*
517 * The "newPrefs" dictionary will contain the new / updated
518 * configuration which will be written to the configuration cache.
519 */
520 newPrefs = CFDictionaryCreateMutable(NULL,
521 0,
522 &kCFTypeDictionaryKeyCallBacks,
523 &kCFTypeDictionaryValueCallBacks);
524
525 /*
526 * create status dictionary associated with current configuration
527 * information including:
528 * - current set "name" to cache
529 * - time stamp indicating when the cache preferences were
530 * last updated.
531 */
532 dict = CFDictionaryCreateMutable(NULL,
533 0,
534 &kCFTypeDictionaryKeyCallBacks,
535 &kCFTypeDictionaryValueCallBacks);
536 date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
537
538 /*
539 * load preferences
540 */
541 keys = SCPreferencesCopyKeyList(prefs);
542 if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) {
543 SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences."));
544 goto done;
545 }
546
547 /*
548 * get "global" system preferences
549 */
550 global = SCPreferencesGetValue(prefs, kSCPrefSystem);
551 if (!global) {
552 /* if no global preferences are defined */
553 goto getSet;
554 }
555
556 if (!isA_CFDictionary(global)) {
557 SCLog(TRUE, LOG_ERR,
558 CFSTR("updateConfiguration(): %@ is not a dictionary."),
559 kSCPrefSystem);
560 goto done;
561 }
562
563 /* flatten property list */
564 flatten(prefs, CFSTR("/"), global);
565
566 getSet :
567
568 /*
569 * get current set name
570 */
571 current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
572 if (!current) {
573 /* if current set not defined */
574 goto done;
575 }
576
577 if (!isA_CFString(current)) {
578 SCLog(TRUE, LOG_ERR,
579 CFSTR("updateConfiguration(): %@ is not a string."),
580 kSCPrefCurrentSet);
581 goto done;
582 }
583
584 /*
585 * get current set
586 */
587 set = SCPreferencesPathGetValue(prefs, current);
588 if (!set) {
589 /* if error with path */
590 SCLog(TRUE, LOG_ERR,
591 CFSTR("%@ value (%@) not valid"),
592 kSCPrefCurrentSet,
593 current);
594 goto done;
595 }
596
597 if (!isA_CFDictionary(set)) {
598 SCLog(TRUE, LOG_ERR,
599 CFSTR("updateConfiguration(): %@ is not a dictionary."),
600 current);
601 goto done;
602 }
603
604 /* flatten property list */
605 flatten(prefs, CFSTR("/"), set);
606
607 CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current);
608
609 done :
610
611 /* add last updated time stamp */
612 CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date);
613
614 /* add Setup: key */
615 CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict);
616
617 /* compare current and new preferences */
618 CFDictionaryApplyFunction(newPrefs, updateCache, NULL);
619
620 /* remove those keys which have not changed from the update */
621 n = CFArrayGetCount(unchangedPrefsKeys);
622 for (i = 0; i < n; i++) {
623 CFStringRef key;
624
625 key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i);
626 CFDictionaryRemoveValue(newPrefs, key);
627 }
628
629 /* Update the dynamic store */
630 #ifndef MAIN
631 if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) {
632 SCLog(TRUE, LOG_ERR,
633 CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
634 SCErrorString(SCError()));
635 }
636 #else // !MAIN
637 SCLog(TRUE, LOG_NOTICE,
638 CFSTR("SCDynamicStore\nset: %@\nremove: %@\n"),
639 newPrefs,
640 removedPrefsKeys);
641 #endif // !MAIN
642
643 CFRelease(currentPrefs);
644 CFRelease(newPrefs);
645 CFRelease(unchangedPrefsKeys);
646 CFRelease(removedPrefsKeys);
647 if (dict) CFRelease(dict);
648 if (date) CFRelease(date);
649 if (keys) CFRelease(keys);
650 return;
651 }
652
653
654 static void
655 updateConfiguration(SCPreferencesRef prefs,
656 SCPreferencesNotification notificationType,
657 void *info)
658 {
659
660
661 #if !TARGET_OS_IPHONE
662 if ((notificationType & kSCPreferencesNotificationCommit) == kSCPreferencesNotificationCommit) {
663 SCNetworkSetRef current;
664
665 current = SCNetworkSetCopyCurrent(prefs);
666 if (current != NULL) {
667 /* network configuration available, disable template creation */
668 watchQuietDisable();
669 CFRelease(current);
670 }
671 }
672 #endif /* !TARGET_OS_IPHONE */
673
674 if ((notificationType & kSCPreferencesNotificationApply) != kSCPreferencesNotificationApply) {
675 return;
676 }
677
678 SCLog(_verbose, LOG_DEBUG, CFSTR("updating configuration"));
679
680 /* update SCDynamicStore (Setup:) */
681 updateSCDynamicStore(prefs);
682
683 /* finished with current prefs, wait for changes */
684 if (!rofs) {
685 SCPreferencesSynchronize(prefs);
686 }
687
688 return;
689 }
690
691
692 __private_extern__
693 void
694 prime_PreferencesMonitor()
695 {
696 SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
697
698 /* load the initial configuration from the database */
699 updateConfiguration(prefs, kSCPreferencesNotificationApply, (void *)store);
700
701 return;
702 }
703
704
705 __private_extern__
706 void
707 load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
708 {
709 Boolean initPrefs = TRUE;
710
711 if (bundleVerbose) {
712 _verbose = TRUE;
713 }
714
715 SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
716 SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
717
718 /* open a SCDynamicStore session to allow cache updates */
719 store = SCDynamicStoreCreate(NULL,
720 CFSTR("PreferencesMonitor.bundle"),
721 watchQuietCallback,
722 NULL);
723 if (store == NULL) {
724 SCLog(TRUE, LOG_ERR,
725 CFSTR("SCDynamicStoreCreate() failed: %s"),
726 SCErrorString(SCError()));
727 goto error;
728 }
729
730 /* open a SCPreferences session */
731 #ifndef MAIN
732 prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
733 #else // !MAIN
734 prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist"));
735 #endif // !MAIN
736 if (prefs != NULL) {
737 Boolean need_update = FALSE;
738 CFStringRef new_model;
739
740 new_model = _SC_hw_model(FALSE);
741
742 /* Need to regenerate the new configuration for new model */
743 if (new_model != NULL) {
744 CFStringRef old_model;
745
746 old_model = SCPreferencesGetValue(prefs, MODEL);
747 if (old_model != NULL && !_SC_CFEqual(old_model, new_model)) {
748 // if new hardware
749 need_update = TRUE;
750 }
751 }
752
753 if (need_update == FALSE) {
754 SCNetworkSetRef current;
755
756 current = SCNetworkSetCopyCurrent(prefs);
757 if (current != NULL) {
758 /* network configuration available, disable template creation */
759 initPrefs = FALSE;
760 CFRelease(current);
761 }
762 }
763 } else {
764 SCLog(TRUE, LOG_ERR,
765 CFSTR("SCPreferencesCreate() failed: %s"),
766 SCErrorString(SCError()));
767 goto error;
768 }
769
770 /*
771 * register for change notifications.
772 */
773 if (!SCPreferencesSetCallback(prefs, updateConfiguration, NULL)) {
774 SCLog(TRUE, LOG_ERR,
775 CFSTR("SCPreferencesSetCallBack() failed: %s"),
776 SCErrorString(SCError()));
777 goto error;
778 }
779
780 if (!SCPreferencesScheduleWithRunLoop(prefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
781 SCLog(TRUE, LOG_ERR,
782 CFSTR("SCPreferencesScheduleWithRunLoop() failed: %s"),
783 SCErrorString(SCError()));
784 goto error;
785 }
786
787 /*
788 * if no preferences, initialize with a template (now or
789 * when IOKit has quiesced).
790 */
791 if (initPrefs) {
792 watchQuietEnable();
793 watchQuietCallback(store, NULL, NULL);
794 }
795
796 return;
797
798 error :
799
800 watchQuietDisable();
801 if (store != NULL) CFRelease(store);
802 if (prefs != NULL) CFRelease(prefs);
803
804 return;
805 }
806
807
808 #ifdef MAIN
809 int
810 main(int argc, char **argv)
811 {
812 _sc_log = FALSE;
813 _sc_verbose = (argc > 1) ? TRUE : FALSE;
814
815 load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
816 prime_PreferencesMonitor();
817 CFRunLoopRun();
818 /* not reached */
819 exit(0);
820 return 0;
821 }
822 #endif