xref: /aosp_15_r20/external/libcups/scheduler/sysman.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * System management functions for the CUPS scheduler.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2006 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "cupsd.h"
16*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
17*5e7646d2SAndroid Build Coastguard Worker #  include <IOKit/pwr_mgt/IOPMLib.h>
18*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
19*5e7646d2SAndroid Build Coastguard Worker 
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker /*
22*5e7646d2SAndroid Build Coastguard Worker  * The system management functions cover disk and power management which
23*5e7646d2SAndroid Build Coastguard Worker  * are primarily used for portable computers.
24*5e7646d2SAndroid Build Coastguard Worker  *
25*5e7646d2SAndroid Build Coastguard Worker  * Disk management involves delaying the write of certain configuration
26*5e7646d2SAndroid Build Coastguard Worker  * and state files to minimize the number of times the disk has to spin
27*5e7646d2SAndroid Build Coastguard Worker  * up or flash to be written to.
28*5e7646d2SAndroid Build Coastguard Worker  *
29*5e7646d2SAndroid Build Coastguard Worker  * Power management support is currently only implemented on macOS, but
30*5e7646d2SAndroid Build Coastguard Worker  * essentially we use four functions to let the OS know when it is OK to
31*5e7646d2SAndroid Build Coastguard Worker  * put the system to sleep, typically when we are not in the middle of
32*5e7646d2SAndroid Build Coastguard Worker  * printing a job.  And on macOS we can also "sleep print" - basically the
33*5e7646d2SAndroid Build Coastguard Worker  * system only wakes up long enough to service network requests and process
34*5e7646d2SAndroid Build Coastguard Worker  * print jobs.
35*5e7646d2SAndroid Build Coastguard Worker  */
36*5e7646d2SAndroid Build Coastguard Worker 
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker /*
39*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdCleanDirty()' - Write dirty config and state files.
40*5e7646d2SAndroid Build Coastguard Worker  */
41*5e7646d2SAndroid Build Coastguard Worker 
42*5e7646d2SAndroid Build Coastguard Worker void
cupsdCleanDirty(void)43*5e7646d2SAndroid Build Coastguard Worker cupsdCleanDirty(void)
44*5e7646d2SAndroid Build Coastguard Worker {
45*5e7646d2SAndroid Build Coastguard Worker   if (DirtyFiles & CUPSD_DIRTY_PRINTERS)
46*5e7646d2SAndroid Build Coastguard Worker     cupsdSaveAllPrinters();
47*5e7646d2SAndroid Build Coastguard Worker 
48*5e7646d2SAndroid Build Coastguard Worker   if (DirtyFiles & CUPSD_DIRTY_CLASSES)
49*5e7646d2SAndroid Build Coastguard Worker     cupsdSaveAllClasses();
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker   if (DirtyFiles & CUPSD_DIRTY_PRINTCAP)
52*5e7646d2SAndroid Build Coastguard Worker     cupsdWritePrintcap();
53*5e7646d2SAndroid Build Coastguard Worker 
54*5e7646d2SAndroid Build Coastguard Worker   if (DirtyFiles & CUPSD_DIRTY_JOBS)
55*5e7646d2SAndroid Build Coastguard Worker   {
56*5e7646d2SAndroid Build Coastguard Worker     cupsd_job_t	*job;			/* Current job */
57*5e7646d2SAndroid Build Coastguard Worker 
58*5e7646d2SAndroid Build Coastguard Worker     cupsdSaveAllJobs();
59*5e7646d2SAndroid Build Coastguard Worker 
60*5e7646d2SAndroid Build Coastguard Worker     for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
61*5e7646d2SAndroid Build Coastguard Worker          job;
62*5e7646d2SAndroid Build Coastguard Worker 	 job = (cupsd_job_t *)cupsArrayNext(Jobs))
63*5e7646d2SAndroid Build Coastguard Worker       if (job->dirty)
64*5e7646d2SAndroid Build Coastguard Worker         cupsdSaveJob(job);
65*5e7646d2SAndroid Build Coastguard Worker   }
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker   if (DirtyFiles & CUPSD_DIRTY_SUBSCRIPTIONS)
68*5e7646d2SAndroid Build Coastguard Worker     cupsdSaveAllSubscriptions();
69*5e7646d2SAndroid Build Coastguard Worker 
70*5e7646d2SAndroid Build Coastguard Worker   DirtyFiles     = CUPSD_DIRTY_NONE;
71*5e7646d2SAndroid Build Coastguard Worker   DirtyCleanTime = 0;
72*5e7646d2SAndroid Build Coastguard Worker 
73*5e7646d2SAndroid Build Coastguard Worker   cupsdSetBusyState(0);
74*5e7646d2SAndroid Build Coastguard Worker }
75*5e7646d2SAndroid Build Coastguard Worker 
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker /*
78*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdMarkDirty()' - Mark config or state files as needing a write.
79*5e7646d2SAndroid Build Coastguard Worker  */
80*5e7646d2SAndroid Build Coastguard Worker 
81*5e7646d2SAndroid Build Coastguard Worker void
cupsdMarkDirty(int what)82*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(int what)		/* I - What file(s) are dirty? */
83*5e7646d2SAndroid Build Coastguard Worker {
84*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c)",
85*5e7646d2SAndroid Build Coastguard Worker 		  (what & CUPSD_DIRTY_PRINTERS) ? 'P' : '-',
86*5e7646d2SAndroid Build Coastguard Worker 		  (what & CUPSD_DIRTY_CLASSES) ? 'C' : '-',
87*5e7646d2SAndroid Build Coastguard Worker 		  (what & CUPSD_DIRTY_PRINTCAP) ? 'p' : '-',
88*5e7646d2SAndroid Build Coastguard Worker 		  (what & CUPSD_DIRTY_JOBS) ? 'J' : '-',
89*5e7646d2SAndroid Build Coastguard Worker 		  (what & CUPSD_DIRTY_SUBSCRIPTIONS) ? 'S' : '-');
90*5e7646d2SAndroid Build Coastguard Worker 
91*5e7646d2SAndroid Build Coastguard Worker   if (what == CUPSD_DIRTY_PRINTCAP && !Printcap)
92*5e7646d2SAndroid Build Coastguard Worker     return;
93*5e7646d2SAndroid Build Coastguard Worker 
94*5e7646d2SAndroid Build Coastguard Worker   DirtyFiles |= what;
95*5e7646d2SAndroid Build Coastguard Worker 
96*5e7646d2SAndroid Build Coastguard Worker   if (!DirtyCleanTime)
97*5e7646d2SAndroid Build Coastguard Worker     DirtyCleanTime = time(NULL) + DirtyCleanInterval;
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker   cupsdSetBusyState(0);
100*5e7646d2SAndroid Build Coastguard Worker }
101*5e7646d2SAndroid Build Coastguard Worker 
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker /*
104*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
105*5e7646d2SAndroid Build Coastguard Worker  */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker void
cupsdSetBusyState(int working)108*5e7646d2SAndroid Build Coastguard Worker cupsdSetBusyState(int working)          /* I - Doing significant work? */
109*5e7646d2SAndroid Build Coastguard Worker {
110*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
111*5e7646d2SAndroid Build Coastguard Worker   cupsd_job_t		*job;		/* Current job */
112*5e7646d2SAndroid Build Coastguard Worker   cupsd_printer_t	*p;		/* Current printer */
113*5e7646d2SAndroid Build Coastguard Worker   int			newbusy;	/* New busy state */
114*5e7646d2SAndroid Build Coastguard Worker   static int		busy = 0;	/* Current busy state */
115*5e7646d2SAndroid Build Coastguard Worker   static const char * const busy_text[] =
116*5e7646d2SAndroid Build Coastguard Worker   {					/* Text for busy states */
117*5e7646d2SAndroid Build Coastguard Worker     "Not busy",
118*5e7646d2SAndroid Build Coastguard Worker     "Dirty files",
119*5e7646d2SAndroid Build Coastguard Worker     "Printing jobs",
120*5e7646d2SAndroid Build Coastguard Worker     "Printing jobs and dirty files",
121*5e7646d2SAndroid Build Coastguard Worker     "Active clients",
122*5e7646d2SAndroid Build Coastguard Worker     "Active clients and dirty files",
123*5e7646d2SAndroid Build Coastguard Worker     "Active clients and printing jobs",
124*5e7646d2SAndroid Build Coastguard Worker     "Active clients, printing jobs, and dirty files"
125*5e7646d2SAndroid Build Coastguard Worker   };
126*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
127*5e7646d2SAndroid Build Coastguard Worker   static IOPMAssertionID keep_awake = 0;/* Keep the system awake while printing */
128*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
129*5e7646d2SAndroid Build Coastguard Worker 
130*5e7646d2SAndroid Build Coastguard Worker 
131*5e7646d2SAndroid Build Coastguard Worker  /*
132*5e7646d2SAndroid Build Coastguard Worker   * Figure out how busy we are...
133*5e7646d2SAndroid Build Coastguard Worker   */
134*5e7646d2SAndroid Build Coastguard Worker 
135*5e7646d2SAndroid Build Coastguard Worker   newbusy = (DirtyCleanTime ? 1 : 0) |
136*5e7646d2SAndroid Build Coastguard Worker 	    ((working || cupsArrayCount(ActiveClients) > 0) ? 4 : 0);
137*5e7646d2SAndroid Build Coastguard Worker 
138*5e7646d2SAndroid Build Coastguard Worker   for (job = (cupsd_job_t *)cupsArrayFirst(PrintingJobs);
139*5e7646d2SAndroid Build Coastguard Worker        job;
140*5e7646d2SAndroid Build Coastguard Worker        job = (cupsd_job_t *)cupsArrayNext(PrintingJobs))
141*5e7646d2SAndroid Build Coastguard Worker   {
142*5e7646d2SAndroid Build Coastguard Worker     if ((p = job->printer) != NULL)
143*5e7646d2SAndroid Build Coastguard Worker     {
144*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < p->num_reasons; i ++)
145*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(p->reasons[i], "connecting-to-device"))
146*5e7646d2SAndroid Build Coastguard Worker 	  break;
147*5e7646d2SAndroid Build Coastguard Worker 
148*5e7646d2SAndroid Build Coastguard Worker       if (!p->num_reasons || i >= p->num_reasons)
149*5e7646d2SAndroid Build Coastguard Worker 	break;
150*5e7646d2SAndroid Build Coastguard Worker     }
151*5e7646d2SAndroid Build Coastguard Worker   }
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker   if (job)
154*5e7646d2SAndroid Build Coastguard Worker     newbusy |= 2;
155*5e7646d2SAndroid Build Coastguard Worker 
156*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG,
157*5e7646d2SAndroid Build Coastguard Worker                   "cupsdSetBusyState: newbusy=\"%s\", busy=\"%s\"",
158*5e7646d2SAndroid Build Coastguard Worker                   busy_text[newbusy], busy_text[busy]);
159*5e7646d2SAndroid Build Coastguard Worker 
160*5e7646d2SAndroid Build Coastguard Worker  /*
161*5e7646d2SAndroid Build Coastguard Worker   * Manage state changes...
162*5e7646d2SAndroid Build Coastguard Worker   */
163*5e7646d2SAndroid Build Coastguard Worker 
164*5e7646d2SAndroid Build Coastguard Worker   if (newbusy != busy)
165*5e7646d2SAndroid Build Coastguard Worker     busy = newbusy;
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
168*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake)
169*5e7646d2SAndroid Build Coastguard Worker   {
170*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting NetworkClientActive.");
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker     IOPMAssertionCreateWithName(kIOPMAssertNetworkClientActive,
173*5e7646d2SAndroid Build Coastguard Worker 				kIOPMAssertionLevelOn,
174*5e7646d2SAndroid Build Coastguard Worker 				CFSTR("org.cups.cupsd"), &keep_awake);
175*5e7646d2SAndroid Build Coastguard Worker   }
176*5e7646d2SAndroid Build Coastguard Worker   else if (cupsArrayCount(PrintingJobs) == 0 && keep_awake)
177*5e7646d2SAndroid Build Coastguard Worker   {
178*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing power assertion.");
179*5e7646d2SAndroid Build Coastguard Worker     IOPMAssertionRelease(keep_awake);
180*5e7646d2SAndroid Build Coastguard Worker     keep_awake = 0;
181*5e7646d2SAndroid Build Coastguard Worker   }
182*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
183*5e7646d2SAndroid Build Coastguard Worker }
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
187*5e7646d2SAndroid Build Coastguard Worker /*
188*5e7646d2SAndroid Build Coastguard Worker  * This is the Apple-specific system event code.  It works by creating
189*5e7646d2SAndroid Build Coastguard Worker  * a worker thread that waits for events from the OS and relays them
190*5e7646d2SAndroid Build Coastguard Worker  * to the main thread via a traditional pipe.
191*5e7646d2SAndroid Build Coastguard Worker  */
192*5e7646d2SAndroid Build Coastguard Worker 
193*5e7646d2SAndroid Build Coastguard Worker /*
194*5e7646d2SAndroid Build Coastguard Worker  * Include MacOS-specific headers...
195*5e7646d2SAndroid Build Coastguard Worker  */
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker #  include <notify.h>
198*5e7646d2SAndroid Build Coastguard Worker #  include <IOKit/IOKitLib.h>
199*5e7646d2SAndroid Build Coastguard Worker #  include <IOKit/IOMessage.h>
200*5e7646d2SAndroid Build Coastguard Worker #  include <IOKit/ps/IOPowerSources.h>
201*5e7646d2SAndroid Build Coastguard Worker #  include <IOKit/pwr_mgt/IOPMLib.h>
202*5e7646d2SAndroid Build Coastguard Worker #  include <SystemConfiguration/SystemConfiguration.h>
203*5e7646d2SAndroid Build Coastguard Worker #  include <pthread.h>
204*5e7646d2SAndroid Build Coastguard Worker 
205*5e7646d2SAndroid Build Coastguard Worker 
206*5e7646d2SAndroid Build Coastguard Worker /*
207*5e7646d2SAndroid Build Coastguard Worker  * Constants...
208*5e7646d2SAndroid Build Coastguard Worker  */
209*5e7646d2SAndroid Build Coastguard Worker 
210*5e7646d2SAndroid Build Coastguard Worker #  define SYSEVENT_CANSLEEP	0x1	/* Decide whether to allow sleep or not */
211*5e7646d2SAndroid Build Coastguard Worker #  define SYSEVENT_WILLSLEEP	0x2	/* Computer will go to sleep */
212*5e7646d2SAndroid Build Coastguard Worker #  define SYSEVENT_WOKE		0x4	/* Computer woke from sleep */
213*5e7646d2SAndroid Build Coastguard Worker #  define SYSEVENT_NETCHANGED	0x8	/* Network changed */
214*5e7646d2SAndroid Build Coastguard Worker #  define SYSEVENT_NAMECHANGED	0x10	/* Computer name changed */
215*5e7646d2SAndroid Build Coastguard Worker 
216*5e7646d2SAndroid Build Coastguard Worker 
217*5e7646d2SAndroid Build Coastguard Worker /*
218*5e7646d2SAndroid Build Coastguard Worker  * Structures...
219*5e7646d2SAndroid Build Coastguard Worker  */
220*5e7646d2SAndroid Build Coastguard Worker 
221*5e7646d2SAndroid Build Coastguard Worker typedef struct cupsd_sysevent_s		/*** System event data ****/
222*5e7646d2SAndroid Build Coastguard Worker {
223*5e7646d2SAndroid Build Coastguard Worker   unsigned char	event;			/* Event bit field */
224*5e7646d2SAndroid Build Coastguard Worker   io_connect_t	powerKernelPort;	/* Power context data */
225*5e7646d2SAndroid Build Coastguard Worker   long		powerNotificationID;	/* Power event data */
226*5e7646d2SAndroid Build Coastguard Worker } cupsd_sysevent_t;
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker 
229*5e7646d2SAndroid Build Coastguard Worker typedef struct cupsd_thread_data_s	/*** Thread context data  ****/
230*5e7646d2SAndroid Build Coastguard Worker {
231*5e7646d2SAndroid Build Coastguard Worker   cupsd_sysevent_t	sysevent;	/* System event */
232*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopTimerRef	timerRef;	/* Timer to delay some change *
233*5e7646d2SAndroid Build Coastguard Worker 					 * notifications              */
234*5e7646d2SAndroid Build Coastguard Worker } cupsd_thread_data_t;
235*5e7646d2SAndroid Build Coastguard Worker 
236*5e7646d2SAndroid Build Coastguard Worker 
237*5e7646d2SAndroid Build Coastguard Worker /*
238*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
239*5e7646d2SAndroid Build Coastguard Worker  */
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker static pthread_t	SysEventThread = NULL;
242*5e7646d2SAndroid Build Coastguard Worker 					/* Thread to host a runloop */
243*5e7646d2SAndroid Build Coastguard Worker static pthread_mutex_t	SysEventThreadMutex = { 0 };
244*5e7646d2SAndroid Build Coastguard Worker 					/* Coordinates access to shared gloabals */
245*5e7646d2SAndroid Build Coastguard Worker static pthread_cond_t	SysEventThreadCond = { 0 };
246*5e7646d2SAndroid Build Coastguard Worker 					/* Thread initialization complete condition */
247*5e7646d2SAndroid Build Coastguard Worker static CFRunLoopRef	SysEventRunloop = NULL;
248*5e7646d2SAndroid Build Coastguard Worker 					/* The runloop. Access must be protected! */
249*5e7646d2SAndroid Build Coastguard Worker static CFStringRef	ComputerNameKey = NULL,
250*5e7646d2SAndroid Build Coastguard Worker 					/* Computer name key */
251*5e7646d2SAndroid Build Coastguard Worker 			BTMMKey = NULL,	/* Back to My Mac key */
252*5e7646d2SAndroid Build Coastguard Worker 			NetworkGlobalKeyIPv4 = NULL,
253*5e7646d2SAndroid Build Coastguard Worker 					/* Network global IPv4 key */
254*5e7646d2SAndroid Build Coastguard Worker 			NetworkGlobalKeyIPv6 = NULL,
255*5e7646d2SAndroid Build Coastguard Worker 					/* Network global IPv6 key */
256*5e7646d2SAndroid Build Coastguard Worker 			NetworkGlobalKeyDNS = NULL,
257*5e7646d2SAndroid Build Coastguard Worker 					/* Network global DNS key */
258*5e7646d2SAndroid Build Coastguard Worker 			HostNamesKey = NULL,
259*5e7646d2SAndroid Build Coastguard Worker 					/* Host name key */
260*5e7646d2SAndroid Build Coastguard Worker 			NetworkInterfaceKeyIPv4 = NULL,
261*5e7646d2SAndroid Build Coastguard Worker 					/* Netowrk interface key */
262*5e7646d2SAndroid Build Coastguard Worker 			NetworkInterfaceKeyIPv6 = NULL;
263*5e7646d2SAndroid Build Coastguard Worker 					/* Netowrk interface key */
264*5e7646d2SAndroid Build Coastguard Worker static cupsd_sysevent_t	LastSysEvent;	/* Last system event (for delayed sleep) */
265*5e7646d2SAndroid Build Coastguard Worker static int		NameChanged = 0;/* Did we get a 'name changed' event during sleep? */
266*5e7646d2SAndroid Build Coastguard Worker static int		PSToken = 0;	/* Power source notifications */
267*5e7646d2SAndroid Build Coastguard Worker 
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker /*
270*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
271*5e7646d2SAndroid Build Coastguard Worker  */
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker static void	*sysEventThreadEntry(void);
274*5e7646d2SAndroid Build Coastguard Worker static void	sysEventPowerNotifier(void *context, io_service_t service,
275*5e7646d2SAndroid Build Coastguard Worker 		                      natural_t messageType,
276*5e7646d2SAndroid Build Coastguard Worker 				      void *messageArgument);
277*5e7646d2SAndroid Build Coastguard Worker static void	sysEventConfigurationNotifier(SCDynamicStoreRef store,
278*5e7646d2SAndroid Build Coastguard Worker 		                              CFArrayRef changedKeys,
279*5e7646d2SAndroid Build Coastguard Worker 					      void *context);
280*5e7646d2SAndroid Build Coastguard Worker static void	sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context);
281*5e7646d2SAndroid Build Coastguard Worker static void	sysUpdate(void);
282*5e7646d2SAndroid Build Coastguard Worker static void	sysUpdateNames(void);
283*5e7646d2SAndroid Build Coastguard Worker 
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker /*
286*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdAllowSleep()' - Tell the OS it is now OK to sleep.
287*5e7646d2SAndroid Build Coastguard Worker  */
288*5e7646d2SAndroid Build Coastguard Worker 
289*5e7646d2SAndroid Build Coastguard Worker void
cupsdAllowSleep(void)290*5e7646d2SAndroid Build Coastguard Worker cupsdAllowSleep(void)
291*5e7646d2SAndroid Build Coastguard Worker {
292*5e7646d2SAndroid Build Coastguard Worker   cupsdCleanDirty();
293*5e7646d2SAndroid Build Coastguard Worker 
294*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
295*5e7646d2SAndroid Build Coastguard Worker   IOAllowPowerChange(LastSysEvent.powerKernelPort,
296*5e7646d2SAndroid Build Coastguard Worker 		     LastSysEvent.powerNotificationID);
297*5e7646d2SAndroid Build Coastguard Worker }
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker 
300*5e7646d2SAndroid Build Coastguard Worker /*
301*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdStartSystemMonitor()' - Start monitoring for system change.
302*5e7646d2SAndroid Build Coastguard Worker  */
303*5e7646d2SAndroid Build Coastguard Worker 
304*5e7646d2SAndroid Build Coastguard Worker void
cupsdStartSystemMonitor(void)305*5e7646d2SAndroid Build Coastguard Worker cupsdStartSystemMonitor(void)
306*5e7646d2SAndroid Build Coastguard Worker {
307*5e7646d2SAndroid Build Coastguard Worker   int	flags;				/* fcntl flags on pipe */
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor()");
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker   if (cupsdOpenPipe(SysEventPipes))
313*5e7646d2SAndroid Build Coastguard Worker   {
314*5e7646d2SAndroid Build Coastguard Worker     cupsdLogMessage(CUPSD_LOG_ERROR, "System event monitor pipe() failed - %s!",
315*5e7646d2SAndroid Build Coastguard Worker                     strerror(errno));
316*5e7646d2SAndroid Build Coastguard Worker     return;
317*5e7646d2SAndroid Build Coastguard Worker   }
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker   cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)sysUpdate, NULL, NULL);
320*5e7646d2SAndroid Build Coastguard Worker 
321*5e7646d2SAndroid Build Coastguard Worker  /*
322*5e7646d2SAndroid Build Coastguard Worker   * Set non-blocking mode on the descriptor we will be receiving notification
323*5e7646d2SAndroid Build Coastguard Worker   * events on.
324*5e7646d2SAndroid Build Coastguard Worker   */
325*5e7646d2SAndroid Build Coastguard Worker 
326*5e7646d2SAndroid Build Coastguard Worker   flags = fcntl(SysEventPipes[0], F_GETFL, 0);
327*5e7646d2SAndroid Build Coastguard Worker   fcntl(SysEventPipes[0], F_SETFL, flags | O_NONBLOCK);
328*5e7646d2SAndroid Build Coastguard Worker 
329*5e7646d2SAndroid Build Coastguard Worker  /*
330*5e7646d2SAndroid Build Coastguard Worker   * Start the thread that runs the runloop...
331*5e7646d2SAndroid Build Coastguard Worker   */
332*5e7646d2SAndroid Build Coastguard Worker 
333*5e7646d2SAndroid Build Coastguard Worker   pthread_mutex_init(&SysEventThreadMutex, NULL);
334*5e7646d2SAndroid Build Coastguard Worker   pthread_cond_init(&SysEventThreadCond, NULL);
335*5e7646d2SAndroid Build Coastguard Worker   pthread_create(&SysEventThread, NULL, (void *(*)(void *))sysEventThreadEntry, NULL);
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker  /*
338*5e7646d2SAndroid Build Coastguard Worker   * Monitor for power source changes via dispatch queue...
339*5e7646d2SAndroid Build Coastguard Worker   */
340*5e7646d2SAndroid Build Coastguard Worker 
341*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor: IOPSGetTimeRemainingEstimate=%f", IOPSGetTimeRemainingEstimate());
342*5e7646d2SAndroid Build Coastguard Worker   ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited;
343*5e7646d2SAndroid Build Coastguard Worker   notify_register_dispatch(kIOPSNotifyPowerSource, &PSToken, dispatch_get_main_queue(), ^(int t) { (void)t;
344*5e7646d2SAndroid Build Coastguard Worker       ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; });
345*5e7646d2SAndroid Build Coastguard Worker }
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker 
348*5e7646d2SAndroid Build Coastguard Worker /*
349*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdStopSystemMonitor()' - Stop monitoring for system change.
350*5e7646d2SAndroid Build Coastguard Worker  */
351*5e7646d2SAndroid Build Coastguard Worker 
352*5e7646d2SAndroid Build Coastguard Worker void
cupsdStopSystemMonitor(void)353*5e7646d2SAndroid Build Coastguard Worker cupsdStopSystemMonitor(void)
354*5e7646d2SAndroid Build Coastguard Worker {
355*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopRef	rl;			/* The event handler runloop */
356*5e7646d2SAndroid Build Coastguard Worker 
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker   cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSystemMonitor()");
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker   if (SysEventThread)
361*5e7646d2SAndroid Build Coastguard Worker   {
362*5e7646d2SAndroid Build Coastguard Worker    /*
363*5e7646d2SAndroid Build Coastguard Worker     * Make sure the thread has completed it's initialization and
364*5e7646d2SAndroid Build Coastguard Worker     * stored it's runloop reference in the shared global.
365*5e7646d2SAndroid Build Coastguard Worker     */
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker     pthread_mutex_lock(&SysEventThreadMutex);
368*5e7646d2SAndroid Build Coastguard Worker 
369*5e7646d2SAndroid Build Coastguard Worker     if (!SysEventRunloop)
370*5e7646d2SAndroid Build Coastguard Worker       pthread_cond_wait(&SysEventThreadCond, &SysEventThreadMutex);
371*5e7646d2SAndroid Build Coastguard Worker 
372*5e7646d2SAndroid Build Coastguard Worker     rl              = SysEventRunloop;
373*5e7646d2SAndroid Build Coastguard Worker     SysEventRunloop = NULL;
374*5e7646d2SAndroid Build Coastguard Worker 
375*5e7646d2SAndroid Build Coastguard Worker     pthread_mutex_unlock(&SysEventThreadMutex);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     if (rl)
378*5e7646d2SAndroid Build Coastguard Worker       CFRunLoopStop(rl);
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker     pthread_join(SysEventThread, NULL);
381*5e7646d2SAndroid Build Coastguard Worker     pthread_mutex_destroy(&SysEventThreadMutex);
382*5e7646d2SAndroid Build Coastguard Worker     pthread_cond_destroy(&SysEventThreadCond);
383*5e7646d2SAndroid Build Coastguard Worker   }
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker   if (SysEventPipes[0] >= 0)
386*5e7646d2SAndroid Build Coastguard Worker   {
387*5e7646d2SAndroid Build Coastguard Worker     cupsdRemoveSelect(SysEventPipes[0]);
388*5e7646d2SAndroid Build Coastguard Worker     cupsdClosePipe(SysEventPipes);
389*5e7646d2SAndroid Build Coastguard Worker   }
390*5e7646d2SAndroid Build Coastguard Worker 
391*5e7646d2SAndroid Build Coastguard Worker   if (PSToken != 0)
392*5e7646d2SAndroid Build Coastguard Worker   {
393*5e7646d2SAndroid Build Coastguard Worker     notify_cancel(PSToken);
394*5e7646d2SAndroid Build Coastguard Worker     PSToken = 0;
395*5e7646d2SAndroid Build Coastguard Worker   }
396*5e7646d2SAndroid Build Coastguard Worker }
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker 
399*5e7646d2SAndroid Build Coastguard Worker /*
400*5e7646d2SAndroid Build Coastguard Worker  * 'sysEventThreadEntry()' - A thread to receive power and computer name
401*5e7646d2SAndroid Build Coastguard Worker  *                           change notifications.
402*5e7646d2SAndroid Build Coastguard Worker  */
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker static void *				/* O - Return status/value */
sysEventThreadEntry(void)405*5e7646d2SAndroid Build Coastguard Worker sysEventThreadEntry(void)
406*5e7646d2SAndroid Build Coastguard Worker {
407*5e7646d2SAndroid Build Coastguard Worker   io_object_t		powerNotifierObj;
408*5e7646d2SAndroid Build Coastguard Worker 					/* Power notifier object */
409*5e7646d2SAndroid Build Coastguard Worker   IONotificationPortRef powerNotifierPort;
410*5e7646d2SAndroid Build Coastguard Worker 					/* Power notifier port */
411*5e7646d2SAndroid Build Coastguard Worker   SCDynamicStoreRef	store    = NULL;/* System Config dynamic store */
412*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopSourceRef	powerRLS = NULL,/* Power runloop source */
413*5e7646d2SAndroid Build Coastguard Worker 			storeRLS = NULL;/* System Config runloop source */
414*5e7646d2SAndroid Build Coastguard Worker   CFStringRef		key[6],		/* System Config keys */
415*5e7646d2SAndroid Build Coastguard Worker 			pattern[2];	/* System Config patterns */
416*5e7646d2SAndroid Build Coastguard Worker   CFArrayRef		keys = NULL,	/* System Config key array*/
417*5e7646d2SAndroid Build Coastguard Worker 			patterns = NULL;/* System Config pattern array */
418*5e7646d2SAndroid Build Coastguard Worker   SCDynamicStoreContext	storeContext;	/* Dynamic store context */
419*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopTimerContext timerContext;	/* Timer context */
420*5e7646d2SAndroid Build Coastguard Worker   cupsd_thread_data_t	threadData;	/* Thread context data for the *
421*5e7646d2SAndroid Build Coastguard Worker 					 * runloop notifiers           */
422*5e7646d2SAndroid Build Coastguard Worker 
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker  /*
425*5e7646d2SAndroid Build Coastguard Worker   * Register for power state change notifications
426*5e7646d2SAndroid Build Coastguard Worker   */
427*5e7646d2SAndroid Build Coastguard Worker 
428*5e7646d2SAndroid Build Coastguard Worker   memset(&threadData, 0, sizeof(threadData));
429*5e7646d2SAndroid Build Coastguard Worker 
430*5e7646d2SAndroid Build Coastguard Worker   threadData.sysevent.powerKernelPort =
431*5e7646d2SAndroid Build Coastguard Worker       IORegisterForSystemPower(&threadData, &powerNotifierPort,
432*5e7646d2SAndroid Build Coastguard Worker                                sysEventPowerNotifier, &powerNotifierObj);
433*5e7646d2SAndroid Build Coastguard Worker 
434*5e7646d2SAndroid Build Coastguard Worker   if (threadData.sysevent.powerKernelPort)
435*5e7646d2SAndroid Build Coastguard Worker   {
436*5e7646d2SAndroid Build Coastguard Worker     powerRLS = IONotificationPortGetRunLoopSource(powerNotifierPort);
437*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode);
438*5e7646d2SAndroid Build Coastguard Worker   }
439*5e7646d2SAndroid Build Coastguard Worker 
440*5e7646d2SAndroid Build Coastguard Worker  /*
441*5e7646d2SAndroid Build Coastguard Worker   * Register for system configuration change notifications
442*5e7646d2SAndroid Build Coastguard Worker   */
443*5e7646d2SAndroid Build Coastguard Worker 
444*5e7646d2SAndroid Build Coastguard Worker   memset(&storeContext, 0, sizeof(storeContext));
445*5e7646d2SAndroid Build Coastguard Worker   storeContext.info = &threadData;
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker   store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"),
448*5e7646d2SAndroid Build Coastguard Worker                                sysEventConfigurationNotifier, &storeContext);
449*5e7646d2SAndroid Build Coastguard Worker 
450*5e7646d2SAndroid Build Coastguard Worker   if (!ComputerNameKey)
451*5e7646d2SAndroid Build Coastguard Worker     ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault);
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker   if (!BTMMKey)
454*5e7646d2SAndroid Build Coastguard Worker     BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault,
455*5e7646d2SAndroid Build Coastguard Worker                                       CFSTR("Setup:/Network/BackToMyMac"));
456*5e7646d2SAndroid Build Coastguard Worker 
457*5e7646d2SAndroid Build Coastguard Worker   if (!NetworkGlobalKeyIPv4)
458*5e7646d2SAndroid Build Coastguard Worker     NetworkGlobalKeyIPv4 =
459*5e7646d2SAndroid Build Coastguard Worker         SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
460*5e7646d2SAndroid Build Coastguard Worker                                                    kSCDynamicStoreDomainState,
461*5e7646d2SAndroid Build Coastguard Worker 						   kSCEntNetIPv4);
462*5e7646d2SAndroid Build Coastguard Worker 
463*5e7646d2SAndroid Build Coastguard Worker   if (!NetworkGlobalKeyIPv6)
464*5e7646d2SAndroid Build Coastguard Worker     NetworkGlobalKeyIPv6 =
465*5e7646d2SAndroid Build Coastguard Worker         SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
466*5e7646d2SAndroid Build Coastguard Worker                                                    kSCDynamicStoreDomainState,
467*5e7646d2SAndroid Build Coastguard Worker 						   kSCEntNetIPv6);
468*5e7646d2SAndroid Build Coastguard Worker 
469*5e7646d2SAndroid Build Coastguard Worker   if (!NetworkGlobalKeyDNS)
470*5e7646d2SAndroid Build Coastguard Worker     NetworkGlobalKeyDNS =
471*5e7646d2SAndroid Build Coastguard Worker 	SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
472*5e7646d2SAndroid Build Coastguard Worker 						   kSCDynamicStoreDomainState,
473*5e7646d2SAndroid Build Coastguard Worker 						   kSCEntNetDNS);
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker   if (!HostNamesKey)
476*5e7646d2SAndroid Build Coastguard Worker     HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault);
477*5e7646d2SAndroid Build Coastguard Worker 
478*5e7646d2SAndroid Build Coastguard Worker   if (!NetworkInterfaceKeyIPv4)
479*5e7646d2SAndroid Build Coastguard Worker     NetworkInterfaceKeyIPv4 =
480*5e7646d2SAndroid Build Coastguard Worker         SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
481*5e7646d2SAndroid Build Coastguard Worker 	                                              kSCDynamicStoreDomainState,
482*5e7646d2SAndroid Build Coastguard Worker 						      kSCCompAnyRegex,
483*5e7646d2SAndroid Build Coastguard Worker 						      kSCEntNetIPv4);
484*5e7646d2SAndroid Build Coastguard Worker 
485*5e7646d2SAndroid Build Coastguard Worker   if (!NetworkInterfaceKeyIPv6)
486*5e7646d2SAndroid Build Coastguard Worker     NetworkInterfaceKeyIPv6 =
487*5e7646d2SAndroid Build Coastguard Worker         SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
488*5e7646d2SAndroid Build Coastguard Worker 	                                              kSCDynamicStoreDomainState,
489*5e7646d2SAndroid Build Coastguard Worker 						      kSCCompAnyRegex,
490*5e7646d2SAndroid Build Coastguard Worker 						      kSCEntNetIPv6);
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker   if (store && ComputerNameKey && HostNamesKey &&
493*5e7646d2SAndroid Build Coastguard Worker       NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS &&
494*5e7646d2SAndroid Build Coastguard Worker       NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6)
495*5e7646d2SAndroid Build Coastguard Worker   {
496*5e7646d2SAndroid Build Coastguard Worker     key[0]     = ComputerNameKey;
497*5e7646d2SAndroid Build Coastguard Worker     key[1]     = BTMMKey;
498*5e7646d2SAndroid Build Coastguard Worker     key[2]     = NetworkGlobalKeyIPv4;
499*5e7646d2SAndroid Build Coastguard Worker     key[3]     = NetworkGlobalKeyIPv6;
500*5e7646d2SAndroid Build Coastguard Worker     key[4]     = NetworkGlobalKeyDNS;
501*5e7646d2SAndroid Build Coastguard Worker     key[5]     = HostNamesKey;
502*5e7646d2SAndroid Build Coastguard Worker 
503*5e7646d2SAndroid Build Coastguard Worker     pattern[0] = NetworkInterfaceKeyIPv4;
504*5e7646d2SAndroid Build Coastguard Worker     pattern[1] = NetworkInterfaceKeyIPv6;
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker     keys     = CFArrayCreate(kCFAllocatorDefault, (const void **)key,
507*5e7646d2SAndroid Build Coastguard Worker 			     sizeof(key) / sizeof(key[0]),
508*5e7646d2SAndroid Build Coastguard Worker 			     &kCFTypeArrayCallBacks);
509*5e7646d2SAndroid Build Coastguard Worker 
510*5e7646d2SAndroid Build Coastguard Worker     patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern,
511*5e7646d2SAndroid Build Coastguard Worker                              sizeof(pattern) / sizeof(pattern[0]),
512*5e7646d2SAndroid Build Coastguard Worker 			     &kCFTypeArrayCallBacks);
513*5e7646d2SAndroid Build Coastguard Worker 
514*5e7646d2SAndroid Build Coastguard Worker     if (keys && patterns &&
515*5e7646d2SAndroid Build Coastguard Worker         SCDynamicStoreSetNotificationKeys(store, keys, patterns))
516*5e7646d2SAndroid Build Coastguard Worker     {
517*5e7646d2SAndroid Build Coastguard Worker       if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault,
518*5e7646d2SAndroid Build Coastguard Worker                                                         store, 0)) != NULL)
519*5e7646d2SAndroid Build Coastguard Worker       {
520*5e7646d2SAndroid Build Coastguard Worker 	CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS,
521*5e7646d2SAndroid Build Coastguard Worker 	                   kCFRunLoopDefaultMode);
522*5e7646d2SAndroid Build Coastguard Worker       }
523*5e7646d2SAndroid Build Coastguard Worker     }
524*5e7646d2SAndroid Build Coastguard Worker   }
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker   if (keys)
527*5e7646d2SAndroid Build Coastguard Worker     CFRelease(keys);
528*5e7646d2SAndroid Build Coastguard Worker 
529*5e7646d2SAndroid Build Coastguard Worker   if (patterns)
530*5e7646d2SAndroid Build Coastguard Worker     CFRelease(patterns);
531*5e7646d2SAndroid Build Coastguard Worker 
532*5e7646d2SAndroid Build Coastguard Worker  /*
533*5e7646d2SAndroid Build Coastguard Worker   * Set up a timer to delay the wake change notifications.
534*5e7646d2SAndroid Build Coastguard Worker   *
535*5e7646d2SAndroid Build Coastguard Worker   * The initial time is set a decade or so into the future, we'll adjust
536*5e7646d2SAndroid Build Coastguard Worker   * this later.
537*5e7646d2SAndroid Build Coastguard Worker   */
538*5e7646d2SAndroid Build Coastguard Worker 
539*5e7646d2SAndroid Build Coastguard Worker   memset(&timerContext, 0, sizeof(timerContext));
540*5e7646d2SAndroid Build Coastguard Worker   timerContext.info = &threadData;
541*5e7646d2SAndroid Build Coastguard Worker 
542*5e7646d2SAndroid Build Coastguard Worker   threadData.timerRef =
543*5e7646d2SAndroid Build Coastguard Worker       CFRunLoopTimerCreate(kCFAllocatorDefault,
544*5e7646d2SAndroid Build Coastguard Worker                            CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
545*5e7646d2SAndroid Build Coastguard Worker 			   86400L * 365L * 10L, 0, 0, sysEventTimerNotifier,
546*5e7646d2SAndroid Build Coastguard Worker 			   &timerContext);
547*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef,
548*5e7646d2SAndroid Build Coastguard Worker                     kCFRunLoopDefaultMode);
549*5e7646d2SAndroid Build Coastguard Worker 
550*5e7646d2SAndroid Build Coastguard Worker  /*
551*5e7646d2SAndroid Build Coastguard Worker   * Store our runloop in a global so the main thread can use it to stop us.
552*5e7646d2SAndroid Build Coastguard Worker   */
553*5e7646d2SAndroid Build Coastguard Worker 
554*5e7646d2SAndroid Build Coastguard Worker   pthread_mutex_lock(&SysEventThreadMutex);
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker   SysEventRunloop = CFRunLoopGetCurrent();
557*5e7646d2SAndroid Build Coastguard Worker 
558*5e7646d2SAndroid Build Coastguard Worker   pthread_cond_signal(&SysEventThreadCond);
559*5e7646d2SAndroid Build Coastguard Worker   pthread_mutex_unlock(&SysEventThreadMutex);
560*5e7646d2SAndroid Build Coastguard Worker 
561*5e7646d2SAndroid Build Coastguard Worker  /*
562*5e7646d2SAndroid Build Coastguard Worker   * Disappear into the runloop until it's stopped by the main thread.
563*5e7646d2SAndroid Build Coastguard Worker   */
564*5e7646d2SAndroid Build Coastguard Worker 
565*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopRun();
566*5e7646d2SAndroid Build Coastguard Worker 
567*5e7646d2SAndroid Build Coastguard Worker  /*
568*5e7646d2SAndroid Build Coastguard Worker   * Clean up before exiting.
569*5e7646d2SAndroid Build Coastguard Worker   */
570*5e7646d2SAndroid Build Coastguard Worker 
571*5e7646d2SAndroid Build Coastguard Worker   if (threadData.timerRef)
572*5e7646d2SAndroid Build Coastguard Worker   {
573*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData.timerRef,
574*5e7646d2SAndroid Build Coastguard Worker                          kCFRunLoopDefaultMode);
575*5e7646d2SAndroid Build Coastguard Worker     CFRelease(threadData.timerRef);
576*5e7646d2SAndroid Build Coastguard Worker   }
577*5e7646d2SAndroid Build Coastguard Worker 
578*5e7646d2SAndroid Build Coastguard Worker   if (threadData.sysevent.powerKernelPort)
579*5e7646d2SAndroid Build Coastguard Worker   {
580*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS,
581*5e7646d2SAndroid Build Coastguard Worker                           kCFRunLoopDefaultMode);
582*5e7646d2SAndroid Build Coastguard Worker     IODeregisterForSystemPower(&powerNotifierObj);
583*5e7646d2SAndroid Build Coastguard Worker     IOServiceClose(threadData.sysevent.powerKernelPort);
584*5e7646d2SAndroid Build Coastguard Worker     IONotificationPortDestroy(powerNotifierPort);
585*5e7646d2SAndroid Build Coastguard Worker   }
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker   if (storeRLS)
588*5e7646d2SAndroid Build Coastguard Worker   {
589*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS,
590*5e7646d2SAndroid Build Coastguard Worker                           kCFRunLoopDefaultMode);
591*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopSourceInvalidate(storeRLS);
592*5e7646d2SAndroid Build Coastguard Worker     CFRelease(storeRLS);
593*5e7646d2SAndroid Build Coastguard Worker   }
594*5e7646d2SAndroid Build Coastguard Worker 
595*5e7646d2SAndroid Build Coastguard Worker   if (store)
596*5e7646d2SAndroid Build Coastguard Worker     CFRelease(store);
597*5e7646d2SAndroid Build Coastguard Worker 
598*5e7646d2SAndroid Build Coastguard Worker   pthread_exit(NULL);
599*5e7646d2SAndroid Build Coastguard Worker }
600*5e7646d2SAndroid Build Coastguard Worker 
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker /*
603*5e7646d2SAndroid Build Coastguard Worker  * 'sysEventPowerNotifier()' - Handle power notification events.
604*5e7646d2SAndroid Build Coastguard Worker  */
605*5e7646d2SAndroid Build Coastguard Worker 
606*5e7646d2SAndroid Build Coastguard Worker static void
sysEventPowerNotifier(void * context,io_service_t service,natural_t messageType,void * messageArgument)607*5e7646d2SAndroid Build Coastguard Worker sysEventPowerNotifier(
608*5e7646d2SAndroid Build Coastguard Worker     void         *context,		/* I - Thread context data */
609*5e7646d2SAndroid Build Coastguard Worker     io_service_t service,		/* I - Unused service info */
610*5e7646d2SAndroid Build Coastguard Worker     natural_t    messageType,		/* I - Type of message */
611*5e7646d2SAndroid Build Coastguard Worker     void         *messageArgument)	/* I - Message data */
612*5e7646d2SAndroid Build Coastguard Worker {
613*5e7646d2SAndroid Build Coastguard Worker   int			sendit = 1;	/* Send event to main thread?    *
614*5e7646d2SAndroid Build Coastguard Worker 					 * (0 = no, 1 = yes, 2 = delayed */
615*5e7646d2SAndroid Build Coastguard Worker   cupsd_thread_data_t	*threadData;	/* Thread context data */
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker 
618*5e7646d2SAndroid Build Coastguard Worker   threadData = (cupsd_thread_data_t *)context;
619*5e7646d2SAndroid Build Coastguard Worker 
620*5e7646d2SAndroid Build Coastguard Worker   (void)service;			/* anti-compiler-warning-code */
621*5e7646d2SAndroid Build Coastguard Worker 
622*5e7646d2SAndroid Build Coastguard Worker   switch (messageType)
623*5e7646d2SAndroid Build Coastguard Worker   {
624*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageCanSystemPowerOff :
625*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageCanSystemSleep :
626*5e7646d2SAndroid Build Coastguard Worker 	threadData->sysevent.event |= SYSEVENT_CANSLEEP;
627*5e7646d2SAndroid Build Coastguard Worker 	break;
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillRestart :
630*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillPowerOff :
631*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillSleep :
632*5e7646d2SAndroid Build Coastguard Worker 	threadData->sysevent.event |= SYSEVENT_WILLSLEEP;
633*5e7646d2SAndroid Build Coastguard Worker 	threadData->sysevent.event &= ~SYSEVENT_WOKE;
634*5e7646d2SAndroid Build Coastguard Worker 	break;
635*5e7646d2SAndroid Build Coastguard Worker 
636*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemHasPoweredOn :
637*5e7646d2SAndroid Build Coastguard Worker        /*
638*5e7646d2SAndroid Build Coastguard Worker 	* Because powered on is followed by a net-changed event, delay
639*5e7646d2SAndroid Build Coastguard Worker 	* before sending it.
640*5e7646d2SAndroid Build Coastguard Worker 	*/
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker         sendit = 2;
643*5e7646d2SAndroid Build Coastguard Worker 	threadData->sysevent.event |= SYSEVENT_WOKE;
644*5e7646d2SAndroid Build Coastguard Worker 	break;
645*5e7646d2SAndroid Build Coastguard Worker 
646*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillNotPowerOff :
647*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillNotSleep :
648*5e7646d2SAndroid Build Coastguard Worker #  ifdef kIOMessageSystemWillPowerOn
649*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillPowerOn :
650*5e7646d2SAndroid Build Coastguard Worker #  endif /* kIOMessageSystemWillPowerOn */
651*5e7646d2SAndroid Build Coastguard Worker     default:
652*5e7646d2SAndroid Build Coastguard Worker 	sendit = 0;
653*5e7646d2SAndroid Build Coastguard Worker 	break;
654*5e7646d2SAndroid Build Coastguard Worker   }
655*5e7646d2SAndroid Build Coastguard Worker 
656*5e7646d2SAndroid Build Coastguard Worker   switch (messageType)
657*5e7646d2SAndroid Build Coastguard Worker   {
658*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageCanSystemPowerOff :
659*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
660*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageCanSystemPowerOff message.");
661*5e7646d2SAndroid Build Coastguard Worker 	break;
662*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageCanSystemSleep :
663*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
664*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageCannSystemSleep message.");
665*5e7646d2SAndroid Build Coastguard Worker 	break;
666*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillRestart :
667*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
668*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillRestart message.");
669*5e7646d2SAndroid Build Coastguard Worker 	break;
670*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillPowerOff :
671*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
672*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillPowerOff message.");
673*5e7646d2SAndroid Build Coastguard Worker 	break;
674*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillSleep :
675*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
676*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillSleep message.");
677*5e7646d2SAndroid Build Coastguard Worker 	break;
678*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemHasPoweredOn :
679*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
680*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemHasPoweredOn message.");
681*5e7646d2SAndroid Build Coastguard Worker 	break;
682*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillNotPowerOff :
683*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
684*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillNotPowerOff message.");
685*5e7646d2SAndroid Build Coastguard Worker 	break;
686*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillNotSleep :
687*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
688*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillNotSleep message.");
689*5e7646d2SAndroid Build Coastguard Worker 	break;
690*5e7646d2SAndroid Build Coastguard Worker #  ifdef kIOMessageSystemWillPowerOn
691*5e7646d2SAndroid Build Coastguard Worker     case kIOMessageSystemWillPowerOn :
692*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
693*5e7646d2SAndroid Build Coastguard Worker                         "Got kIOMessageSystemWillPowerOn message.");
694*5e7646d2SAndroid Build Coastguard Worker 	break;
695*5e7646d2SAndroid Build Coastguard Worker #  endif /* kIOMessageSystemWillPowerOn */
696*5e7646d2SAndroid Build Coastguard Worker     default:
697*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG, "Got unknown power message %d.",
698*5e7646d2SAndroid Build Coastguard Worker                         (int)messageType);
699*5e7646d2SAndroid Build Coastguard Worker 	break;
700*5e7646d2SAndroid Build Coastguard Worker   }
701*5e7646d2SAndroid Build Coastguard Worker 
702*5e7646d2SAndroid Build Coastguard Worker   if (sendit == 0)
703*5e7646d2SAndroid Build Coastguard Worker     IOAllowPowerChange(threadData->sysevent.powerKernelPort,
704*5e7646d2SAndroid Build Coastguard Worker                        (long)messageArgument);
705*5e7646d2SAndroid Build Coastguard Worker   else
706*5e7646d2SAndroid Build Coastguard Worker   {
707*5e7646d2SAndroid Build Coastguard Worker     threadData->sysevent.powerNotificationID = (long)messageArgument;
708*5e7646d2SAndroid Build Coastguard Worker 
709*5e7646d2SAndroid Build Coastguard Worker     if (sendit == 1)
710*5e7646d2SAndroid Build Coastguard Worker     {
711*5e7646d2SAndroid Build Coastguard Worker      /*
712*5e7646d2SAndroid Build Coastguard Worker       * Send the event to the main thread now.
713*5e7646d2SAndroid Build Coastguard Worker       */
714*5e7646d2SAndroid Build Coastguard Worker 
715*5e7646d2SAndroid Build Coastguard Worker       write(SysEventPipes[1], &threadData->sysevent,
716*5e7646d2SAndroid Build Coastguard Worker 	    sizeof(threadData->sysevent));
717*5e7646d2SAndroid Build Coastguard Worker       threadData->sysevent.event = 0;
718*5e7646d2SAndroid Build Coastguard Worker     }
719*5e7646d2SAndroid Build Coastguard Worker     else
720*5e7646d2SAndroid Build Coastguard Worker     {
721*5e7646d2SAndroid Build Coastguard Worker      /*
722*5e7646d2SAndroid Build Coastguard Worker       * Send the event to the main thread after 1 to 2 seconds.
723*5e7646d2SAndroid Build Coastguard Worker       */
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker       CFRunLoopTimerSetNextFireDate(threadData->timerRef,
726*5e7646d2SAndroid Build Coastguard Worker                                     CFAbsoluteTimeGetCurrent() + 2);
727*5e7646d2SAndroid Build Coastguard Worker     }
728*5e7646d2SAndroid Build Coastguard Worker   }
729*5e7646d2SAndroid Build Coastguard Worker }
730*5e7646d2SAndroid Build Coastguard Worker 
731*5e7646d2SAndroid Build Coastguard Worker 
732*5e7646d2SAndroid Build Coastguard Worker /*
733*5e7646d2SAndroid Build Coastguard Worker  * 'sysEventConfigurationNotifier()' - Network configuration change notification
734*5e7646d2SAndroid Build Coastguard Worker  *                                     callback.
735*5e7646d2SAndroid Build Coastguard Worker  */
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker static void
sysEventConfigurationNotifier(SCDynamicStoreRef store,CFArrayRef changedKeys,void * context)738*5e7646d2SAndroid Build Coastguard Worker sysEventConfigurationNotifier(
739*5e7646d2SAndroid Build Coastguard Worker     SCDynamicStoreRef store,		/* I - System data (unused) */
740*5e7646d2SAndroid Build Coastguard Worker     CFArrayRef        changedKeys,	/* I - Changed data */
741*5e7646d2SAndroid Build Coastguard Worker     void              *context)		/* I - Thread context data */
742*5e7646d2SAndroid Build Coastguard Worker {
743*5e7646d2SAndroid Build Coastguard Worker   cupsd_thread_data_t	*threadData;	/* Thread context data */
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker 
746*5e7646d2SAndroid Build Coastguard Worker   threadData = (cupsd_thread_data_t *)context;
747*5e7646d2SAndroid Build Coastguard Worker 
748*5e7646d2SAndroid Build Coastguard Worker   (void)store;				/* anti-compiler-warning-code */
749*5e7646d2SAndroid Build Coastguard Worker 
750*5e7646d2SAndroid Build Coastguard Worker   CFRange range = CFRangeMake(0, CFArrayGetCount(changedKeys));
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker   if (CFArrayContainsValue(changedKeys, range, ComputerNameKey) ||
753*5e7646d2SAndroid Build Coastguard Worker       CFArrayContainsValue(changedKeys, range, BTMMKey))
754*5e7646d2SAndroid Build Coastguard Worker     threadData->sysevent.event |= SYSEVENT_NAMECHANGED;
755*5e7646d2SAndroid Build Coastguard Worker   else
756*5e7646d2SAndroid Build Coastguard Worker   {
757*5e7646d2SAndroid Build Coastguard Worker     threadData->sysevent.event |= SYSEVENT_NETCHANGED;
758*5e7646d2SAndroid Build Coastguard Worker 
759*5e7646d2SAndroid Build Coastguard Worker    /*
760*5e7646d2SAndroid Build Coastguard Worker     * Indicate the network interface list needs updating...
761*5e7646d2SAndroid Build Coastguard Worker     */
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker     NetIFUpdate = 1;
764*5e7646d2SAndroid Build Coastguard Worker   }
765*5e7646d2SAndroid Build Coastguard Worker 
766*5e7646d2SAndroid Build Coastguard Worker  /*
767*5e7646d2SAndroid Build Coastguard Worker   * Because we registered for several different kinds of change notifications
768*5e7646d2SAndroid Build Coastguard Worker   * this callback usually gets called several times in a row. We use a timer to
769*5e7646d2SAndroid Build Coastguard Worker   * de-bounce these so we only end up generating one event for the main thread.
770*5e7646d2SAndroid Build Coastguard Worker   */
771*5e7646d2SAndroid Build Coastguard Worker 
772*5e7646d2SAndroid Build Coastguard Worker   CFRunLoopTimerSetNextFireDate(threadData->timerRef,
773*5e7646d2SAndroid Build Coastguard Worker   				CFAbsoluteTimeGetCurrent() + 5);
774*5e7646d2SAndroid Build Coastguard Worker }
775*5e7646d2SAndroid Build Coastguard Worker 
776*5e7646d2SAndroid Build Coastguard Worker 
777*5e7646d2SAndroid Build Coastguard Worker /*
778*5e7646d2SAndroid Build Coastguard Worker  * 'sysEventTimerNotifier()' - Handle delayed event notifications.
779*5e7646d2SAndroid Build Coastguard Worker  */
780*5e7646d2SAndroid Build Coastguard Worker 
781*5e7646d2SAndroid Build Coastguard Worker static void
sysEventTimerNotifier(CFRunLoopTimerRef timer,void * context)782*5e7646d2SAndroid Build Coastguard Worker sysEventTimerNotifier(
783*5e7646d2SAndroid Build Coastguard Worker     CFRunLoopTimerRef timer,		/* I - Timer information */
784*5e7646d2SAndroid Build Coastguard Worker     void              *context)		/* I - Thread context data */
785*5e7646d2SAndroid Build Coastguard Worker {
786*5e7646d2SAndroid Build Coastguard Worker   cupsd_thread_data_t	*threadData;	/* Thread context data */
787*5e7646d2SAndroid Build Coastguard Worker 
788*5e7646d2SAndroid Build Coastguard Worker 
789*5e7646d2SAndroid Build Coastguard Worker   (void)timer;
790*5e7646d2SAndroid Build Coastguard Worker 
791*5e7646d2SAndroid Build Coastguard Worker   threadData = (cupsd_thread_data_t *)context;
792*5e7646d2SAndroid Build Coastguard Worker 
793*5e7646d2SAndroid Build Coastguard Worker  /*
794*5e7646d2SAndroid Build Coastguard Worker   * If an event is still pending send it to the main thread.
795*5e7646d2SAndroid Build Coastguard Worker   */
796*5e7646d2SAndroid Build Coastguard Worker 
797*5e7646d2SAndroid Build Coastguard Worker   if (threadData->sysevent.event)
798*5e7646d2SAndroid Build Coastguard Worker   {
799*5e7646d2SAndroid Build Coastguard Worker     write(SysEventPipes[1], &threadData->sysevent,
800*5e7646d2SAndroid Build Coastguard Worker           sizeof(threadData->sysevent));
801*5e7646d2SAndroid Build Coastguard Worker     threadData->sysevent.event = 0;
802*5e7646d2SAndroid Build Coastguard Worker   }
803*5e7646d2SAndroid Build Coastguard Worker }
804*5e7646d2SAndroid Build Coastguard Worker 
805*5e7646d2SAndroid Build Coastguard Worker 
806*5e7646d2SAndroid Build Coastguard Worker /*
807*5e7646d2SAndroid Build Coastguard Worker  * 'sysUpdate()' - Update the current system state.
808*5e7646d2SAndroid Build Coastguard Worker  */
809*5e7646d2SAndroid Build Coastguard Worker 
810*5e7646d2SAndroid Build Coastguard Worker static void
sysUpdate(void)811*5e7646d2SAndroid Build Coastguard Worker sysUpdate(void)
812*5e7646d2SAndroid Build Coastguard Worker {
813*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
814*5e7646d2SAndroid Build Coastguard Worker   cupsd_sysevent_t	sysevent;	/* The system event */
815*5e7646d2SAndroid Build Coastguard Worker   cupsd_printer_t	*p;		/* Printer information */
816*5e7646d2SAndroid Build Coastguard Worker 
817*5e7646d2SAndroid Build Coastguard Worker 
818*5e7646d2SAndroid Build Coastguard Worker  /*
819*5e7646d2SAndroid Build Coastguard Worker   * Drain the event pipe...
820*5e7646d2SAndroid Build Coastguard Worker   */
821*5e7646d2SAndroid Build Coastguard Worker 
822*5e7646d2SAndroid Build Coastguard Worker   while (read((int)SysEventPipes[0], &sysevent, sizeof(sysevent))
823*5e7646d2SAndroid Build Coastguard Worker              == sizeof(sysevent))
824*5e7646d2SAndroid Build Coastguard Worker   {
825*5e7646d2SAndroid Build Coastguard Worker     if (sysevent.event & SYSEVENT_CANSLEEP)
826*5e7646d2SAndroid Build Coastguard Worker     {
827*5e7646d2SAndroid Build Coastguard Worker      /*
828*5e7646d2SAndroid Build Coastguard Worker       * If there are active printers that don't have the connecting-to-device
829*5e7646d2SAndroid Build Coastguard Worker       * or cups-waiting-for-job-completed printer-state-reason then cancel the
830*5e7646d2SAndroid Build Coastguard Worker       * sleep request, i.e., these reasons indicate a job that is not actively
831*5e7646d2SAndroid Build Coastguard Worker       * doing anything...
832*5e7646d2SAndroid Build Coastguard Worker       */
833*5e7646d2SAndroid Build Coastguard Worker 
834*5e7646d2SAndroid Build Coastguard Worker       for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
835*5e7646d2SAndroid Build Coastguard Worker            p;
836*5e7646d2SAndroid Build Coastguard Worker 	   p = (cupsd_printer_t *)cupsArrayNext(Printers))
837*5e7646d2SAndroid Build Coastguard Worker       {
838*5e7646d2SAndroid Build Coastguard Worker         if (p->job)
839*5e7646d2SAndroid Build Coastguard Worker         {
840*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < p->num_reasons; i ++)
841*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(p->reasons[i], "connecting-to-device") ||
842*5e7646d2SAndroid Build Coastguard Worker 	        !strcmp(p->reasons[i], "cups-waiting-for-job-completed"))
843*5e7646d2SAndroid Build Coastguard Worker 	      break;
844*5e7646d2SAndroid Build Coastguard Worker 
845*5e7646d2SAndroid Build Coastguard Worker 	  if (!p->num_reasons || i >= p->num_reasons)
846*5e7646d2SAndroid Build Coastguard Worker 	    break;
847*5e7646d2SAndroid Build Coastguard Worker         }
848*5e7646d2SAndroid Build Coastguard Worker       }
849*5e7646d2SAndroid Build Coastguard Worker 
850*5e7646d2SAndroid Build Coastguard Worker       if (p)
851*5e7646d2SAndroid Build Coastguard Worker       {
852*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_INFO,
853*5e7646d2SAndroid Build Coastguard Worker 	                "System sleep canceled because printer %s is active.",
854*5e7646d2SAndroid Build Coastguard Worker 	                p->name);
855*5e7646d2SAndroid Build Coastguard Worker         IOCancelPowerChange(sysevent.powerKernelPort,
856*5e7646d2SAndroid Build Coastguard Worker 	                    sysevent.powerNotificationID);
857*5e7646d2SAndroid Build Coastguard Worker       }
858*5e7646d2SAndroid Build Coastguard Worker       else
859*5e7646d2SAndroid Build Coastguard Worker       {
860*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep.");
861*5e7646d2SAndroid Build Coastguard Worker         IOAllowPowerChange(sysevent.powerKernelPort,
862*5e7646d2SAndroid Build Coastguard Worker 	                   sysevent.powerNotificationID);
863*5e7646d2SAndroid Build Coastguard Worker       }
864*5e7646d2SAndroid Build Coastguard Worker     }
865*5e7646d2SAndroid Build Coastguard Worker 
866*5e7646d2SAndroid Build Coastguard Worker     if (sysevent.event & SYSEVENT_WILLSLEEP)
867*5e7646d2SAndroid Build Coastguard Worker     {
868*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep.");
869*5e7646d2SAndroid Build Coastguard Worker 
870*5e7646d2SAndroid Build Coastguard Worker       Sleeping = 1;
871*5e7646d2SAndroid Build Coastguard Worker 
872*5e7646d2SAndroid Build Coastguard Worker       cupsdCleanDirty();
873*5e7646d2SAndroid Build Coastguard Worker 
874*5e7646d2SAndroid Build Coastguard Worker      /*
875*5e7646d2SAndroid Build Coastguard Worker       * If we have no printing jobs, allow the power change immediately.
876*5e7646d2SAndroid Build Coastguard Worker       * Otherwise set the SleepJobs time to 10 seconds in the future when
877*5e7646d2SAndroid Build Coastguard Worker       * we'll take more drastic measures...
878*5e7646d2SAndroid Build Coastguard Worker       */
879*5e7646d2SAndroid Build Coastguard Worker 
880*5e7646d2SAndroid Build Coastguard Worker       if (cupsArrayCount(PrintingJobs) == 0)
881*5e7646d2SAndroid Build Coastguard Worker       {
882*5e7646d2SAndroid Build Coastguard Worker 	cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
883*5e7646d2SAndroid Build Coastguard Worker 	IOAllowPowerChange(sysevent.powerKernelPort,
884*5e7646d2SAndroid Build Coastguard Worker 			   sysevent.powerNotificationID);
885*5e7646d2SAndroid Build Coastguard Worker       }
886*5e7646d2SAndroid Build Coastguard Worker       else
887*5e7646d2SAndroid Build Coastguard Worker       {
888*5e7646d2SAndroid Build Coastguard Worker        /*
889*5e7646d2SAndroid Build Coastguard Worker 	* If there are active printers that don't have the connecting-to-device
890*5e7646d2SAndroid Build Coastguard Worker 	* or cups-waiting-for-job-completed printer-state-reasons then delay the
891*5e7646d2SAndroid Build Coastguard Worker 	* sleep request, i.e., these reasons indicate a job is active...
892*5e7646d2SAndroid Build Coastguard Worker 	*/
893*5e7646d2SAndroid Build Coastguard Worker 
894*5e7646d2SAndroid Build Coastguard Worker 	for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
895*5e7646d2SAndroid Build Coastguard Worker 	     p;
896*5e7646d2SAndroid Build Coastguard Worker 	     p = (cupsd_printer_t *)cupsArrayNext(Printers))
897*5e7646d2SAndroid Build Coastguard Worker 	{
898*5e7646d2SAndroid Build Coastguard Worker 	  if (p->job)
899*5e7646d2SAndroid Build Coastguard Worker 	  {
900*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < p->num_reasons; i ++)
901*5e7646d2SAndroid Build Coastguard Worker 	      if (!strcmp(p->reasons[i], "connecting-to-device") ||
902*5e7646d2SAndroid Build Coastguard Worker 	          !strcmp(p->reasons[i], "cups-waiting-for-job-completed"))
903*5e7646d2SAndroid Build Coastguard Worker 		break;
904*5e7646d2SAndroid Build Coastguard Worker 
905*5e7646d2SAndroid Build Coastguard Worker 	    if (!p->num_reasons || i >= p->num_reasons)
906*5e7646d2SAndroid Build Coastguard Worker 	      break;
907*5e7646d2SAndroid Build Coastguard Worker 	  }
908*5e7646d2SAndroid Build Coastguard Worker 	}
909*5e7646d2SAndroid Build Coastguard Worker 
910*5e7646d2SAndroid Build Coastguard Worker 	if (p)
911*5e7646d2SAndroid Build Coastguard Worker 	{
912*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_INFO,
913*5e7646d2SAndroid Build Coastguard Worker 			  "System sleep delayed because printer %s is active.",
914*5e7646d2SAndroid Build Coastguard Worker 			  p->name);
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker 	  LastSysEvent = sysevent;
917*5e7646d2SAndroid Build Coastguard Worker 	  SleepJobs    = time(NULL) + 10;
918*5e7646d2SAndroid Build Coastguard Worker 	}
919*5e7646d2SAndroid Build Coastguard Worker 	else
920*5e7646d2SAndroid Build Coastguard Worker 	{
921*5e7646d2SAndroid Build Coastguard Worker 	  cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
922*5e7646d2SAndroid Build Coastguard Worker 	  IOAllowPowerChange(sysevent.powerKernelPort,
923*5e7646d2SAndroid Build Coastguard Worker 			     sysevent.powerNotificationID);
924*5e7646d2SAndroid Build Coastguard Worker 	}
925*5e7646d2SAndroid Build Coastguard Worker       }
926*5e7646d2SAndroid Build Coastguard Worker     }
927*5e7646d2SAndroid Build Coastguard Worker 
928*5e7646d2SAndroid Build Coastguard Worker     if (sysevent.event & SYSEVENT_WOKE)
929*5e7646d2SAndroid Build Coastguard Worker     {
930*5e7646d2SAndroid Build Coastguard Worker       cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep.");
931*5e7646d2SAndroid Build Coastguard Worker       IOAllowPowerChange(sysevent.powerKernelPort,
932*5e7646d2SAndroid Build Coastguard Worker                          sysevent.powerNotificationID);
933*5e7646d2SAndroid Build Coastguard Worker       Sleeping = 0;
934*5e7646d2SAndroid Build Coastguard Worker 
935*5e7646d2SAndroid Build Coastguard Worker      /*
936*5e7646d2SAndroid Build Coastguard Worker       * Make sure jobs that were queued prior to the system going to sleep don't
937*5e7646d2SAndroid Build Coastguard Worker       * get canceled right away...
938*5e7646d2SAndroid Build Coastguard Worker       */
939*5e7646d2SAndroid Build Coastguard Worker 
940*5e7646d2SAndroid Build Coastguard Worker       if (MaxJobTime > 0)
941*5e7646d2SAndroid Build Coastguard Worker       {
942*5e7646d2SAndroid Build Coastguard Worker         cupsd_job_t	*job;		/* Current job */
943*5e7646d2SAndroid Build Coastguard Worker 
944*5e7646d2SAndroid Build Coastguard Worker         for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
945*5e7646d2SAndroid Build Coastguard Worker              job;
946*5e7646d2SAndroid Build Coastguard Worker              job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
947*5e7646d2SAndroid Build Coastguard Worker         {
948*5e7646d2SAndroid Build Coastguard Worker           if (job->cancel_time)
949*5e7646d2SAndroid Build Coastguard Worker           {
950*5e7646d2SAndroid Build Coastguard Worker             ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
951*5e7646d2SAndroid Build Coastguard Worker                                                              "job-cancel-after",
952*5e7646d2SAndroid Build Coastguard Worker                                                              IPP_TAG_INTEGER);
953*5e7646d2SAndroid Build Coastguard Worker 
954*5e7646d2SAndroid Build Coastguard Worker             if (cancel_after)
955*5e7646d2SAndroid Build Coastguard Worker               job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0);
956*5e7646d2SAndroid Build Coastguard Worker             else
957*5e7646d2SAndroid Build Coastguard Worker               job->cancel_time = time(NULL) + MaxJobTime;
958*5e7646d2SAndroid Build Coastguard Worker           }
959*5e7646d2SAndroid Build Coastguard Worker         }
960*5e7646d2SAndroid Build Coastguard Worker       }
961*5e7646d2SAndroid Build Coastguard Worker 
962*5e7646d2SAndroid Build Coastguard Worker       if (NameChanged)
963*5e7646d2SAndroid Build Coastguard Worker         sysUpdateNames();
964*5e7646d2SAndroid Build Coastguard Worker 
965*5e7646d2SAndroid Build Coastguard Worker       cupsdCheckJobs();
966*5e7646d2SAndroid Build Coastguard Worker     }
967*5e7646d2SAndroid Build Coastguard Worker 
968*5e7646d2SAndroid Build Coastguard Worker     if (sysevent.event & SYSEVENT_NETCHANGED)
969*5e7646d2SAndroid Build Coastguard Worker     {
970*5e7646d2SAndroid Build Coastguard Worker       if (Sleeping)
971*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
972*5e7646d2SAndroid Build Coastguard Worker 	                "System network configuration changed - "
973*5e7646d2SAndroid Build Coastguard Worker 			"ignored while sleeping.");
974*5e7646d2SAndroid Build Coastguard Worker       else
975*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
976*5e7646d2SAndroid Build Coastguard Worker 	                "System network configuration changed.");
977*5e7646d2SAndroid Build Coastguard Worker     }
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker     if (sysevent.event & SYSEVENT_NAMECHANGED)
980*5e7646d2SAndroid Build Coastguard Worker     {
981*5e7646d2SAndroid Build Coastguard Worker       if (Sleeping)
982*5e7646d2SAndroid Build Coastguard Worker       {
983*5e7646d2SAndroid Build Coastguard Worker         NameChanged = 1;
984*5e7646d2SAndroid Build Coastguard Worker 
985*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
986*5e7646d2SAndroid Build Coastguard Worker 	                "Computer name or BTMM domains changed - ignored while "
987*5e7646d2SAndroid Build Coastguard Worker 			"sleeping.");
988*5e7646d2SAndroid Build Coastguard Worker       }
989*5e7646d2SAndroid Build Coastguard Worker       else
990*5e7646d2SAndroid Build Coastguard Worker       {
991*5e7646d2SAndroid Build Coastguard Worker         cupsdLogMessage(CUPSD_LOG_DEBUG,
992*5e7646d2SAndroid Build Coastguard Worker 	                "Computer name or BTMM domains changed.");
993*5e7646d2SAndroid Build Coastguard Worker 
994*5e7646d2SAndroid Build Coastguard Worker         sysUpdateNames();
995*5e7646d2SAndroid Build Coastguard Worker       }
996*5e7646d2SAndroid Build Coastguard Worker     }
997*5e7646d2SAndroid Build Coastguard Worker   }
998*5e7646d2SAndroid Build Coastguard Worker }
999*5e7646d2SAndroid Build Coastguard Worker 
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker /*
1002*5e7646d2SAndroid Build Coastguard Worker  * 'sysUpdateNames()' - Update computer and/or BTMM domains.
1003*5e7646d2SAndroid Build Coastguard Worker  */
1004*5e7646d2SAndroid Build Coastguard Worker 
1005*5e7646d2SAndroid Build Coastguard Worker static void
sysUpdateNames(void)1006*5e7646d2SAndroid Build Coastguard Worker sysUpdateNames(void)
1007*5e7646d2SAndroid Build Coastguard Worker {
1008*5e7646d2SAndroid Build Coastguard Worker   cupsd_printer_t	*p;		/* Current printer */
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker 
1011*5e7646d2SAndroid Build Coastguard Worker   NameChanged = 0;
1012*5e7646d2SAndroid Build Coastguard Worker 
1013*5e7646d2SAndroid Build Coastguard Worker  /*
1014*5e7646d2SAndroid Build Coastguard Worker   * De-register the individual printers...
1015*5e7646d2SAndroid Build Coastguard Worker   */
1016*5e7646d2SAndroid Build Coastguard Worker 
1017*5e7646d2SAndroid Build Coastguard Worker   for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
1018*5e7646d2SAndroid Build Coastguard Worker        p;
1019*5e7646d2SAndroid Build Coastguard Worker        p = (cupsd_printer_t *)cupsArrayNext(Printers))
1020*5e7646d2SAndroid Build Coastguard Worker     cupsdDeregisterPrinter(p, 1);
1021*5e7646d2SAndroid Build Coastguard Worker 
1022*5e7646d2SAndroid Build Coastguard Worker #  if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1023*5e7646d2SAndroid Build Coastguard Worker  /*
1024*5e7646d2SAndroid Build Coastguard Worker   * Update the computer name and BTMM domain list...
1025*5e7646d2SAndroid Build Coastguard Worker   */
1026*5e7646d2SAndroid Build Coastguard Worker 
1027*5e7646d2SAndroid Build Coastguard Worker   cupsdUpdateDNSSDName();
1028*5e7646d2SAndroid Build Coastguard Worker #  endif /* HAVE_DNSSD || HAVE_AVAHI */
1029*5e7646d2SAndroid Build Coastguard Worker 
1030*5e7646d2SAndroid Build Coastguard Worker  /*
1031*5e7646d2SAndroid Build Coastguard Worker   * Now re-register them...
1032*5e7646d2SAndroid Build Coastguard Worker   */
1033*5e7646d2SAndroid Build Coastguard Worker 
1034*5e7646d2SAndroid Build Coastguard Worker   for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
1035*5e7646d2SAndroid Build Coastguard Worker        p;
1036*5e7646d2SAndroid Build Coastguard Worker        p = (cupsd_printer_t *)cupsArrayNext(Printers))
1037*5e7646d2SAndroid Build Coastguard Worker     cupsdRegisterPrinter(p);
1038*5e7646d2SAndroid Build Coastguard Worker }
1039*5e7646d2SAndroid Build Coastguard Worker #endif	/* __APPLE__ */
1040