2 * Copyright (c) 2000-2008, 2010, 2012-2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * April 2, 2004 Allan Nathanson <ajn@apple.com>
28 * - use SCPreference notification APIs
30 * June 24, 2001 Allan Nathanson <ajn@apple.com>
31 * - update to public SystemConfiguration.framework APIs
33 * November 10, 2000 Allan Nathanson <ajn@apple.com>
38 #include <TargetConditionals.h>
40 #include <sys/types.h>
45 #include <SystemConfiguration/SystemConfiguration.h>
46 #include <SystemConfiguration/SCPrivate.h>
47 #include <SystemConfiguration/SCValidation.h>
53 static SCPreferencesRef prefs
= NULL
;
54 static SCDynamicStoreRef store
= NULL
;
56 /* preferences "initialization" globals */
57 static CFStringRef initKey
= NULL
;
58 static CFRunLoopSourceRef initRls
= NULL
;
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 */
66 static Boolean rofs
= FALSE
;
67 static Boolean restorePrefs
= FALSE
;
69 #define MY_PLUGIN_NAME "PreferencesMonitor"
70 #define MY_PLUGIN_ID CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
76 CFStringRef currentModel
= NULL
;
77 CFMutableStringRef modelPrefixStr
= NULL
;
78 CFArrayRef keyList
= NULL
;
81 Boolean modified
= FALSE
;
82 int sc_status
= kSCStatusFailed
;
85 ok
= SCPreferencesLock(prefs
, TRUE
);
90 sc_status
= SCError();
91 if (sc_status
== kSCStatusStale
) {
92 SCPreferencesSynchronize(prefs
);
94 SC_log(LOG_NOTICE
, "Could not acquire network configuration lock: %s",
95 SCErrorString(sc_status
));
100 keyList
= SCPreferencesCopyKeyList(prefs
);
101 if (keyList
== NULL
) {
105 currentModel
= _SC_hw_model(FALSE
);
106 if (currentModel
== NULL
) {
110 /* Create "model:" string for prefix-check */
111 modelPrefixStr
= CFStringCreateMutableCopy(NULL
, 0, currentModel
);
112 CFStringAppend(modelPrefixStr
, CFSTR(":"));
114 keyListCount
= CFArrayGetCount(keyList
);
115 for (idx
= 0; idx
< keyListCount
; idx
++) {
116 CFStringRef existingKey
= CFArrayGetValueAtIndex(keyList
, idx
);
118 CFArrayRef splitKey
= NULL
;
119 CFPropertyListRef value
;
121 if (isA_CFString(existingKey
) == NULL
) {
125 if (CFStringHasPrefix(existingKey
, modelPrefixStr
) == FALSE
) {
129 splitKey
= CFStringCreateArrayBySeparatingStrings(NULL
, existingKey
, CFSTR(":"));
130 key
= CFArrayGetValueAtIndex(splitKey
, 1);
131 value
= SCPreferencesGetValue(prefs
, existingKey
);
132 SCPreferencesSetValue(prefs
, key
, value
);
133 SCPreferencesRemoveValue(prefs
, existingKey
);
138 if (modified
== TRUE
) {
139 SCPreferencesRef ni_prefs
= NULL
;
140 ni_prefs
= SCPreferencesCreate(NULL
, MY_PLUGIN_ID
, CFSTR("NetworkInterfaces.plist"));
141 if (ni_prefs
== NULL
) {
145 ok
= _SCNetworkConfigurationCheckValidityWithPreferences(prefs
, ni_prefs
, NULL
);
148 //Commit the changes only if prefs files valid
150 if (!SCPreferencesCommitChanges(prefs
)) {
151 if (SCError() != EROFS
) {
152 SC_log(LOG_NOTICE
, "SCPreferencesCommitChanges() failed: %s",
153 SCErrorString(SCError()));
159 (void) SCPreferencesApplyChanges(prefs
);
164 (void) SCPreferencesUnlock(prefs
);
166 if (keyList
!= NULL
) {
169 if (modelPrefixStr
!= NULL
) {
170 CFRelease(modelPrefixStr
);
177 establishNewPreferences()
180 SCNetworkSetRef current
= NULL
;
181 CFStringRef new_model
;
183 int sc_status
= kSCStatusFailed
;
184 SCNetworkSetRef set
= NULL
;
185 CFStringRef setName
= NULL
;
186 Boolean updated
= FALSE
;
189 ok
= SCPreferencesLock(prefs
, TRUE
);
194 sc_status
= SCError();
195 if (sc_status
== kSCStatusStale
) {
196 SCPreferencesSynchronize(prefs
);
198 SC_log(LOG_NOTICE
, "Could not acquire network configuration lock: %s",
199 SCErrorString(sc_status
));
204 /* Ensure that the preferences has the new model */
205 new_model
= _SC_hw_model(FALSE
);
207 /* Need to regenerate the new configuration for new model */
208 if (new_model
!= NULL
) {
209 CFStringRef old_model
;
211 old_model
= SCPreferencesGetValue(prefs
, MODEL
);
212 if ((old_model
!= NULL
) && !_SC_CFEqual(old_model
, new_model
)) {
217 keys
= SCPreferencesCopyKeyList(prefs
);
218 count
= (keys
!= NULL
) ? CFArrayGetCount(keys
) : 0;
220 for (index
= 0; index
< count
; index
++) {
221 CFStringRef existing_key
;
223 existing_key
= CFArrayGetValueAtIndex(keys
, index
);
224 if (isA_CFString(existing_key
) != NULL
) {
226 CFPropertyListRef value
;
228 /* If it already contains a Model
229 or if it already contains a MODEL:KEY key skip it*/
230 if (CFEqual(existing_key
, MODEL
)
231 || CFStringFind(existing_key
, CFSTR(":"), 0).location
236 value
= SCPreferencesGetValue(prefs
, existing_key
);
238 /* Create a new key as OLD_MODEL:OLD_KEY */
239 new_key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@:%@"),
240 old_model
, existing_key
);
241 SCPreferencesSetValue(prefs
, new_key
, value
);
242 if (!CFEqual(existing_key
, kSCPrefSystem
)) {
243 /* preserve existing host names */
244 SCPreferencesRemoveValue(prefs
, existing_key
);
254 /* Set the new model */
255 SCPreferencesSetValue(prefs
, MODEL
, new_model
);
258 current
= SCNetworkSetCopyCurrent(prefs
);
259 if (current
!= NULL
) {
264 set
= SCNetworkSetCreate(prefs
);
267 sc_status
= SCError();
271 bundle
= _SC_CFBundleGet();
272 if (bundle
!= NULL
) {
273 setName
= CFBundleCopyLocalizedString(bundle
,
274 CFSTR("DEFAULT_SET_NAME"),
279 ok
= SCNetworkSetSetName(set
, (setName
!= NULL
) ? setName
: CFSTR("Automatic"));
281 sc_status
= SCError();
285 ok
= SCNetworkSetSetCurrent(set
);
287 sc_status
= SCError();
292 ok
= SCNetworkSetEstablishDefaultConfiguration(set
);
294 sc_status
= SCError();
301 ok
= SCPreferencesCommitChanges(prefs
);
303 SC_log(LOG_NOTICE
, "New network configuration saved");
306 sc_status
= SCError();
307 if (sc_status
== EROFS
) {
308 /* a read-only fileysstem is OK */
311 /* ... but we don't want to synchronize */
316 /* apply (committed or temporary/read-only) changes */
317 (void) SCPreferencesApplyChanges(prefs
);
318 } else if ((current
== NULL
) && (set
!= NULL
)) {
319 (void) SCNetworkSetRemove(set
);
323 SC_log(LOG_NOTICE
, "Could not establish network configuration: %s",
324 SCErrorString(sc_status
));
327 (void)SCPreferencesUnlock(prefs
);
328 if (setName
!= NULL
) CFRelease(setName
);
329 if (set
!= NULL
) CFRelease(set
);
335 quiet(Boolean
*timeout
)
337 CFDictionaryRef dict
;
338 Boolean _quiet
= FALSE
;
339 Boolean _timeout
= FALSE
;
342 dict
= SCDynamicStoreCopyValue(store
, initKey
);
344 if (isA_CFDictionary(dict
)) {
345 if (CFDictionaryContainsKey(dict
, CFSTR("*QUIET*"))) {
348 if (CFDictionaryContainsKey(dict
, CFSTR("*TIMEOUT*"))) {
355 if (timeout
!= NULL
) {
365 if ((initKey
== NULL
) || (initRls
== NULL
)) {
369 (void) SCDynamicStoreSetNotificationKeys(store
, NULL
, NULL
);
371 CFRunLoopSourceInvalidate(initRls
);
388 initKey
= SCDynamicStoreKeyCreate(NULL
,
389 CFSTR("%@" "InterfaceNamer"),
390 kSCDynamicStoreDomainPlugin
);
392 initRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
393 CFRunLoopAddSource(CFRunLoopGetCurrent(), initRls
, kCFRunLoopDefaultMode
);
395 keys
= CFArrayCreate(NULL
, (const void **)&initKey
, 1, &kCFTypeArrayCallBacks
);
396 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
399 SC_log(LOG_NOTICE
, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError()));
409 previousConfigurationAvailable()
411 CFStringRef backupKey
= NULL
;
412 CFStringRef currentModel
= NULL
;
413 CFPropertyListRef properties
= NULL
;
415 currentModel
= _SC_hw_model(FALSE
);
416 if (currentModel
== NULL
) {
420 /* Currently relying only if a backup of "Sets" is present */
421 backupKey
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@:Sets"), currentModel
);
422 properties
= SCPreferencesGetValue(prefs
, backupKey
);
423 CFRelease(backupKey
);
425 return (properties
!= NULL
);
429 watchQuietCallback(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *info
)
432 Boolean _timeout
= FALSE
;
434 _quiet
= quiet(&_timeout
);
436 #if !TARGET_OS_IPHONE
438 #endif /* !TARGET_OS_IPHONE */
443 if (_quiet
|| _timeout
) {
444 static int logged
= 0;
446 (void) establishNewPreferences();
448 if (restorePrefs
== TRUE
) {
449 (void) restorePreferences();
450 restorePrefs
= FALSE
;
453 if (_timeout
&& (logged
++ == 0)) {
454 SC_log(LOG_ERR
, "Network configuration creation timed out waiting for IORegistry");
463 updateCache(const void *key
, const void *value
, void *context
)
465 CFStringRef configKey
= (CFStringRef
)key
;
466 CFPropertyListRef configData
= (CFPropertyListRef
)value
;
467 CFPropertyListRef cacheData
;
470 cacheData
= CFDictionaryGetValue(currentPrefs
, configKey
);
473 if (CFEqual(cacheData
, configData
)) {
475 * if the old & new property list values have
476 * not changed then we don't need to update
479 CFArrayAppendValue(unchangedPrefsKeys
, configKey
);
483 /* in any case, this key should not be removed */
484 i
= CFArrayGetFirstIndexOfValue(removedPrefsKeys
,
485 CFRangeMake(0, CFArrayGetCount(removedPrefsKeys
)),
487 if (i
!= kCFNotFound
) {
488 CFArrayRemoveValueAtIndex(removedPrefsKeys
, i
);
496 flatten(SCPreferencesRef prefs
,
498 CFDictionaryRef base
)
500 CFDictionaryRef subset
;
502 CFMutableDictionaryRef myDict
;
509 if (!CFDictionaryGetValueIfPresent(base
, kSCResvLink
, (const void **)&link
)) {
510 /* if this dictionary is not linked */
513 /* if __LINK__ key is present */
514 subset
= SCPreferencesPathGetValue(prefs
, link
);
516 /* if error with link */
517 SC_log(LOG_NOTICE
, "SCPreferencesPathGetValue(,%@,) failed: %s",
519 SCErrorString(SCError()));
524 if (CFDictionaryContainsKey(subset
, kSCResvInactive
)) {
525 /* if __INACTIVE__ key is present */
529 myKey
= CFStringCreateWithFormat(NULL
,
532 kSCDynamicStoreDomainSetup
,
535 myDict
= (CFMutableDictionaryRef
)CFDictionaryGetValue(newPrefs
, myKey
);
537 myDict
= CFDictionaryCreateMutableCopy(NULL
,
539 (CFDictionaryRef
)myDict
);
541 myDict
= CFDictionaryCreateMutable(NULL
,
543 &kCFTypeDictionaryKeyCallBacks
,
544 &kCFTypeDictionaryValueCallBacks
);
547 nKeys
= CFDictionaryGetCount(subset
);
549 keys
= CFAllocatorAllocate(NULL
, nKeys
* sizeof(CFStringRef
) , 0);
550 vals
= CFAllocatorAllocate(NULL
, nKeys
* sizeof(CFPropertyListRef
), 0);
551 CFDictionaryGetKeysAndValues(subset
, keys
, vals
);
552 for (i
= 0; i
< nKeys
; i
++) {
553 if (CFGetTypeID((CFTypeRef
)vals
[i
]) != CFDictionaryGetTypeID()) {
554 /* add this key/value to the current dictionary */
555 CFDictionarySetValue(myDict
, keys
[i
], vals
[i
]);
559 /* flatten [sub]dictionaries */
560 subKey
= CFStringCreateWithFormat(NULL
,
564 CFEqual(key
, CFSTR("/")) ? "" : "/",
566 flatten(prefs
, subKey
, vals
[i
]);
570 CFAllocatorDeallocate(NULL
, keys
);
571 CFAllocatorDeallocate(NULL
, vals
);
574 if (CFDictionaryGetCount(myDict
) > 0) {
575 /* add this dictionary to the new preferences */
576 CFDictionarySetValue(newPrefs
, myKey
, myDict
);
587 updateSCDynamicStore(SCPreferencesRef prefs
)
589 CFStringRef current
= NULL
;
590 CFDateRef date
= NULL
;
591 CFMutableDictionaryRef dict
= NULL
;
592 CFDictionaryRef global
= NULL
;
597 CFMutableArrayRef patterns
;
598 CFDictionaryRef set
= NULL
;
601 * initialize old preferences, new preferences, an array
602 * of keys which have not changed, and an array of keys
603 * to be removed (cleaned up).
606 patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
607 pattern
= CFStringCreateWithFormat(NULL
,
610 kSCDynamicStoreDomainSetup
);
611 CFArrayAppendValue(patterns
, pattern
);
612 dict
= (CFMutableDictionaryRef
)SCDynamicStoreCopyMultiple(store
, NULL
, patterns
);
616 currentPrefs
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
619 currentPrefs
= CFDictionaryCreateMutable(NULL
,
621 &kCFTypeDictionaryKeyCallBacks
,
622 &kCFTypeDictionaryValueCallBacks
);
625 unchangedPrefsKeys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
627 i
= CFDictionaryGetCount(currentPrefs
);
629 const void **currentKeys
;
632 currentKeys
= CFAllocatorAllocate(NULL
, i
* sizeof(CFStringRef
), 0);
633 CFDictionaryGetKeysAndValues(currentPrefs
, currentKeys
, NULL
);
634 array
= CFArrayCreate(NULL
, currentKeys
, i
, &kCFTypeArrayCallBacks
);
635 removedPrefsKeys
= CFArrayCreateMutableCopy(NULL
, 0, array
);
637 CFAllocatorDeallocate(NULL
, currentKeys
);
639 removedPrefsKeys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
643 * The "newPrefs" dictionary will contain the new / updated
644 * configuration which will be written to the configuration cache.
646 newPrefs
= CFDictionaryCreateMutable(NULL
,
648 &kCFTypeDictionaryKeyCallBacks
,
649 &kCFTypeDictionaryValueCallBacks
);
652 * create status dictionary associated with current configuration
653 * information including:
654 * - current set "name" to cache
655 * - time stamp indicating when the cache preferences were
658 dict
= CFDictionaryCreateMutable(NULL
,
660 &kCFTypeDictionaryKeyCallBacks
,
661 &kCFTypeDictionaryValueCallBacks
);
662 date
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
667 keys
= SCPreferencesCopyKeyList(prefs
);
668 if ((keys
== NULL
) || (CFArrayGetCount(keys
) == 0)) {
669 SC_log(LOG_NOTICE
, "updateConfiguration(): no preferences");
674 * get "global" system preferences
676 global
= SCPreferencesGetValue(prefs
, kSCPrefSystem
);
678 /* if no global preferences are defined */
682 if (!isA_CFDictionary(global
)) {
683 SC_log(LOG_NOTICE
, "updateConfiguration(): %@ is not a dictionary",
688 /* flatten property list */
689 flatten(prefs
, CFSTR("/"), global
);
694 * get current set name
696 current
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
698 /* if current set not defined */
702 if (!isA_CFString(current
)) {
703 SC_log(LOG_NOTICE
, "updateConfiguration(): %@ is not a string",
711 set
= SCPreferencesPathGetValue(prefs
, current
);
713 /* if error with path */
714 SC_log(LOG_NOTICE
, "%@ value (%@) not valid",
720 if (!isA_CFDictionary(set
)) {
721 SC_log(LOG_NOTICE
, "updateConfiguration(): %@ is not a dictionary",
726 /* flatten property list */
727 flatten(prefs
, CFSTR("/"), set
);
729 CFDictionarySetValue(dict
, kSCDynamicStorePropSetupCurrentSet
, current
);
733 /* add last updated time stamp */
734 CFDictionarySetValue(dict
, kSCDynamicStorePropSetupLastUpdated
, date
);
737 CFDictionarySetValue(newPrefs
, kSCDynamicStoreDomainSetup
, dict
);
739 /* compare current and new preferences */
740 CFDictionaryApplyFunction(newPrefs
, updateCache
, NULL
);
742 /* remove those keys which have not changed from the update */
743 n
= CFArrayGetCount(unchangedPrefsKeys
);
744 for (i
= 0; i
< n
; i
++) {
747 key
= CFArrayGetValueAtIndex(unchangedPrefsKeys
, i
);
748 CFDictionaryRemoveValue(newPrefs
, key
);
751 /* Update the dynamic store */
753 if (!SCDynamicStoreSetMultiple(store
, newPrefs
, removedPrefsKeys
, NULL
)) {
754 SC_log(LOG_NOTICE
, "SCDynamicStoreSetMultiple() failed: %s", SCErrorString(SCError()));
757 SC_log(LOG_DEBUG
, "SCDynamicStore\nset: %@\nremove: %@",
762 CFRelease(currentPrefs
);
764 CFRelease(unchangedPrefsKeys
);
765 CFRelease(removedPrefsKeys
);
766 if (dict
) CFRelease(dict
);
767 if (date
) CFRelease(date
);
768 if (keys
) CFRelease(keys
);
774 updateConfiguration(SCPreferencesRef prefs
,
775 SCPreferencesNotification notificationType
,
778 os_activity_t activity_id
;
781 activity_id
= os_activity_start("processing [SC] preferences.plist changes",
782 OS_ACTIVITY_FLAG_DEFAULT
);
784 #if !TARGET_OS_IPHONE
785 if ((notificationType
& kSCPreferencesNotificationCommit
) == kSCPreferencesNotificationCommit
) {
786 SCNetworkSetRef current
;
788 current
= SCNetworkSetCopyCurrent(prefs
);
789 if (current
!= NULL
) {
790 /* network configuration available, disable template creation */
795 #endif /* !TARGET_OS_IPHONE */
797 if ((notificationType
& kSCPreferencesNotificationApply
) != kSCPreferencesNotificationApply
) {
801 SC_log(LOG_INFO
, "updating configuration");
803 /* update SCDynamicStore (Setup:) */
804 updateSCDynamicStore(prefs
);
806 /* finished with current prefs, wait for changes */
808 SCPreferencesSynchronize(prefs
);
813 os_activity_end(activity_id
);
821 prime_PreferencesMonitor()
823 SC_log(LOG_DEBUG
, "prime() called");
825 /* load the initial configuration from the database */
826 updateConfiguration(prefs
, kSCPreferencesNotificationApply
, (void *)store
);
834 load_PreferencesMonitor(CFBundleRef bundle
, Boolean bundleVerbose
)
836 Boolean initPrefs
= TRUE
;
838 SC_log(LOG_DEBUG
, "load() called");
839 SC_log(LOG_DEBUG
, " bundle ID = %@", CFBundleGetIdentifier(bundle
));
841 /* open a SCDynamicStore session to allow cache updates */
842 store
= SCDynamicStoreCreate(NULL
,
843 CFSTR("PreferencesMonitor.bundle"),
847 SC_log(LOG_NOTICE
, "SCDynamicStoreCreate() failed: %s", SCErrorString(SCError()));
851 /* open a SCPreferences session */
853 prefs
= SCPreferencesCreate(NULL
, CFSTR("PreferencesMonitor.bundle"), NULL
);
855 prefs
= SCPreferencesCreate(NULL
, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist"));
858 Boolean need_update
= FALSE
;
859 CFStringRef new_model
;
861 new_model
= _SC_hw_model(FALSE
);
863 /* Need to regenerate the new configuration for new model */
864 if (new_model
!= NULL
) {
865 CFStringRef old_model
;
867 old_model
= SCPreferencesGetValue(prefs
, MODEL
);
868 if (old_model
!= NULL
&& !_SC_CFEqual(old_model
, new_model
)) {
871 restorePrefs
= previousConfigurationAvailable();
875 if (need_update
== FALSE
) {
876 SCNetworkSetRef current
;
878 current
= SCNetworkSetCopyCurrent(prefs
);
879 if (current
!= NULL
) {
880 /* network configuration available, disable template creation */
886 SC_log(LOG_NOTICE
, "SCPreferencesCreate() failed: %s", SCErrorString(SCError()));
891 * register for change notifications.
893 if (!SCPreferencesSetCallback(prefs
, updateConfiguration
, NULL
)) {
894 SC_log(LOG_NOTICE
, "SCPreferencesSetCallBack() failed: %s", SCErrorString(SCError()));
898 if (!SCPreferencesScheduleWithRunLoop(prefs
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
)) {
899 SC_log(LOG_NOTICE
, "SCPreferencesScheduleWithRunLoop() failed: %s", SCErrorString(SCError()));
904 * if no preferences, initialize with a template (now or
905 * when IOKit has quiesced).
909 watchQuietCallback(store
, NULL
, NULL
);
917 if (store
!= NULL
) CFRelease(store
);
918 if (prefs
!= NULL
) CFRelease(prefs
);
926 main(int argc
, char **argv
)
929 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
931 load_PreferencesMonitor(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);
932 prime_PreferencesMonitor();