2 * Copyright (c) 2000-2007 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 * October 30, 2003 Allan Nathanson <ajn@apple.com>
28 * - add plugin "stop()" function support
30 * June 11, 2001 Allan Nathanson <ajn@apple.com>
31 * - start using CFBundle code
33 * June 1, 2001 Allan Nathanson <ajn@apple.com>
34 * - public API conversion
36 * May 26, 2000 Allan Nathanson <ajn@apple.com>
40 #include <mach-o/dyld.h>
41 #include <sys/types.h>
43 #include <sys/param.h>
48 #include <NSSystemDirectories.h>
51 #include "configd_server.h"
52 #include <SystemConfiguration/SCDPlugin.h>
53 void _SCDPluginExecInit();
57 * path components, extensions, entry points, ...
59 #define BUNDLE_DIRECTORY "/SystemConfiguration" /* [/System/Library]/... */
60 #define BUNDLE_DIR_EXTENSION ".bundle"
69 SCDynamicStoreBundleLoadFunction load
;
70 SCDynamicStoreBundleStartFunction start
;
71 SCDynamicStoreBundlePrimeFunction prime
;
72 SCDynamicStoreBundleStopFunction stop
;
77 static CFMutableArrayRef allBundles
= NULL
;
80 static CFMutableDictionaryRef exiting
= NULL
;
82 // plugin CFRunLoopRef
84 CFRunLoopRef plugin_runLoop
= NULL
;
87 extern SCDynamicStoreBundleLoadFunction load_ATconfig
;
88 extern SCDynamicStoreBundleStopFunction stop_ATconfig
;
89 extern SCDynamicStoreBundleLoadFunction load_IPMonitor
;
90 extern SCDynamicStoreBundlePrimeFunction prime_IPMonitor
;
91 extern SCDynamicStoreBundleLoadFunction load_InterfaceNamer
;
92 extern SCDynamicStoreBundleLoadFunction load_KernelEventMonitor
;
93 extern SCDynamicStoreBundlePrimeFunction prime_KernelEventMonitor
;
95 extern SCDynamicStoreBundleLoadFunction load_Kicker
;
96 #endif // INCLUDE_KICKER
97 extern SCDynamicStoreBundleLoadFunction load_LinkConfiguration
;
98 extern SCDynamicStoreBundleLoadFunction load_PreferencesMonitor
;
99 extern SCDynamicStoreBundlePrimeFunction prime_PreferencesMonitor
;
100 extern SCDynamicStoreBundleStopFunction stop_PreferencesMonitor
;
101 extern SCDynamicStoreBundleLoadFunction load_NetworkIdentification
;
102 extern SCDynamicStoreBundlePrimeFunction prime_NetworkIdentification
;
103 extern SCDynamicStoreBundleStopFunction stop_NetworkIdentification
;
107 const CFStringRef bundleID
;
108 const void *load
; // SCDynamicStoreBundleLoadFunction
109 const void *start
; // SCDynamicStoreBundleStartFunction
110 const void *prime
; // SCDynamicStoreBundlePrimeFunction
111 const void *stop
; // SCDynamicStoreBundleStopFunction
112 } builtin
, *builtinRef
;
115 static const builtin builtin_plugins
[] = {
117 CFSTR("com.apple.SystemConfiguration.ATconfig"),
124 CFSTR("com.apple.SystemConfiguration.IPMonitor"),
131 CFSTR("com.apple.SystemConfiguration.InterfaceNamer"),
132 &load_InterfaceNamer
,
138 CFSTR("com.apple.SystemConfiguration.KernelEventMonitor"),
139 &load_KernelEventMonitor
,
141 &prime_KernelEventMonitor
,
144 #ifdef INCLUDE_KICKER
146 CFSTR("com.apple.SystemConfiguration.Kicker"),
152 #endif // INCLUDE_KICKER
154 CFSTR("com.apple.SystemConfiguration.LinkConfiguration"),
155 &load_LinkConfiguration
,
161 CFSTR("com.apple.SystemConfiguration.NetworkIdentification"),
162 &load_NetworkIdentification
,
164 &prime_NetworkIdentification
,
165 &stop_NetworkIdentification
168 CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
169 &load_PreferencesMonitor
,
171 &prime_PreferencesMonitor
,
172 &stop_PreferencesMonitor
179 traceBundle(const char *op
, CFBundleRef bundle
)
181 if (_configd_trace
!= NULL
) {
182 if (bundle
!= NULL
) {
183 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
185 SCTrace(TRUE
, _configd_trace
,
186 CFSTR("bundle : %s %@\n"),
190 SCTrace(TRUE
, _configd_trace
,
191 CFSTR("bundle : %s\n"),
202 addBundle(CFBundleRef bundle
, Boolean forceEnabled
)
204 CFDictionaryRef bundleDict
;
205 bundleInfoRef bundleInfo
;
207 bundleInfo
= CFAllocatorAllocate(NULL
, sizeof(*bundleInfo
), 0);
208 bundleInfo
->bundle
= (CFBundleRef
)CFRetain(bundle
);
209 bundleInfo
->loaded
= FALSE
;
210 bundleInfo
->builtin
= FALSE
;
211 bundleInfo
->enabled
= TRUE
;
212 bundleInfo
->verbose
= FALSE
;
213 bundleInfo
->load
= NULL
;
214 bundleInfo
->start
= NULL
;
215 bundleInfo
->prime
= NULL
;
216 bundleInfo
->stop
= NULL
;
218 bundleDict
= CFBundleGetInfoDictionary(bundle
);
219 if (isA_CFDictionary(bundleDict
)) {
222 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleIsBuiltinKey
);
223 if (isA_CFBoolean(bVal
)) {
224 bundleInfo
->builtin
= CFBooleanGetValue(bVal
);
227 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleEnabledKey
);
228 if (isA_CFBoolean(bVal
)) {
229 bundleInfo
->enabled
= CFBooleanGetValue(bVal
);
232 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleVerboseKey
);
233 if (isA_CFBoolean(bVal
)) {
234 bundleInfo
->verbose
= CFBooleanGetValue(bVal
);
239 bundleInfo
->enabled
= TRUE
;
242 CFArrayAppendValue(allBundles
, bundleInfo
);
248 shortBundleIdentifier(CFStringRef bundleID
)
250 CFIndex len
= CFStringGetLength(bundleID
);
252 CFStringRef shortID
= NULL
;
254 if (CFStringFindWithOptions(bundleID
,
259 range
.location
= range
.location
+ range
.length
;
260 range
.length
= len
- range
.location
;
261 shortID
= CFStringCreateWithSubstring(NULL
, bundleID
, range
);
269 getBundleSymbol(CFBundleRef bundle
, CFStringRef functionName
, CFStringRef shortID
)
273 // search for load(), start(), prime(), stop(), ...
274 func
= CFBundleGetFunctionPointerForName(bundle
, functionName
);
279 if (shortID
!= NULL
) {
280 CFStringRef altFunctionName
;
282 // search for load_XXX(), ...
283 altFunctionName
= CFStringCreateWithFormat(NULL
,
288 func
= CFBundleGetFunctionPointerForName(bundle
, altFunctionName
);
289 CFRelease(altFunctionName
);
297 loadBundle(const void *value
, void *context
) {
298 CFStringRef bundleID
;
299 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
300 Boolean bundleExclude
;
301 CFIndex
*nLoaded
= (CFIndex
*)context
;
304 bundleID
= CFBundleGetIdentifier(bundleInfo
->bundle
);
305 if (bundleID
== NULL
) {
306 // sorry, no bundles without a bundle identifier
307 SCLog(TRUE
, LOG_DEBUG
, CFSTR("skipped %@ (no bundle ID)"), bundleInfo
->bundle
);
311 shortID
= shortBundleIdentifier(bundleID
);
313 bundleExclude
= CFSetContainsValue(_plugins_exclude
, bundleID
);
314 if (!bundleExclude
) {
315 if (shortID
!= NULL
) {
316 bundleExclude
= CFSetContainsValue(_plugins_exclude
, shortID
);
321 // sorry, this bundle has been excluded
322 SCLog(TRUE
, LOG_DEBUG
, CFSTR("skipped %@ (excluded)"), bundleID
);
326 if (!bundleInfo
->enabled
) {
327 // sorry, this bundle has not been enaabled
328 SCLog(TRUE
, LOG_DEBUG
, CFSTR("skipped %@ (disabled)"), bundleID
);
332 if (!bundleInfo
->verbose
) {
333 bundleInfo
->verbose
= CFSetContainsValue(_plugins_verbose
, bundleID
);
334 if (!bundleInfo
->verbose
) {
335 if (shortID
!= NULL
) {
336 bundleInfo
->verbose
= CFSetContainsValue(_plugins_verbose
, shortID
);
341 if (bundleInfo
->builtin
) {
344 SCLog(TRUE
, LOG_DEBUG
, CFSTR("adding %@"), bundleID
);
346 for (i
= 0; i
< sizeof(builtin_plugins
)/sizeof(builtin_plugins
[0]); i
++) {
347 if (CFEqual(bundleID
, builtin_plugins
[i
].bundleID
)) {
348 bundleInfo
->load
= builtin_plugins
[i
].load
;
349 bundleInfo
->start
= builtin_plugins
[i
].start
;
350 bundleInfo
->prime
= builtin_plugins
[i
].prime
;
351 bundleInfo
->stop
= builtin_plugins
[i
].stop
;
356 if ((bundleInfo
->load
== NULL
) &&
357 (bundleInfo
->start
== NULL
) &&
358 (bundleInfo
->prime
== NULL
) &&
359 (bundleInfo
->stop
== NULL
)) {
360 SCLog(TRUE
, LOG_NOTICE
, CFSTR("%@ add failed"), bundleID
);
364 SCLog(TRUE
, LOG_DEBUG
, CFSTR("loading %@"), bundleID
);
367 traceBundle("loading", bundleInfo
->bundle
);
370 if (!CFBundleLoadExecutable(bundleInfo
->bundle
)) {
371 SCLog(TRUE
, LOG_NOTICE
, CFSTR("%@ load failed"), bundleID
);
375 // get bundle entry points
376 bundleInfo
->load
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("load" ), shortID
);
377 bundleInfo
->start
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("start"), shortID
);
378 bundleInfo
->prime
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("prime"), shortID
);
379 bundleInfo
->stop
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("stop" ), shortID
);
382 /* mark this bundle as having been loaded */
383 bundleInfo
->loaded
= TRUE
;
385 /* bump the count of loaded bundles */
386 *nLoaded
= *nLoaded
+ 1;
390 if (shortID
!= NULL
) CFRelease(shortID
);
396 callLoadFunction(const void *value
, void *context
) {
397 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
399 if (!bundleInfo
->loaded
) {
403 if (bundleInfo
->load
== NULL
) {
404 // if no load() function
409 traceBundle("calling load() for", bundleInfo
->bundle
);
412 (*bundleInfo
->load
)(bundleInfo
->bundle
, bundleInfo
->verbose
);
419 callStartFunction(const void *value
, void *context
) {
420 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
422 char bundleName
[MAXNAMLEN
+ 1];
423 char bundlePath
[MAXPATHLEN
];
428 if (!bundleInfo
->loaded
) {
432 if (bundleInfo
->start
== NULL
) {
433 // if no start() function
437 bundleURL
= CFBundleCopyBundleURL(bundleInfo
->bundle
);
438 if (bundleURL
== NULL
) {
442 ok
= CFURLGetFileSystemRepresentation(bundleURL
,
444 (UInt8
*)&bundlePath
,
446 CFRelease(bundleURL
);
451 cp
= strrchr(bundlePath
, '/');
458 /* check if this directory entry is a valid bundle name */
460 if (len
<= (int)sizeof(BUNDLE_DIR_EXTENSION
)) {
461 /* if entry name isn't long enough */
465 len
-= sizeof(BUNDLE_DIR_EXTENSION
) - 1;
466 if (strcmp(&cp
[len
], BUNDLE_DIR_EXTENSION
) != 0) {
467 /* if entry name doesn end with ".bundle" */
471 /* get (just) the bundle's name */
472 bundleName
[0] = '\0';
473 (void) strncat(bundleName
, cp
, len
);
476 traceBundle("calling start() for", bundleInfo
->bundle
);
479 (*bundleInfo
->start
)(bundleName
, bundlePath
);
486 callPrimeFunction(const void *value
, void *context
) {
487 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
489 if (!bundleInfo
->loaded
) {
493 if (bundleInfo
->prime
== NULL
) {
494 // if no prime() function
499 traceBundle("calling prime() for", bundleInfo
->bundle
);
502 (*bundleInfo
->prime
)();
509 stopComplete(void *info
)
511 CFBundleRef bundle
= (CFBundleRef
)info
;
512 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
513 CFRunLoopSourceRef stopRls
;
515 SCLog(TRUE
, LOG_DEBUG
, CFSTR("** %@ complete (%f)"), bundleID
, CFAbsoluteTimeGetCurrent());
517 stopRls
= (CFRunLoopSourceRef
)CFDictionaryGetValue(exiting
, bundle
);
518 CFRunLoopSourceInvalidate(stopRls
);
520 CFDictionaryRemoveValue(exiting
, bundle
);
522 if (CFDictionaryGetCount(exiting
) == 0) {
525 // if all of the plugins are happy
526 status
= server_shutdown();
527 SCLog(TRUE
, LOG_DEBUG
, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
536 stopDelayed(CFRunLoopTimerRef timer
, void *info
)
543 SCLog(TRUE
, LOG_ERR
, CFSTR("server shutdown was delayed, unresponsive plugins:"));
546 * we've asked our plugins to shutdown but someone
549 n
= CFDictionaryGetCount(exiting
);
550 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
551 CFDictionaryGetKeysAndValues(exiting
, keys
, NULL
);
552 for (i
= 0; i
< n
; i
++) {
554 CFStringRef bundleID
;
556 bundle
= (CFBundleRef
)keys
[i
];
557 bundleID
= CFBundleGetIdentifier(bundle
);
558 SCLog(TRUE
, LOG_ERR
, CFSTR("** %@"), bundleID
);
560 CFAllocatorDeallocate(NULL
, keys
);
562 status
= server_shutdown();
567 stopRLSCopyDescription(const void *info
)
569 CFBundleRef bundle
= (CFBundleRef
)info
;
571 return CFStringCreateWithFormat(NULL
,
573 CFSTR("<stopRLS %p> {bundleID = %@}"),
575 CFBundleGetIdentifier(bundle
));
580 stopBundle(const void *value
, void *context
) {
581 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
582 CFRunLoopSourceRef stopRls
;
583 CFRunLoopSourceContext stopContext
= { 0 // version
584 , bundleInfo
->bundle
// info
586 , CFRelease
// release
587 , stopRLSCopyDescription
// copyDescription
592 , stopComplete
// perform
595 if (!bundleInfo
->loaded
) {
599 if (bundleInfo
->stop
== NULL
) {
600 // if no stop() function
604 stopRls
= CFRunLoopSourceCreate(NULL
, 0, &stopContext
);
605 CFRunLoopAddSource(CFRunLoopGetCurrent(), stopRls
, kCFRunLoopDefaultMode
);
606 CFDictionaryAddValue(exiting
, bundleInfo
->bundle
, stopRls
);
609 (*bundleInfo
->stop
)(stopRls
);
619 * If defined, call each bundles stop() function. This function is
620 * called when configd has been asked to shut down (via a SIGTERM). The
621 * function should signal the provided run loop source when it is "ready"
622 * for the shut down to proceeed.
624 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle stop() functions"));
625 CFArrayApplyFunction(allBundles
,
626 CFRangeMake(0, CFArrayGetCount(allBundles
)),
630 if (CFDictionaryGetCount(exiting
) == 0) {
633 // if all of the plugins are happy
634 status
= server_shutdown();
635 SCLog(TRUE
, LOG_DEBUG
, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
638 CFRunLoopTimerRef timer
;
640 /* sorry, we're not going to wait longer than 20 seconds */
641 timer
= CFRunLoopTimerCreate(NULL
, /* allocator */
642 CFAbsoluteTimeGetCurrent() + 20.0, /* fireDate (in 20 seconds) */
643 0.0, /* interval (== one-shot) */
646 stopDelayed
, /* callout */
648 CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer
, kCFRunLoopDefaultMode
);
657 termRLSCopyDescription(const void *info
)
659 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SIGTERM RLS>"));
665 plugin_term(int *status
)
667 CFRunLoopSourceContext termContext
= { 0 // version
671 , termRLSCopyDescription
// copyDescription
676 , stopBundles
// perform
678 CFRunLoopSourceRef termRls
;
680 if (plugin_runLoop
== NULL
) {
683 return FALSE
; // don't delay shutdown
686 if (exiting
!= NULL
) {
687 // if shutdown already active
691 SCLog(TRUE
, LOG_DEBUG
, CFSTR("starting server shutdown (%f)"), CFAbsoluteTimeGetCurrent());
693 exiting
= CFDictionaryCreateMutable(NULL
,
695 &kCFTypeDictionaryKeyCallBacks
,
696 &kCFTypeDictionaryValueCallBacks
);
698 termRls
= CFRunLoopSourceCreate(NULL
, 0, &termContext
);
699 CFRunLoopAddSource(plugin_runLoop
, termRls
, kCFRunLoopDefaultMode
);
700 CFRunLoopSourceSignal(termRls
);
702 CFRunLoopWakeUp(plugin_runLoop
);
710 timerCallback(CFRunLoopTimerRef timer
, void *info
)
715 if ((pass
> 120) && ((pass
% 60) != 0)) {
719 traceBundle("the [plugin] CFRunLoop is waiting...", NULL
);
726 sortBundles(CFMutableArrayRef orig
)
728 CFMutableArrayRef
new;
730 new = CFArrayCreateMutable(NULL
, 0, NULL
);
731 while (CFArrayGetCount(orig
) > 0) {
733 Boolean inserted
= FALSE
;
734 int nOrig
= CFArrayGetCount(orig
);
736 for (i
= 0; i
< nOrig
; i
++) {
737 bundleInfoRef bundleInfo1
= (bundleInfoRef
)CFArrayGetValueAtIndex(orig
, i
);
738 CFStringRef bundleID1
= CFBundleGetIdentifier(bundleInfo1
->bundle
);
740 CFDictionaryRef dict
;
743 CFArrayRef
requires = NULL
;
745 dict
= isA_CFDictionary(CFBundleGetInfoDictionary(bundleInfo1
->bundle
));
747 requires = CFDictionaryGetValue(dict
, kSCBundleRequiresKey
);
748 requires = isA_CFArray(requires);
750 if (bundleID1
== NULL
|| requires == NULL
) {
751 CFArrayInsertValueAtIndex(new, 0, bundleInfo1
);
752 CFArrayRemoveValueAtIndex(orig
, i
);
756 count
= nRequires
= CFArrayGetCount(requires);
757 for (j
= 0; j
< nRequires
; j
++) {
760 CFStringRef r
= CFArrayGetValueAtIndex(requires, j
);
762 nNew
= CFArrayGetCount(new);
763 for (k
= 0; k
< nNew
; k
++) {
764 bundleInfoRef bundleInfo2
= (bundleInfoRef
)CFArrayGetValueAtIndex(new, k
);
765 CFStringRef bundleID2
= CFBundleGetIdentifier(bundleInfo2
->bundle
);
767 if (bundleID2
&& CFEqual(bundleID2
, r
)) {
773 /* all dependencies are met, append */
774 CFArrayAppendValue(new, bundleInfo1
);
775 CFArrayRemoveValueAtIndex(orig
, i
);
781 if (inserted
== FALSE
) {
782 SCLog(TRUE
, LOG_NOTICE
, CFSTR("Bundles have circular dependency!!!"));
786 if (CFArrayGetCount(orig
) > 0) {
787 /* we have a circular dependency, append remaining items on new array */
788 CFArrayAppendArray(new, orig
, CFRangeMake(0, CFArrayGetCount(orig
)));
791 /* new one is a sorted version of original */
794 CFArrayRemoveAllValues(orig
);
795 CFArrayAppendArray(orig
, new, CFRangeMake(0, CFArrayGetCount(new)));
803 plugin_exec(void *arg
)
807 /* keep track of bundles */
808 allBundles
= CFArrayCreateMutable(NULL
, 0, NULL
);
810 /* allow plug-ins to exec child/helper processes */
811 _SCDPluginExecInit();
814 char path
[MAXPATHLEN
];
815 NSSearchPathEnumerationState state
;
818 * identify and load all bundles
820 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
822 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
826 /* load any available bundle */
827 strlcat(path
, BUNDLE_DIRECTORY
, sizeof(path
));
828 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("searching for bundles in \".\""));
829 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
833 bundles
= CFBundleCreateBundlesFromDirectory(NULL
, url
, CFSTR(".bundle"));
836 if (bundles
!= NULL
) {
840 n
= CFArrayGetCount(bundles
);
841 for (i
= 0; i
< n
; i
++) {
844 bundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundles
, i
);
845 addBundle(bundle
, FALSE
);
851 sortBundles(allBundles
);
857 * load (only) the specified bundle
859 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
863 bundle
= CFBundleCreate(NULL
, url
);
864 if (bundle
!= NULL
) {
865 addBundle(bundle
, TRUE
);
872 traceBundle("before loading any plugins", NULL
);
878 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("loading bundles"));
879 CFArrayApplyFunction(allBundles
,
880 CFRangeMake(0, CFArrayGetCount(allBundles
)),
885 * If defined, call each bundles load() function. This function (or
886 * the start() function) should initialize any variables, open any
887 * sessions with "configd", and register any needed notifications.
889 * Note: Establishing initial information in the store should be
890 * deferred until the prime() initialization function so that
891 * any bundles which want to receive a notification that the
892 * data has changed will have an opportunity to install a
893 * notification handler.
895 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle load() functions"));
896 CFArrayApplyFunction(allBundles
,
897 CFRangeMake(0, CFArrayGetCount(allBundles
)),
902 * If defined, call each bundles start() function. This function is
903 * called after the bundle has been loaded and its load() function has
904 * been called. It should initialize any variables, open any sessions
905 * with "configd", and register any needed notifications.
907 * Note: Establishing initial information in the store should be
908 * deferred until the prime() initialization function so that
909 * any bundles which want to receive a notification that the
910 * data has changed will have an opportunity to install a
911 * notification handler.
913 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle start() functions"));
914 CFArrayApplyFunction(allBundles
,
915 CFRangeMake(0, CFArrayGetCount(allBundles
)),
920 * If defined, call each bundles prime() function. This function is
921 * called after the bundle has been loaded and its load() and start()
922 * functions have been called. It should initialize any configuration
923 * information and/or state in the store.
925 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle prime() functions"));
926 CFArrayApplyFunction(allBundles
,
927 CFRangeMake(0, CFArrayGetCount(allBundles
)),
932 if (arg
== NULL
&& (nLoaded
> 0)) {
933 CFRunLoopTimerRef timer
;
935 /* allocate a periodic event (to help show we're not blocking) */
936 timer
= CFRunLoopTimerCreate(NULL
, /* allocator */
937 CFAbsoluteTimeGetCurrent() + 1.0, /* fireDate */
941 timerCallback
, /* callout */
943 CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer
, kCFRunLoopDefaultMode
);
949 traceBundle("about to start plugin CFRunLoop", NULL
);
953 * The assumption is that each loaded plugin will establish CFMachPortRef,
954 * CFSocketRef, and CFRunLoopTimerRef input sources to handle any events
955 * and register these sources with this threads run loop. If the plugin
956 * needs to wait and/or block at any time it should do so only in its a
959 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("starting plugin CFRunLoop"));
960 plugin_runLoop
= CFRunLoopGetCurrent();
963 SCLog(_configd_verbose
, LOG_INFO
, CFSTR("No more work for the \"configd\" plugins"));
964 plugin_runLoop
= NULL
;
973 pthread_attr_t tattr
;
976 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("Starting thread for plug-ins..."));
977 pthread_attr_init(&tattr
);
978 pthread_attr_setscope(&tattr
, PTHREAD_SCOPE_SYSTEM
);
979 pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
980 // pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
981 pthread_create(&tid
, &tattr
, plugin_exec
, NULL
);
982 pthread_attr_destroy(&tattr
);
983 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" thread id=0x%08x"), tid
);