2 * Copyright (c) 2000-2008 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_IPMonitor
;
88 extern SCDynamicStoreBundlePrimeFunction prime_IPMonitor
;
89 extern SCDynamicStoreBundleLoadFunction load_InterfaceNamer
;
90 extern SCDynamicStoreBundleLoadFunction load_KernelEventMonitor
;
91 extern SCDynamicStoreBundlePrimeFunction prime_KernelEventMonitor
;
92 extern SCDynamicStoreBundleLoadFunction load_LinkConfiguration
;
93 extern SCDynamicStoreBundleLoadFunction load_PreferencesMonitor
;
94 extern SCDynamicStoreBundlePrimeFunction prime_PreferencesMonitor
;
95 extern SCDynamicStoreBundleLoadFunction load_NetworkIdentification
;
96 extern SCDynamicStoreBundlePrimeFunction prime_NetworkIdentification
;
100 const CFStringRef bundleID
;
101 const void *load
; // SCDynamicStoreBundleLoadFunction
102 const void *start
; // SCDynamicStoreBundleStartFunction
103 const void *prime
; // SCDynamicStoreBundlePrimeFunction
104 const void *stop
; // SCDynamicStoreBundleStopFunction
105 } builtin
, *builtinRef
;
108 static const builtin builtin_plugins
[] = {
110 CFSTR("com.apple.SystemConfiguration.IPMonitor"),
117 CFSTR("com.apple.SystemConfiguration.InterfaceNamer"),
118 &load_InterfaceNamer
,
124 CFSTR("com.apple.SystemConfiguration.KernelEventMonitor"),
125 &load_KernelEventMonitor
,
127 &prime_KernelEventMonitor
,
131 CFSTR("com.apple.SystemConfiguration.LinkConfiguration"),
132 &load_LinkConfiguration
,
138 CFSTR("com.apple.SystemConfiguration.NetworkIdentification"),
139 &load_NetworkIdentification
,
141 &prime_NetworkIdentification
,
145 CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
146 &load_PreferencesMonitor
,
148 &prime_PreferencesMonitor
,
156 traceBundle(const char *op
, CFBundleRef bundle
)
158 if (_configd_trace
!= NULL
) {
159 if (bundle
!= NULL
) {
160 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
162 SCTrace(TRUE
, _configd_trace
,
163 CFSTR("bundle : %s %@\n"),
167 SCTrace(TRUE
, _configd_trace
,
168 CFSTR("bundle : %s\n"),
179 addBundle(CFBundleRef bundle
, Boolean forceEnabled
)
181 CFDictionaryRef bundleDict
;
182 bundleInfoRef bundleInfo
;
184 bundleInfo
= CFAllocatorAllocate(NULL
, sizeof(*bundleInfo
), 0);
185 bundleInfo
->bundle
= (CFBundleRef
)CFRetain(bundle
);
186 bundleInfo
->loaded
= FALSE
;
187 bundleInfo
->builtin
= FALSE
;
188 bundleInfo
->enabled
= TRUE
;
189 bundleInfo
->verbose
= FALSE
;
190 bundleInfo
->load
= NULL
;
191 bundleInfo
->start
= NULL
;
192 bundleInfo
->prime
= NULL
;
193 bundleInfo
->stop
= NULL
;
195 bundleDict
= CFBundleGetInfoDictionary(bundle
);
196 if (isA_CFDictionary(bundleDict
)) {
199 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleIsBuiltinKey
);
200 if (isA_CFBoolean(bVal
)) {
201 bundleInfo
->builtin
= CFBooleanGetValue(bVal
);
204 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleEnabledKey
);
205 if (isA_CFBoolean(bVal
)) {
206 bundleInfo
->enabled
= CFBooleanGetValue(bVal
);
209 bVal
= CFDictionaryGetValue(bundleDict
, kSCBundleVerboseKey
);
210 if (isA_CFBoolean(bVal
)) {
211 bundleInfo
->verbose
= CFBooleanGetValue(bVal
);
216 bundleInfo
->enabled
= TRUE
;
219 CFArrayAppendValue(allBundles
, bundleInfo
);
225 shortBundleIdentifier(CFStringRef bundleID
)
227 CFIndex len
= CFStringGetLength(bundleID
);
229 CFStringRef shortID
= NULL
;
231 if (CFStringFindWithOptions(bundleID
,
236 range
.location
= range
.location
+ range
.length
;
237 range
.length
= len
- range
.location
;
238 shortID
= CFStringCreateWithSubstring(NULL
, bundleID
, range
);
246 getBundleSymbol(CFBundleRef bundle
, CFStringRef functionName
, CFStringRef shortID
)
250 // search for load(), start(), prime(), stop(), ...
251 func
= CFBundleGetFunctionPointerForName(bundle
, functionName
);
256 if (shortID
!= NULL
) {
257 CFStringRef altFunctionName
;
259 // search for load_XXX(), ...
260 altFunctionName
= CFStringCreateWithFormat(NULL
,
265 func
= CFBundleGetFunctionPointerForName(bundle
, altFunctionName
);
266 CFRelease(altFunctionName
);
274 getBundleDirNameAndPath(CFBundleRef bundle
, char *buf
, size_t buf_len
)
281 url
= CFBundleCopyBundleURL(bundle
);
286 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)buf
, buf_len
);
292 cp
= strrchr(buf
, '/');
299 /* check if this directory entry is a valid bundle name */
301 if (len
<= (int)sizeof(BUNDLE_DIR_EXTENSION
)) {
302 /* if entry name isn't long enough */
306 len
-= sizeof(BUNDLE_DIR_EXTENSION
) - 1;
307 if (strcmp(&cp
[len
], BUNDLE_DIR_EXTENSION
) != 0) {
308 /* if entry name doesn't end with ".bundle" */
321 forkBundle_setup(pid_t pid
, void *setupContext
)
325 unsetenv("__LAUNCHD_FD");
326 setenv("__FORKED_PLUGIN__", "Yes", 1);
334 forkBundle(CFBundleRef bundle
, CFStringRef bundleID
)
336 char *argv
[] = { "configd", "-d", "-t", NULL
, NULL
};
338 char path
[MAXPATHLEN
];
341 // get the bundle's path
342 name
= getBundleDirNameAndPath(bundle
, path
, sizeof(path
));
344 SCLog(TRUE
, LOG_ERR
, CFSTR("skipped %@ (could not determine path)"), bundle
);
348 // fork and exec configd opting to load only this plugin
350 pid
= _SCDPluginExecCommand2(NULL
, NULL
, 0, 0, "/usr/libexec/configd", argv
, forkBundle_setup
, NULL
);
353 CFSTR("skipped %@ (could not exec child) : %s"),
359 SCLog(TRUE
, LOG_NOTICE
, CFSTR("forked %@, pid=%d"), bundleID
, pid
);
365 loadBundle(const void *value
, void *context
) {
366 CFStringRef bundleID
;
367 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
368 Boolean bundleExclude
;
369 CFIndex
*nLoaded
= (CFIndex
*)context
;
372 bundleID
= CFBundleGetIdentifier(bundleInfo
->bundle
);
373 if (bundleID
== NULL
) {
374 // sorry, no bundles without a bundle identifier
375 SCLog(TRUE
, LOG_NOTICE
, CFSTR("skipped %@ (no bundle ID)"), bundleInfo
->bundle
);
379 shortID
= shortBundleIdentifier(bundleID
);
381 bundleExclude
= CFSetContainsValue(_plugins_exclude
, bundleID
);
382 if (!bundleExclude
) {
383 if (shortID
!= NULL
) {
384 bundleExclude
= CFSetContainsValue(_plugins_exclude
, shortID
);
389 // sorry, this bundle has been excluded
390 SCLog(TRUE
, LOG_NOTICE
, CFSTR("skipped %@ (excluded)"), bundleID
);
394 if (!bundleInfo
->enabled
) {
395 // sorry, this bundle has not been enabled
396 SCLog(TRUE
, LOG_INFO
, CFSTR("skipped %@ (disabled)"), bundleID
);
401 forkBundle(bundleInfo
->bundle
, bundleID
);
405 if (!bundleInfo
->verbose
) {
406 bundleInfo
->verbose
= CFSetContainsValue(_plugins_verbose
, bundleID
);
407 if (!bundleInfo
->verbose
) {
408 if (shortID
!= NULL
) {
409 bundleInfo
->verbose
= CFSetContainsValue(_plugins_verbose
, shortID
);
414 if (bundleInfo
->builtin
) {
417 SCLog(TRUE
, LOG_DEBUG
, CFSTR("adding %@"), bundleID
);
419 for (i
= 0; i
< sizeof(builtin_plugins
)/sizeof(builtin_plugins
[0]); i
++) {
420 if (CFEqual(bundleID
, builtin_plugins
[i
].bundleID
)) {
421 bundleInfo
->load
= builtin_plugins
[i
].load
;
422 bundleInfo
->start
= builtin_plugins
[i
].start
;
423 bundleInfo
->prime
= builtin_plugins
[i
].prime
;
424 bundleInfo
->stop
= builtin_plugins
[i
].stop
;
429 if ((bundleInfo
->load
== NULL
) &&
430 (bundleInfo
->start
== NULL
) &&
431 (bundleInfo
->prime
== NULL
) &&
432 (bundleInfo
->stop
== NULL
)) {
433 SCLog(TRUE
, LOG_NOTICE
, CFSTR("%@ add failed"), bundleID
);
437 CFErrorRef error
= NULL
;
439 SCLog(TRUE
, LOG_DEBUG
, CFSTR("loading %@"), bundleID
);
442 traceBundle("loading", bundleInfo
->bundle
);
445 if (!CFBundleLoadExecutableAndReturnError(bundleInfo
->bundle
, &error
)) {
446 CFStringRef description
;
448 description
= CFErrorCopyDescription(error
);
449 SCLog(TRUE
, LOG_NOTICE
, CFSTR("%@ load failed"), bundleID
);
450 SCLog(TRUE
, LOG_NOTICE
, CFSTR(" %@"), description
);
451 CFRelease(description
);
456 // get bundle entry points
457 bundleInfo
->load
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("load" ), shortID
);
458 bundleInfo
->start
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("start"), shortID
);
459 bundleInfo
->prime
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("prime"), shortID
);
460 bundleInfo
->stop
= getBundleSymbol(bundleInfo
->bundle
, CFSTR("stop" ), shortID
);
463 /* mark this bundle as having been loaded */
464 bundleInfo
->loaded
= TRUE
;
466 /* bump the count of loaded bundles */
467 *nLoaded
= *nLoaded
+ 1;
471 if (shortID
!= NULL
) CFRelease(shortID
);
477 callLoadFunction(const void *value
, void *context
) {
478 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
480 if (!bundleInfo
->loaded
) {
484 if (bundleInfo
->load
== NULL
) {
485 // if no load() function
490 traceBundle("calling load() for", bundleInfo
->bundle
);
493 (*bundleInfo
->load
)(bundleInfo
->bundle
, bundleInfo
->verbose
);
504 callStartFunction(const void *value
, void *context
) {
505 const char *bundleDirName
;
506 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
507 char bundleName
[MAXNAMLEN
+ 1];
508 char bundlePath
[MAXPATHLEN
];
511 if (!bundleInfo
->loaded
) {
515 if (bundleInfo
->start
== NULL
) {
516 // if no start() function
520 /* copy the bundle's path */
521 bundleDirName
= getBundleDirNameAndPath(bundleInfo
->bundle
, bundlePath
, sizeof(bundlePath
));
522 if (bundleDirName
== NULL
) {
523 // if we have a problem with the bundle's path
527 /* copy (just) the bundle's name */
528 if (strlcpy(bundleName
, bundleDirName
, sizeof(bundleName
)) > sizeof(bundleName
)) {
529 // if we have a problem with the bundle's name
532 len
= strlen(bundleName
) - (sizeof(BUNDLE_DIR_EXTENSION
) - 1);
533 bundleName
[len
] = '\0';
536 traceBundle("calling start() for", bundleInfo
->bundle
);
539 (*bundleInfo
->start
)(bundleName
, bundlePath
);
550 callPrimeFunction(const void *value
, void *context
) {
551 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
553 if (!bundleInfo
->loaded
) {
557 if (bundleInfo
->prime
== NULL
) {
558 // if no prime() function
563 traceBundle("calling prime() for", bundleInfo
->bundle
);
566 (*bundleInfo
->prime
)();
577 stopComplete(void *info
)
579 CFBundleRef bundle
= (CFBundleRef
)info
;
580 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
581 CFRunLoopSourceRef stopRls
;
583 SCLog(TRUE
, LOG_DEBUG
, CFSTR("** %@ complete (%f)"), bundleID
, CFAbsoluteTimeGetCurrent());
585 stopRls
= (CFRunLoopSourceRef
)CFDictionaryGetValue(exiting
, bundle
);
586 if (stopRls
== NULL
) {
590 CFRunLoopSourceInvalidate(stopRls
);
592 CFDictionaryRemoveValue(exiting
, bundle
);
594 if (CFDictionaryGetCount(exiting
) == 0) {
597 // if all of the plugins are happy
598 status
= server_shutdown();
599 SCLog(TRUE
, LOG_DEBUG
, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
608 stopDelayed(CFRunLoopTimerRef timer
, void *info
)
615 SCLog(TRUE
, LOG_ERR
, CFSTR("server shutdown was delayed, unresponsive plugins:"));
618 * we've asked our plugins to shutdown but someone
621 n
= CFDictionaryGetCount(exiting
);
622 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
623 CFDictionaryGetKeysAndValues(exiting
, keys
, NULL
);
624 for (i
= 0; i
< n
; i
++) {
626 CFStringRef bundleID
;
628 bundle
= (CFBundleRef
)keys
[i
];
629 bundleID
= CFBundleGetIdentifier(bundle
);
630 SCLog(TRUE
, LOG_ERR
, CFSTR("** %@"), bundleID
);
632 CFAllocatorDeallocate(NULL
, keys
);
634 status
= server_shutdown();
639 stopRLSCopyDescription(const void *info
)
641 CFBundleRef bundle
= (CFBundleRef
)info
;
643 return CFStringCreateWithFormat(NULL
,
645 CFSTR("<stopRLS %p> {bundleID = %@}"),
647 CFBundleGetIdentifier(bundle
));
652 stopBundle(const void *value
, void *context
) {
653 bundleInfoRef bundleInfo
= (bundleInfoRef
)value
;
654 CFRunLoopSourceRef stopRls
;
655 CFRunLoopSourceContext stopContext
= { 0 // version
656 , bundleInfo
->bundle
// info
658 , CFRelease
// release
659 , stopRLSCopyDescription
// copyDescription
664 , stopComplete
// perform
667 if (!bundleInfo
->loaded
) {
671 if (bundleInfo
->stop
== NULL
) {
672 // if no stop() function
676 stopRls
= CFRunLoopSourceCreate(NULL
, 0, &stopContext
);
677 CFRunLoopAddSource(CFRunLoopGetCurrent(), stopRls
, kCFRunLoopDefaultMode
);
678 CFDictionaryAddValue(exiting
, bundleInfo
->bundle
, stopRls
);
681 (*bundleInfo
->stop
)(stopRls
);
691 * If defined, call each bundles stop() function. This function is
692 * called when configd has been asked to shut down (via a SIGTERM). The
693 * function should signal the provided run loop source when it is "ready"
694 * for the shut down to proceeed.
696 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle stop() functions"));
697 CFArrayApplyFunction(allBundles
,
698 CFRangeMake(0, CFArrayGetCount(allBundles
)),
702 if (CFDictionaryGetCount(exiting
) == 0) {
705 // if all of the plugins are happy
706 status
= server_shutdown();
707 SCLog(TRUE
, LOG_DEBUG
, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
710 CFRunLoopTimerRef timer
;
712 /* sorry, we're not going to wait longer than 20 seconds */
713 timer
= CFRunLoopTimerCreate(NULL
, /* allocator */
714 CFAbsoluteTimeGetCurrent() + 20.0, /* fireDate (in 20 seconds) */
715 0.0, /* interval (== one-shot) */
718 stopDelayed
, /* callout */
720 CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer
, kCFRunLoopDefaultMode
);
733 termRLSCopyDescription(const void *info
)
735 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SIGTERM RLS>"));
741 plugin_term(int *status
)
743 CFRunLoopSourceContext termContext
= { 0 // version
747 , termRLSCopyDescription
// copyDescription
752 , stopBundles
// perform
754 CFRunLoopSourceRef termRls
;
756 if (plugin_runLoop
== NULL
) {
759 return FALSE
; // don't delay shutdown
762 if (exiting
!= NULL
) {
763 // if shutdown already active
767 SCLog(TRUE
, LOG_DEBUG
, CFSTR("starting server shutdown (%f)"), CFAbsoluteTimeGetCurrent());
769 exiting
= CFDictionaryCreateMutable(NULL
,
771 &kCFTypeDictionaryKeyCallBacks
,
772 &kCFTypeDictionaryValueCallBacks
);
774 termRls
= CFRunLoopSourceCreate(NULL
, 0, &termContext
);
775 CFRunLoopAddSource(plugin_runLoop
, termRls
, kCFRunLoopDefaultMode
);
776 CFRunLoopSourceSignal(termRls
);
778 CFRunLoopWakeUp(plugin_runLoop
);
785 #pragma mark initialization
790 timerCallback(CFRunLoopTimerRef timer
, void *info
)
795 if ((pass
> 120) && ((pass
% 60) != 0)) {
799 traceBundle("the [plugin] CFRunLoop is waiting...", NULL
);
806 sortBundles(CFMutableArrayRef orig
)
808 CFMutableArrayRef
new;
810 new = CFArrayCreateMutable(NULL
, 0, NULL
);
811 while (CFArrayGetCount(orig
) > 0) {
813 Boolean inserted
= FALSE
;
814 int nOrig
= CFArrayGetCount(orig
);
816 for (i
= 0; i
< nOrig
; i
++) {
817 bundleInfoRef bundleInfo1
= (bundleInfoRef
)CFArrayGetValueAtIndex(orig
, i
);
818 CFStringRef bundleID1
= CFBundleGetIdentifier(bundleInfo1
->bundle
);
820 CFDictionaryRef dict
;
823 CFArrayRef
requires = NULL
;
825 dict
= isA_CFDictionary(CFBundleGetInfoDictionary(bundleInfo1
->bundle
));
827 requires = CFDictionaryGetValue(dict
, kSCBundleRequiresKey
);
828 requires = isA_CFArray(requires);
830 if (bundleID1
== NULL
|| requires == NULL
) {
831 CFArrayInsertValueAtIndex(new, 0, bundleInfo1
);
832 CFArrayRemoveValueAtIndex(orig
, i
);
836 count
= nRequires
= CFArrayGetCount(requires);
837 for (j
= 0; j
< nRequires
; j
++) {
840 CFStringRef r
= CFArrayGetValueAtIndex(requires, j
);
842 nNew
= CFArrayGetCount(new);
843 for (k
= 0; k
< nNew
; k
++) {
844 bundleInfoRef bundleInfo2
= (bundleInfoRef
)CFArrayGetValueAtIndex(new, k
);
845 CFStringRef bundleID2
= CFBundleGetIdentifier(bundleInfo2
->bundle
);
847 if (bundleID2
&& CFEqual(bundleID2
, r
)) {
853 /* all dependencies are met, append */
854 CFArrayAppendValue(new, bundleInfo1
);
855 CFArrayRemoveValueAtIndex(orig
, i
);
861 if (inserted
== FALSE
) {
862 SCLog(TRUE
, LOG_NOTICE
, CFSTR("Bundles have circular dependency!!!"));
866 if (CFArrayGetCount(orig
) > 0) {
867 /* we have a circular dependency, append remaining items on new array */
868 CFArrayAppendArray(new, orig
, CFRangeMake(0, CFArrayGetCount(orig
)));
871 /* new one is a sorted version of original */
874 CFArrayRemoveAllValues(orig
);
875 CFArrayAppendArray(orig
, new, CFRangeMake(0, CFArrayGetCount(new)));
883 plugin_exec(void *arg
)
887 /* keep track of bundles */
888 allBundles
= CFArrayCreateMutable(NULL
, 0, NULL
);
890 /* allow plug-ins to exec child/helper processes */
891 _SCDPluginExecInit();
894 char path
[MAXPATHLEN
];
895 NSSearchPathEnumerationState state
;
898 * identify and load all bundles
900 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
902 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
906 /* load any available bundle */
907 strlcat(path
, BUNDLE_DIRECTORY
, sizeof(path
));
908 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("searching for bundles in \".\""));
909 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
913 bundles
= CFBundleCreateBundlesFromDirectory(NULL
, url
, CFSTR(".bundle"));
916 if (bundles
!= NULL
) {
920 n
= CFArrayGetCount(bundles
);
921 for (i
= 0; i
< n
; i
++) {
924 bundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundles
, i
);
925 addBundle(bundle
, FALSE
);
931 sortBundles(allBundles
);
937 * load (only) the specified bundle
939 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
943 bundle
= CFBundleCreate(NULL
, url
);
944 if (bundle
!= NULL
) {
945 addBundle(bundle
, TRUE
);
952 traceBundle("before loading any plugins", NULL
);
958 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("loading bundles"));
959 CFArrayApplyFunction(allBundles
,
960 CFRangeMake(0, CFArrayGetCount(allBundles
)),
965 * If defined, call each bundles load() function. This function (or
966 * the start() function) should initialize any variables, open any
967 * sessions with "configd", and register any needed notifications.
969 * Note: Establishing initial information in the store should be
970 * deferred until the prime() initialization function so that
971 * any bundles which want to receive a notification that the
972 * data has changed will have an opportunity to install a
973 * notification handler.
975 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle load() functions"));
976 CFArrayApplyFunction(allBundles
,
977 CFRangeMake(0, CFArrayGetCount(allBundles
)),
982 // if no bundles loaded
987 * If defined, call each bundles start() function. This function is
988 * called after the bundle has been loaded and its load() function has
989 * been called. It should initialize any variables, open any sessions
990 * with "configd", and register any needed notifications.
992 * Note: Establishing initial information in the store should be
993 * deferred until the prime() initialization function so that
994 * any bundles which want to receive a notification that the
995 * data has changed will have an opportunity to install a
996 * notification handler.
998 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle start() functions"));
999 CFArrayApplyFunction(allBundles
,
1000 CFRangeMake(0, CFArrayGetCount(allBundles
)),
1005 * If defined, call each bundles prime() function. This function is
1006 * called after the bundle has been loaded and its load() and start()
1007 * functions have been called. It should initialize any configuration
1008 * information and/or state in the store.
1010 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("calling bundle prime() functions"));
1011 CFArrayApplyFunction(allBundles
,
1012 CFRangeMake(0, CFArrayGetCount(allBundles
)),
1017 if (arg
== NULL
&& (nLoaded
> 0)) {
1018 CFRunLoopTimerRef timer
;
1020 /* allocate a periodic event (to help show we're not blocking) */
1021 timer
= CFRunLoopTimerCreate(NULL
, /* allocator */
1022 CFAbsoluteTimeGetCurrent() + 1.0, /* fireDate */
1026 timerCallback
, /* callout */
1027 NULL
); /* context */
1028 CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer
, kCFRunLoopDefaultMode
);
1034 traceBundle("about to start plugin CFRunLoop", NULL
);
1038 * The assumption is that each loaded plugin will establish CFMachPortRef,
1039 * CFSocketRef, and CFRunLoopTimerRef input sources to handle any events
1040 * and register these sources with this threads run loop. If the plugin
1041 * needs to wait and/or block at any time it should do so only in its a
1044 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("starting plugin CFRunLoop"));
1045 plugin_runLoop
= CFRunLoopGetCurrent();
1050 SCLog(_configd_verbose
, LOG_INFO
, CFSTR("No more work for the \"configd\" plugins"));
1051 plugin_runLoop
= NULL
;
1060 pthread_attr_t tattr
;
1063 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("Starting thread for plug-ins..."));
1064 pthread_attr_init(&tattr
);
1065 pthread_attr_setscope(&tattr
, PTHREAD_SCOPE_SYSTEM
);
1066 pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
1067 // pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
1068 pthread_create(&tid
, &tattr
, plugin_exec
, NULL
);
1069 pthread_attr_destroy(&tattr
);
1070 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" thread id=0x%08x"), tid
);