/*
- * "$Id: main.c 5216 2006-03-02 17:47:53Z mike $"
+ * "$Id: main.c 6914 2007-09-05 21:05:04Z mike $"
*
* Scheduler main loop for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 2007 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
* "LICENSE" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
* main() - Main entry for the CUPS scheduler.
* cupsdClosePipe() - Close a pipe as necessary.
* cupsdOpenPipe() - Create a pipe which is closed on exec.
- * cupsdCatchChildSignals() - Catch SIGCHLD signals...
* cupsdHoldSignals() - Hold child and termination signals.
- * cupsdIgnoreChildSignals() - Ignore SIGCHLD signals...
* cupsdReleaseSignals() - Release signals for delivery.
* cupsdSetString() - Set a string value.
* cupsdSetStringf() - Set a formatted string value.
* launchd_checkin() - Check-in with launchd and collect the
* listening fds.
- * launchd_reload() - Tell launchd to reload the configuration
- * file to pick up the new listening directives.
- * launchd_sync_conf() - Re-write the launchd(8) config file
- * org.cups.cupsd.plist based on cupsd.conf.
+ * launchd_checkout() - Check-out with launchd.
* parent_handler() - Catch USR1/CHLD signals...
* process_children() - Process all dead children...
* sigchld_handler() - Handle 'child' signals from old processes.
#include <sys/resource.h>
#include <syslog.h>
#include <grp.h>
+#include <cups/dir.h>
#ifdef HAVE_LAUNCH_H
# include <launch.h>
# include <libgen.h>
+# define CUPS_KEEPALIVE CUPS_CACHEDIR "/org.cups.cupsd"
+ /* Name of the launchd KeepAlive file */
+# ifndef LAUNCH_JOBKEY_KEEPALIVE
+# define LAUNCH_JOBKEY_KEEPALIVE "KeepAlive"
+# endif /* !LAUNCH_JOBKEY_KEEPALIVE */
+# ifndef LAUNCH_JOBKEY_PATHSTATE
+# define LAUNCH_JOBKEY_PATHSTATE "PathState"
+# endif /* !LAUNCH_JOBKEY_PATHSTATE */
+# ifndef LAUNCH_JOBKEY_SERVICEIPC
+# define LAUNCH_JOBKEY_SERVICEIPC "ServiceIPC"
+# endif /* !LAUNCH_JOBKEY_SERVICEIPC */
#endif /* HAVE_LAUNCH_H */
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
# include <notify.h>
#endif /* HAVE_NOTIFY_H */
+#if defined(__APPLE__) && defined(HAVE_DLFCN_H)
+# include <dlfcn.h>
+#endif /* __APPLE__ && HAVE_DLFCN_H */
+
/*
* Local functions...
*/
#ifdef HAVE_LAUNCHD
-static void launchd_checkin(void);
-static void launchd_reload(void);
-static int launchd_sync_conf(void);
+static void launchd_checkin(void);
+static void launchd_checkout(void);
#endif /* HAVE_LAUNCHD */
-
-static void parent_handler(int sig);
-static void process_children(void);
-static void sigchld_handler(int sig);
-static void sighup_handler(int sig);
-static void sigterm_handler(int sig);
-static long select_timeout(int fds);
-static void usage(int status);
+static void parent_handler(int sig);
+static void process_children(void);
+static void sigchld_handler(int sig);
+static void sighup_handler(int sig);
+static void sigterm_handler(int sig);
+static long select_timeout(int fds);
+static void usage(int status);
/*
* Local globals...
*/
-static int parent_signal = 0; /* Set to signal number from child */
-static int holdcount = 0; /* Number of times "hold" was called */
+static int parent_signal = 0;
+ /* Set to signal number from child */
+static int holdcount = 0; /* Number of times "hold" was called */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-static sigset_t holdmask; /* Old POSIX signal mask */
+static sigset_t holdmask; /* Old POSIX signal mask */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-static int dead_children = 0; /* Dead children? */
-static int stop_scheduler = 0; /* Should the scheduler stop? */
+static int dead_children = 0;
+ /* Dead children? */
+static int stop_scheduler = 0;
+ /* Should the scheduler stop? */
+
+#if defined(__APPLE__) && defined(HAVE_DLFCN_H)
+static const char *PSQLibPath = "/usr/lib/libPrintServiceQuota.dylib";
+static const char *PSQLibFuncName = "PSQUpdateQuota";
+static void *PSQLibRef; /* libPrintServiceQuota.dylib */
+#endif /* HAVE_DLFCN_H */
/*
char *opt; /* Option character */
int fg; /* Run in the foreground */
int fds; /* Number of ready descriptors */
- fd_set *input, /* Input set for select() */
- *output; /* Output set for select() */
cupsd_client_t *con; /* Current client */
cupsd_job_t *job; /* Current job */
cupsd_listener_t *lis; /* Current listener */
activity, /* Client activity timer */
browse_time, /* Next browse send time */
senddoc_time, /* Send-Document time */
- expire_time; /* Subscription expire time */
- time_t mallinfo_time; /* Malloc information time */
+ expire_time, /* Subscription expire time */
+ mallinfo_time; /* Malloc information time */
size_t string_count, /* String count */
alloc_bytes, /* Allocated string bytes */
total_bytes; /* Total string bytes */
- struct timeval timeout; /* select() timeout */
+ long timeout; /* Timeout for cupsdDoSelect() */
struct rlimit limit; /* Runtime limit */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
#endif /* HAVE_LAUNCHD */
+#ifdef HAVE_GETEUID
+ /*
+ * Check for setuid invocation, which we do not support!
+ */
+
+ if (getuid() != geteuid())
+ {
+ fputs("cupsd: Cannot run as a setuid program!\n", stderr);
+ return (1);
+ }
+#endif /* HAVE_GETEUID */
+
/*
* Check for command-line arguments...
*/
fg = 0;
+#ifdef HAVE_LAUNCHD
+ if (getenv("CUPSD_LAUNCHD"))
+ {
+ Launchd = 1;
+ fg = 1;
+ }
+#endif /* HAVE_LAUNCHD */
+
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
for (opt = argv[i] + 1; *opt != '\0'; opt ++)
#endif /* HAVE_LAUNCHD */
break;
+ case 'p' : /* Stop immediately for profiling */
+ puts("Warning: -p option is for internal testing use only!");
+ stop_scheduler = 1;
+ fg = 1;
+ break;
+
+ case 't' : /* Test the cupsd.conf file... */
+ TestConfigFile = 1;
+ fg = 1;
+ break;
+
default : /* Unknown option */
_cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - "
"aborting!\n"), *opt);
getrlimit(RLIMIT_NOFILE, &limit);
- for (i = 0; i < limit.rlim_cur; i ++)
+ for (i = 0; i < limit.rlim_cur && i < 1024; i ++)
close(i);
#endif /* DEBUG */
}
getrlimit(RLIMIT_NOFILE, &limit);
- if (limit.rlim_max > CUPS_MAX_FDS)
- MaxFDs = CUPS_MAX_FDS;
+#if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE)
+ if (limit.rlim_max > FD_SETSIZE)
+ MaxFDs = FD_SETSIZE;
else
+#endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */
+#ifdef RLIM_INFINITY
+ if (limit.rlim_max == RLIM_INFINITY)
+ MaxFDs = 16384;
+ else
+#endif /* RLIM_INFINITY */
MaxFDs = limit.rlim_max;
limit.rlim_cur = MaxFDs;
setrlimit(RLIMIT_NOFILE, &limit);
- /*
- * Allocate memory for the input and output sets...
- */
-
- SetSize = (MaxFDs + 31) / 8 + 4;
- if (SetSize < sizeof(fd_set))
- SetSize = sizeof(fd_set);
-
- InputSet = (fd_set *)calloc(1, SetSize);
- OutputSet = (fd_set *)calloc(1, SetSize);
- input = (fd_set *)calloc(1, SetSize);
- output = (fd_set *)calloc(1, SetSize);
-
- if (InputSet == NULL || OutputSet == NULL || input == NULL || output == NULL)
- {
- syslog(LOG_LPR, "Unable to allocate memory for select() sets - exiting!");
- return (1);
- }
+ cupsdStartSelect();
/*
* Read configuration...
if (!cupsdReadConfiguration())
{
- syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
- ConfigurationFile);
+ if (TestConfigFile)
+ printf("%s contains errors\n", ConfigurationFile);
+ else
+ syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
+ ConfigurationFile);
return (1);
}
+ else if (TestConfigFile)
+ {
+ printf("%s is OK\n", ConfigurationFile);
+ return (0);
+ }
-#if HAVE_LAUNCHD
- if (Launchd)
+ if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)))
{
/*
- * If we were started by launchd make sure the cupsd plist file contains the
- * same listeners as cupsd.conf; If it didn't then reload it before getting
- * the list of listening file descriptors...
+ * Clean out the temporary directory...
*/
- if (launchd_sync_conf())
+ cups_dir_t *dir; /* Temporary directory */
+ cups_dentry_t *dent; /* Directory entry */
+ char tempfile[1024]; /* Temporary filename */
+
+
+ if ((dir = cupsDirOpen(TempDir)) != NULL)
{
- launchd_reload();
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Cleaning out old temporary files in \"%s\"...", TempDir);
- /*
- * Until rdar://3854821 is fixed we have to exit after the reload...
- */
+ while ((dent = cupsDirRead(dir)) != NULL)
+ {
+ snprintf(tempfile, sizeof(tempfile), "%s/%s", TempDir, dent->filename);
+
+ if (cupsdRemoveFile(tempfile))
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to remove temporary file \"%s\" - %s",
+ tempfile, strerror(errno));
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Removed temporary file \"%s\"...",
+ tempfile);
+ }
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Exiting on launchd_reload");
- exit(0);
+ cupsDirClose(dir);
}
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to open temporary directory \"%s\" - %s",
+ TempDir, strerror(errno));
+ }
+
+#if HAVE_LAUNCHD
+ if (Launchd)
+ {
+ /*
+ * If we were started by launchd get the listen sockets file descriptors...
+ */
launchd_checkin();
}
#endif /* HAVE_LAUNCHD */
+#if defined(__APPLE__) && defined(HAVE_DLFCN_H)
+ /*
+ * Load Print Service quota enforcement library (X Server only)
+ */
+
+ PSQLibRef = dlopen(PSQLibPath, RTLD_LAZY);
+
+ if (PSQLibRef)
+ PSQUpdateQuotaProc = dlsym(PSQLibRef, PSQLibFuncName);
+#endif /* __APPLE__ && HAVE_DLFCN_H */
+
+#ifdef HAVE_GSSAPI
+# ifdef __APPLE__
+ /*
+ * If the weak-linked GSSAPI/Kerberos library is not present, don't try
+ * to use it...
+ */
+
+ if (krb5_init_context != NULL)
+# endif /* __APPLE__ */
+
+ /*
+ * Setup a Kerberos context for the scheduler to use...
+ */
+
+ if (krb5_init_context(&KerberosContext))
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context");
+#endif /* HAVE_GSSAPI */
+
/*
* Startup the server...
*/
*/
#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGCHLD, sigchld_handler);
sigset(SIGHUP, sighup_handler);
sigset(SIGPIPE, SIG_IGN);
sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGCHLD);
+ action.sa_handler = sigchld_handler;
+ sigaction(SIGCHLD, &action, NULL);
+
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGHUP);
action.sa_handler = sighup_handler;
action.sa_handler = sigterm_handler;
sigaction(SIGTERM, &action, NULL);
#else
+ signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */
signal(SIGHUP, sighup_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGTERM, sigterm_handler);
kill(i, SIGUSR1);
}
+#ifdef __APPLE__
/*
* Start power management framework...
*/
cupsdStartSystemMonitor();
-
- /*
- * Catch signals...
- */
-
- cupsdCatchChildSignals();
+#endif /* __APPLE__ */
/*
* Start any pending print jobs...
#if HAVE_LAUNCHD
if (Launchd)
{
- if (launchd_sync_conf())
- {
- launchd_reload();
-
- /*
- * Until rdar://3854821 is fixed we have to exit after the reload...
- */
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Exiting on launchd_reload");
- stop_scheduler = 1;
- break;
- }
+ /*
+ * If we were started by launchd get the listen sockets file descriptors...
+ */
launchd_checkin();
}
}
/*
- * Check for available input or ready output. If select() returns
- * 0 or -1, something bad happened and we should exit immediately.
+ * Check for available input or ready output. If cupsdDoSelect()
+ * returns 0 or -1, something bad happened and we should exit
+ * immediately.
*
* Note that we at least have one listening socket open at all
* times.
*/
- memcpy(input, InputSet, SetSize);
- memcpy(output, OutputSet, SetSize);
-
- timeout.tv_sec = select_timeout(fds);
- timeout.tv_usec = 0;
+ timeout = select_timeout(fds);
#if HAVE_LAUNCHD
/*
* If no other work is scheduled and we're being controlled by
- * launchd(8) then timeout after 'LaunchdTimeout' seconds of
+ * launchd then timeout after 'LaunchdTimeout' seconds of
* inactivity...
*/
- if (timeout.tv_sec == 86400 && Launchd && LaunchdTimeout &&
- (!Browsing || !(BrowseLocalProtocols & BROWSE_DNSSD) ||
- cupsArrayCount(Printers) == 0))
+ if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled &&
+ !cupsArrayCount(ActiveJobs) &&
+ (!Browsing ||
+ (!BrowseRemoteProtocols &&
+ (!NumBrowsers || !BrowseLocalProtocols ||
+ cupsArrayCount(Printers) == 0))))
{
- timeout.tv_sec = LaunchdTimeout;
+ timeout = LaunchdTimeout;
launchd_idle_exit = 1;
}
else
launchd_idle_exit = 0;
#endif /* HAVE_LAUNCHD */
- if (timeout.tv_sec < 86400) /* Only use timeout for < 1 day */
- fds = select(MaxFDs, input, output, NULL, &timeout);
- else
- fds = select(MaxFDs, input, output, NULL, NULL);
-
- if (fds < 0)
+ if ((fds = cupsdDoSelect(timeout)) < 0)
{
- char s[16384], /* String buffer */
- *sptr; /* Pointer into buffer */
- int slen; /* Length of string buffer */
-
-
/*
* Got an error from select!
*/
- if (errno == EINTR) /* Just interrupted by a signal */
+#ifdef HAVE_DNSSD
+ cupsd_printer_t *p; /* Current printer */
+#endif /* HAVE_DNSSD */
+
+
+ if (errno == EINTR) /* Just interrupted by a signal */
continue;
/*
* Log all sorts of debug info to help track down the problem.
*/
- cupsdLogMessage(CUPSD_LOG_EMERG, "select() failed - %s!",
+ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!",
strerror(errno));
- strcpy(s, "InputSet =");
- slen = 10;
- sptr = s + 10;
-
- for (i = 0; i < MaxFDs; i ++)
- if (FD_ISSET(i, InputSet))
- {
- snprintf(sptr, sizeof(s) - slen, " %d", i);
- slen += strlen(sptr);
- sptr += strlen(sptr);
- }
-
- cupsdLogMessage(CUPSD_LOG_EMERG, s);
-
- strcpy(s, "OutputSet =");
- slen = 11;
- sptr = s + 11;
-
- for (i = 0; i < MaxFDs; i ++)
- if (FD_ISSET(i, OutputSet))
- {
- snprintf(sptr, sizeof(s) - slen, " %d", i);
- slen += strlen(sptr);
- sptr += strlen(sptr);
- }
-
- cupsdLogMessage(CUPSD_LOG_EMERG, s);
-
for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients);
con;
i ++, con = (cupsd_client_t *)cupsArrayNext(Clients))
job->status_buffer ? job->status_buffer->fd : -1,
job->print_pipes[0], job->print_pipes[1],
job->back_pipes[0], job->back_pipes[1]);
+
+#ifdef HAVE_DNSSD
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] %d", p->name,
+ p->dnssd_ipp_fd);
+#endif /* HAVE_DNSSD */
+
break;
}
#if HAVE_LAUNCHD
/*
- * If no other work was scheduled and we're being controlled by launchd(8)
+ * If no other work was scheduled and we're being controlled by launchd
* then timeout after 'LaunchdTimeout' seconds of inactivity...
*/
#endif /* HAVE_LAUNCHD */
/*
- * Check for status info from job filters...
- */
-
- for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
- job;
- job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
- if (job->status_buffer && FD_ISSET(job->status_buffer->fd, input))
- {
- /*
- * Clear the input bit to avoid updating the next job
- * using the same status pipe file descriptor...
- */
-
- FD_CLR(job->status_buffer->fd, input);
-
- /*
- * Read any status messages from the filters...
- */
-
- cupsdUpdateJob(job);
- }
-
- /*
- * Update CGI messages as needed...
- */
-
- if (CGIPipes[0] >= 0 && FD_ISSET(CGIPipes[0], input))
- cupsdUpdateCGI();
-
- /*
- * Handle system management events as needed...
- */
-
-#ifdef __APPLE__
- if (SysEventPipes[0] >= 0 && FD_ISSET(SysEventPipes[0], input))
- cupsdUpdateSystemMonitor();
-#endif /* __APPLE__ */
-
- /*
- * Update notifier messages as needed...
+ * Resume listening for new connections as needed...
*/
- if (NotifierPipes[0] >= 0 && FD_ISSET(NotifierPipes[0], input))
- cupsdUpdateNotifierStatus();
+ if (ListeningPaused && ListeningPaused <= current_time &&
+ cupsArrayCount(Clients) < MaxClients)
+ cupsdResumeListening();
/*
* Expire subscriptions and unload completed jobs as needed...
* Update the browse list as needed...
*/
- if (Browsing && BrowseRemoteProtocols)
+ if (Browsing)
{
- if (BrowseSocket >= 0 && FD_ISSET(BrowseSocket, input))
- cupsdUpdateCUPSBrowse();
-
- if (PollPipe >= 0 && FD_ISSET(PollPipe, input))
- cupsdUpdatePolling();
-
#ifdef HAVE_LIBSLP
if ((BrowseRemoteProtocols & BROWSE_SLP) &&
BrowseSLPRefresh <= current_time)
}
/*
- * Check for new connections on the "listen" sockets...
+ * Update the root certificate once every 5 minutes if we have client
+ * connections...
*/
- for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
- lis;
- lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- if (lis->fd >= 0 && FD_ISSET(lis->fd, input))
- {
- FD_CLR(lis->fd, input);
- cupsdAcceptClient(lis);
- }
+ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration &&
+ !RunUser && cupsArrayCount(Clients))
+ {
+ /*
+ * Update the root certificate...
+ */
+
+ cupsdDeleteCert(0);
+ cupsdAddCert(0, "root");
+ }
/*
* Check for new data on the client sockets...
con = (cupsd_client_t *)cupsArrayNext(Clients))
{
/*
- * Process the input buffer...
- */
-
- if (FD_ISSET(con->http.fd, input) || con->http.used)
- {
- int fd = con->file;
-
-
- FD_CLR(con->http.fd, input);
-
- if (!cupsdReadClient(con))
- {
- if (fd >= 0)
- FD_CLR(fd, input);
-
- continue;
- }
- }
-
- /*
- * Write data as needed...
+ * Process pending data in the input buffer...
*/
- if (con->pipe_pid && FD_ISSET(con->file, input))
- {
- /*
- * Keep track of pending input from the file/pipe separately
- * so that we don't needlessly spin on select() when the web
- * client is not ready to receive data...
- */
-
- FD_CLR(con->file, input);
- con->file_ready = 1;
-
-#ifdef DEBUG
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "main: Data ready file %d!",
- con->file);
-#endif /* DEBUG */
-
- if (!FD_ISSET(con->http.fd, output))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "main: Removing fd %d from InputSet...", con->file);
- FD_CLR(con->file, input);
- FD_CLR(con->file, InputSet);
- }
- }
-
- if (FD_ISSET(con->http.fd, output))
+ if (con->http.used)
{
- FD_CLR(con->http.fd, output);
-
- if (!con->pipe_pid || con->file_ready)
- if (!cupsdWriteClient(con))
- continue;
+ cupsdReadClient(con);
+ continue;
}
/*
mem.fsmblks + mem.fordblks);
#endif /* HAVE_MALLINFO */
- string_count = _cups_sp_statistics(&alloc_bytes, &total_bytes);
+ string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"stringpool: " CUPS_LLFMT " strings, "
CUPS_LLFMT " allocated, " CUPS_LLFMT " total bytes",
mallinfo_time = current_time;
}
- /*
- * Update the root certificate once every 5 minutes...
- */
-
- if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration &&
- !RunUser)
- {
- /*
- * Update the root certificate...
- */
-
- cupsdDeleteCert(0);
- cupsdAddCert(0, "root");
- }
-
/*
* Handle OS-specific event notification for any events that have
* accumulated. Don't send these more than once a second...
*/
- if (LastEvent && (time(NULL) - LastEventTime) > 1)
+ if (LastEvent)
{
#ifdef HAVE_NOTIFY_POST
if (LastEvent & CUPSD_EVENT_PRINTER_CHANGED)
#endif /* HAVE_NOTIFY_POST */
/*
- * Reset the accumulated events and notification time...
+ * Reset the accumulated events...
*/
- LastEventTime = time(NULL);
LastEvent = CUPSD_EVENT_NONE;
}
}
"Scheduler shutting down due to program error.");
/*
- * Close all network clients and stop all jobs...
+ * Close all network clients...
*/
cupsdStopServer();
+#ifdef HAVE_LAUNCHD
+ /*
+ * Update the launchd KeepAlive file as needed...
+ */
+
+ if (Launchd)
+ launchd_checkout();
+#endif /* HAVE_LAUNCHD */
+
+ /*
+ * Stop all jobs...
+ */
+
cupsdFreeAllJobs();
+#ifdef __APPLE__
+ /*
+ * Stop monitoring system event monitoring...
+ */
+
cupsdStopSystemMonitor();
+#endif /* __APPLE__ */
-#ifdef HAVE_LAUNCHD
+#ifdef HAVE_GSSAPI
/*
- * Update the launchd config file as needed...
+ * Free the scheduler's Kerberos context...
*/
- launchd_sync_conf();
-#endif /* HAVE_LAUNCHD */
+# ifdef __APPLE__
+ /*
+ * If the weak-linked GSSAPI/Kerberos library is not present, don't try
+ * to use it...
+ */
+
+ if (krb5_init_context != NULL)
+# endif /* __APPLE__ */
+ krb5_free_context(KerberosContext);
+#endif /* HAVE_GSSAPI */
+
+#ifdef __APPLE__
+#ifdef HAVE_DLFCN_H
+ /*
+ * Unload Print Service quota enforcement library (X Server only)
+ */
+
+ PSQUpdateQuotaProc = NULL;
+ if (PSQLibRef)
+ {
+ dlclose(PSQLibRef);
+ PSQLibRef = NULL;
+ }
+#endif /* HAVE_DLFCN_H */
+#endif /* __APPLE__ */
#ifdef __sgi
/*
unlink("/var/spool/lp/SCHEDLOCK");
#endif /* __sgi */
- /*
- * Free memory used by FD sets and return...
- */
-
- free(InputSet);
- free(OutputSet);
- free(input);
- free(output);
+ cupsdStopSelect();
return (!stop_scheduler);
}
*/
if (pipe(fds))
+ {
+ fds[0] = -1;
+ fds[1] = -1;
+
return (-1);
+ }
/*
* Set the "close on exec" flag on each end of the pipe...
{
close(fds[0]);
close(fds[1]);
+
+ fds[0] = -1;
+ fds[1] = -1;
+
return (-1);
}
{
close(fds[0]);
close(fds[1]);
+
+ fds[0] = -1;
+ fds[1] = -1;
+
return (-1);
}
}
-/*
- * 'cupsdCatchChildSignals()' - Catch SIGCHLD signals...
- */
-
-void
-cupsdCatchChildSignals(void)
-{
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
- sigset(SIGCHLD, sigchld_handler);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
-
- sigemptyset(&action.sa_mask);
- sigaddset(&action.sa_mask, SIGTERM);
- sigaddset(&action.sa_mask, SIGCHLD);
- action.sa_handler = sigchld_handler;
- sigaction(SIGCHLD, &action, NULL);
-#else
- signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */
-#endif /* HAVE_SIGSET */
-}
-
-
/*
* 'cupsdClearString()' - Clear a string.
*/
{
if (s && *s)
{
- free(*s);
+ _cupsStrFree(*s);
*s = NULL;
}
}
}
-/*
- * 'cupsdIgnoreChildSignals()' - Ignore SIGCHLD signals...
- *
- * We don't really ignore them, we set the signal handler to SIG_DFL,
- * since some OS's rely on signals for the wait4() function to work.
- */
-
-void
-cupsdIgnoreChildSignals(void)
-{
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
- sigset(SIGCHLD, SIG_DFL);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
-
- sigemptyset(&action.sa_mask);
- sigaddset(&action.sa_mask, SIGCHLD);
- action.sa_handler = SIG_DFL;
- sigaction(SIGCHLD, &action, NULL);
-#else
- signal(SIGCLD, SIG_DFL); /* No, SIGCLD isn't a typo... */
-#endif /* HAVE_SIGSET */
-}
-
-
/*
* 'cupsdReleaseSignals()' - Release signals for delivery.
*/
return;
if (*s)
- free(*s);
+ _cupsStrFree(*s);
if (v)
- *s = strdup(v);
+ *s = _cupsStrAlloc(v);
else
*s = NULL;
}
vsnprintf(v, sizeof(v), f, ap);
va_end(ap);
- *s = strdup(v);
+ *s = _cupsStrAlloc(v);
}
else
*s = NULL;
if (olds)
- free(olds);
+ _cupsStrFree(olds);
}
ld_resp, /* Launch data response */
ld_array, /* Launch data array */
ld_sockets, /* Launch data sockets dictionary */
- ld_runatload, /* Run-at-load setting */
tmp; /* Launch data */
cupsd_listener_t *lis; /* Listeners array */
http_addr_t addr; /* Address variable */
socklen_t addrlen; /* Length of address */
- bool runatload; /* Run-at-load setting value */
+ int fd; /* File descriptor */
+ char s[256]; /* String addresss */
cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid());
exit(EXIT_FAILURE);
}
- /*
- * Get the "run-at-load" setting...
- */
-
- if ((ld_runatload =
- launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_RUNATLOAD)) != NULL &&
- launch_data_get_type(ld_runatload) == LAUNCH_DATA_BOOL)
- runatload = launch_data_get_bool(ld_runatload);
- else
- {
- errno = launch_data_get_errno(ld_resp);
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to find Run-at-load setting: %s",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Run-at-load=%s",
- runatload ? "true" : "false");
-
/*
* Get the sockets dictionary...
*/
if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY)
{
- /*
- * Free the listeners array built from cupsd.conf...
- */
-
- cupsdDeleteAllListeners();
-
- /*
- * Create a new array of listeners from the launchd data...
- */
-
- Listeners = cupsArrayNew(NULL, NULL);
- count = launch_data_array_get_count(ld_array);
+ count = launch_data_array_get_count(ld_array);
for (i = 0; i < count; i ++)
{
/*
- * Copy the current address and log it...
+ * Get the launchd file descriptor and address...
*/
- if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+ tmp = launch_data_array_get_index(ld_array, i);
+ fd = launch_data_get_fd(tmp);
+ addrlen = sizeof(addr);
+
+ if (getsockname(fd, (struct sockaddr *)&addr, &addrlen))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to allocate listener - %s.",
- strerror(errno));
- exit(EXIT_FAILURE);
+ "launchd_checkin: Unable to get local address - %s",
+ strerror(errno));
+ continue;
}
- cupsArrayAdd(Listeners, lis);
+ /*
+ * Try to match the launchd socket address to one of the listeners...
+ */
- tmp = launch_data_array_get_index(ld_array, i);
- lis->fd = launch_data_get_fd(tmp);
- addrlen = sizeof(lis->address);
+ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+ lis;
+ lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+ if (httpAddrEqual(&lis->address, &addr))
+ break;
+
+ /*
+ * Add a new listener If there's no match...
+ */
- if (getsockname(lis->fd, (struct sockaddr *)&(lis->address), &addrlen))
+ if (lis)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to get local address - %s",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Matched existing listener %s with fd %d...",
+ httpAddrString(&(lis->address), s, sizeof(s)), fd);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Adding new listener %s with fd %d...",
+ httpAddrString(&addr, s, sizeof(s)), fd);
+
+ if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "launchd_checkin: Unable to allocate listener - %s.",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ cupsArrayAdd(Listeners, lis);
+
+ memcpy(&lis->address, &addr, sizeof(lis->address));
}
+ lis->fd = fd;
+
# ifdef HAVE_SSL
portnum = 0;
# ifdef AF_INET6
- if (addr.addr.sa_family == AF_INET6)
- portnum = ntohs(addr.ipv6.sin6_port);
+ if (lis->address.addr.sa_family == AF_INET6)
+ portnum = ntohs(lis->address.ipv6.sin6_port);
else
# endif /* AF_INET6 */
- if (addr.addr.sa_family == AF_INET)
- portnum = ntohs(addr.ipv4.sin_port);
+ if (lis->address.addr.sa_family == AF_INET)
+ portnum = ntohs(lis->address.ipv4.sin_port);
if (portnum == 443)
lis->encryption = HTTP_ENCRYPT_ALWAYS;
}
}
- /*
- * Collect the browse socket (if there is one)...
- */
-
- if ((ld_array = launch_data_dict_lookup(ld_sockets, "BrowseSockets")))
- {
- if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY)
- {
- tmp = launch_data_array_get_index(ld_array, 0);
-
- if (launch_data_get_type(tmp) == LAUNCH_DATA_FD)
- {
- if (BrowseSocket != -1)
- close(BrowseSocket);
-
- BrowseSocket = launch_data_get_fd(tmp);
- }
- else
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_checkin: BrowseSocket not a fd!");
- }
- else
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_checkin: BrowseSockets is not an array!");
- }
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: No BrowseSockets");
-
launch_data_free(ld_msg);
launch_data_free(ld_resp);
}
/*
- * 'launchd_reload()' - Tell launchd to reload the configuration file to pick
- * up the new listening directives.
+ * 'launchd_checkout()' - Update the launchd KeepAlive file as needed.
*/
static void
-launchd_reload(void)
-{
- int child_status; /* Exit status of child process */
- pid_t child_pid, /* Child PID */
- waitpid_status; /* Child process exit status */
- char *argv[4]; /* Argument strings */
-
-
- /*
- * The current launchd doesn't support a reload option (rdar://3854821).
- * Until this is fixed we need to reload the config file by execing launchctl
- * twice (to unload then load). NOTE: This will cause us to exit on SIGTERM
- * which will cancel all client & job activity.
- *
- * After this is fixed we'll be able to tell launchd to reload the file
- * and pick up the new listening descriptors without disrupting current
- * activity.
- */
-
- /*
- * Unloading the current configuration will cause launchd to send us a SIGTERM;
- * block it for now so we can get our work done...
- */
-
- cupsdHoldSignals();
-
- /*
- * Set up the unload arguments to launchctl...
- */
-
- argv[0] = "/bin/launchctl";
- argv[1] = "unload";
- argv[2] = LaunchdConf;
- argv[3] = NULL;
-
- if (cupsdStartProcess(argv[0], argv, NULL, -1, -1, -1, -1, 1, &child_pid) < 0)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_reload: Unable to execute %s - %s", argv[0],
- strerror(errno));
- else
- {
- do
- {
- waitpid_status = waitpid(child_pid, &child_status, 0);
- }
- while (waitpid_status == (pid_t)-1 && errno == EINTR);
-
- if (WIFSIGNALED(child_status))
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d crashed on signal %d!",
- basename(argv[0]), child_pid, WTERMSIG(child_status));
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d stopped with status %d!",
- basename(argv[0]), child_pid, WEXITSTATUS(child_status));
-
- /*
- * Do it again with the load command...
- */
-
- argv[1] = "load";
-
- if (cupsdStartProcess(argv[0], argv, NULL, -1, -1, -1, -1, 1,
- &child_pid) < 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_reload: Unable to fork for %s - %s", argv[0],
- strerror(errno));
- }
- else
- {
- do
- {
- waitpid_status = waitpid(child_pid, &child_status, 0);
- } while (waitpid_status == (pid_t)-1 && errno == EINTR);
-
- if (WIFSIGNALED(child_status))
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d crashed on signal %d!",
- basename(argv[0]), child_pid, WTERMSIG(child_status));
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d stopped with status %d",
- basename(argv[0]), child_pid,
- WEXITSTATUS(child_status));
- }
- }
-
- /*
- * Leave signals blocked since exit() will be called momentarily anyways...
- */
-}
-
-
-/*
- * 'launchd_sync_conf()' - Re-write the launchd(8) config file
- * org.cups.cupsd.plist based on cupsd.conf.
- */
-
-static int /* O - 1 if the file was updated */
-launchd_sync_conf(void)
+launchd_checkout(void)
{
- int portnum; /* Port number */
- CFMutableDictionaryRef cupsd_dict, /* org.cups.cupsd.plist dictionary */
- sockets, /* Sockets dictionary */
- listener; /* Listener dictionary */
- CFDataRef resourceData; /* XML property list */
- CFMutableArrayRef array; /* Array */
- CFNumberRef socket_mode; /* Domain socket mode bits */
- CFStringRef socket_path; /* Domain socket path */
- CFTypeRef value; /* CF value */
- CFURLRef fileURL; /* File URL */
- SInt32 errorCode; /* Error code */
- cupsd_listener_t *lis; /* Current listening socket */
- struct servent *service; /* Services data base entry */
- char temp[1024]; /* Temporary buffer for value */
- struct stat cupsd_sb, /* File info for cupsd.conf */
- launchd_sb; /* File info for org.cups.cupsd.plist */
+ int fd; /* File descriptor */
/*
- * If the launchd conf file modification time is newer than the cupsd.conf
- * time then there's nothing to do...
+ * Create or remove the launchd KeepAlive file based on whether
+ * there are active jobs, polling, browsing for remote printers or
+ * shared printers to advertise...
*/
- if (!stat(ConfigurationFile, &cupsd_sb) &&
- !stat(LaunchdConf, &launchd_sb) &&
- launchd_sb.st_mtimespec.tv_sec >= cupsd_sb.st_mtimespec.tv_sec)
+ if ((cupsArrayCount(ActiveJobs) || NumPolled ||
+ (Browsing &&
+ (BrowseRemoteProtocols ||
+ (BrowseLocalProtocols && NumBrowsers && cupsArrayCount(Printers))))))
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_sync_conf: Nothing to do, pid=%d.",
- (int)getpid());
- return (0);
- }
+ "Creating launchd keepalive file \"" CUPS_KEEPALIVE "\"...");
- /*
- * Time to write a new 'org.cups.cupsd.plist' file.
- * Create the new dictionary and populate it with values...
- */
-
- if ((cupsd_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
+ if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0)
+ close(fd);
+ }
+ else
{
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_LABEL),
- CFSTR("org.cups.cupsd"));
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_ONDEMAND),
- kCFBooleanTrue);
-
- if ((Browsing && BrowseLocalProtocols && cupsArrayCount(Printers)) ||
- cupsArrayCount(ActiveJobs))
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD),
- kCFBooleanTrue);
- else
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD),
- kCFBooleanFalse);
-
-#ifdef LAUNCH_JOBKEY_SERVICEIPC
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SERVICEIPC),
- kCFBooleanTrue);
-#endif /* LAUNCH_JOBKEY_SERVICEIPC */
-
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 2,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS),
- array);
- CFArrayAppendValue(array, CFSTR("/usr/sbin/cupsd"));
- CFArrayAppendValue(array, CFSTR("-l"));
- CFRelease(array);
- }
-
- /*
- * Add a sockets dictionary...
- */
-
- if ((sockets = (CFMutableDictionaryRef)CFDictionaryCreateMutable(
- kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SOCKETS), sockets);
-
- /*
- * Add a Listeners array to the sockets dictionary...
- */
-
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(sockets, CFSTR("Listeners"), array);
-
- /*
- * For each listener add a dictionary to the listeners array...
- */
-
- for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
- lis;
- lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- {
- if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFArrayAppendValue(array, listener);
-
-# ifdef AF_LOCAL
- if (lis->address.addr.sa_family == AF_LOCAL)
- {
- if ((socket_path = CFStringCreateWithCString(kCFAllocatorDefault,
- lis->address.un.sun_path,
- kCFStringEncodingUTF8)))
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_PATHNAME),
- socket_path);
- CFRelease(socket_path);
- }
- portnum = 0140777; /* (S_IFSOCK|S_IRWXU|S_IRWXG|S_IRWXO) or *
- * 49663d decimal */
- if ((socket_mode = CFNumberCreate(kCFAllocatorDefault,
- kCFNumberIntType, &portnum)))
- {
- CFDictionaryAddValue(listener, CFSTR("SockPathMode"),
- socket_mode);
- CFRelease(socket_mode);
- }
- }
- else
-# endif /* AF_LOCAL */
- {
-# ifdef AF_INET6
- if (lis->address.addr.sa_family == AF_INET6)
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv6"));
- portnum = lis->address.ipv6.sin6_port;
- }
- else
-# endif /* AF_INET6 */
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv4"));
- portnum = lis->address.ipv4.sin_port;
- }
-
- if ((service = getservbyport(portnum, NULL)))
- value = CFStringCreateWithCString(kCFAllocatorDefault,
- service->s_name,
- kCFStringEncodingUTF8);
- else
- value = CFNumberCreate(kCFAllocatorDefault,
- kCFNumberIntType, &portnum);
-
- if (value)
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME),
- value);
- CFRelease(value);
- }
-
- httpAddrString(&lis->address, temp, sizeof(temp));
- if ((value = CFStringCreateWithCString(kCFAllocatorDefault, temp,
- kCFStringEncodingUTF8)))
- {
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_NODENAME),
- value);
- CFRelease(value);
- }
- }
-
- CFRelease(listener);
- }
- }
-
- CFRelease(array);
- }
-
- /*
- * Add the BrowseSocket to the sockets dictionary...
- */
-
- if (Browsing && (BrowseRemoteProtocols & BROWSE_CUPS))
- {
- if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks)) != NULL)
- {
- CFDictionaryAddValue(sockets, CFSTR("BrowseSockets"), array);
-
- if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks)) != NULL)
- {
- CFArrayAppendValue(array, listener);
-
- CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY),
- CFSTR("IPv4"));
- CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_TYPE),
- CFSTR("dgram"));
-
- if ((service = getservbyport(BrowsePort, NULL)))
- value = CFStringCreateWithCString(kCFAllocatorDefault,
- service->s_name,
- kCFStringEncodingUTF8);
- else
- value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
- &BrowsePort);
-
- CFDictionaryAddValue(listener,
- CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), value);
- CFRelease(value);
-
- CFRelease(listener);
- }
-
- CFRelease(array);
- }
- }
-
- CFRelease(sockets);
- }
-
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_sync_conf: Updating \"%s\", pid=%d\n",
- LaunchdConf, (int)getpid());
+ "Removing launchd keepalive file \"" CUPS_KEEPALIVE "\"...");
- if ((fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
- (const unsigned char *)LaunchdConf,
- strlen(LaunchdConf), false)))
- {
- if ((resourceData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
- cupsd_dict)))
- {
- if (!CFURLWriteDataAndPropertiesToResource(fileURL, resourceData,
- NULL, &errorCode))
- {
- cupsdLogMessage(CUPSD_LOG_WARN,
- "launchd_sync_conf: "
- "CFURLWriteDataAndPropertiesToResource(\"%s\") "
- "failed: %d\n",
- LaunchdConf, (int)errorCode);
- }
-
- CFRelease(resourceData);
- }
-
- CFRelease(fileURL);
- }
-
- CFRelease(cupsd_dict);
+ unlink(CUPS_KEEPALIVE);
}
-
- /*
- * Let the caller know we updated the file...
- */
-
- return (1);
}
#endif /* HAVE_LAUNCHD */
#endif /* HAVE_WAITPID */
{
/*
- * Ignore SIGTERM errors - that comes when a job is cancelled...
+ * Ignore SIGTERM errors - that comes when a job is canceled...
*/
cupsdFinishProcess(pid, name, sizeof(name));
return (0);
/*
- * If select has been active in the last second (fds != 0) or we have
+ * If select has been active in the last second (fds > 0) or we have
* many resources in use then don't bother trying to optimize the
* timeout, just make it 1 second.
*/
- if (fds || cupsArrayCount(Clients) > 50)
- return (1);
-
- /*
- * If we had a recent event notification, timeout in 1 second...
- */
-
- if (LastEvent)
+ if (fds > 0 || cupsArrayCount(Clients) > 50)
return (1);
/*
timeout = now + 86400; /* 86400 == 1 day */
why = "do nothing";
+ /*
+ * Check whether we are accepting new connections...
+ */
+
+ if (ListeningPaused > 0 && cupsArrayCount(Clients) < MaxClients &&
+ ListeningPaused < timeout)
+ {
+ if (ListeningPaused <= now)
+ timeout = now;
+ else
+ timeout = ListeningPaused;
+
+ why = "resume listening";
+ }
+
/*
* Check the activity and close old clients...
*/
}
#endif /* HAVE_LDAP */
- if (BrowseLocalProtocols & BROWSE_CUPS)
+ if ((BrowseLocalProtocols & BROWSE_CUPS) && NumBrowsers)
{
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
why = "browse timeout a printer";
}
}
- else if (!(p->type & CUPS_PRINTER_IMPLICIT))
+ else if (p->shared && !(p->type & CUPS_PRINTER_IMPLICIT))
{
if (BrowseInterval && (p->browse_time + BrowseInterval) < timeout)
{
* Log and return the timeout value...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout: %ld seconds to %s",
- timeout, why);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout(%d): %ld seconds to %s",
+ fds, timeout, why);
return (timeout);
}
/*
- * End of "$Id: main.c 5216 2006-03-02 17:47:53Z mike $".
+ * End of "$Id: main.c 6914 2007-09-05 21:05:04Z mike $".
*/