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); }
__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); });
/* 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; }