|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* System management functions for the CUPS scheduler.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Copyright 2007-2017 by Apple Inc.
|
|
Packit |
2fc92b |
* Copyright 2006 by Easy Software Products.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* These coded instructions, statements, and computer programs are the
|
|
Packit |
2fc92b |
* property of Apple Inc. and are protected by Federal copyright
|
|
Packit |
2fc92b |
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
|
|
Packit |
2fc92b |
* which should have been included with this file. If this file is
|
|
Packit |
2fc92b |
* missing or damaged, see the license at "http://www.cups.org/".
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Include necessary headers...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#include "cupsd.h"
|
|
Packit |
2fc92b |
#ifdef __APPLE__
|
|
Packit |
2fc92b |
# include <xpc/xpc.h>
|
|
Packit |
2fc92b |
# include <IOKit/pwr_mgt/IOPMLib.h>
|
|
Packit |
2fc92b |
#endif /* __APPLE__ */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* The system management functions cover disk and power management which
|
|
Packit |
2fc92b |
* are primarily used for portable computers.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Disk management involves delaying the write of certain configuration
|
|
Packit |
2fc92b |
* and state files to minimize the number of times the disk has to spin
|
|
Packit |
2fc92b |
* up or flash to be written to.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Power management support is currently only implemented on macOS, but
|
|
Packit |
2fc92b |
* essentially we use four functions to let the OS know when it is OK to
|
|
Packit |
2fc92b |
* put the system to sleep, typically when we are not in the middle of
|
|
Packit |
2fc92b |
* printing a job. And on macOS we can also "sleep print" - basically the
|
|
Packit |
2fc92b |
* system only wakes up long enough to service network requests and process
|
|
Packit |
2fc92b |
* print jobs.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdCleanDirty()' - Write dirty config and state files.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdCleanDirty(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (DirtyFiles & CUPSD_DIRTY_PRINTERS)
|
|
Packit |
2fc92b |
cupsdSaveAllPrinters();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (DirtyFiles & CUPSD_DIRTY_CLASSES)
|
|
Packit |
2fc92b |
cupsdSaveAllClasses();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (DirtyFiles & CUPSD_DIRTY_PRINTCAP)
|
|
Packit |
2fc92b |
cupsdWritePrintcap();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (DirtyFiles & CUPSD_DIRTY_JOBS)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_job_t *job; /* Current job */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdSaveAllJobs();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
|
|
Packit |
2fc92b |
job;
|
|
Packit |
2fc92b |
job = (cupsd_job_t *)cupsArrayNext(Jobs))
|
|
Packit |
2fc92b |
if (job->dirty)
|
|
Packit |
2fc92b |
cupsdSaveJob(job);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (DirtyFiles & CUPSD_DIRTY_SUBSCRIPTIONS)
|
|
Packit |
2fc92b |
cupsdSaveAllSubscriptions();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DirtyFiles = CUPSD_DIRTY_NONE;
|
|
Packit |
2fc92b |
DirtyCleanTime = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdSetBusyState(0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdMarkDirty()' - Mark config or state files as needing a write.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdMarkDirty(int what) /* I - What file(s) are dirty? */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c)",
|
|
Packit |
2fc92b |
(what & CUPSD_DIRTY_PRINTERS) ? 'P' : '-',
|
|
Packit |
2fc92b |
(what & CUPSD_DIRTY_CLASSES) ? 'C' : '-',
|
|
Packit |
2fc92b |
(what & CUPSD_DIRTY_PRINTCAP) ? 'p' : '-',
|
|
Packit |
2fc92b |
(what & CUPSD_DIRTY_JOBS) ? 'J' : '-',
|
|
Packit |
2fc92b |
(what & CUPSD_DIRTY_SUBSCRIPTIONS) ? 'S' : '-');
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (what == CUPSD_DIRTY_PRINTCAP && !Printcap)
|
|
Packit |
2fc92b |
return;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DirtyFiles |= what;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!DirtyCleanTime)
|
|
Packit |
2fc92b |
DirtyCleanTime = time(NULL) + DirtyCleanInterval;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdSetBusyState(0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdSetBusyState(int working) /* I - Doing significant work? */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int i; /* Looping var */
|
|
Packit |
2fc92b |
cupsd_job_t *job; /* Current job */
|
|
Packit |
2fc92b |
cupsd_printer_t *p; /* Current printer */
|
|
Packit |
2fc92b |
int newbusy; /* New busy state */
|
|
Packit |
2fc92b |
static int busy = 0; /* Current busy state */
|
|
Packit |
2fc92b |
static const char * const busy_text[] =
|
|
Packit |
2fc92b |
{ /* Text for busy states */
|
|
Packit |
2fc92b |
"Not busy",
|
|
Packit |
2fc92b |
"Dirty files",
|
|
Packit |
2fc92b |
"Printing jobs",
|
|
Packit |
2fc92b |
"Printing jobs and dirty files",
|
|
Packit |
2fc92b |
"Active clients",
|
|
Packit |
2fc92b |
"Active clients and dirty files",
|
|
Packit |
2fc92b |
"Active clients and printing jobs",
|
|
Packit |
2fc92b |
"Active clients, printing jobs, and dirty files"
|
|
Packit |
2fc92b |
};
|
|
Packit |
2fc92b |
#ifdef __APPLE__
|
|
Packit |
2fc92b |
static int tran = 0; /* Current busy transaction */
|
|
Packit |
2fc92b |
static IOPMAssertionID keep_awake = 0;/* Keep the system awake while printing */
|
|
Packit |
2fc92b |
#endif /* __APPLE__ */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Figure out how busy we are...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
newbusy = (DirtyCleanTime ? 1 : 0) |
|
|
Packit |
2fc92b |
((working || cupsArrayCount(ActiveClients) > 0) ? 4 : 0);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (job = (cupsd_job_t *)cupsArrayFirst(PrintingJobs);
|
|
Packit |
2fc92b |
job;
|
|
Packit |
2fc92b |
job = (cupsd_job_t *)cupsArrayNext(PrintingJobs))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if ((p = job->printer) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
for (i = 0; i < p->num_reasons; i ++)
|
|
Packit |
2fc92b |
if (!strcmp(p->reasons[i], "connecting-to-device"))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!p->num_reasons || i >= p->num_reasons)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (job)
|
|
Packit |
2fc92b |
newbusy |= 2;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"cupsdSetBusyState: newbusy=\"%s\", busy=\"%s\"",
|
|
Packit |
2fc92b |
busy_text[newbusy], busy_text[busy]);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Manage state changes...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (newbusy != busy)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
busy = newbusy;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#ifdef __APPLE__
|
|
Packit |
2fc92b |
if (busy && !tran)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
xpc_transaction_begin();
|
|
Packit |
2fc92b |
tran = 1;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (!busy && tran)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
xpc_transaction_end();
|
|
Packit |
2fc92b |
tran = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
#endif /* __APPLE__ */
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#ifdef __APPLE__
|
|
Packit |
2fc92b |
if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting NetworkClientActive.");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
IOPMAssertionCreateWithName(kIOPMAssertNetworkClientActive,
|
|
Packit |
2fc92b |
kIOPMAssertionLevelOn,
|
|
Packit |
2fc92b |
CFSTR("org.cups.cupsd"), &keep_awake);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (cupsArrayCount(PrintingJobs) == 0 && keep_awake)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing power assertion.");
|
|
Packit |
2fc92b |
IOPMAssertionRelease(keep_awake);
|
|
Packit |
2fc92b |
keep_awake = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
#endif /* __APPLE__ */
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#ifdef __APPLE__
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* This is the Apple-specific system event code. It works by creating
|
|
Packit |
2fc92b |
* a worker thread that waits for events from the OS and relays them
|
|
Packit |
2fc92b |
* to the main thread via a traditional pipe.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Include MacOS-specific headers...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
# include <notify.h>
|
|
Packit |
2fc92b |
# include <IOKit/IOKitLib.h>
|
|
Packit |
2fc92b |
# include <IOKit/IOMessage.h>
|
|
Packit |
2fc92b |
# include <IOKit/ps/IOPowerSources.h>
|
|
Packit |
2fc92b |
# include <IOKit/pwr_mgt/IOPMLib.h>
|
|
Packit |
2fc92b |
# include <SystemConfiguration/SystemConfiguration.h>
|
|
Packit |
2fc92b |
# include <pthread.h>
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Constants...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
# define SYSEVENT_CANSLEEP 0x1 /* Decide whether to allow sleep or not */
|
|
Packit |
2fc92b |
# define SYSEVENT_WILLSLEEP 0x2 /* Computer will go to sleep */
|
|
Packit |
2fc92b |
# define SYSEVENT_WOKE 0x4 /* Computer woke from sleep */
|
|
Packit |
2fc92b |
# define SYSEVENT_NETCHANGED 0x8 /* Network changed */
|
|
Packit |
2fc92b |
# define SYSEVENT_NAMECHANGED 0x10 /* Computer name changed */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Structures...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
typedef struct cupsd_sysevent_s /*** System event data ****/
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
unsigned char event; /* Event bit field */
|
|
Packit |
2fc92b |
io_connect_t powerKernelPort; /* Power context data */
|
|
Packit |
2fc92b |
long powerNotificationID; /* Power event data */
|
|
Packit |
2fc92b |
} cupsd_sysevent_t;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
typedef struct cupsd_thread_data_s /*** Thread context data ****/
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_sysevent_t sysevent; /* System event */
|
|
Packit |
2fc92b |
CFRunLoopTimerRef timerRef; /* Timer to delay some change *
|
|
Packit |
2fc92b |
* notifications */
|
|
Packit |
2fc92b |
} cupsd_thread_data_t;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Local globals...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static pthread_t SysEventThread = NULL;
|
|
Packit |
2fc92b |
/* Thread to host a runloop */
|
|
Packit |
2fc92b |
static pthread_mutex_t SysEventThreadMutex = { 0 };
|
|
Packit |
2fc92b |
/* Coordinates access to shared gloabals */
|
|
Packit |
2fc92b |
static pthread_cond_t SysEventThreadCond = { 0 };
|
|
Packit |
2fc92b |
/* Thread initialization complete condition */
|
|
Packit |
2fc92b |
static CFRunLoopRef SysEventRunloop = NULL;
|
|
Packit |
2fc92b |
/* The runloop. Access must be protected! */
|
|
Packit |
2fc92b |
static CFStringRef ComputerNameKey = NULL,
|
|
Packit |
2fc92b |
/* Computer name key */
|
|
Packit |
2fc92b |
BTMMKey = NULL, /* Back to My Mac key */
|
|
Packit |
2fc92b |
NetworkGlobalKeyIPv4 = NULL,
|
|
Packit |
2fc92b |
/* Network global IPv4 key */
|
|
Packit |
2fc92b |
NetworkGlobalKeyIPv6 = NULL,
|
|
Packit |
2fc92b |
/* Network global IPv6 key */
|
|
Packit |
2fc92b |
NetworkGlobalKeyDNS = NULL,
|
|
Packit |
2fc92b |
/* Network global DNS key */
|
|
Packit |
2fc92b |
HostNamesKey = NULL,
|
|
Packit |
2fc92b |
/* Host name key */
|
|
Packit |
2fc92b |
NetworkInterfaceKeyIPv4 = NULL,
|
|
Packit |
2fc92b |
/* Netowrk interface key */
|
|
Packit |
2fc92b |
NetworkInterfaceKeyIPv6 = NULL;
|
|
Packit |
2fc92b |
/* Netowrk interface key */
|
|
Packit |
2fc92b |
static cupsd_sysevent_t LastSysEvent; /* Last system event (for delayed sleep) */
|
|
Packit |
2fc92b |
static int NameChanged = 0;/* Did we get a 'name changed' event during sleep? */
|
|
Packit |
2fc92b |
static int PSToken = 0; /* Power source notifications */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Local functions...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void *sysEventThreadEntry(void);
|
|
Packit |
2fc92b |
static void sysEventPowerNotifier(void *context, io_service_t service,
|
|
Packit |
2fc92b |
natural_t messageType,
|
|
Packit |
2fc92b |
void *messageArgument);
|
|
Packit |
2fc92b |
static void sysEventConfigurationNotifier(SCDynamicStoreRef store,
|
|
Packit |
2fc92b |
CFArrayRef changedKeys,
|
|
Packit |
2fc92b |
void *context);
|
|
Packit |
2fc92b |
static void sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context);
|
|
Packit |
2fc92b |
static void sysUpdate(void);
|
|
Packit |
2fc92b |
static void sysUpdateNames(void);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdAllowSleep()' - Tell the OS it is now OK to sleep.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdAllowSleep(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdCleanDirty();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
|
|
Packit |
2fc92b |
IOAllowPowerChange(LastSysEvent.powerKernelPort,
|
|
Packit |
2fc92b |
LastSysEvent.powerNotificationID);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdStartSystemMonitor()' - Start monitoring for system change.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdStartSystemMonitor(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int flags; /* fcntl flags on pipe */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor()");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cupsdOpenPipe(SysEventPipes))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_ERROR, "System event monitor pipe() failed - %s!",
|
|
Packit |
2fc92b |
strerror(errno));
|
|
Packit |
2fc92b |
return;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)sysUpdate, NULL, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Set non-blocking mode on the descriptor we will be receiving notification
|
|
Packit |
2fc92b |
* events on.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
flags = fcntl(SysEventPipes[0], F_GETFL, 0);
|
|
Packit |
2fc92b |
fcntl(SysEventPipes[0], F_SETFL, flags | O_NONBLOCK);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Start the thread that runs the runloop...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_mutex_init(&SysEventThreadMutex, NULL);
|
|
Packit |
2fc92b |
pthread_cond_init(&SysEventThreadCond, NULL);
|
|
Packit |
2fc92b |
pthread_create(&SysEventThread, NULL, (void *(*)(void *))sysEventThreadEntry, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Monitor for power source changes via dispatch queue...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor: IOPSGetTimeRemainingEstimate=%f", IOPSGetTimeRemainingEstimate());
|
|
Packit |
2fc92b |
ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited;
|
|
Packit |
2fc92b |
notify_register_dispatch(kIOPSNotifyPowerSource, &PSToken, dispatch_get_main_queue(), ^(int t) { (void)t;
|
|
Packit |
2fc92b |
ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; });
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cupsdStopSystemMonitor()' - Stop monitoring for system change.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
cupsdStopSystemMonitor(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
CFRunLoopRef rl; /* The event handler runloop */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSystemMonitor()");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (SysEventThread)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Make sure the thread has completed it's initialization and
|
|
Packit |
2fc92b |
* stored it's runloop reference in the shared global.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_mutex_lock(&SysEventThreadMutex);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!SysEventRunloop)
|
|
Packit |
2fc92b |
pthread_cond_wait(&SysEventThreadCond, &SysEventThreadMutex);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
rl = SysEventRunloop;
|
|
Packit |
2fc92b |
SysEventRunloop = NULL;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_mutex_unlock(&SysEventThreadMutex);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (rl)
|
|
Packit |
2fc92b |
CFRunLoopStop(rl);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_join(SysEventThread, NULL);
|
|
Packit |
2fc92b |
pthread_mutex_destroy(&SysEventThreadMutex);
|
|
Packit |
2fc92b |
pthread_cond_destroy(&SysEventThreadCond);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (SysEventPipes[0] >= 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdRemoveSelect(SysEventPipes[0]);
|
|
Packit |
2fc92b |
cupsdClosePipe(SysEventPipes);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (PSToken != 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
notify_cancel(PSToken);
|
|
Packit |
2fc92b |
PSToken = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysEventThreadEntry()' - A thread to receive power and computer name
|
|
Packit |
2fc92b |
* change notifications.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void * /* O - Return status/value */
|
|
Packit |
2fc92b |
sysEventThreadEntry(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
io_object_t powerNotifierObj;
|
|
Packit |
2fc92b |
/* Power notifier object */
|
|
Packit |
2fc92b |
IONotificationPortRef powerNotifierPort;
|
|
Packit |
2fc92b |
/* Power notifier port */
|
|
Packit |
2fc92b |
SCDynamicStoreRef store = NULL;/* System Config dynamic store */
|
|
Packit |
2fc92b |
CFRunLoopSourceRef powerRLS = NULL,/* Power runloop source */
|
|
Packit |
2fc92b |
storeRLS = NULL;/* System Config runloop source */
|
|
Packit |
2fc92b |
CFStringRef key[6], /* System Config keys */
|
|
Packit |
2fc92b |
pattern[2]; /* System Config patterns */
|
|
Packit |
2fc92b |
CFArrayRef keys = NULL, /* System Config key array*/
|
|
Packit |
2fc92b |
patterns = NULL;/* System Config pattern array */
|
|
Packit |
2fc92b |
SCDynamicStoreContext storeContext; /* Dynamic store context */
|
|
Packit |
2fc92b |
CFRunLoopTimerContext timerContext; /* Timer context */
|
|
Packit |
2fc92b |
cupsd_thread_data_t threadData; /* Thread context data for the *
|
|
Packit |
2fc92b |
* runloop notifiers */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Register for power state change notifications
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
bzero(&threadData, sizeof(threadData));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
threadData.sysevent.powerKernelPort =
|
|
Packit |
2fc92b |
IORegisterForSystemPower(&threadData, &powerNotifierPort,
|
|
Packit |
2fc92b |
sysEventPowerNotifier, &powerNotifierObj);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (threadData.sysevent.powerKernelPort)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
powerRLS = IONotificationPortGetRunLoopSource(powerNotifierPort);
|
|
Packit |
2fc92b |
CFRunLoopAddSource(CFRunLoopGetCurrent(), powerRLS, kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
DEBUG_puts("sysEventThreadEntry: error registering for system power "
|
|
Packit |
2fc92b |
"notifications");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Register for system configuration change notifications
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
bzero(&storeContext, sizeof(storeContext));
|
|
Packit |
2fc92b |
storeContext.info = &threadData;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"),
|
|
Packit |
2fc92b |
sysEventConfigurationNotifier, &storeContext);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!ComputerNameKey)
|
|
Packit |
2fc92b |
ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!BTMMKey)
|
|
Packit |
2fc92b |
BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
CFSTR("Setup:/Network/BackToMyMac"));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!NetworkGlobalKeyIPv4)
|
|
Packit |
2fc92b |
NetworkGlobalKeyIPv4 =
|
|
Packit |
2fc92b |
SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
kSCDynamicStoreDomainState,
|
|
Packit |
2fc92b |
kSCEntNetIPv4);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!NetworkGlobalKeyIPv6)
|
|
Packit |
2fc92b |
NetworkGlobalKeyIPv6 =
|
|
Packit |
2fc92b |
SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
kSCDynamicStoreDomainState,
|
|
Packit |
2fc92b |
kSCEntNetIPv6);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!NetworkGlobalKeyDNS)
|
|
Packit |
2fc92b |
NetworkGlobalKeyDNS =
|
|
Packit |
2fc92b |
SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
kSCDynamicStoreDomainState,
|
|
Packit |
2fc92b |
kSCEntNetDNS);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!HostNamesKey)
|
|
Packit |
2fc92b |
HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!NetworkInterfaceKeyIPv4)
|
|
Packit |
2fc92b |
NetworkInterfaceKeyIPv4 =
|
|
Packit |
2fc92b |
SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
kSCDynamicStoreDomainState,
|
|
Packit |
2fc92b |
kSCCompAnyRegex,
|
|
Packit |
2fc92b |
kSCEntNetIPv4);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!NetworkInterfaceKeyIPv6)
|
|
Packit |
2fc92b |
NetworkInterfaceKeyIPv6 =
|
|
Packit |
2fc92b |
SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
kSCDynamicStoreDomainState,
|
|
Packit |
2fc92b |
kSCCompAnyRegex,
|
|
Packit |
2fc92b |
kSCEntNetIPv6);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (store && ComputerNameKey && HostNamesKey &&
|
|
Packit |
2fc92b |
NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS &&
|
|
Packit |
2fc92b |
NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
key[0] = ComputerNameKey;
|
|
Packit |
2fc92b |
key[1] = BTMMKey;
|
|
Packit |
2fc92b |
key[2] = NetworkGlobalKeyIPv4;
|
|
Packit |
2fc92b |
key[3] = NetworkGlobalKeyIPv6;
|
|
Packit |
2fc92b |
key[4] = NetworkGlobalKeyDNS;
|
|
Packit |
2fc92b |
key[5] = HostNamesKey;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pattern[0] = NetworkInterfaceKeyIPv4;
|
|
Packit |
2fc92b |
pattern[1] = NetworkInterfaceKeyIPv6;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
keys = CFArrayCreate(kCFAllocatorDefault, (const void **)key,
|
|
Packit |
2fc92b |
sizeof(key) / sizeof(key[0]),
|
|
Packit |
2fc92b |
&kCFTypeArrayCallBacks);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern,
|
|
Packit |
2fc92b |
sizeof(pattern) / sizeof(pattern[0]),
|
|
Packit |
2fc92b |
&kCFTypeArrayCallBacks);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (keys && patterns &&
|
|
Packit |
2fc92b |
SCDynamicStoreSetNotificationKeys(store, keys, patterns))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
store, 0)) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS,
|
|
Packit |
2fc92b |
kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreateRunLoopSource "
|
|
Packit |
2fc92b |
"failed: %s\n", SCErrorString(SCError())));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreSetNotificationKeys "
|
|
Packit |
2fc92b |
"failed: %s\n", SCErrorString(SCError())));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
DEBUG_printf(("sysEventThreadEntry: SCDynamicStoreCreate failed: %s\n",
|
|
Packit |
2fc92b |
SCErrorString(SCError())));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (keys)
|
|
Packit |
2fc92b |
CFRelease(keys);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (patterns)
|
|
Packit |
2fc92b |
CFRelease(patterns);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Set up a timer to delay the wake change notifications.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* The initial time is set a decade or so into the future, we'll adjust
|
|
Packit |
2fc92b |
* this later.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
bzero(&timerContext, sizeof(timerContext));
|
|
Packit |
2fc92b |
timerContext.info = &threadData;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
threadData.timerRef =
|
|
Packit |
2fc92b |
CFRunLoopTimerCreate(kCFAllocatorDefault,
|
|
Packit |
2fc92b |
CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
|
|
Packit |
2fc92b |
86400L * 365L * 10L, 0, 0, sysEventTimerNotifier,
|
|
Packit |
2fc92b |
&timerContext);
|
|
Packit |
2fc92b |
CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef,
|
|
Packit |
2fc92b |
kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Store our runloop in a global so the main thread can use it to stop us.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_mutex_lock(&SysEventThreadMutex);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
SysEventRunloop = CFRunLoopGetCurrent();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_cond_signal(&SysEventThreadCond);
|
|
Packit |
2fc92b |
pthread_mutex_unlock(&SysEventThreadMutex);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Disappear into the runloop until it's stopped by the main thread.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
CFRunLoopRun();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Clean up before exiting.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (threadData.timerRef)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), threadData.timerRef,
|
|
Packit |
2fc92b |
kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
CFRelease(threadData.timerRef);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (threadData.sysevent.powerKernelPort)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), powerRLS,
|
|
Packit |
2fc92b |
kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
IODeregisterForSystemPower(&powerNotifierObj);
|
|
Packit |
2fc92b |
IOServiceClose(threadData.sysevent.powerKernelPort);
|
|
Packit |
2fc92b |
IONotificationPortDestroy(powerNotifierPort);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (storeRLS)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), storeRLS,
|
|
Packit |
2fc92b |
kCFRunLoopDefaultMode);
|
|
Packit |
2fc92b |
CFRunLoopSourceInvalidate(storeRLS);
|
|
Packit |
2fc92b |
CFRelease(storeRLS);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (store)
|
|
Packit |
2fc92b |
CFRelease(store);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pthread_exit(NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysEventPowerNotifier()' - Handle power notification events.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
sysEventPowerNotifier(
|
|
Packit |
2fc92b |
void *context, /* I - Thread context data */
|
|
Packit |
2fc92b |
io_service_t service, /* I - Unused service info */
|
|
Packit |
2fc92b |
natural_t messageType, /* I - Type of message */
|
|
Packit |
2fc92b |
void *messageArgument) /* I - Message data */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int sendit = 1; /* Send event to main thread? *
|
|
Packit |
2fc92b |
* (0 = no, 1 = yes, 2 = delayed */
|
|
Packit |
2fc92b |
cupsd_thread_data_t *threadData; /* Thread context data */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
threadData = (cupsd_thread_data_t *)context;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
(void)service; /* anti-compiler-warning-code */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
switch (messageType)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
case kIOMessageCanSystemPowerOff :
|
|
Packit |
2fc92b |
case kIOMessageCanSystemSleep :
|
|
Packit |
2fc92b |
threadData->sysevent.event |= SYSEVENT_CANSLEEP;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
case kIOMessageSystemWillRestart :
|
|
Packit |
2fc92b |
case kIOMessageSystemWillPowerOff :
|
|
Packit |
2fc92b |
case kIOMessageSystemWillSleep :
|
|
Packit |
2fc92b |
threadData->sysevent.event |= SYSEVENT_WILLSLEEP;
|
|
Packit |
2fc92b |
threadData->sysevent.event &= ~SYSEVENT_WOKE;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
case kIOMessageSystemHasPoweredOn :
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Because powered on is followed by a net-changed event, delay
|
|
Packit |
2fc92b |
* before sending it.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
sendit = 2;
|
|
Packit |
2fc92b |
threadData->sysevent.event |= SYSEVENT_WOKE;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
case kIOMessageSystemWillNotPowerOff :
|
|
Packit |
2fc92b |
case kIOMessageSystemWillNotSleep :
|
|
Packit |
2fc92b |
# ifdef kIOMessageSystemWillPowerOn
|
|
Packit |
2fc92b |
case kIOMessageSystemWillPowerOn :
|
|
Packit |
2fc92b |
# endif /* kIOMessageSystemWillPowerOn */
|
|
Packit |
2fc92b |
default:
|
|
Packit |
2fc92b |
sendit = 0;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
switch (messageType)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
case kIOMessageCanSystemPowerOff :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageCanSystemPowerOff message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageCanSystemSleep :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageCannSystemSleep message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemWillRestart :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillRestart message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemWillPowerOff :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillPowerOff message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemWillSleep :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillSleep message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemHasPoweredOn :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemHasPoweredOn message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemWillNotPowerOff :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillNotPowerOff message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
case kIOMessageSystemWillNotSleep :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillNotSleep message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
# ifdef kIOMessageSystemWillPowerOn
|
|
Packit |
2fc92b |
case kIOMessageSystemWillPowerOn :
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Got kIOMessageSystemWillPowerOn message.");
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
# endif /* kIOMessageSystemWillPowerOn */
|
|
Packit |
2fc92b |
default:
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Got unknown power message %d.",
|
|
Packit |
2fc92b |
(int)messageType);
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sendit == 0)
|
|
Packit |
2fc92b |
IOAllowPowerChange(threadData->sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
(long)messageArgument);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
threadData->sysevent.powerNotificationID = (long)messageArgument;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sendit == 1)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Send the event to the main thread now.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
write(SysEventPipes[1], &threadData->sysevent,
|
|
Packit |
2fc92b |
sizeof(threadData->sysevent));
|
|
Packit |
2fc92b |
threadData->sysevent.event = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Send the event to the main thread after 1 to 2 seconds.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
CFRunLoopTimerSetNextFireDate(threadData->timerRef,
|
|
Packit |
2fc92b |
CFAbsoluteTimeGetCurrent() + 2);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysEventConfigurationNotifier()' - Network configuration change notification
|
|
Packit |
2fc92b |
* callback.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
sysEventConfigurationNotifier(
|
|
Packit |
2fc92b |
SCDynamicStoreRef store, /* I - System data (unused) */
|
|
Packit |
2fc92b |
CFArrayRef changedKeys, /* I - Changed data */
|
|
Packit |
2fc92b |
void *context) /* I - Thread context data */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_thread_data_t *threadData; /* Thread context data */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
threadData = (cupsd_thread_data_t *)context;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
(void)store; /* anti-compiler-warning-code */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
CFRange range = CFRangeMake(0, CFArrayGetCount(changedKeys));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (CFArrayContainsValue(changedKeys, range, ComputerNameKey) ||
|
|
Packit |
2fc92b |
CFArrayContainsValue(changedKeys, range, BTMMKey))
|
|
Packit |
2fc92b |
threadData->sysevent.event |= SYSEVENT_NAMECHANGED;
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
threadData->sysevent.event |= SYSEVENT_NETCHANGED;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Indicate the network interface list needs updating...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
NetIFUpdate = 1;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Because we registered for several different kinds of change notifications
|
|
Packit |
2fc92b |
* this callback usually gets called several times in a row. We use a timer to
|
|
Packit |
2fc92b |
* de-bounce these so we only end up generating one event for the main thread.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
CFRunLoopTimerSetNextFireDate(threadData->timerRef,
|
|
Packit |
2fc92b |
CFAbsoluteTimeGetCurrent() + 5);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysEventTimerNotifier()' - Handle delayed event notifications.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
sysEventTimerNotifier(
|
|
Packit |
2fc92b |
CFRunLoopTimerRef timer, /* I - Timer information */
|
|
Packit |
2fc92b |
void *context) /* I - Thread context data */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_thread_data_t *threadData; /* Thread context data */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
(void)timer;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
threadData = (cupsd_thread_data_t *)context;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* If an event is still pending send it to the main thread.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (threadData->sysevent.event)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
write(SysEventPipes[1], &threadData->sysevent,
|
|
Packit |
2fc92b |
sizeof(threadData->sysevent));
|
|
Packit |
2fc92b |
threadData->sysevent.event = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysUpdate()' - Update the current system state.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
sysUpdate(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int i; /* Looping var */
|
|
Packit |
2fc92b |
cupsd_sysevent_t sysevent; /* The system event */
|
|
Packit |
2fc92b |
cupsd_printer_t *p; /* Printer information */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Drain the event pipe...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (read((int)SysEventPipes[0], &sysevent, sizeof(sysevent))
|
|
Packit |
2fc92b |
== sizeof(sysevent))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (sysevent.event & SYSEVENT_CANSLEEP)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* If there are active printers that don't have the connecting-to-device
|
|
Packit |
2fc92b |
* or cups-waiting-for-job-completed printer-state-reason then cancel the
|
|
Packit |
2fc92b |
* sleep request, i.e., these reasons indicate a job that is not actively
|
|
Packit |
2fc92b |
* doing anything...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
|
|
Packit |
2fc92b |
p;
|
|
Packit |
2fc92b |
p = (cupsd_printer_t *)cupsArrayNext(Printers))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (p->job)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
for (i = 0; i < p->num_reasons; i ++)
|
|
Packit |
2fc92b |
if (!strcmp(p->reasons[i], "connecting-to-device") ||
|
|
Packit |
2fc92b |
!strcmp(p->reasons[i], "cups-waiting-for-job-completed"))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!p->num_reasons || i >= p->num_reasons)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (p)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_INFO,
|
|
Packit |
2fc92b |
"System sleep canceled because printer %s is active.",
|
|
Packit |
2fc92b |
p->name);
|
|
Packit |
2fc92b |
IOCancelPowerChange(sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
sysevent.powerNotificationID);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep.");
|
|
Packit |
2fc92b |
IOAllowPowerChange(sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
sysevent.powerNotificationID);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sysevent.event & SYSEVENT_WILLSLEEP)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep.");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
Sleeping = 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdCleanDirty();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* If we have no printing jobs, allow the power change immediately.
|
|
Packit |
2fc92b |
* Otherwise set the SleepJobs time to 10 seconds in the future when
|
|
Packit |
2fc92b |
* we'll take more drastic measures...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cupsArrayCount(PrintingJobs) == 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
|
|
Packit |
2fc92b |
IOAllowPowerChange(sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
sysevent.powerNotificationID);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* If there are active printers that don't have the connecting-to-device
|
|
Packit |
2fc92b |
* or cups-waiting-for-job-completed printer-state-reasons then delay the
|
|
Packit |
2fc92b |
* sleep request, i.e., these reasons indicate a job is active...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
|
|
Packit |
2fc92b |
p;
|
|
Packit |
2fc92b |
p = (cupsd_printer_t *)cupsArrayNext(Printers))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (p->job)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
for (i = 0; i < p->num_reasons; i ++)
|
|
Packit |
2fc92b |
if (!strcmp(p->reasons[i], "connecting-to-device") ||
|
|
Packit |
2fc92b |
!strcmp(p->reasons[i], "cups-waiting-for-job-completed"))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!p->num_reasons || i >= p->num_reasons)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (p)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_INFO,
|
|
Packit |
2fc92b |
"System sleep delayed because printer %s is active.",
|
|
Packit |
2fc92b |
p->name);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
LastSysEvent = sysevent;
|
|
Packit |
2fc92b |
SleepJobs = time(NULL) + 10;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep.");
|
|
Packit |
2fc92b |
IOAllowPowerChange(sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
sysevent.powerNotificationID);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sysevent.event & SYSEVENT_WOKE)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep.");
|
|
Packit |
2fc92b |
IOAllowPowerChange(sysevent.powerKernelPort,
|
|
Packit |
2fc92b |
sysevent.powerNotificationID);
|
|
Packit |
2fc92b |
Sleeping = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Make sure jobs that were queued prior to the system going to sleep don't
|
|
Packit |
2fc92b |
* get canceled right away...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (MaxJobTime > 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_job_t *job; /* Current job */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
|
|
Packit |
2fc92b |
job;
|
|
Packit |
2fc92b |
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (job->cancel_time)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
|
|
Packit |
2fc92b |
"job-cancel-after",
|
|
Packit |
2fc92b |
IPP_TAG_INTEGER);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cancel_after)
|
|
Packit |
2fc92b |
job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
job->cancel_time = time(NULL) + MaxJobTime;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (NameChanged)
|
|
Packit |
2fc92b |
sysUpdateNames();
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdCheckJobs();
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sysevent.event & SYSEVENT_NETCHANGED)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (Sleeping)
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"System network configuration changed - "
|
|
Packit |
2fc92b |
"ignored while sleeping.");
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"System network configuration changed.");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (sysevent.event & SYSEVENT_NAMECHANGED)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (Sleeping)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
NameChanged = 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Computer name or BTMM domains changed - ignored while "
|
|
Packit |
2fc92b |
"sleeping.");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsdLogMessage(CUPSD_LOG_DEBUG,
|
|
Packit |
2fc92b |
"Computer name or BTMM domains changed.");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
sysUpdateNames();
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'sysUpdateNames()' - Update computer and/or BTMM domains.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
sysUpdateNames(void)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsd_printer_t *p; /* Current printer */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
NameChanged = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* De-register the individual printers...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
|
|
Packit |
2fc92b |
p;
|
|
Packit |
2fc92b |
p = (cupsd_printer_t *)cupsArrayNext(Printers))
|
|
Packit |
2fc92b |
cupsdDeregisterPrinter(p, 1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Update the computer name and BTMM domain list...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsdUpdateDNSSDName();
|
|
Packit |
2fc92b |
# endif /* HAVE_DNSSD || HAVE_AVAHI */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Now re-register them...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
|
|
Packit |
2fc92b |
p;
|
|
Packit |
2fc92b |
p = (cupsd_printer_t *)cupsArrayNext(Printers))
|
|
Packit |
2fc92b |
cupsdRegisterPrinter(p);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
#endif /* __APPLE__ */
|