static CFRunLoopSourceRef InstallComputerNameMonitor(void) { CFRunLoopSourceRef runLoopSource = NULL; SCDynamicStoreContext context = { 0, NULL, NULL, NULL, NULL }; SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("DirectoryService"), ComputerNameChangedCallBack, &context); if (store) { CFStringRef computerNameKey = SCDynamicStoreKeyCreateComputerName(NULL); CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); CFArrayAppendValue(keys, computerNameKey); if (SCDynamicStoreSetNotificationKeys(store, keys, NULL)) { runLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (runLoopSource) { CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); } } CFRelease(computerNameKey); CFRelease(keys); CFRelease(store); } return runLoopSource; }
__private_extern__ void load_smb_configuration(Boolean verbose) { CFStringRef key; CFMutableArrayRef keys = NULL; dispatch_block_t notify_block; Boolean ok; CFMutableArrayRef patterns = NULL; uint32_t status; /* initialize a few globals */ store = SCDynamicStoreCreate(NULL, CFSTR("smb-configuration"), configuration_changed, NULL); if (store == NULL) { my_log(LOG_ERR, "SCDynamicStoreCreate() failed: %s", SCErrorString(SCError())); goto error; } /* establish notification keys and patterns */ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); /* ...watch for SMB configuration changes */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetSMB); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for ComputerName changes */ key = SCDynamicStoreKeyCreateComputerName(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for local (multicast DNS) hostname changes */ key = SCDynamicStoreKeyCreateHostNames(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* register the keys/patterns */ ok = SCDynamicStoreSetNotificationKeys(store, keys, patterns); CFRelease(keys); CFRelease(patterns); if (!ok) { my_log(LOG_ERR, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError())); goto error; } rl = CFRunLoopGetCurrent(); rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (rls == NULL) { my_log(LOG_ERR, "SCDynamicStoreCreateRunLoopSource() failed: %s", SCErrorString(SCError())); goto error; } CFRunLoopAddSource(rl, rls, kCFRunLoopDefaultMode); /* ...watch for primary service/interface and DNS configuration changes */ notify_block = ^{ CFArrayRef changes; CFStringRef key; key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS); changes = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks); (*configuration_changed)(store, changes, NULL); CFRelease(changes); CFRelease(key); return; }; status = notify_register_dispatch(_SC_NOTIFY_NETWORK_CHANGE, ¬ify_token, dispatch_get_main_queue(), ^(int token){ CFRunLoopPerformBlock(rl, kCFRunLoopDefaultMode, notify_block); CFRunLoopWakeUp(rl); });
static void smb_set_configuration(SCDynamicStoreRef store, CFDictionaryRef dict) { CFArrayRef array; Boolean changed = FALSE; UInt32 dosCodepage = 0; CFStringEncoding dosEncoding = 0; CFStringEncoding macEncoding = kCFStringEncodingMacRoman; uint32_t macRegion = 0; Boolean ok; SCPreferencesRef prefs; CFStringRef str; prefs = SCPreferencesCreate(NULL, CFSTR("smb-configuration"), CFSTR(kSMBPreferencesAppID)); if (prefs == NULL) { my_log(LOG_ERR, "smb_set_configuration: SCPreferencesCreate() failed: %s", SCErrorString(SCError())); return; } ok = SCPreferencesLock(prefs, TRUE); if (!ok) { my_log(LOG_ERR, "smb_set_configuration: SCPreferencesLock() failed: %s", SCErrorString(SCError())); goto done; } // Server description str = SCDynamicStoreCopyComputerName(store, &macEncoding); update_pref(prefs, CFSTR(kSMBPrefServerDescription), str, &changed); // DOS code page if (str != NULL) { if (macEncoding == kCFStringEncodingMacRoman) { CFStringRef key; CFDictionaryRef dict; // get region key = SCDynamicStoreKeyCreateComputerName(NULL); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (dict != NULL) { if (isA_CFDictionary(dict)) { CFNumberRef num; SInt32 val; num = CFDictionaryGetValue(dict, kSCPropSystemComputerNameRegion); if (isA_CFNumber(num) && CFNumberGetValue(num, kCFNumberSInt32Type, &val)) { macRegion = (uint32_t)val; } } CFRelease(dict); } } CFRelease(str); } else { // Important: must have root acccess (eUID==0) to access the config file! __CFStringGetInstallationEncodingAndRegion((uint32_t *)&macEncoding, &macRegion); } _SC_dos_encoding_and_codepage(macEncoding, macRegion, &dosEncoding, &dosCodepage); str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (unsigned int)dosCodepage); assert(str != NULL); update_pref(prefs, CFSTR(kSMBPrefDOSCodePage), str, &changed); CFRelease(str); // NetBIOS name str = CFDictionaryGetValue(dict, kSCPropNetSMBNetBIOSName); str = isA_CFString(str); update_pref(prefs, CFSTR(kSMBPrefNetBIOSName), str, &changed); // NetBIOS node type str = CFDictionaryGetValue(dict, kSCPropNetSMBNetBIOSNodeType); str = isA_CFString(str); if (str != NULL) { if (CFEqual(str, kSCValNetSMBNetBIOSNodeTypeBroadcast)) { // B-node str = CFSTR(kSMBPrefNetBIOSNodeBroadcast); } else if (CFEqual(str, kSCValNetSMBNetBIOSNodeTypePeer)) { // P-node str = CFSTR(kSMBPrefNetBIOSNodePeer); } else if (CFEqual(str, kSCValNetSMBNetBIOSNodeTypeMixed)) { // M-node str = CFSTR(kSMBPrefNetBIOSNodeMixed); } else if (CFEqual(str, kSCValNetSMBNetBIOSNodeTypeHybrid)) { // H-node str = CFSTR(kSMBPrefNetBIOSNodeHybrid); } else { str = NULL; } } update_pref(prefs, CFSTR(kSMBPrefNetBIOSNodeType), str, &changed); #ifdef ADD_NETBIOS_SCOPE // NetBIOS scope str = CFDictionaryGetValue(dict, kSCPropNetSMBNetBIOSScope); str = isA_CFString(str); update_pref(prefs, CFSTR(kSMBPrefNetBIOSScope), str, &changed); #endif // ADD_NETBIOS_SCOPE // WINS addresses array = CFDictionaryGetValue(dict, kSCPropNetSMBWINSAddresses); array = isA_CFArray(array); update_pref(prefs, CFSTR(kSMBPrefWINSServerAddressList), array, &changed); // Workgroup (or domain) str = CFDictionaryGetValue(dict, kSCPropNetSMBWorkgroup); str = isA_CFString(str); update_pref(prefs, CFSTR(kSMBPrefWorkgroup), str, &changed); if (changed) { ok = SCPreferencesCommitChanges(prefs); if (!ok) { if ((SCError() != EROFS)) { my_log(LOG_ERR, "smb_set_configuration: SCPreferencesCommitChanges() failed: %s", SCErrorString(SCError())); } goto done; } ok = SCPreferencesApplyChanges(prefs); if (!ok) { my_log(LOG_ERR, "smb_set_configuration: SCPreferencesApplyChanges() failed: %s", SCErrorString(SCError())); goto done; } } done : (void) SCPreferencesUnlock(prefs); CFRelease(prefs); return; }
static void * /* O - Return status/value */ sysEventThreadEntry(void) { io_object_t powerNotifierObj; /* Power notifier object */ IONotificationPortRef powerNotifierPort; /* Power notifier port */ SCDynamicStoreRef store = NULL;/* System Config dynamic store */ CFRunLoopSourceRef powerRLS = NULL,/* Power runloop source */ storeRLS = NULL;/* System Config runloop source */ CFStringRef key[6], /* System Config keys */ pattern[2]; /* System Config patterns */ CFArrayRef keys = NULL, /* System Config key array*/ patterns = NULL;/* System Config pattern array */ SCDynamicStoreContext storeContext; /* Dynamic store context */ CFRunLoopTimerContext timerContext; /* Timer context */ cupsd_thread_data_t threadData; /* Thread context data for the * * runloop notifiers */ /* * Register for power state change notifications */ bzero(&threadData, sizeof(threadData)); threadData.sysevent.powerKernelPort = IORegisterForSystemPower(&threadData, &powerNotifierPort, sysEventPowerNotifier, &powerNotifierObj); if (threadData.sysevent.powerKernelPort) { powerRLS = IONotificationPortGetRunLoopSource(powerNotifierPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); } else DEBUG_puts("sysEventThreadEntry: error registering for system power " "notifications"); /* * Register for system configuration change notifications */ bzero(&storeContext, sizeof(storeContext)); storeContext.info = &threadData; store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), sysEventConfigurationNotifier, &storeContext); if (!ComputerNameKey) ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault); if (!BTMMKey) BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault, CFSTR("Setup:/Network/BackToMyMac")); if (!NetworkGlobalKeyIPv4) NetworkGlobalKeyIPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv4); if (!NetworkGlobalKeyIPv6) NetworkGlobalKeyIPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv6); if (!NetworkGlobalKeyDNS) NetworkGlobalKeyDNS = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetDNS); if (!HostNamesKey) HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault); if (!NetworkInterfaceKeyIPv4) NetworkInterfaceKeyIPv4 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); if (!NetworkInterfaceKeyIPv6) NetworkInterfaceKeyIPv6 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); if (store && ComputerNameKey && HostNamesKey && NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS && NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6) { key[0] = ComputerNameKey; key[1] = BTMMKey; key[2] = NetworkGlobalKeyIPv4; key[3] = NetworkGlobalKeyIPv6; key[4] = NetworkGlobalKeyDNS; key[5] = HostNamesKey; pattern[0] = NetworkInterfaceKeyIPv4; pattern[1] = NetworkInterfaceKeyIPv6; keys = CFArrayCreate(kCFAllocatorDefault, (const void **)key, sizeof(key) / sizeof(key[0]), &kCFTypeArrayCallBacks); patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern, sizeof(pattern) / sizeof(pattern[0]), &kCFTypeArrayCallBacks); if (keys && patterns && SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0)) != NULL) { CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreateRunLoopSource " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreSetNotificationKeys " "failed: %s\n", SCErrorString(SCError()))); } else DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreate failed: %s\n", SCErrorString(SCError()))); if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); /* * Set up a timer to delay the wake change notifications. * * The initial time is set a decade or so into the future, we'll adjust * this later. */ bzero(&timerContext, sizeof(timerContext)); timerContext.info = &threadData; threadData.timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), 86400L * 365L * 10L, 0, 0, sysEventTimerNotifier, &timerContext); CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); /* * Store our runloop in a global so the main thread can use it to stop us. */ pthread_mutex_lock(&SysEventThreadMutex); SysEventRunloop = CFRunLoopGetCurrent(); pthread_cond_signal(&SysEventThreadCond); pthread_mutex_unlock(&SysEventThreadMutex); /* * Disappear into the runloop until it's stopped by the main thread. */ CFRunLoopRun(); /* * Clean up before exiting. */ if (threadData.timerRef) { CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData.timerRef, kCFRunLoopDefaultMode); CFRelease(threadData.timerRef); } if (threadData.sysevent.powerKernelPort) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode); IODeregisterForSystemPower(&powerNotifierObj); IOServiceClose(threadData.sysevent.powerKernelPort); IONotificationPortDestroy(powerNotifierPort); } if (storeRLS) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(storeRLS); CFRelease(storeRLS); } if (store) CFRelease(store); pthread_exit(NULL); }
void load(CFBundleRef bundle, Boolean bundleVerbose) { CFStringRef key; CFMutableArrayRef keys = NULL; CFStringRef pattern; CFMutableArrayRef patterns = NULL; CFRunLoopSourceRef rls; if (bundleVerbose) { _verbose = TRUE; } SCLog(_verbose, LOG_DEBUG, CFSTR("load() called")); SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle)); /* initialize a few globals */ curGlobals = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); curConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); curDefaults = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); curStartup = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* open a "configd" store to allow cache updates */ store = SCDynamicStoreCreate(NULL, CFSTR("AppleTalk Configuraton plug-in"), atConfigChangedCallback, NULL); if (!store) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError())); goto error; } /* establish notificaiton keys and patterns */ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); /* ...watch for (global) AppleTalk configuration changes */ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetAppleTalk); CFArrayAppendValue(keys, key); CFRelease(key); /* ...watch for (per-service) AppleTalk configuration changes */ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetAppleTalk); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for network interface link status changes */ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetLink); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for (per-interface) AppleTalk configuration changes */ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetAppleTalk); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); /* ...watch for computer name changes */ key = SCDynamicStoreKeyCreateComputerName(NULL); CFArrayAppendValue(keys, key); CFRelease(key); /* register the keys/patterns */ if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError())); goto error; } rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); if (!rls) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"), SCErrorString(SCError())); goto error; } CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); CFRelease(keys); CFRelease(patterns); return; error : if (curGlobals) CFRelease(curGlobals); if (curConfigFile) CFRelease(curConfigFile); if (curDefaults) CFRelease(curDefaults); if (curStartup) CFRelease(curStartup); if (store) CFRelease(store); if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); return; }
/* This code adapted from "Living in a Dynamic TCP/IP Environment" technote. */ static Boolean install_ipaddr_source (void) { CFRunLoopSourceRef source = NULL; SCDynamicStoreContext context = {0}; SCDynamicStoreRef ref; ref = SCDynamicStoreCreate (NULL, CFSTR ("AddIPAddressListChangeCallbackSCF"), ipaddr_callback, &context); if (ref != NULL) { const void *keys[4], *patterns[2]; int i; keys[0] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); keys[1] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6); keys[2] = SCDynamicStoreKeyCreateComputerName (NULL); keys[3] = SCDynamicStoreKeyCreateHostNames (NULL); patterns[0] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); patterns[1] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); if (keys[0] != NULL && keys[1] != NULL && keys[2] != NULL && keys[3] != NULL && patterns[0] != NULL && patterns[1] != NULL) { CFArrayRef key_array, pattern_array; key_array = CFArrayCreate (NULL, keys, 4, &kCFTypeArrayCallBacks); pattern_array = CFArrayCreate (NULL, patterns, 2, &kCFTypeArrayCallBacks); if (key_array != NULL || pattern_array != NULL) { SCDynamicStoreSetNotificationKeys (ref, key_array, pattern_array); source = SCDynamicStoreCreateRunLoopSource (NULL, ref, 0); } if (key_array != NULL) CFRelease (key_array); if (pattern_array != NULL) CFRelease (pattern_array); } for (i = 0; i < 4; i++) if (keys[i] != NULL) CFRelease (keys[i]); for (i = 0; i < 2; i++) if (patterns[i] != NULL) CFRelease (patterns[i]); CFRelease (ref); } if (source != NULL) { CFRunLoopAddSource (CFRunLoopGetCurrent (), source, kCFRunLoopDefaultMode); CFRelease (source); } return source != NULL; }