示例#1
0
文件: themagic.c 项目: saelo/weesleep
int main(int argc, char** argv)
{
    //
    // From https://developer.apple.com/library/mac/qa/qa1340/_index.html
    // I have basically no idea how this works :)
    //
    // notification port allocated by IORegisterForSystemPower
    IONotificationPortRef  notifyPortRef;

    // notifier object, used to deregister later
    io_object_t            notifierObject;
    // this parameter is passed to the callback
    void*                  refCon;

    // register to receive system sleep notifications

    root_port = IORegisterForSystemPower(refCon, &notifyPortRef, SleepCallBack, &notifierObject);
    if (root_port == 0) {
        printf("IORegisterForSystemPower failed\n");
        return 1;
    }

    // add the notification port to the application runloop
    CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes);

    /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
        is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
        manage the main thread's run loop for you as part of their event handling
        mechanisms.
    */
    CFRunLoopRun();

    //Not reached, CFRunLoopRun doesn't return in this case.
    return 0;
}
示例#2
0
void CCocoaPowerSyscall::CreateOSPowerCallBacks(void)
{
#if !defined(TARGET_DARWIN_IOS)
  CCocoaAutoPool autopool;
  // we want sleep/wake notifications, register to receive system power notifications
  m_root_port = IORegisterForSystemPower(this, &m_notify_port, OSPowerCallBack, &m_notifier_object);
  if (m_root_port)
  {
    // add the notification port to the application runloop
    CFRunLoopAddSource(CFRunLoopGetCurrent(),
      IONotificationPortGetRunLoopSource(m_notify_port), kCFRunLoopDefaultMode);
  }
  else
  {
    CLog::Log(LOGERROR, "%s - IORegisterForSystemPower failed", __FUNCTION__);
  }

  // if we have a battery, we want power source change notifications (on AC, on Battery, etc)
  if (m_HasBattery)
  {
    m_power_source = IOPSNotificationCreateRunLoopSource(OSPowerSourceCallBack, this);
    if (m_power_source)
      CFRunLoopAddSource(CFRunLoopGetCurrent(), m_power_source, kCFRunLoopDefaultMode);
    else
      CLog::Log(LOGERROR, "%s - IOPSNotificationCreateRunLoopSource failed", __FUNCTION__);
  }
#endif
}
示例#3
0
    bool mac_sleep_start()
    {
      if (!root_port)
	{
	  root_port = IORegisterForSystemPower(this, &notifyPortRef, callback_static, &notifierObject);
	  if (!root_port)
	    return false;
	  CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes);
	}
      return true;
    }
示例#4
0
void
COSXScreen::watchSystemPowerThread(void*)
{
	io_object_t				notifier;
	IONotificationPortRef	notificationPortRef;
	CFRunLoopSourceRef		runloopSourceRef = 0;

	m_pmRunloop = CFRunLoopGetCurrent();
	// install system power change callback
	m_pmRootPort = IORegisterForSystemPower(this, &notificationPortRef,
											powerChangeCallback, &notifier);
	if (m_pmRootPort == 0) {
		LOG((CLOG_WARN "IORegisterForSystemPower failed"));
	}
	else {
		runloopSourceRef =
			IONotificationPortGetRunLoopSource(notificationPortRef);
		CFRunLoopAddSource(m_pmRunloop, runloopSourceRef,
								kCFRunLoopCommonModes);
	}
	
	// thread is ready
	{
		CLock lock(m_pmMutex);
		*m_pmThreadReady = true;
		m_pmThreadReady->signal();
	}

	// if we were unable to initialize then exit.  we must do this after
	// setting m_pmThreadReady to true otherwise the parent thread will
	// block waiting for it.
	if (m_pmRootPort == 0) {
		return;
	}

	// start the run loop
	LOG((CLOG_DEBUG "started watchSystemPowerThread"));
	CFRunLoopRun();
	
	// cleanup
	if (notificationPortRef) {
		CFRunLoopRemoveSource(m_pmRunloop,
								runloopSourceRef, kCFRunLoopDefaultMode);
		CFRunLoopSourceInvalidate(runloopSourceRef);
		CFRelease(runloopSourceRef);
	}

	CLock lock(m_pmMutex);
	IODeregisterForSystemPower(&notifier);
	m_pmRootPort = 0;
	LOG((CLOG_DEBUG "stopped watchSystemPowerThread"));
}
示例#5
0
int main( int argc, char **argv ) {
    IONotificationPortRef notifyPortRef; 
    io_object_t notifierObject; 
    void* refCon; 
    root_port = IORegisterForSystemPower( refCon, &notifyPortRef, MySleepCallBack, &notifierObject );
    if ( root_port == 0 ) {
        printf("IORegisterForSystemPower failed\n");
        return 1;
    }
    CFRunLoopAddSource( CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes ); 
    CFRunLoopRun();
    return (0);
}
MacSystemWatch::MacSystemWatch()
{
    // Initialize sleep callback
    IONotificationPortRef notify;
    io_object_t           anIterator;
    root_port = IORegisterForSystemPower(this, &notify, sleepCallBack, &anIterator);
    if (!root_port) {
        printf("IORegisterForSystemPower failed\n");
    }
    else {
        CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopCommonModes);
    }
}
示例#7
0
static void initializePowerNotifications (void)
{
	static io_connect_t	rootPort;	/* used by powerCallback() via context pointer */
	
	IONotificationPortRef	notificationPort;
	io_object_t		notifier;

	rootPort = IORegisterForSystemPower(&rootPort, &notificationPort, powerCallback, &notifier);
	if (! rootPort) {
		message (LOG_ERR, "IORegisterForSystemPower failed\n");
		exit (1);
	}
	CFRunLoopAddSource (CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode);
}
示例#8
0
/*! Registers the daemon with the kernel to receive power events
 *  (e.g., sleep/wake notifications).
 *  @return true if the daemon was successfully registered. */
