2 * "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $"
4 * System management definitions for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 by Apple Inc.
7 * Copyright 2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * cupsdCleanDirty() - Write dirty config and state files.
18 * cupsdMarkDirty() - Mark config or state files as needing a
20 * cupsdSetBusyState() - Let the system know when we are busy
22 * cupsdAllowSleep() - Tell the OS it is now OK to sleep.
23 * cupsdStartSystemMonitor() - Start monitoring for system change.
24 * cupsdStopSystemMonitor() - Stop monitoring for system change.
25 * sysEventThreadEntry() - A thread to receive power and computer
26 * name change notifications.
27 * sysEventPowerNotifier() - Handle power notification events.
28 * sysEventConfigurationNotifier() - Computer name changed notification
30 * sysEventTimerNotifier() - Handle delayed event notifications.
31 * sysUpdate() - Update the current system state.
36 * Include necessary headers...
40 #ifdef HAVE_VPROC_TRANSACTION_BEGIN
42 #endif /* HAVE_VPROC_TRANSACTION_BEGIN */
46 * The system management functions cover disk and power management which
47 * are primarily used on portable computers.
49 * Disk management involves delaying the write of certain configuration
50 * and state files to minimize the number of times the disk has to spin
53 * Power management support is currently only implemented on MacOS X, but
54 * essentially we use four functions to let the OS know when it is OK to
55 * put the system to idle sleep, typically when we are not in the middle of
58 * Once put to sleep, we invalidate all remote printers since it is common
59 * to wake up in a new location/on a new wireless network.
64 * 'cupsdCleanDirty()' - Write dirty config and state files.
70 if (DirtyFiles
& CUPSD_DIRTY_PRINTERS
)
71 cupsdSaveAllPrinters();
73 if (DirtyFiles
& CUPSD_DIRTY_CLASSES
)
74 cupsdSaveAllClasses();
76 if (DirtyFiles
& CUPSD_DIRTY_REMOTE
)
77 cupsdSaveRemoteCache();
79 if (DirtyFiles
& CUPSD_DIRTY_PRINTCAP
)
82 if (DirtyFiles
& CUPSD_DIRTY_JOBS
)
84 cupsd_job_t
*job
; /* Current job */
88 for (job
= (cupsd_job_t
*)cupsArrayFirst(Jobs
);
90 job
= (cupsd_job_t
*)cupsArrayNext(Jobs
))
95 if (DirtyFiles
& CUPSD_DIRTY_SUBSCRIPTIONS
)
96 cupsdSaveAllSubscriptions();
98 DirtyFiles
= CUPSD_DIRTY_NONE
;
106 * 'cupsdMarkDirty()' - Mark config or state files as needing a write.
110 cupsdMarkDirty(int what
) /* I - What file(s) are dirty? */
112 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdMarkDirty(%c%c%c%c%c%c)",
113 (what
& CUPSD_DIRTY_PRINTERS
) ? 'P' : '-',
114 (what
& CUPSD_DIRTY_CLASSES
) ? 'C' : '-',
115 (what
& CUPSD_DIRTY_REMOTE
) ? 'R' : '-',
116 (what
& CUPSD_DIRTY_PRINTCAP
) ? 'p' : '-',
117 (what
& CUPSD_DIRTY_JOBS
) ? 'J' : '-',
118 (what
& CUPSD_DIRTY_SUBSCRIPTIONS
) ? 'S' : '-');
120 if (what
== CUPSD_DIRTY_PRINTCAP
&& !Printcap
)
126 DirtyCleanTime
= time(NULL
) + DirtyCleanInterval
;
133 * 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
137 cupsdSetBusyState(void)
139 int newbusy
; /* New busy state */
140 static int busy
= 0; /* Current busy state */
141 static const char * const busy_text
[] =
142 { /* Text for busy states */
146 "Printing jobs and dirty files",
148 "Active clients and dirty files",
149 "Active clients and printing jobs",
150 "Active clients, printing jobs, and dirty files"
152 #ifdef HAVE_VPROC_TRANSACTION_BEGIN
153 static vproc_transaction_t vtran
= 0; /* Current busy transaction */
154 #endif /* HAVE_VPROC_TRANSACTION_BEGIN */
157 newbusy
= (DirtyCleanTime
? 1 : 0) |
158 (cupsArrayCount(PrintingJobs
) ? 2 : 0) |
159 (cupsArrayCount(ActiveClients
) ? 4 : 0);
165 #ifdef HAVE_VPROC_TRANSACTION_BEGIN
167 vtran
= vproc_transaction_begin(NULL
);
168 else if (!busy
&& vtran
)
170 vproc_transaction_end(NULL
, vtran
);
173 #endif /* HAVE_VPROC_TRANSACTION_BEGIN */
175 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdSetBusyState: %s", busy_text
[busy
]);
182 * This is the Apple-specific system event code. It works by creating
183 * a worker thread that waits for events from the OS and relays them
184 * to the main thread via a traditional pipe.
188 * Include MacOS-specific headers...
191 # include <IOKit/IOKitLib.h>
192 # include <IOKit/IOMessage.h>
193 # include <IOKit/pwr_mgt/IOPMLib.h>
194 # include <SystemConfiguration/SystemConfiguration.h>
195 # include <pthread.h>
202 # define SYSEVENT_CANSLEEP 0x1 /* Decide whether to allow sleep or not */
203 # define SYSEVENT_WILLSLEEP 0x2 /* Computer will go to sleep */
204 # define SYSEVENT_WOKE 0x4 /* Computer woke from sleep */
205 # define SYSEVENT_NETCHANGED 0x8 /* Network changed */
206 # define SYSEVENT_NAMECHANGED 0x10 /* Computer name changed */
213 typedef struct cupsd_sysevent_s
/*** System event data ****/
215 unsigned char event
; /* Event bit field */
216 io_connect_t powerKernelPort
; /* Power context data */
217 long powerNotificationID
; /* Power event data */
221 typedef struct cupsd_thread_data_s
/*** Thread context data ****/
223 cupsd_sysevent_t sysevent
; /* System event */
224 CFRunLoopTimerRef timerRef
; /* Timer to delay some change *
226 } cupsd_thread_data_t
;
233 static pthread_t SysEventThread
= NULL
;
234 /* Thread to host a runloop */
235 static pthread_mutex_t SysEventThreadMutex
= { 0 };
236 /* Coordinates access to shared gloabals */
237 static pthread_cond_t SysEventThreadCond
= { 0 };
238 /* Thread initialization complete condition */
239 static CFRunLoopRef SysEventRunloop
= NULL
;
240 /* The runloop. Access must be protected! */
241 static CFStringRef ComputerNameKey
= NULL
,
242 /* Computer name key */
243 BTMMKey
= NULL
, /* Back to My Mac key */
244 NetworkGlobalKeyIPv4
= NULL
,
245 /* Network global IPv4 key */
246 NetworkGlobalKeyIPv6
= NULL
,
247 /* Network global IPv6 key */
248 NetworkGlobalKeyDNS
= NULL
,
249 /* Network global DNS key */
252 NetworkInterfaceKeyIPv4
= NULL
,
253 /* Netowrk interface key */
254 NetworkInterfaceKeyIPv6
= NULL
;
255 /* Netowrk interface key */
256 static cupsd_sysevent_t LastSysEvent
; /* Last system event (for delayed sleep) */
263 static void *sysEventThreadEntry(void);
264 static void sysEventPowerNotifier(void *context
, io_service_t service
,
265 natural_t messageType
,
266 void *messageArgument
);
267 static void sysEventConfigurationNotifier(SCDynamicStoreRef store
,
268 CFArrayRef changedKeys
,
270 static void sysEventTimerNotifier(CFRunLoopTimerRef timer
, void *context
);
271 static void sysUpdate(void);
275 * 'cupsdAllowSleep()' - Tell the OS it is now OK to sleep.
279 cupsdAllowSleep(void)
283 IOAllowPowerChange(LastSysEvent
.powerKernelPort
,
284 LastSysEvent
.powerNotificationID
);
289 * 'cupsdStartSystemMonitor()' - Start monitoring for system change.
293 cupsdStartSystemMonitor(void)
295 int flags
; /* fcntl flags on pipe */
298 if (cupsdOpenPipe(SysEventPipes
))
300 cupsdLogMessage(CUPSD_LOG_ERROR
, "System event monitor pipe() failed - %s!",
305 cupsdAddSelect(SysEventPipes
[0], (cupsd_selfunc_t
)sysUpdate
, NULL
, NULL
);
308 * Set non-blocking mode on the descriptor we will be receiving notification
312 flags
= fcntl(SysEventPipes
[0], F_GETFL
, 0);
313 fcntl(SysEventPipes
[0], F_SETFL
, flags
| O_NONBLOCK
);
316 * Start the thread that runs the runloop...
319 pthread_mutex_init(&SysEventThreadMutex
, NULL
);
320 pthread_cond_init(&SysEventThreadCond
, NULL
);
321 pthread_create(&SysEventThread
, NULL
, (void *(*)())sysEventThreadEntry
, NULL
);
326 * 'cupsdStopSystemMonitor()' - Stop monitoring for system change.
330 cupsdStopSystemMonitor(void)
332 CFRunLoopRef rl
; /* The event handler runloop */
338 * Make sure the thread has completed it's initialization and
339 * stored it's runloop reference in the shared global.
342 pthread_mutex_lock(&SysEventThreadMutex
);
344 if (!SysEventRunloop
)
345 pthread_cond_wait(&SysEventThreadCond
, &SysEventThreadMutex
);
347 rl
= SysEventRunloop
;
348 SysEventRunloop
= NULL
;
350 pthread_mutex_unlock(&SysEventThreadMutex
);
355 pthread_join(SysEventThread
, NULL
);
356 pthread_mutex_destroy(&SysEventThreadMutex
);
357 pthread_cond_destroy(&SysEventThreadCond
);
360 if (SysEventPipes
[0] >= 0)
362 cupsdRemoveSelect(SysEventPipes
[0]);
363 cupsdClosePipe(SysEventPipes
);
369 * 'sysEventThreadEntry()' - A thread to receive power and computer name
370 * change notifications.
373 static void * /* O - Return status/value */
374 sysEventThreadEntry(void)
376 io_object_t powerNotifierObj
;
377 /* Power notifier object */
378 IONotificationPortRef powerNotifierPort
;
379 /* Power notifier port */
380 SCDynamicStoreRef store
= NULL
;/* System Config dynamic store */
381 CFRunLoopSourceRef powerRLS
= NULL
,/* Power runloop source */
382 storeRLS
= NULL
;/* System Config runloop source */
383 CFStringRef key
[6], /* System Config keys */
384 pattern
[2]; /* System Config patterns */
385 CFArrayRef keys
= NULL
, /* System Config key array*/
386 patterns
= NULL
;/* System Config pattern array */
387 SCDynamicStoreContext storeContext
; /* Dynamic store context */
388 CFRunLoopTimerContext timerContext
; /* Timer context */
389 cupsd_thread_data_t threadData
; /* Thread context data for the *
390 * runloop notifiers */
394 * Register for power state change notifications
397 bzero(&threadData
, sizeof(threadData
));
399 threadData
.sysevent
.powerKernelPort
=
400 IORegisterForSystemPower(&threadData
, &powerNotifierPort
,
401 sysEventPowerNotifier
, &powerNotifierObj
);
403 if (threadData
.sysevent
.powerKernelPort
)
405 powerRLS
= IONotificationPortGetRunLoopSource(powerNotifierPort
);
406 CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS
, kCFRunLoopDefaultMode
);
409 DEBUG_puts("sysEventThreadEntry: error registering for system power "
413 * Register for system configuration change notifications
416 bzero(&storeContext
, sizeof(storeContext
));
417 storeContext
.info
= &threadData
;
419 store
= SCDynamicStoreCreate(kCFAllocatorDefault
, CFSTR("cupsd"),
420 sysEventConfigurationNotifier
, &storeContext
);
422 if (!ComputerNameKey
)
423 ComputerNameKey
= SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault
);
426 BTMMKey
= SCDynamicStoreKeyCreate(kCFAllocatorDefault
,
427 CFSTR("Setup:/Network/BackToMyMac"));
429 if (!NetworkGlobalKeyIPv4
)
430 NetworkGlobalKeyIPv4
=
431 SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault
,
432 kSCDynamicStoreDomainState
,
435 if (!NetworkGlobalKeyIPv6
)
436 NetworkGlobalKeyIPv6
=
437 SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault
,
438 kSCDynamicStoreDomainState
,
441 if (!NetworkGlobalKeyDNS
)
442 NetworkGlobalKeyDNS
=
443 SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault
,
444 kSCDynamicStoreDomainState
,
448 HostNamesKey
= SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault
);
450 if (!NetworkInterfaceKeyIPv4
)
451 NetworkInterfaceKeyIPv4
=
452 SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault
,
453 kSCDynamicStoreDomainState
,
457 if (!NetworkInterfaceKeyIPv6
)
458 NetworkInterfaceKeyIPv6
=
459 SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault
,
460 kSCDynamicStoreDomainState
,
464 if (store
&& ComputerNameKey
&& HostNamesKey
&&
465 NetworkGlobalKeyIPv4
&& NetworkGlobalKeyIPv6
&& NetworkGlobalKeyDNS
&&
466 NetworkInterfaceKeyIPv4
&& NetworkInterfaceKeyIPv6
)
468 key
[0] = ComputerNameKey
;
470 key
[2] = NetworkGlobalKeyIPv4
;
471 key
[3] = NetworkGlobalKeyIPv6
;
472 key
[4] = NetworkGlobalKeyDNS
;
473 key
[5] = HostNamesKey
;
475 pattern
[0] = NetworkInterfaceKeyIPv4
;
476 pattern
[1] = NetworkInterfaceKeyIPv6
;
478 keys
= CFArrayCreate(kCFAllocatorDefault
, (const void **)key
,
479 sizeof(key
) / sizeof(key
[0]),
480 &kCFTypeArrayCallBacks
);
482 patterns
= CFArrayCreate(kCFAllocatorDefault
, (const void **)pattern
,
483 sizeof(pattern
) / sizeof(pattern
[0]),
484 &kCFTypeArrayCallBacks
);
486 if (keys
&& patterns
&&
487 SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
))
489 if ((storeRLS
= SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault
,
492 CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS
,
493 kCFRunLoopDefaultMode
);
496 DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreateRunLoopSource "
497 "failed: %s\n", SCErrorString(SCError())));
500 DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreSetNotificationKeys "
501 "failed: %s\n", SCErrorString(SCError())));
504 DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreate failed: %s\n",
505 SCErrorString(SCError())));
514 * Set up a timer to delay the wake change notifications.
516 * The initial time is set a decade or so into the future, we'll adjust
520 bzero(&timerContext
, sizeof(timerContext
));
521 timerContext
.info
= &threadData
;
523 threadData
.timerRef
=
524 CFRunLoopTimerCreate(kCFAllocatorDefault
,
525 CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
526 86400L * 365L * 10L, 0, 0, sysEventTimerNotifier
,
528 CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData
.timerRef
,
529 kCFRunLoopDefaultMode
);
532 * Store our runloop in a global so the main thread can use it to stop us.
535 pthread_mutex_lock(&SysEventThreadMutex
);
537 SysEventRunloop
= CFRunLoopGetCurrent();
539 pthread_cond_signal(&SysEventThreadCond
);
540 pthread_mutex_unlock(&SysEventThreadMutex
);
543 * Disappear into the runloop until it's stopped by the main thread.
549 * Clean up before exiting.
552 if (threadData
.timerRef
)
554 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData
.timerRef
,
555 kCFRunLoopDefaultMode
);
556 CFRelease(threadData
.timerRef
);
559 if (threadData
.sysevent
.powerKernelPort
)
561 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS
,
562 kCFRunLoopDefaultMode
);
563 IODeregisterForSystemPower(&powerNotifierObj
);
564 IOServiceClose(threadData
.sysevent
.powerKernelPort
);
565 IONotificationPortDestroy(powerNotifierPort
);
570 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS
,
571 kCFRunLoopDefaultMode
);
572 CFRunLoopSourceInvalidate(storeRLS
);
584 * 'sysEventPowerNotifier()' - Handle power notification events.
588 sysEventPowerNotifier(
589 void *context
, /* I - Thread context data */
590 io_service_t service
, /* I - Unused service info */
591 natural_t messageType
, /* I - Type of message */
592 void *messageArgument
) /* I - Message data */
594 int sendit
= 1; /* Send event to main thread? *
595 * (0 = no, 1 = yes, 2 = delayed */
596 cupsd_thread_data_t
*threadData
; /* Thread context data */
599 threadData
= (cupsd_thread_data_t
*)context
;
601 (void)service
; /* anti-compiler-warning-code */
605 case kIOMessageCanSystemPowerOff
:
606 case kIOMessageCanSystemSleep
:
607 threadData
->sysevent
.event
|= SYSEVENT_CANSLEEP
;
610 case kIOMessageSystemWillRestart
:
611 case kIOMessageSystemWillPowerOff
:
612 case kIOMessageSystemWillSleep
:
613 threadData
->sysevent
.event
|= SYSEVENT_WILLSLEEP
;
616 case kIOMessageSystemHasPoweredOn
:
618 * Because powered on is followed by a net-changed event, delay
623 threadData
->sysevent
.event
|= SYSEVENT_WOKE
;
626 case kIOMessageSystemWillNotPowerOff
:
627 case kIOMessageSystemWillNotSleep
:
628 # ifdef kIOMessageSystemWillPowerOn
629 case kIOMessageSystemWillPowerOn
:
630 # endif /* kIOMessageSystemWillPowerOn */
637 IOAllowPowerChange(threadData
->sysevent
.powerKernelPort
,
638 (long)messageArgument
);
641 threadData
->sysevent
.powerNotificationID
= (long)messageArgument
;
646 * Send the event to the main thread now.
649 write(SysEventPipes
[1], &threadData
->sysevent
,
650 sizeof(threadData
->sysevent
));
651 threadData
->sysevent
.event
= 0;
656 * Send the event to the main thread after 1 to 2 seconds.
659 CFRunLoopTimerSetNextFireDate(threadData
->timerRef
,
660 CFAbsoluteTimeGetCurrent() + 2);
667 * 'sysEventConfigurationNotifier()' - Network configuration change notification
672 sysEventConfigurationNotifier(
673 SCDynamicStoreRef store
, /* I - System data (unused) */
674 CFArrayRef changedKeys
, /* I - Changed data */
675 void *context
) /* I - Thread context data */
677 cupsd_thread_data_t
*threadData
; /* Thread context data */
680 threadData
= (cupsd_thread_data_t
*)context
;
682 (void)store
; /* anti-compiler-warning-code */
684 CFRange range
= CFRangeMake(0, CFArrayGetCount(changedKeys
));
686 if (CFArrayContainsValue(changedKeys
, range
, ComputerNameKey
) ||
687 CFArrayContainsValue(changedKeys
, range
, BTMMKey
))
688 threadData
->sysevent
.event
|= SYSEVENT_NAMECHANGED
;
691 threadData
->sysevent
.event
|= SYSEVENT_NETCHANGED
;
694 * Indicate the network interface list needs updating...
701 * Because we registered for several different kinds of change notifications
702 * this callback usually gets called several times in a row. We use a timer to
703 * de-bounce these so we only end up generating one event for the main thread.
706 CFRunLoopTimerSetNextFireDate(threadData
->timerRef
,
707 CFAbsoluteTimeGetCurrent() + 5);
712 * 'sysEventTimerNotifier()' - Handle delayed event notifications.
716 sysEventTimerNotifier(
717 CFRunLoopTimerRef timer
, /* I - Timer information */
718 void *context
) /* I - Thread context data */
720 cupsd_thread_data_t
*threadData
; /* Thread context data */
723 threadData
= (cupsd_thread_data_t
*)context
;
726 * If an event is still pending send it to the main thread.
729 if (threadData
->sysevent
.event
)
731 write(SysEventPipes
[1], &threadData
->sysevent
,
732 sizeof(threadData
->sysevent
));
733 threadData
->sysevent
.event
= 0;
739 * 'sysUpdate()' - Update the current system state.
745 int i
; /* Looping var */
746 cupsd_sysevent_t sysevent
; /* The system event */
747 cupsd_printer_t
*p
; /* Printer information */
751 * Drain the event pipe...
754 while (read((int)SysEventPipes
[0], &sysevent
, sizeof(sysevent
))
757 if (sysevent
.event
& SYSEVENT_CANSLEEP
)
760 * If there are active printers that don't have the connecting-to-device
761 * printer-state-reason then cancel the sleep request (i.e. this reason
762 * indicates a job that is not yet connected to the printer)...
765 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
767 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
771 for (i
= 0; i
< p
->num_reasons
; i
++)
772 if (!strcmp(p
->reasons
[i
], "connecting-to-device"))
775 if (!p
->num_reasons
|| i
>= p
->num_reasons
)
782 cupsdLogMessage(CUPSD_LOG_INFO
,
783 "System sleep canceled because printer %s is active",
785 IOCancelPowerChange(sysevent
.powerKernelPort
,
786 sysevent
.powerNotificationID
);
790 cupsdLogMessage(CUPSD_LOG_DEBUG
, "System wants to sleep");
791 IOAllowPowerChange(sysevent
.powerKernelPort
,
792 sysevent
.powerNotificationID
);
796 if (sysevent
.event
& SYSEVENT_WILLSLEEP
)
798 cupsdLogMessage(CUPSD_LOG_DEBUG
, "System going to sleep");
802 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
804 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
806 if (p
->type
& CUPS_PRINTER_DISCOVERED
)
808 cupsdLogMessage(CUPSD_LOG_DEBUG
,
809 "Deleting remote destination \"%s\"", p
->name
);
810 cupsArraySave(Printers
);
811 cupsdDeletePrinter(p
, 0);
812 cupsArrayRestore(Printers
);
816 cupsdLogMessage(CUPSD_LOG_DEBUG
,
817 "Deregistering local printer \"%s\"", p
->name
);
818 cupsdDeregisterPrinter(p
, 0);
825 * If we have no printing jobs, allow the power change immediately.
826 * Otherwise set the SleepJobs time to 15 seconds in the future when
827 * we'll take more drastic measures...
830 if (cupsArrayCount(PrintingJobs
) == 0)
831 IOAllowPowerChange(sysevent
.powerKernelPort
,
832 sysevent
.powerNotificationID
);
835 LastSysEvent
= sysevent
;
836 SleepJobs
= time(NULL
) + 15;
840 if (sysevent
.event
& SYSEVENT_WOKE
)
842 cupsdLogMessage(CUPSD_LOG_DEBUG
, "System woke from sleep");
843 IOAllowPowerChange(sysevent
.powerKernelPort
,
844 sysevent
.powerNotificationID
);
849 if (sysevent
.event
& SYSEVENT_NETCHANGED
)
853 cupsdLogMessage(CUPSD_LOG_DEBUG
,
854 "System network configuration changed");
857 * Resetting browse_time before calling cupsdSendBrowseList causes
858 * browse packets to be sent for local shared printers.
861 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
863 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
866 cupsdSendBrowseList();
867 cupsdRestartPolling();
870 cupsdLogMessage(CUPSD_LOG_DEBUG
,
871 "System network configuration changed; "
872 "ignored while sleeping");
875 if (sysevent
.event
& SYSEVENT_NAMECHANGED
)
879 cupsdLogMessage(CUPSD_LOG_DEBUG
,
880 "Computer name or BTMM domains changed");
883 * De-register the individual printers...
886 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
888 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
889 cupsdDeregisterPrinter(p
, 1);
892 * Update the computer name and BTMM domain list...
895 cupsdUpdateDNSSDName();
898 * Now re-register them...
901 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
903 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
906 cupsdRegisterPrinter(p
);
910 cupsdLogMessage(CUPSD_LOG_DEBUG
,
911 "Computer name or BTMM domains changed; ignored while "
916 #endif /* __APPLE__ */
920 * End of "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $".