summaryrefslogtreecommitdiff
path: root/scheduler
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2008-04-21 23:14:57 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2008-04-21 23:14:57 +0000
commit3dfe78b3363fe9e058a98197eda9a856991cbc6f (patch)
tree4fe49470197216a2d1860e6dd327693f3636b084 /scheduler
parentae71f5deb42f3d526b5f35d2eed9241abb6405ba (diff)
downloadcups-3dfe78b3363fe9e058a98197eda9a856991cbc6f.tar.gz
Merge changes from CUPS 1.4svn-r7485.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@718 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'scheduler')
-rw-r--r--scheduler/auth.c15
-rw-r--r--scheduler/client.c67
-rw-r--r--scheduler/client.h4
-rw-r--r--scheduler/conf.c6
-rw-r--r--scheduler/dirsvc.c60
-rw-r--r--scheduler/ipp.c216
-rw-r--r--scheduler/job.c173
-rw-r--r--scheduler/job.h7
-rw-r--r--scheduler/main.c69
-rw-r--r--scheduler/printers.c7
-rw-r--r--scheduler/server.c10
-rw-r--r--scheduler/subscriptions.c6
-rw-r--r--scheduler/sysman.c115
-rw-r--r--scheduler/sysman.h23
14 files changed, 589 insertions, 189 deletions
diff --git a/scheduler/auth.c b/scheduler/auth.c
index ed49087a8..9516f28ba 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -114,7 +114,8 @@ static int compare_locations(cupsd_location_t *a,
static char *cups_crypt(const char *pw, const char *salt);
#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */
#ifdef HAVE_GSSAPI
-static gss_cred_id_t get_gss_creds(const char *service_name);
+static gss_cred_id_t get_gss_creds(const char *service_name,
+ const char *con_server_name);
#endif /* HAVE_GSSAPI */
static char *get_md5_password(const char *username,
const char *group, char passwd[33]);
@@ -990,7 +991,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
* Get the server credentials...
*/
- if ((server_creds = get_gss_creds(GSSServiceName)) == NULL)
+ if ((server_creds = get_gss_creds(GSSServiceName, con->servername)) == NULL)
return;
/*
@@ -2468,7 +2469,9 @@ cups_crypt(const char *pw, /* I - Password string */
*/
static gss_cred_id_t /* O - Server credentials */
-get_gss_creds(const char *service_name) /* I - Service name */
+get_gss_creds(
+ const char *service_name, /* I - Service name */
+ const char *con_server_name) /* I - Hostname of server */
{
OM_uint32 major_status, /* Major status code */
minor_status; /* Minor status code */
@@ -2476,12 +2479,10 @@ get_gss_creds(const char *service_name) /* I - Service name */
gss_cred_id_t server_creds; /* Server credentials */
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
/* Service name token */
- char buf[1024], /* Service name buffer */
- fqdn[HTTP_MAX_URI]; /* Hostname of server */
+ char buf[1024]; /* Service name buffer */
- snprintf(buf, sizeof(buf), "%s@%s", service_name,
- httpGetHostname(NULL, fqdn, sizeof(fqdn)));
+ snprintf(buf, sizeof(buf), "%s@%s", service_name, con_server_name);
token.value = buf;
token.length = strlen(buf);
diff --git a/scheduler/client.c b/scheduler/client.c
index ba016434a..107482773 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -28,6 +28,7 @@
* cupsdUpdateCGI() - Read status messages from CGI scripts and programs.
* cupsdWriteClient() - Write data to a client as needed.
* check_if_modified() - Decode an "If-Modified-Since" line.
+ * compare_clients() - Compare two client connections.
* encrypt_client() - Enable encryption for the client...
* get_cdsa_certificate() - Convert a keychain name into the CFArrayRef
* required by SSLSetCertificate.
@@ -82,6 +83,8 @@ extern const char *cssmErrorString(int error);
static int check_if_modified(cupsd_client_t *con,
struct stat *filestats);
+static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
+ void *data);
#ifdef HAVE_SSL
static int encrypt_client(cupsd_client_t *con);
#endif /* HAVE_SSL */
@@ -145,7 +148,18 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
if (!Clients)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to allocate memory for client array!");
+ "Unable to allocate memory for clients array!");
+ cupsdPauseListening();
+ return;
+ }
+
+ if (!ActiveClients)
+ ActiveClients = cupsArrayNew((cups_array_func_t)compare_clients, NULL);
+
+ if (!ActiveClients)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for active clients array!");
cupsdPauseListening();
return;
}
@@ -607,8 +621,11 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */
* Close the socket and clear the file from the input set for select()...
*/
- if (con->http.fd > 0)
+ if (con->http.fd >= 0)
{
+ cupsArrayRemove(ActiveClients, con);
+ cupsdSetBusyState();
+
if (partial)
{
/*
@@ -973,6 +990,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
con->http.status = HTTP_OK;
+ cupsArrayAdd(ActiveClients, con);
+ cupsdSetBusyState();
+
case HTTP_OPTIONS :
case HTTP_DELETE :
case HTTP_GET :
@@ -2144,8 +2164,16 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
break; /* Anti-compiler-warning-code */
}
- if (!con->http.keep_alive && con->http.state == HTTP_WAITING)
- cupsdCloseClient(con);
+ if (con->http.state == HTTP_WAITING)
+ {
+ if (!con->http.keep_alive)
+ cupsdCloseClient(con);
+ else
+ {
+ cupsArrayRemove(ActiveClients, con);
+ cupsdSetBusyState();
+ }
+ }
}
@@ -2913,6 +2941,26 @@ check_if_modified(
}
+/*
+ * 'compare_clients()' - Compare two client connections.
+ */
+
+static int /* O - Result of comparison */
+compare_clients(cupsd_client_t *a, /* I - First client */
+ cupsd_client_t *b, /* I - Second client */
+ void *data) /* I - User data (not used) */
+{
+ (void)data;
+
+ if (a == b)
+ return (0);
+ else if (a < b)
+ return (-1);
+ else
+ return (1);
+}
+
+
#ifdef HAVE_SSL
/*
* 'encrypt_client()' - Enable encryption for the client...
@@ -3649,12 +3697,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */
*/
if ((options = strchr(con->uri, '?')) != NULL)
- {
- options ++;
-
- if (strchr(options, '='))
- cupsdSetStringf(&(con->query_string), "QUERY_STRING=%s", options);
- }
+ cupsdSetStringf(&(con->query_string), "QUERY_STRING=%s", options + 1);
/*
* Check for known types...
@@ -3677,7 +3720,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */
filename = strrchr(filename, '/') + 1; /* Filename always absolute */
- cupsdSetString(&con->options, options);
+ cupsdSetStringf(&con->options, " %s", options);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
@@ -4678,6 +4721,8 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
envp[envc ++] = con->query_string;
}
+ else
+ envp[envc ++] = "QUERY_STRING=";
}
else
{
diff --git a/scheduler/client.h b/scheduler/client.h
index f185c1e91..e6d946d47 100644
--- a/scheduler/client.h
+++ b/scheduler/client.h
@@ -93,8 +93,10 @@ VAR cups_array_t *Listeners VALUE(NULL);
/* Listening sockets */
VAR time_t ListeningPaused VALUE(0);
/* Time when listening was paused */
-VAR cups_array_t *Clients VALUE(NULL);
+VAR cups_array_t *Clients VALUE(NULL),
/* HTTP clients */
+ *ActiveClients VALUE(NULL);
+ /* Active HTTP clients */
VAR http_addrlist_t *ServerAddrs VALUE(NULL);
/* Server address(es) */
VAR char *ServerHeader VALUE(NULL);
diff --git a/scheduler/conf.c b/scheduler/conf.c
index c8e814886..de4d98adc 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -103,6 +103,7 @@ static const cupsd_var_t variables[] =
{ "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_INTEGER },
{ "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING },
{ "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN },
+ { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_INTEGER },
{ "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING },
{ "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING },
{ "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING },
@@ -516,6 +517,7 @@ cupsdReadConfiguration(void)
#ifdef HAVE_SSL
DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
#endif /* HAVE_SSL */
+ DirtyCleanInterval = 60;
JobRetryLimit = 5;
JobRetryInterval = 300;
FileDevice = FALSE;
@@ -1188,7 +1190,7 @@ cupsdReadConfiguration(void)
cupsdLoadAllPrinters();
cupsdLoadAllClasses();
cupsdLoadRemoteCache();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
cupsdCreateCommonData();
@@ -1219,7 +1221,7 @@ cupsdReadConfiguration(void)
*/
cupsdUpdatePrinters();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
cupsdLogMessage(CUPSD_LOG_INFO, "Partial reload complete.");
}
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index f9ee02320..5bc61f680 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -98,7 +98,7 @@ static void process_browse_data(const char *uri, const char *host,
ipp_pstate_t state, const char *location,
const char *info, const char *make_model,
int num_attrs, cups_option_t *attrs);
-static void process_implicit_classes(int *write_printcap);
+static void process_implicit_classes(void);
static void send_cups_browse(cupsd_printer_t *p);
#ifdef HAVE_LDAP
static void send_ldap_browse(cupsd_printer_t *p);
@@ -616,7 +616,7 @@ cupsdLoadRemoteCache(void)
* Do auto-classing if needed...
*/
- process_implicit_classes(NULL);
+ process_implicit_classes();
}
@@ -801,7 +801,6 @@ cupsdSendBrowseList(void)
cupsd_printer_t *p; /* Current printer */
time_t ut, /* Minimum update time */
to; /* Timeout time */
- int write_printcap; /* Write the printcap file? */
if (!Browsing || !BrowseLocalProtocols || !Printers)
@@ -899,7 +898,7 @@ cupsdSendBrowseList(void)
* Loop through all of the printers and send local updates as needed...
*/
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), write_printcap = 0;
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
{
@@ -924,13 +923,10 @@ cupsdSendBrowseList(void)
cupsArraySave(Printers);
cupsdDeletePrinter(p, 1);
cupsArrayRestore(Printers);
- write_printcap = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
}
}
-
- if (write_printcap)
- cupsdWritePrintcap();
}
@@ -1749,8 +1745,7 @@ process_browse_data(
cups_option_t *attrs) /* I - Attributes */
{
int i; /* Looping var */
- int update, /* Update printer attributes? */
- write_printcap; /* Write the printcap file? */
+ int update; /* Update printer attributes? */
char finaluri[HTTP_MAX_URI], /* Final URI for printer */
name[IPP_MAX_NAME], /* Name of printer */
newname[IPP_MAX_NAME], /* New name of printer */
@@ -1837,12 +1832,11 @@ process_browse_data(
* See if we already have it listed in the Printers list, and add it if not...
*/
- type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED;
- type &= ~CUPS_PRINTER_IMPLICIT;
- update = 0;
- write_printcap = 0;
- hptr = strchr(host, '.');
- sptr = strchr(ServerName, '.');
+ type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED;
+ type &= ~CUPS_PRINTER_IMPLICIT;
+ update = 0;
+ hptr = strchr(host, '.');
+ sptr = strchr(ServerName, '.');
if (!ServerNameIsIP && sptr != NULL && hptr != NULL)
{
@@ -1965,8 +1959,9 @@ process_browse_data(
cupsdSetString(&p->device_uri, uri);
cupsdSetString(&p->hostname, host);
- update = 1;
- write_printcap = 1;
+ update = 1;
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
}
else
@@ -2072,8 +2067,9 @@ process_browse_data(
cupsdSetString(&p->uri, uri);
cupsdSetString(&p->device_uri, uri);
- write_printcap = 1;
- update = 1;
+ update = 1;
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
}
@@ -2132,8 +2128,9 @@ process_browse_data(
if (info && (!p->info || strcmp(p->info, info)))
{
cupsdSetString(&p->info, info);
- update = 1;
- write_printcap = 1;
+ update = 1;
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
if (!make_model || !make_model[0])
@@ -2198,7 +2195,7 @@ process_browse_data(
cupsdDeletePrinter(p, 1);
cupsdUpdateImplicitClasses();
- write_printcap = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
else if (update)
{
@@ -2223,7 +2220,7 @@ process_browse_data(
if (p->type & CUPS_PRINTER_DEFAULT)
{
DefaultPrinter = p;
- write_printcap = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
break;
}
}
@@ -2232,14 +2229,7 @@ process_browse_data(
* Do auto-classing if needed...
*/
- process_implicit_classes(&write_printcap);
-
- /*
- * Update the printcap file...
- */
-
- if (write_printcap)
- cupsdWritePrintcap();
+ process_implicit_classes();
}
@@ -2766,8 +2756,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
*/
static void
-process_implicit_classes(
- int *write_printcap) /* O - Write printcap file? */
+process_implicit_classes(void)
{
int i; /* Looping var */
int update; /* Update printer attributes? */
@@ -2848,8 +2837,7 @@ process_implicit_classes(
update = 1;
- if (write_printcap)
- *write_printcap = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added implicit class \"%s\"...",
name);
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index f29006b86..dc08f621b 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -42,6 +42,8 @@
* cancel_job() - Cancel a print job.
* cancel_subscription() - Cancel a subscription.
* check_quotas() - Check quotas for a printer and user.
+ * check_rss_recipient() - Check that we do not have a duplicate RSS
+ * feed URI.
* copy_attribute() - Copy a single attribute.
* copy_attrs() - Copy attributes from one request to another.
* copy_banner() - Copy a banner file to the requests directory
@@ -157,6 +159,7 @@ static void authenticate_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_all_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void cancel_subscription(cupsd_client_t *con, int id);
+static int check_rss_recipient(const char *recipient);
static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr,
int quickcopy);
@@ -858,14 +861,14 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */
if (dtype & CUPS_PRINTER_CLASS)
{
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" now accepting jobs (\"%s\").",
printer->name, get_username(con));
}
else
{
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
cupsdLogMessage(CUPSD_LOG_INFO,
"Printer \"%s\" now accepting jobs (\"%s\").",
@@ -1162,7 +1165,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */
*/
cupsdSetPrinterAttrs(pclass);
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
if (need_restart_job && pclass->job)
{
@@ -1183,7 +1186,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */
if (need_restart_job)
cupsdCheckJobs();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
if (modify)
{
@@ -1265,6 +1268,9 @@ add_file(cupsd_client_t *con, /* I - Connection to client */
job->num_files ++;
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
return (0);
}
@@ -1320,7 +1326,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */
send_http_error(con, status, printer);
return (NULL);
}
- else if ((printer->type & CUPS_PRINTER_AUTHENTICATED) &&
+ else if (printer->num_auth_info_required > 0 &&
+ strcmp(printer->auth_info_required[0], "none") &&
!con->username[0] && !auth_info)
{
send_http_error(con, HTTP_UNAUTHORIZED, printer);
@@ -1388,6 +1395,34 @@ add_job(cupsd_client_t *con, /* I - Client connection */
}
}
+ if ((attr = ippFindAttribute(con->request, "job-sheets",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ if (attr->value_tag != IPP_TAG_KEYWORD &&
+ attr->value_tag != IPP_TAG_NAME)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value type!"));
+ return (NULL);
+ }
+
+ if (attr->num_values > 2)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Too many job-sheets values (%d > 2)!"),
+ attr->num_values);
+ return (NULL);
+ }
+
+ for (i = 0; i < attr->num_values; i ++)
+ if (strcmp(attr->values[i].string.text, "none") &&
+ !cupsdFindBanner(attr->values[i].string.text))
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value \"%s\"!"),
+ attr->values[i].string.text);
+ return (NULL);
+ }
+ }
+
if ((attr = ippFindAttribute(con->request, "number-up",
IPP_TAG_INTEGER)) != NULL)
{
@@ -1487,8 +1522,11 @@ add_job(cupsd_client_t *con, /* I - Client connection */
job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
CUPS_PRINTER_REMOTE);
job->attrs = con->request;
+ job->dirty = 1;
con->request = ippNewRequest(job->attrs->request.op.operation_id);
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
add_job_uuid(con, job);
apply_printer_defaults(printer, job);
@@ -1812,7 +1850,10 @@ add_job(cupsd_client_t *con, /* I - Client connection */
job->id, attr->values[0].string.text);
if ((kbytes = copy_banner(con, job, attr->values[0].string.text)) < 0)
+ {
+ cupsdDeleteJob(job);
return (NULL);
+ }
cupsdUpdateQuota(printer, job->username, 0, kbytes);
}
@@ -1986,10 +2027,70 @@ add_job_subscriptions(
{
if (!strcmp(attr->name, "notify-recipient-uri") &&
attr->value_tag == IPP_TAG_URI)
+ {
+ /*
+ * Validate the recipient scheme against the ServerBin/notifier
+ * directory...
+ */
+
+ char notifier[1024], /* Notifier filename */
+ scheme[HTTP_MAX_URI], /* Scheme portion of URI */
+ userpass[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
recipient = attr->values[0].string.text;
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, recipient,
+ scheme, sizeof(scheme), userpass, sizeof(userpass),
+ host, sizeof(host), &port,
+ resource, sizeof(resource)) < HTTP_URI_OK)
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("Bad notify-recipient-uri URI \"%s\"!"), recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_URI_SCHEME);
+ return;
+ }
+
+ snprintf(notifier, sizeof(notifier), "%s/notifier/%s", ServerBin,
+ scheme);
+ if (access(notifier, X_OK))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient-uri URI \"%s\" uses unknown "
+ "scheme!"), recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_URI_SCHEME);
+ return;
+ }
+
+ if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient-uri URI \"%s\" is already used!"),
+ recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ return;
+ }
+ }
else if (!strcmp(attr->name, "notify-pull-method") &&
attr->value_tag == IPP_TAG_KEYWORD)
+ {
pullmethod = attr->values[0].string.text;
+
+ if (strcmp(pullmethod, "ippget"))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("Bad notify-pull-method \"%s\"!"), pullmethod);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ return;
+ }
+ }
else if (!strcmp(attr->name, "notify-charset") &&
attr->value_tag == IPP_TAG_CHARSET &&
strcmp(attr->values[0].string.text, "us-ascii") &&
@@ -2071,7 +2172,7 @@ add_job_subscriptions(
attr = attr->next;
}
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
/*
* Remove all of the subscription attributes from the job request...
@@ -2720,7 +2821,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
*/
cupsdSetPrinterAttrs(printer);
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
if (need_restart_job && printer->job)
{
@@ -2741,7 +2842,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
if (need_restart_job)
cupsdCheckJobs();
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
if (modify)
{
@@ -3914,6 +4015,40 @@ cancel_subscription(
/*
+ * 'check_rss_recipient()' - Check that we do not have a duplicate RSS feed URI.
+ */
+
+static int /* O - 1 if OK, 0 if not */
+check_rss_recipient(
+ const char *recipient) /* I - Recipient URI */
+{
+ cupsd_subscription_t *sub; /* Current subscription */
+
+
+ for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
+ sub;
+ sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ if (sub->recipient)
+ {
+ /*
+ * Compare the URIs up to the first ?...
+ */
+
+ const char *r1, *r2;
+
+ for (r1 = recipient, r2 = sub->recipient;
+ *r1 == *r2 && *r1 && *r1 != '?' && *r2 && *r2 != '?';
+ r1 ++, r2 ++);
+
+ if (*r1 == *r2)
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
* 'check_quotas()' - Check quotas for a printer and user.
*/
@@ -4436,7 +4571,8 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *attr; /* Attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_banner(%p[%d], %p[%d], %s)",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")",
con, con ? con->http.fd : -1, job, job->id,
name ? name : "(null)");
@@ -4460,7 +4596,7 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */
if ((out = cupsFileOpen(filename, "w")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "copy_banner: Unable to create banner job file %s - %s",
+ "Unable to create banner job file %s - %s",
filename, strerror(errno));
job->num_files --;
return (0);
@@ -4516,7 +4652,7 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */
cupsFileClose(out);
unlink(filename);
cupsdLogMessage(CUPSD_LOG_ERROR,
- "copy_banner: Unable to open banner template file %s - %s",
+ "Unable to open banner template file %s - %s",
filename, strerror(errno));
job->num_files --;
return (0);
@@ -5453,8 +5589,6 @@ create_job(cupsd_client_t *con, /* I - Client connection */
* Save and log the job...
*/
- cupsdSaveJob(job);
-
cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Queued on \"%s\" by \"%s\".",
job->id, job->dest, job->username);
}
@@ -5694,10 +5828,10 @@ create_subscription(
for (attr = con->request->attrs; attr; attr = attr->next)
{
if (attr->group_tag != IPP_TAG_ZERO)
- cupsdLogMessage(CUPSD_LOG_DEBUG, "g%04x v%04x %s", attr->group_tag,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "g%04x v%04x %s", attr->group_tag,
attr->value_tag, attr->name);
else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "----SEP----");
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "----SEP----");
}
#endif /* DEBUG */
@@ -5851,6 +5985,16 @@ create_subscription(
"notify-status-code", IPP_URI_SCHEME);
return;
}
+
+ if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE,
+ _("notify-recipient-uri URI \"%s\" is already used!"),
+ recipient);
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
+ "notify-status-code", IPP_ATTRIBUTES);
+ return;
+ }
}
else if (!strcmp(attr->name, "notify-pull-method") &&
attr->value_tag == IPP_TAG_KEYWORD)
@@ -6001,8 +6145,7 @@ create_subscription(
attr = attr->next;
}
- cupsdSaveAllSubscriptions();
-
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
@@ -6091,7 +6234,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
}
else
{
@@ -6099,10 +6242,10 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
/*
* Return with no errors...
@@ -6597,6 +6740,11 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
completed = 0;
list = Jobs;
}
+ else if (attr && !strcmp(attr->values[0].string.text, "printing"))
+ {
+ completed = 0;
+ list = PrintingJobs;
+ }
else
{
completed = 0;
@@ -6611,7 +6759,7 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
IPP_TAG_INTEGER)) != NULL)
limit = attr->values[0].integer;
else
- limit = 1000000;
+ limit = 0;
if ((attr = ippFindAttribute(con->request, "first-job-id",
IPP_TAG_INTEGER)) != NULL)
@@ -6637,7 +6785,7 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
*/
for (count = 0, job = (cupsd_job_t *)cupsArrayFirst(list);
- count < limit && job;
+ (limit <= 0 || count < limit) && job;
job = (cupsd_job_t *)cupsArrayNext(list))
{
/*
@@ -8271,8 +8419,6 @@ print_job(cupsd_client_t *con, /* I - Client connection */
cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] hold_until = %d", job->id,
(int)job->hold_until);
- cupsdSaveJob(job);
-
/*
* Start the job if possible...
*/
@@ -8525,14 +8671,14 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */
if (dtype & CUPS_PRINTER_CLASS)
{
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").",
printer->name, get_username(con));
}
else
{
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").",
printer->name, get_username(con));
@@ -8761,7 +8907,7 @@ renew_subscription(
sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
con->response->request.status.status_code = IPP_OK;
@@ -9485,7 +9631,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */
}
}
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
/*
* Start the job if possible... Since cupsdCheckJobs() can cancel a
@@ -9509,7 +9656,9 @@ send_document(cupsd_client_t *con, /* I - Client connection */
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
job->hold_until = time(NULL) + 60;
- cupsdSaveJob(job);
+ job->dirty = 1;
+
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
}
@@ -9676,10 +9825,8 @@ set_default(cupsd_client_t *con, /* I - Client connection */
DefaultPrinter = printer;
- cupsdSaveAllPrinters();
- cupsdSaveAllClasses();
-
- cupsdWritePrintcap();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
+ CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP);
cupsdLogMessage(CUPSD_LOG_INFO,
"Default destination set to \"%s\" by \"%s\".",
@@ -10025,7 +10172,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */
* Save the job...
*/
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
/*
* Send events as needed...
diff --git a/scheduler/job.c b/scheduler/job.c
index 11cc5fe1d..0e4e94af9 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -21,6 +21,7 @@
* cupsdCheckJobs() - Check the pending jobs and start any if
* the destination is available.
* cupsdCleanJobs() - Clean out old jobs.
+ * cupsdDeleteJob() - Free all memory used by a job.
* cupsdFinishJob() - Finish a job.
* cupsdFreeAllJobs() - Free all jobs from memory.
* cupsdFindJob() - Find the specified job.
@@ -44,7 +45,6 @@
* compare_active_jobs() - Compare the job IDs and priorities of two
* jobs.
* compare_jobs() - Compare the job IDs of two jobs.
- * free_job() - Free all memory used by a job.
* ipp_length() - Compute the size of the buffer needed to
* hold the textual IPP attributes.
* load_job_cache() - Load jobs from the job.cache file.
@@ -89,7 +89,6 @@ static mime_filter_t gziptoany_filter =
static int compare_active_jobs(void *first, void *second, void *data);
static int compare_jobs(void *first, void *second, void *data);
-static void free_job(cupsd_job_t *job);
static int ipp_length(ipp_t *ipp);
static void load_job_cache(const char *filename);
static void load_next_job_id(const char *filename);
@@ -211,10 +210,11 @@ cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */
cupsdExpireSubscriptions(NULL, job);
/*
- * Remove the job from the active list...
+ * Remove the job from the active and printing lists...
*/
cupsArrayRemove(ActiveJobs, job);
+ cupsArrayRemove(PrintingJobs, job);
/*
* Remove any authentication data...
@@ -277,7 +277,8 @@ cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */
* Save job state info...
*/
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
else
{
@@ -299,8 +300,10 @@ cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */
* Free all memory used...
*/
- free_job(job);
+ cupsdDeleteJob(job);
}
+
+ cupsdSetBusyState();
}
@@ -395,7 +398,8 @@ cupsdCheckJobs(void)
{
attr->value_tag = IPP_TAG_KEYWORD;
cupsdSetString(&(attr->values[0].string.text), "no-hold");
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
}
@@ -462,6 +466,9 @@ cupsdCheckJobs(void)
else
ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI,
"job-actual-printer-uri", NULL, printer->uri);
+
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */
@@ -511,6 +518,45 @@ cupsdCleanJobs(void)
/*
+ * 'cupsdDeleteJob()' - Free all memory used by a job.
+ */
+
+void
+cupsdDeleteJob(cupsd_job_t *job) /* I - Job */
+{
+ cupsdClearString(&job->username);
+ cupsdClearString(&job->dest);
+ cupsdClearString(&job->auth_username);
+ cupsdClearString(&job->auth_domain);
+ cupsdClearString(&job->auth_password);
+
+#ifdef HAVE_GSSAPI
+ /*
+ * Destroy the credential cache and clear the KRB5CCNAME env var string.
+ */
+
+ if (job->ccache)
+ {
+ krb5_cc_destroy(KerberosContext, job->ccache);
+ job->ccache = NULL;
+ }
+
+ cupsdClearString(&job->ccname);
+#endif /* HAVE_GSSAPI */
+
+ if (job->num_files > 0)
+ {
+ free(job->compressions);
+ free(job->filetypes);
+ }
+
+ ippDelete(job->attrs);
+
+ free(job);
+}
+
+
+/*
* 'cupsdFinishJob()' - Finish a job.
*/
@@ -608,7 +654,8 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
job->state_value = IPP_JOB_PENDING;
}
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
/*
* If the job was queued to a class, try requeuing it... For
@@ -686,7 +733,8 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
"Job held due to backend errors; please consult "
@@ -703,7 +751,9 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
cupsdSetPrinterState(printer, IPP_PRINTER_STOPPED, 1);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
@@ -730,7 +780,8 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
"Authentication is required for job %d.", job->id);
@@ -752,7 +803,8 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Job %d] Job stopped due to filter errors.", job->id);
cupsdStopJob(job, 1);
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
"Job stopped due to filter errors; please consult the "
"error_log file for details.");
@@ -812,8 +864,9 @@ cupsdFreeAllJobs(void)
{
cupsArrayRemove(Jobs, job);
cupsArrayRemove(ActiveJobs, job);
+ cupsArrayRemove(PrintingJobs, job);
- free_job(job);
+ cupsdDeleteJob(job);
}
cupsdReleaseSignals();
@@ -902,7 +955,8 @@ cupsdHoldJob(cupsd_job_t *job) /* I - Job data */
job->state_value = IPP_JOB_HELD;
job->current_file = 0;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdCheckJobs();
}
@@ -931,6 +985,9 @@ cupsdLoadAllJobs(void)
if (!ActiveJobs)
ActiveJobs = cupsArrayNew(compare_active_jobs, NULL);
+ if (!PrintingJobs)
+ PrintingJobs = cupsArrayNew(compare_jobs, NULL);
+
/*
* See whether the job.cache file is older than the RequestRoot directory...
*/
@@ -1317,7 +1374,8 @@ cupsdMoveJob(cupsd_job_t *job, /* I - Job */
"Job #%d moved from %s to %s.", job->id, olddest,
p->name);
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
@@ -1336,7 +1394,8 @@ cupsdReleaseJob(cupsd_job_t *job) /* I - Job */
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdCheckJobs();
}
}
@@ -1364,7 +1423,8 @@ cupsdRestartJob(cupsd_job_t *job) /* I - Job */
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
if (old_state > IPP_JOB_STOPPED)
cupsArrayAdd(ActiveJobs, job);
@@ -1479,6 +1539,8 @@ cupsdSaveJob(cupsd_job_t *job) /* I - Job */
"[Job %d] Unable to write job control file!", job->id);
cupsFileClose(fp);
+
+ job->dirty = 0;
}
@@ -1654,7 +1716,8 @@ cupsdSetJobPriority(
cupsArrayAdd(ActiveJobs, job);
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
@@ -1780,7 +1843,12 @@ cupsdUnloadCompletedJobs(void)
job = (cupsd_job_t *)cupsArrayNext(Jobs))
if (job->attrs && job->state_value >= IPP_JOB_STOPPED &&
job->access_time < expire)
+ {
+ if (job->dirty)
+ cupsdSaveJob(job);
+
unload_job(job);
+ }
}
@@ -1818,45 +1886,6 @@ compare_jobs(void *first, /* I - First job */
/*
- * 'free_job()' - Free all memory used by a job.
- */
-
-static void
-free_job(cupsd_job_t *job) /* I - Job */
-{
- cupsdClearString(&job->username);
- cupsdClearString(&job->dest);
- cupsdClearString(&job->auth_username);
- cupsdClearString(&job->auth_domain);
- cupsdClearString(&job->auth_password);
-
-#ifdef HAVE_GSSAPI
- /*
- * Destroy the credential cache and clear the KRB5CCNAME env var string.
- */
-
- if (job->ccache)
- {
- krb5_cc_destroy(KerberosContext, job->ccache);
- job->ccache = NULL;
- }
-
- cupsdClearString(&job->ccname);
-#endif /* HAVE_GSSAPI */
-
- if (job->num_files > 0)
- {
- free(job->compressions);
- free(job->filetypes);
- }
-
- ippDelete(job->attrs);
-
- free(job);
-}
-
-
-/*
* 'ipp_length()' - Compute the size of the buffer needed to hold
* the textual IPP attributes.
*/
@@ -2426,7 +2455,8 @@ set_hold_until(cupsd_job_t *job, /* I - Job to update */
else
cupsdSetString(&attr->values[0].string.text, holdstr);
- cupsdSaveJob(job);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
@@ -2697,6 +2727,22 @@ start_job(cupsd_job_t *job, /* I - Job ID */
}
/*
+ * Make sure we don't go over the "MAX_FILTERS" limit...
+ */
+
+ if (cupsArrayCount(filters) > MAX_FILTERS)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Too many filters (%d > %d), unable to print!",
+ job->id, cupsArrayCount(filters), MAX_FILTERS);
+
+ cupsArrayDelete(filters);
+ cupsdCancelJob(job, 0, IPP_JOB_STOPPED);
+
+ return;
+ }
+
+ /*
* Update the printer and job state to "processing"...
*/
@@ -2712,6 +2758,13 @@ start_job(cupsd_job_t *job, /* I - Job ID */
if (job->current_file == 0)
{
/*
+ * Add to the printing list...
+ */
+
+ cupsArrayAdd(PrintingJobs, job);
+ cupsdSetBusyState();
+
+ /*
* Set the processing time...
*/
@@ -3676,7 +3729,11 @@ update_job(cupsd_job_t *job) /* I - Job to check */
{
cupsdSetAuthInfoRequired(job->printer, attr, NULL);
cupsdSetPrinterAttrs(job->printer);
- cupsdSaveAllPrinters();
+
+ if (job->printer->type & CUPS_PRINTER_DISCOVERED)
+ cupsdMarkDirty(CUPSD_DIRTY_REMOTE);
+ else
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
if ((attr = cupsGetOption("printer-alert", num_attrs, attrs)) != NULL)
diff --git a/scheduler/job.h b/scheduler/job.h
index 78c836b75..09bf75ce0 100644
--- a/scheduler/job.h
+++ b/scheduler/job.h
@@ -20,7 +20,8 @@
typedef struct cupsd_job_s
{
int id, /* Job ID */
- priority; /* Job priority */
+ priority, /* Job priority */
+ dirty; /* Do we need to write the "c" file? */
ipp_jstate_t state_value; /* Cached job-state */
int pending_timeout;/* Non-zero if the job was created and waiting on files */
char *username; /* Printing user */
@@ -84,8 +85,10 @@ VAR int JobAutoPurge VALUE(0);
/* Automatically purge jobs */
VAR cups_array_t *Jobs VALUE(NULL),
/* List of current jobs */
- *ActiveJobs VALUE(NULL);
+ *ActiveJobs VALUE(NULL),
/* List of active jobs */
+ *PrintingJobs VALUE(NULL);
+ /* List of jobs that are printing */
VAR int NextJobId VALUE(1);
/* Next job ID to use */
VAR int JobRetryLimit VALUE(5),
diff --git a/scheduler/main.c b/scheduler/main.c
index e831920a0..4c7c697e9 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -862,6 +862,16 @@ main(int argc, /* I - Number of command-line args */
current_time = time(NULL);
+ /*
+ * Write dirty config/state files...
+ */
+
+ if (DirtyCleanTime && current_time >= DirtyCleanTime)
+ {
+ cupsdCleanDirty();
+ cupsdSetBusyState();
+ }
+
#ifndef __APPLE__
/*
* Update the network interfaces once a minute...
@@ -1622,27 +1632,6 @@ process_children(void)
cupsdFinishProcess(pid, name, sizeof(name));
- if (status == SIGTERM)
- status = 0;
-
- if (status)
- {
- if (WIFEXITED(status))
- cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) stopped with status %d!",
- pid, name, WEXITSTATUS(status));
- else
- cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) crashed on signal %d!",
- pid, name, WTERMSIG(status));
-
- if (LogLevel < CUPSD_LOG_DEBUG)
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Hint: Try setting the LogLevel to \"debug\" to find "
- "out more.");
- }
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "PID %d (%s) exited with no errors.",
- pid, name);
-
/*
* Delete certificates for CGI processes...
*/
@@ -1674,6 +1663,9 @@ process_children(void)
else
job->backend = -pid;
+ if (job->state_value == IPP_JOB_CANCELED)
+ status = 0; /* Ignore errors when canceling jobs */
+
if (status && job->status >= 0)
{
/*
@@ -1721,6 +1713,31 @@ process_children(void)
break;
}
}
+
+ /*
+ * Show the exit status as needed...
+ */
+
+ if (status == SIGTERM)
+ status = 0;
+
+ if (status)
+ {
+ if (WIFEXITED(status))
+ cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) stopped with status %d!",
+ pid, name, WEXITSTATUS(status));
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) crashed on signal %d!",
+ pid, name, WTERMSIG(status));
+
+ if (LogLevel < CUPSD_LOG_DEBUG)
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Hint: Try setting the LogLevel to \"debug\" to find "
+ "out more.");
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "PID %d (%s) exited with no errors.",
+ pid, name);
}
}
@@ -1910,6 +1927,16 @@ select_timeout(int fds) /* I - Number of descriptors returned */
* Check for any active jobs...
*/
+ if (DirtyCleanTime && timeout > DirtyCleanTime)
+ {
+ timeout = DirtyCleanTime;
+ why = "write dirty config/state files";
+ }
+
+ /*
+ * Check for any active jobs...
+ */
+
if (timeout > (now + 10) && ActiveJobs)
{
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 6dc8bd971..11abd6b8d 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -2793,9 +2793,9 @@ cupsdSetPrinterState(
update)
{
if (p->type & CUPS_PRINTER_CLASS)
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
else
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
}
@@ -2841,8 +2841,9 @@ cupsdStopPrinter(cupsd_printer_t *p, /* I - Printer to stop */
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
+ job->dirty = 1;
- cupsdSaveJob(job);
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
"Job stopped due to printer being paused");
diff --git a/scheduler/server.c b/scheduler/server.c
index dcff28baa..9483ae658 100644
--- a/scheduler/server.c
+++ b/scheduler/server.c
@@ -3,7 +3,7 @@
*
* Server start/stop routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -137,7 +137,6 @@ cupsdStopServer(void)
cupsdStopPolling();
cupsdStopBrowsing();
cupsdStopAllNotifiers();
- cupsdSaveRemoteCache();
cupsdDeleteAllCerts();
if (Clients)
@@ -203,6 +202,13 @@ cupsdStopServer(void)
cupsdDestroyProfile(DefaultProfile);
DefaultProfile = NULL;
+ /*
+ * Write out any dirty files...
+ */
+
+ if (DirtyFiles)
+ cupsdCleanDirty();
+
started = 0;
}
diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c
index 5bbb38c28..cea357fd3 100644
--- a/scheduler/subscriptions.c
+++ b/scheduler/subscriptions.c
@@ -297,7 +297,7 @@ cupsdAddEvent(
}
if (temp)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
else
cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...",
cupsdEventName(event));
@@ -463,7 +463,7 @@ cupsdDeleteSubscription(
*/
if (update)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
@@ -646,7 +646,7 @@ cupsdExpireSubscriptions(
}
if (update)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
diff --git a/scheduler/sysman.c b/scheduler/sysman.c
index 03aa8d035..636cc9475 100644
--- a/scheduler/sysman.c
+++ b/scheduler/sysman.c
@@ -3,7 +3,7 @@
*
* System management definitions for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -14,6 +14,11 @@
*
* Contents:
*
+ * cupsdCleanDirty() - Write dirty config and state files.
+ * cupsdMarkDirty() - Mark config or state files as needing a
+ * write.
+ * cupsdSetBusyState() - Let the system know when we are busy
+ * doing something.
* cupsdStartSystemMonitor() - Start monitoring for system change.
* cupsdStopSystemMonitor() - Stop monitoring for system change.
* cupsdUpdateSystemMonitor() - Update the current system state.
@@ -34,15 +39,108 @@
/*
- * Power management is a new addition to CUPS. Right now it is only
- * implemented on MacOS X, but essentially we use these three functions
- * to let the OS know when it is OK to put the system to sleep, typically
- * when we are not in the middle of printing a job.
+ * The system management functions cover disk and power management which
+ * are primarily used on portable computers.
*
- * Once put to sleep, we invalidate all remote printers since it is
- * common to wake up in a new location.
+ * Disk management involves delaying the write of certain configuration
+ * and state files to minimize the number of times the disk has to spin
+ * up.
+ *
+ * Power management support is currently only implemented on MacOS X, but
+ * essentially we use four functions to let the OS know when it is OK to
+ * put the system to idle sleep, typically when we are not in the middle of
+ * printing a job.
+ *
+ * Once put to sleep, we invalidate all remote printers since it is common
+ * to wake up in a new location/on a new wireless network.
+ */
+
+
+/*
+ * 'cupsdCleanDirty()' - Write dirty config and state files.
+ */
+
+void
+cupsdCleanDirty(void)
+{
+ if (DirtyFiles & CUPSD_DIRTY_PRINTERS)
+ cupsdSaveAllPrinters();
+
+ if (DirtyFiles & CUPSD_DIRTY_CLASSES)
+ cupsdSaveAllClasses();
+
+ if (DirtyFiles & CUPSD_DIRTY_REMOTE)
+ cupsdSaveRemoteCache();
+
+ if (DirtyFiles & CUPSD_DIRTY_PRINTCAP)
+ cupsdWritePrintcap();
+
+ if (DirtyFiles & CUPSD_DIRTY_JOBS)
+ {
+ cupsd_job_t *job; /* Current job */
+
+ cupsdSaveAllJobs();
+
+ for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
+ job;
+ job = (cupsd_job_t *)cupsArrayNext(Jobs))
+ if (job->dirty)
+ cupsdSaveJob(job);
+ }
+
+ if (DirtyFiles & CUPSD_DIRTY_SUBSCRIPTIONS)
+ cupsdSaveAllSubscriptions();
+
+ DirtyFiles = CUPSD_DIRTY_NONE;
+ DirtyCleanTime = 0;
+}
+
+
+/*
+ * 'cupsdMarkDirty()' - Mark config or state files as needing a write.
*/
+void
+cupsdMarkDirty(int what) /* I - What file(s) are dirty? */
+{
+ DirtyFiles |= what;
+
+ if (!DirtyCleanTime)
+ DirtyCleanTime = time(NULL) + DirtyCleanInterval;
+
+ cupsdSetBusyState();
+}
+
+
+/*
+ * 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
+ */
+
+void
+cupsdSetBusyState(void)
+{
+ int newbusy; /* New busy state */
+ static int busy = 0; /* Current busy state */
+
+
+ newbusy = DirtyCleanTime ||
+ cupsArrayCount(PrintingJobs) ||
+ cupsArrayCount(ActiveClients);
+
+ if (newbusy != busy)
+ {
+ busy = newbusy;
+
+ if (busy)
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdSetBusyState: Server no longer busy...");
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdSetBusyState: Server is now busy...");
+ }
+}
+
+
#ifdef __APPLE__
/*
* This is the Apple-specific system event code. It works by creating
@@ -280,7 +378,6 @@ cupsdUpdateSystemMonitor(void)
Sleeping = 1;
cupsdStopAllJobs(0);
- cupsdSaveAllJobs();
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
@@ -302,6 +399,8 @@ cupsdUpdateSystemMonitor(void)
}
}
+ cupsdCleanDirty();
+
IOAllowPowerChange(sysevent.powerKernelPort,
sysevent.powerNotificationID);
}
diff --git a/scheduler/sysman.h b/scheduler/sysman.h
index e30be84bf..50ef17f96 100644
--- a/scheduler/sysman.h
+++ b/scheduler/sysman.h
@@ -3,7 +3,7 @@
*
* System management definitions for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -14,9 +14,27 @@
*/
/*
+ * Constants...
+ */
+
+#define CUPSD_DIRTY_NONE 0 /* Nothing is dirty */
+#define CUPSD_DIRTY_PRINTERS 1 /* printers.conf is dirty */
+#define CUPSD_DIRTY_CLASSES 2 /* classes.conf is dirty */
+#define CUPSD_DIRTY_REMOTE 4 /* remote.cache is dirty */
+#define CUPSD_DIRTY_PRINTCAP 8 /* printcap is dirty */
+#define CUPSD_DIRTY_JOBS 16 /* jobs.cache or "c" file(s) are dirty */
+#define CUPSD_DIRTY_SUBSCRIPTIONS 32 /* subscriptions.conf is dirty */
+
+/*
* Globals...
*/
+VAR int DirtyFiles VALUE(CUPSD_DIRTY_NONE),
+ /* What files are dirty? */
+ DirtyCleanInterval VALUE(60);
+ /* How often do we write dirty files? */
+VAR time_t DirtyCleanTime VALUE(0);
+ /* When to clean dirty files next */
VAR int Sleeping VALUE(0);
/* Non-zero if machine is entering or *
* in a sleep state... */
@@ -30,6 +48,9 @@ VAR int SysEventPipes[2] VALUE2(-1,-1);
* Prototypes...
*/
+extern void cupsdCleanDirty(void);
+extern void cupsdMarkDirty(int what);
+extern void cupsdSetBusyState(void);
extern void cupsdStartSystemMonitor(void);
extern void cupsdStopSystemMonitor(void);
extern void cupsdUpdateSystemMonitor(void);