bool iSCSIDRegisterForPowerEvents()
{
    powerPlaneRoot = IORegisterForSystemPower(NULL,
                     &powerNotifyPortRef,
                     iSCSIDHandlePowerEvent,
                     &powerNotifier);

    if(powerPlaneRoot == 0)
        return false;

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       IONotificationPortGetRunLoopSource(powerNotifyPortRef),
                       kCFRunLoopDefaultMode);
    return true;
}
void SystemEventsManager::runLoop() {
    void* refCon = nullptr;
    
    rootPort = IORegisterForSystemPower(refCon,
                                        &notifyPortRef,
                                        systemEventCallback,
                                        &notifierObject);
    if (rootPort != 0)
    {
        systemEventLoopRunning = true;
        CFRunLoopAddSource(CFRunLoopGetCurrent(),
                           IONotificationPortGetRunLoopSource(notifyPortRef),
                           kCFRunLoopCommonModes);
        CFRunLoopRun();
    }
}
示例#10
0
int main( int argc, char **argv )
{
    syslog(LOG_LEVEL, "start");
 
    root_port = IORegisterForSystemPower( refCon, &notifyPortRef, MySleepCallBack, &notifierObject );
    if ( root_port == 0 )
    {
        syslog(LOG_ERR,"IORegisterForSystemPower failed\n");
        return 1;
    }
 
    CFRunLoopAddSource( CFRunLoopGetCurrent(),
            IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );
 
    CFRunLoopRun();
    syslog(LOG_LEVEL, "end");
    return (0);
}
示例#11
0
static int pypowerobserver_init(PyPowerObserver *self,
                                PyObject *args,
                                PyObject *kwargs)
{
     if (!PyArg_ParseTuple(args, ":__init__"))
        return -1;

     if (self)
     {
         io_object_t            notifier;

         self->rootPort = IORegisterForSystemPower(self, &self->notificationPort, powerCallback, &notifier);
         if (!self->rootPort)
         {
             PyErr_SetString(PyExc_RuntimeError, "IORegisterForSystemPower failed");
             return -1;
         }
     }

     return 0;
}
示例#12
0
DECLCALLBACK(int) HostPowerServiceDarwin::powerChangeNotificationThread(RTTHREAD /* ThreadSelf */, void *pInstance)
{
    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *>(pInstance);

    /* We have to initial set the critical state of the battery, cause we want
     * not the HostPowerService to inform about that state when a VM starts.
     * See lowPowerHandler for more info. */
    pPowerObj->checkBatteryCriticalLevel();

    /* Register to receive system sleep notifications */
    pPowerObj->mRootPort = IORegisterForSystemPower(pPowerObj, &pPowerObj->mNotifyPort,
                                                    HostPowerServiceDarwin::powerChangeNotificationHandler,
                                                    &pPowerObj->mNotifierObject);
    if (pPowerObj->mRootPort == MACH_PORT_NULL)
    {
        LogFlow(("IORegisterForSystemPower failed\n"));
        return VERR_NOT_SUPPORTED;
    }
    pPowerObj->mRunLoop = CFRunLoopGetCurrent();
    /* Add the notification port to the application runloop */
    CFRunLoopAddSource(pPowerObj->mRunLoop,
                       IONotificationPortGetRunLoopSource(pPowerObj->mNotifyPort),
                       kCFRunLoopCommonModes);

    /* Register for all battery change events. The handler will check for low
     * power events itself. */
    CFRunLoopSourceRef runLoopSource = IOPSNotificationCreateRunLoopSource(HostPowerServiceDarwin::lowPowerHandler,
                                                                           pPowerObj);
    CFRunLoopAddSource(pPowerObj->mRunLoop,
                       runLoopSource,
                       kCFRunLoopCommonModes);

    /* Start the run loop. This blocks. */
    CFRunLoopRun();
    return VINF_SUCCESS;
}
示例#13
0
static void iokit_poll_notifications(void *opaque) {
	int phase = 0;
	Semaphore *handshake = opaque;
	IONotificationPortRef notification_port;
	io_object_t notifier;
	io_connect_t root_port;
	CFRunLoopSourceRef notification_run_loop_source;

	log_debug("Started notification poll thread");

	// need to register this PThread with the Objective-C garbage collector,
	// because CoreFoundation uses Objective-C
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
	objc_registerThreadWithCollector();
#endif

	// register for system sleep/wake notifications
	root_port = IORegisterForSystemPower(&root_port, &notification_port,
	                                     iokit_handle_notifications, &notifier);

	if (root_port == MACH_PORT_NULL) {
		log_error("Could not register for root power domain");

		goto cleanup;
	}

	phase = 1;

	// get notification run loop source
	notification_run_loop_source = IONotificationPortGetRunLoopSource(notification_port);

	if (notification_run_loop_source == NULL) {
		log_error("Could not get notification run loop source");

		goto cleanup;
	}

	CFRunLoopAddSource(CFRunLoopGetCurrent(), notification_run_loop_source,
	                   kCFRunLoopDefaultMode);

	phase = 2;

	// start loop
	_run_loop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());

	_running = true;
	semaphore_release(handshake);

	CFRunLoopRun();

	log_debug("Stopped notification poll thread");

cleanup:
	if (!_running) {
		// need to release the handshake in all cases, otherwise iokit_init
		// will block forever in semaphore_acquire
		semaphore_release(handshake);
	}

	switch (phase) { // no breaks, all cases fall through intentionally
	case 2:
		CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notification_run_loop_source,
		                      kCFRunLoopDefaultMode);

	case 1:
		IODeregisterForSystemPower(&notifier);
		IOServiceClose(root_port);
		IONotificationPortDestroy(notification_port);

	default:
		break;
	}

	_running = false;
}
示例#14
0
/* Main program */
int main (int argc, const char * argv[])
{
	enum                   suspend_type {soft, dump, hard};
	int                    vmmib[2] = {CTL_VM, VM_SWAPUSAGE};
	int					   osmib[2] = {CTL_KERN, KERN_OSRELEASE};
	int                    original_mode;
	int                    target_mode;
	int                    default_mode;
	int                    original_profile;
	int                    target_profile = -1;
	void                   *refCon;
	struct xsw_usage       swap;
	size_t                 swlen = sizeof(swap);
	size_t				   oslen;
	char                   *kernel_version;
	int                    major_version = 0;
	int                    minor_version = 0;
	struct stat            sleepimage;
	                                                                                                                               /* By default, */
	int                    do_sleep = 1;                                                                                           /* send the sleep call, */
	int                    repair = 0;                                                                                             /* do not check the validity of the original hibernation mode, */
	int                    check_hibernation = 1;                                                                                  /* check if the hibernation file is present, */
	int                    check_os = 1;                                                                                           /* check if the operating system is supported, */
	enum suspend_type      target_suspend = soft;                                                                                  /* send computer to software suspend mode, */
	int                    restore = 1;                                                                                            /* restore the original mode, */

	if (argc >= 2) {
		if (!strcmp(argv[1], "-v")) {                                                                                              /* Display version number if invoked with -v */
			printf("deepsleep build %s\n", VERSION);
			return 0;
		} else if (!strcmp(argv[1], "-h")) {
			printf("deepsleep usage: deepsleep [-bdhrvsu] [hard|dump|soft]\n");
			printf("                 -b : bypass the hibernation file check\n");
			printf("                 -d : debug mode - be verbose\n");
			printf("                 -h : display this help screen\n");
			printf("                 -m : mute - be silent\n");
			printf("                 -o : do not restore the original hibernation mode\n");
			printf("                 -r : repair the default hibernation mode if needed\n");
			printf("                 -s : simulation - do not send the computer to sleep\n");
			printf("                 -v : display version number\n");
			printf("                 -u : perform operations even on unsupported OS revisions\n");
			printf("                 hard : send computer to hardware suspend mode\n");
			printf("                 dump : send computer to safe hardware suspend mode\n");
			printf("                 soft : send computer to software suspend mode (by default)\n");
			return 0;
		} else {
			if (argc >= 3) {
				if (strstr(argv[1], "b"))                                                                                             /* Do not check the existence of the hibernation file if invoked with -b */
					check_hibernation = 0;	
				if (strstr(argv[1], "d"))                                                                                             /* Print debug information if invoked with -d */
					debug = 1;
				if (strstr(argv[1], "o"))                                                                                             /* Do not restore the original hibernation mode if invoked with -o */
					restore = 0;
				if (strstr(argv[1], "r"))                                                                                             /* Check for the validity of the original hibernation mode if invoked with -r*/ 
					repair = 1;
				if (strstr(argv[1], "s"))                                                                                             /* Do not send the sleep call if invoked with -s */
					do_sleep = 0;
				if (strstr(argv[1], "u"))                                                                                             /* Do not care about OS revision if invoked with -u */
					check_os = 0;
				if (strstr(argv[1], "m"))
					mute = 1;
			} 	
			if (strstr(argv[argc-1], "hard"))                                                                                         /* Send computer to hardware suspend mode instead of software suspend mode if the hard argument is present */
				target_suspend = hard;
			else if (strstr(argv[argc-1], "dump"))                                                                                    /* Send computer to safe hardware suspend mode instead of software suspend mode if the safe argument is present */
				target_suspend = dump;	
		}
	}
	
	if (sysctl(osmib, 2, NULL, &oslen, NULL, 0) == -1) {                                                                          /* Get the operating system revision length */
		printf("Failed to get the operating system revision\n");                                                                     /* On failure: quit */
		return 1;
	} else {
		kernel_version = malloc(oslen * sizeof(char));                                        
		sysctl(osmib, 2, kernel_version, &oslen, NULL, 0);                                                                       /* Get the operating system revision length */
		sscanf(kernel_version, "%d.%d", &major_version, &minor_version);
		free(kernel_version);
	}
	if (debug) {
		printf("OS revision: %d.%d", major_version, minor_version);
		if (!check_os) printf(" (ignored)");
		printf("\n");
	}
	if (check_os && (major_version != 8 || minor_version < 3) && (major_version <= 8)) {                                         /* If needed, check if major version is 8 (Mac OS X 10.4) and minor version is greater or equal than 3. Mac OS X 10.5 is also supported.*/
		printf("This operating system is not supported\n");                                                                           /* On failure: quit */
		return 1;
	}
	
	if (check_hibernation && stat("/private/var/vm/sleepimage", &sleepimage)) {                                                  /* If needed, check if the hibernation file (/private/var/vm/sleepimage) exists */
		printf("Hibernation file is missing\n");                                                                                     /* On failure: quit */   
		return 1;
	}
	
	if (sysctl(vmmib, 2, &swap, &swlen, NULL, 0) == -1) {                                                                       /* Get the current virtual memory parameters */
		printf("Failed to get the virtual memory information\n");                                                                  /* On failure: quit */
		return 1;
	} else {
        default_mode = 3;
        if (target_suspend == dump) {
            target_mode = default_mode;                                                                                               /* we will use the regular mode 3 for safe hardware suspsend */
        } else /*if (target_suspend == soft)*/ {
            target_mode = 25;                                                                                                          /* or the regular mode 25 for software suspsend */
        }        
		if (target_suspend == hard)                                                                                                 /* If we only want to perform basic hardware suspend */
			target_mode = 0;                                                                                                            /* we will sleep with hibernate mode 0 */
		if (debug) printf("target mode: %d\n", target_mode);
	}
	
	ps_info = IOPSCopyPowerSourcesInfo();                                                                                       /* Get the power source information */
	if (ps_info) {
		current_ps = IOPSGetProvidingPowerSourceType(ps_info);                                                                     /* On success, store the active power source */
	} else {
		printf("Failed to get the power source information\n");                                                                    /* On failure: quit */
		return 1;
	}
	if (debug) printf("target power source: %s\n", CFStringGetCStringPtr(current_ps, kCFStringEncodingMacRoman));	
	
	active_prof = IOPMCopyActivePowerProfiles();                                                                                /* Get the power profiles */
    if (!active_prof) {
        printf("Failed to get the active profile\n");
		CFCleanup();
		return 1;
    }
	if (CFDictionaryContainsKey(active_prof, current_ps)) {                                                                     /* Get the active profile corresponding to the current power source */
		profile_ref = (CFNumberRef) CFDictionaryGetValue(active_prof, current_ps);
		profile_type = CFNumberGetType(profile_ref);
		CFNumberGetValue(profile_ref, profile_type, &original_profile);                                                            /* On succes, store its value */
		if (debug) printf("original profile: %d\n", original_profile);
	} else {
		printf("Failed to get the power management settings\n");                                                                   /* On failure: quit */
		CFCleanup();
		return 1;
	}	
		
	ds = SCDynamicStoreCreate(NULL, CFSTR("deepsleep"), NULL, NULL);                                                            /* Create a new dynamic store */
	live_settings = SCDynamicStoreCopyValue(ds, CFSTR(kIOPMDynamicStoreSettingsKey));                                           /* Read current settings */
	if(!isA_CFDictionary(live_settings)) {                                                                                         /* We did not get the settings: quit */
		printf("Failed to get the power management settings\n");
		CFCleanup();
		return 1;                                               
	}
	
	if (CFDictionaryContainsKey(live_settings, CFSTR("Hibernate Mode"))) {                                                      /* Check if the hibernate mode key exists */
		hm_ref = (CFNumberRef) CFDictionaryGetValue(live_settings, CFSTR("Hibernate Mode"));                                       /* On success, get its value */
		hm_type = CFNumberGetType(hm_ref);
		CFNumberGetValue(hm_ref, hm_type, &original_mode);
		if (debug) printf("original mode: %d\n", original_mode);
	}
	else {                                                                                                                         /* On failure, cleanup and quit */ 
		printf("Failed to get the hibernation mode\n");
		CFCleanup();                                                                                                  
		return 1;
	}
	
	if (repair && original_mode == target_mode) {                                                                              /* If the original mode is the same as the target mode */
		original_mode = default_mode;                                                                                              /* A crash has probably happened during hibernation: we will set back the hibernation mode to its default value after wakeup */ 
		if (debug) printf("repair mode to: %d\n", default_mode);
	}
	
	root_power_port = IORegisterForSystemPower(refCon, &notifyPortRef, PowerCallBack, &notifierObject);                         /* Register to the Root Power Domain IOService: notifications will be handled by the PowerCallBack functions */
	if (!root_power_port) {                                                                                                        /* Registering failed: quit */
		printf("Failed to register to the Root Power Domain IOService\n");		
		CFCleanup();
		return 1;
	}
	
	CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes);        /* Add the notification port to the run loop */
	
	if (SetActiveProfile(target_profile, current_ps, active_prof)) {                                                            /* Set the active power profile to custom (-1) */
		printf("Failed to set the active profile\n");
		PortsCleanup();
		CFCleanup();
		return 1;
	}
	if (SetHibernateMode(target_mode, current_ps))	{                                                                           /* Set the hibernate mode to target mode */
		printf("Failed to set the hibernation mode\n");
		SetActiveProfile(original_profile, current_ps, active_prof);
		PortsCleanup();
		CFCleanup();
		return 1;
	}
	
	if (do_sleep) {                                                                                                             /* If we are not in simulation mode */
		sleep(3);                                                                                                                   /* Wait for 3s to allow settings to settle down */
		if (IOPMSleepSystem(root_power_port) == kIOReturnSuccess)                                                                   /* Request the system to sleep */
			CFRunLoopRun();                                                                                                            /* On success, start the run loop */
		else 
			perror("Failed to send the sleep request\n");                                                                              /* On failure, do not start it */
	}																															/* The run loop has stopped: system has woken up */
	
	if (restore) {                                                                                                              /* If we are asked to restore the original hibernate mode */
		if (SetHibernateMode(original_mode, current_ps)) {                                                                          /* Restore the original hibernate mode */
			printf("Failed to set the hibernation mode\n");
			SetActiveProfile(original_profile, current_ps, active_prof);
			PortsCleanup();
			CFCleanup();
			return 1;
		}
		if (SetActiveProfile(original_profile, current_ps, active_prof)) {                                                          /* Restore the original power profile */
			printf("Failed to set the active profile\n");
			PortsCleanup();
			CFCleanup();
			return 1;
		}
	}
																																   
	PortsCleanup();				                                                                                                /* Cleanup */																																																											
	CFCleanup();
    return 0;
}
示例#15
0
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);
}