cups/backport-delay-creating-driverless-printer-until-ppd-generated.patch
2024-10-08 14:35:05 +08:00

1122 lines
37 KiB
Diff

From df3718b09f395d59b454e0aa233490ba7f2aa857 Mon Sep 17 00:00:00 2001
From: Michael R Sweet <msweet@msweet.org>
Date: Thu, 4 Apr 2024 16:25:25 -0400
Subject: [PATCH] Update CUPS-Add-Modify-Printer and CUPS-Create-Local-Printer
code to delay responding until the PPD is successfully generated (Issue #347)
---
scheduler/auth.c | 15 +-
scheduler/auth.h | 2 -
scheduler/client.h | 2 +
scheduler/cupsd.h | 9 +
scheduler/ipp.c | 383 ++++++++++++++++++++++++++++---------------
scheduler/policy.h | 2 -
scheduler/printers.c | 6 +-
scheduler/printers.h | 2 -
8 files changed, 271 insertions(+), 150 deletions(-)
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -105,7 +105,7 @@
cupsd_authmask_t temp; /* New host/domain mask */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)", masks, *masks, address[0], address[1], address[2], address[3], netmask[0], netmask[1], netmask[2], netmask[3]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)", (void *)masks, (void *)*masks, address[0], address[1], address[2], address[3], netmask[0], netmask[1], netmask[2], netmask[3]);
temp.type = CUPSD_AUTH_IP;
memcpy(temp.mask.ip.address, address, sizeof(temp.mask.ip.address));
@@ -158,7 +158,7 @@
cupsdAddName(cupsd_location_t *loc, /* I - Location to add to */
char *name) /* I - Name to add */
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", loc, name);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", (void *)loc, name);
if (!loc->names)
loc->names = cupsArrayNew3(NULL, NULL, NULL, 0,
@@ -188,7 +188,7 @@
*ifptr; /* Pointer to end of name */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", masks, *masks, name);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", (void *)masks, (void *)*masks, name);
if (!_cups_strcasecmp(name, "@LOCAL"))
{
@@ -274,7 +274,7 @@
con->best = cupsdFindBest(con->uri, httpGetState(con->http));
con->type = CUPSD_AUTH_NONE;
- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location : "");
+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "con->uri=\"%s\", con->best=%p(%s)", con->uri, (void *)con->best, con->best ? con->best->location : "");
if (con->best && con->best->type != CUPSD_AUTH_NONE)
{
@@ -1143,7 +1143,7 @@
#endif /* HAVE_MBR_UID_TO_UUID */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", username, user, groupname);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", username, (void *)user, groupname);
/*
* Validate input...
@@ -1558,7 +1558,7 @@
};
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location ? con->best->location : "(null)" : "");
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", con->uri, (void *)con->best, con->best ? con->best->location ? con->best->location : "(null)" : "");
if (owner)
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: owner=\"%s\"", owner);
@@ -2129,7 +2129,6 @@
free(snap_name);
g_clear_object(&snap);
-
# endif // CUPS_SNAP
done:
@@ -2140,6 +2139,8 @@
return (ret);
#else
+ (void)con;
+
// No AppArmor/snapd to deal with...
return (1);
#endif // HAVE_LIBAPPARMOR && HAVE_LIBSNAPDGLIB
--- a/scheduler/auth.h
+++ b/scheduler/auth.h
@@ -98,8 +98,6 @@
http_encryption_t encryption; /* To encrypt or not to encrypt... */
} cupsd_location_t;
-typedef struct cupsd_client_s cupsd_client_t;
-
/*
* Globals...
--- a/scheduler/client.h
+++ b/scheduler/client.h
@@ -42,6 +42,8 @@
*query_string; /* QUERY_STRING environment variable */
int file; /* Input/output file */
int file_ready; /* Input ready on file/pipe? */
+ int bg_pending; /* Background response pending? */
+ cupsd_printer_t *bg_printer; /* Background printer */
int pipe_pid; /* Pipe process ID (or 0 if not a pipe) */
http_status_t pipe_status; /* HTTP status from pipe process */
int sent_header, /* Non-zero if sent HTTP header */
--- a/scheduler/cupsd.h
+++ b/scheduler/cupsd.h
@@ -100,6 +100,15 @@
/*
+ * Base types...
+ */
+
+typedef struct cupsd_client_s cupsd_client_t;
+typedef struct cupsd_job_s cupsd_job_t;
+typedef struct cupsd_printer_s cupsd_printer_t;
+
+
+/*
* Other stuff for the scheduler...
*/
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -73,7 +73,7 @@
cups_array_t *ra,
cups_array_t *exclude);
static void create_job(cupsd_client_t *con, ipp_attribute_t *uri);
-static void *create_local_bg_thread(cupsd_printer_t *printer);
+static void *create_local_bg_thread(cupsd_client_t *con);
static void create_local_printer(cupsd_client_t *con);
static cups_array_t *create_requested_array(ipp_t *request);
static void create_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri);
@@ -111,6 +111,7 @@
static void send_http_error(cupsd_client_t *con, http_status_t status,
cupsd_printer_t *printer);
static void send_ipp_status(cupsd_client_t *con, ipp_status_t status, const char *message, ...) _CUPS_FORMAT(3, 4);
+static int send_response(cupsd_client_t *con);
static void set_default(cupsd_client_t *con, ipp_attribute_t *uri);
static void set_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
static void set_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
@@ -143,7 +144,7 @@
int valid = 1; /* Valid request? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id=%04x(%s)", con, con->number, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id));
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id=%04x(%s)", (void *)con, con->number, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id));
if (LogLevel >= CUPSD_LOG_DEBUG2)
{
@@ -615,68 +616,13 @@
}
}
- if (con->response)
+ if (!con->bg_pending && con->response)
{
/*
* Sending data from the scheduler...
*/
- cupsdLogClient(con, con->response->request.status.status_code >= IPP_STATUS_ERROR_BAD_REQUEST && con->response->request.status.status_code != IPP_STATUS_ERROR_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s.", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", con->http->hostname);
-
- httpClearFields(con->http);
-
-#ifdef CUPSD_USE_CHUNKING
- /*
- * Because older versions of CUPS (1.1.17 and older) and some IPP
- * clients do not implement chunking properly, we cannot use
- * chunking by default. This may become the default in future
- * CUPS releases, or we might add a configuration directive for
- * it.
- */
-
- if (con->http->version == HTTP_1_1)
- {
- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Transfer-Encoding: chunked");
- cupsdSetLength(con->http, 0);
- }
- else
-#endif /* CUPSD_USE_CHUNKING */
- {
- size_t length; /* Length of response */
-
-
- length = ippLength(con->response);
-
- if (con->file >= 0 && !con->pipe_pid)
- {
- struct stat fileinfo; /* File information */
-
- if (!fstat(con->file, &fileinfo))
- length += (size_t)fileinfo.st_size;
- }
-
- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Content-Length: " CUPS_LLFMT, CUPS_LLCAST length);
- httpSetLength(con->http, length);
- }
-
- if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE))
- {
- /*
- * Tell the caller the response header was sent successfully...
- */
-
- cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, (cupsd_selfunc_t)cupsdWriteClient, con);
-
- return (1);
- }
- else
- {
- /*
- * Tell the caller the response header could not be sent...
- */
-
- return (0);
- }
+ return (send_response(con));
}
else
{
@@ -747,7 +693,7 @@
cupsd_printer_t *printer; /* Printer data */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -832,7 +778,7 @@
int need_restart_job; /* Need to restart job? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -1142,7 +1088,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"add_file(con=%p[%d], job=%d, filetype=%s/%s, "
- "compression=%d)", con, con ? con->number : -1, job->id,
+ "compression=%d)", (void *)con, con ? con->number : -1, job->id,
filetype->super, filetype->type, compression);
/*
@@ -1245,8 +1191,8 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
- con, con->number, printer, printer->name,
- filetype, filetype ? filetype->super : "none",
+ (void *)con, con->number, (void *)printer, printer->name,
+ (void *)filetype, filetype ? filetype->super : "none",
filetype ? filetype->type : "none");
/*
@@ -2226,7 +2172,7 @@
set_port_monitor; /* Did we set the port monitor? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -2717,8 +2663,21 @@
return;
}
- // Run a background thread to create the PPD...
- _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer);
+ if (!printer->printer_id)
+ printer->printer_id = NextPrinterId ++;
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
+
+ cupsdSetPrinterAttrs(printer);
+
+ /* Run a background thread to create the PPD... */
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Creating PPD in background thread.");
+
+ con->bg_pending = 1;
+ con->bg_printer = printer;
+
+ _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, con);
+ return;
}
else if (!strcmp(ppd_name, "raw"))
{
@@ -2883,7 +2842,7 @@
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"add_printer_state_reasons(%p[%d], %p[%s])",
- con, con->number, p, p->name);
+ (void *)con, con->number, (void *)p, p->name);
if (p->num_reasons == 0)
ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
@@ -2909,7 +2868,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_queued_job_count(%p[%d], %p[%s])",
- con, con->number, p, p->name);
+ (void *)con, con->number, (void *)p, p->name);
count = cupsdGetPrinterJobCount(p->name);
@@ -2999,7 +2958,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "authenticate_job(%p[%d], %s)",
- con, con->number, uri->values[0].string.text);
+ (void *)con, con->number, uri->values[0].string.text);
/*
* Start with "everything is OK" status...
@@ -3177,7 +3136,7 @@
cupsd_job_t *job; /* Job */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -3414,7 +3373,7 @@
cupsd_jobaction_t purge; /* Purge the job? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -3615,7 +3574,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cancel_subscription(con=%p[%d], sub_id=%d)",
- con, con->number, sub_id);
+ (void *)con, con->number, sub_id);
/*
* Is the subscription ID valid?
@@ -3721,7 +3680,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "check_quotas(%p[%d], %p[%s])",
- con, con->number, p, p->name);
+ (void *)con, con->number, (void *)p, p->name);
/*
* Figure out who is printing...
@@ -3943,7 +3902,7 @@
username[256]; /* User name */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -4063,7 +4022,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"copy_attrs(to=%p, from=%p, ra=%p, group=%x, quickcopy=%d)",
- to, from, ra, group, quickcopy);
+ (void *)to, (void *)from, (void *)ra, group, quickcopy);
if (!to || !from)
return;
@@ -4147,7 +4106,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")",
- con, con ? con->number : -1, job, job->id,
+ (void *)con, con ? con->number : -1, (void *)job, job->id,
name ? name : "(null)");
/*
@@ -4492,7 +4451,7 @@
/* cupsProtocol attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_model(con=%p, from=\"%s\", to=\"%s\")", con, from, to);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_model(con=%p, from=\"%s\", to=\"%s\")", (void *)con, from, to);
/*
* Run cups-driverd to get the PPD file...
@@ -5106,7 +5065,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)",
- con, sub, ra, exclude);
+ (void *)con, (void *)sub, (void *)ra, (void *)exclude);
/*
* Copy the subscription attributes to the response using the
@@ -5220,7 +5179,7 @@
};
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -5285,11 +5244,14 @@
static void * /* O - Exit status */
create_local_bg_thread(
- cupsd_printer_t *printer) /* I - Printer */
+ cupsd_client_t *con) /* I - Client */
{
+ cupsd_printer_t *printer = con->bg_printer;
+ /* Printer */
cups_file_t *from, /* Source file */
*to; /* Destination file */
- char fromppd[1024], /* Source PPD */
+ char device_uri[1024], /* Device URI */
+ fromppd[1024], /* Source PPD */
toppd[1024], /* Destination PPD */
scheme[32], /* URI scheme */
userpass[256], /* User:pass */
@@ -5301,7 +5263,7 @@
http_encryption_t encryption; /* Type of encryption to use */
http_t *http; /* Connection to printer */
ipp_t *request, /* Request to printer */
- *response; /* Response from printer */
+ *response = NULL; /* Response from printer */
ipp_attribute_t *attr; /* Attribute in response */
ipp_status_t status; /* Status code */
static const char * const pattrs[] = /* Printer attributes we need */
@@ -5315,26 +5277,47 @@
* Try connecting to the printer...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, printer->device_uri);
+ _cupsRWLockRead(&printer->lock);
+ strlcpy(device_uri, printer->device_uri, sizeof(device_uri));
+ _cupsRWUnlock(&printer->lock);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, device_uri);
- if (strstr(printer->device_uri, "._tcp"))
+ if (strstr(device_uri, "._tcp"))
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s: Resolving mDNS URI \"%s\".", printer->name, printer->device_uri);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s: Resolving mDNS URI \"%s\".", printer->name, device_uri);
- if (!_httpResolveURI(printer->device_uri, uri, sizeof(uri), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
+ if (!_httpResolveURI(device_uri, uri, sizeof(uri), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Couldn't resolve mDNS URI \"%s\".", printer->name, printer->device_uri);
- return (NULL);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Couldn't resolve mDNS URI \"%s\".", printer->name, device_uri);
+
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Couldn't resolve mDNS URI \"%s\"."), printer->device_uri);
+ goto finish_response;
}
+ _cupsRWLockWrite(&printer->lock);
cupsdSetString(&printer->device_uri, uri);
+ _cupsRWUnlock(&printer->lock);
+
+ strlcpy(device_uri, uri, sizeof(device_uri));
}
- if (httpSeparateURI(HTTP_URI_CODING_ALL, printer->device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, printer->device_uri);
- return (NULL);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, device_uri);
+
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Bad device URI \"%s\"."), device_uri);
+ goto finish_response;
}
if (!strcmp(scheme, "ipps") || port == 443)
@@ -5345,7 +5328,14 @@
if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to %s:%d: %s", printer->name, host, port, cupsLastErrorString());
- return (NULL);
+
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to connect to %s:%d: %s"), host, port, cupsLastErrorString());
+ goto finish_response;
}
/*
@@ -5389,6 +5379,7 @@
* If we did not succeed to obtain the "media-col-database" attribute
* try to get it separately
*/
+
if (ippFindAttribute(response, "media-col-database", IPP_TAG_ZERO) ==
NULL)
{
@@ -5447,17 +5438,29 @@
if ((from = cupsFileOpen(fromppd, "r")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to read generated PPD: %s", printer->name, strerror(errno));
- ippDelete(response);
- return (NULL);
+
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to read generated PPD: %s"), strerror(errno));
+ goto finish_response;
}
snprintf(toppd, sizeof(toppd), "%s/ppd/%s.ppd", ServerRoot, printer->name);
if ((to = cupsdCreateConfFile(toppd, ConfigFilePerm)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to create PPD for printer: %s", printer->name, strerror(errno));
- ippDelete(response);
cupsFileClose(from);
- return (NULL);
+
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to create PPD for printer: %s"), strerror(errno));
+ goto finish_response;
}
while (cupsFileGets(from, line, sizeof(line)))
@@ -5466,10 +5469,14 @@
cupsFileClose(from);
if (!cupsdCloseCreatedConfFile(to, toppd))
{
+ _cupsRWLockWrite(&printer->lock);
+
printer->config_time = time(NULL);
printer->state = IPP_PSTATE_IDLE;
printer->accepting = 1;
+ _cupsRWUnlock(&printer->lock);
+
cupsdSetPrinterAttrs(printer);
cupsdAddEvent(CUPSD_EVENT_PRINTER_CONFIG, printer, NULL, "Printer \"%s\" is now available.", printer->name);
@@ -5477,10 +5484,39 @@
}
}
else
+ {
cupsdLogMessage(CUPSD_LOG_ERROR, "%s: PPD creation failed: %s", printer->name, cupsLastErrorString());
+ /* Force printer to timeout and be deleted */
+ _cupsRWLockWrite(&printer->lock);
+ printer->state_time = 0;
+ _cupsRWUnlock(&printer->lock);
+
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to create PPD: %s"), cupsLastErrorString());
+ goto finish_response;
+ }
+
+ /*
+ * Respond to the client...
+ */
+
+ send_ipp_status(con, IPP_STATUS_OK, _("Local printer created."));
+
+ ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting);
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", (int)printer->state);
+ add_printer_state_reasons(con, printer);
+
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), httpIsEncrypted(con->http) ? "ipps" : "ipp", NULL, con->clientname, con->clientport, "/printers/%s", printer->name);
+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, uri);
+
+ finish_response:
+
ippDelete(response);
+ send_response(con);
+
+ con->bg_pending = 0;
+
return (NULL);
}
@@ -5592,10 +5628,21 @@
if ((printer = cupsdFindDest(name)) != NULL)
{
- send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Printer \"%s\" already exists."), name);
+ printer->state_time = time(NULL);
+ send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), name);
goto add_printer_attributes;
}
+ for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); printer; printer = (cupsd_printer_t *)cupsArrayNext(Printers))
+ {
+ if (printer->device_uri && !strcmp(ptr, printer->device_uri))
+ {
+ printer->state_time = time(NULL);
+ send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name);
+ goto add_printer_attributes;
+ }
+ }
+
/*
* Create the printer...
*/
@@ -5682,14 +5729,17 @@
* Run a background thread to create the PPD...
*/
- _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer);
+ con->bg_pending = 1;
+ con->bg_printer = printer;
+
+ _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, con);
+
+ return;
/*
* Return printer attributes...
*/
- send_ipp_status(con, IPP_STATUS_OK, _("Local printer created."));
-
add_printer_attributes:
ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting);
@@ -5795,7 +5845,7 @@
* Is the destination valid?
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", con, con->number, uri->values[0].string.text);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", (void *)con, con->number, uri->values[0].string.text);
httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
sizeof(scheme), userpass, sizeof(userpass), host,
@@ -6143,7 +6193,7 @@
int temporary; /* Temporary queue? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -6256,7 +6306,7 @@
cups_array_t *ra; /* Requested attributes array */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", con, con->number);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", (void *)con, con->number);
/*
* Check policy...
@@ -6306,7 +6356,7 @@
/* String for included schemes */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->number);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", (void *)con, con->number);
/*
* Check policy...
@@ -6399,7 +6449,7 @@
format[1024]; /* Format for document */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -6546,7 +6596,7 @@
*exclude; /* Private attributes array */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -6677,7 +6727,7 @@
cupsd_policy_t *policy; /* Current policy */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->number,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", (void *)con, con->number,
uri->values[0].string.text);
/*
@@ -6988,7 +7038,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"get_jobs: job->id=%d, dest=\"%s\", username=\"%s\", "
"state_value=%d, attrs=%p", job->id, job->dest,
- job->username, job->state_value, job->attrs);
+ job->username, job->state_value, (void *)job->attrs);
if (!job->dest || !job->username)
cupsdLoadJob(job);
@@ -7067,7 +7117,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_notifications(con=%p[%d])",
- con, con->number);
+ (void *)con, con->number);
/*
* Get subscription attributes...
@@ -7200,8 +7250,8 @@
cups_ptype_t dtype; /* Destination type */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con,
- con->number, uri, uri->name, uri->values[0].string.text);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", (void *)con,
+ con->number, (void *)uri, uri->name, uri->values[0].string.text);
if (!strcmp(ippGetName(uri), "ppd-name"))
{
@@ -7373,7 +7423,7 @@
/* String for included schemes */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->number);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", (void *)con, con->number);
/*
* Check policy...
@@ -7517,7 +7567,7 @@
cups_array_t *ra; /* Requested attributes array */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -7573,7 +7623,7 @@
cupsd_printer_t *printer; /* Printer/class */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -7643,7 +7693,7 @@
int local; /* Local connection? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", (void *)con,
con->number, type);
/*
@@ -7804,7 +7854,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"get_subscription_attrs(con=%p[%d], sub_id=%d)",
- con, con->number, sub_id);
+ (void *)con, con->number, sub_id);
/*
* Expire subscriptions as needed...
@@ -7891,7 +7941,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"get_subscriptions(con=%p[%d], uri=%s)",
- con, con->number, uri->values[0].string.text);
+ (void *)con, con->number, uri->values[0].string.text);
/*
* Is the destination valid?
@@ -8059,7 +8109,7 @@
cupsd_job_t *job; /* Job information */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", con, con->number,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", (void *)con, con->number,
uri->values[0].string.text);
/*
@@ -8190,7 +8240,7 @@
cupsd_printer_t *printer; /* Printer data */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -8267,7 +8317,7 @@
*dprinter; /* Destination printer */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", con, con->number,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", (void *)con, con->number,
uri->values[0].string.text);
/*
@@ -8596,7 +8646,7 @@
int compression; /* Document compression */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", con, con->number,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", (void *)con, con->number,
uri->values[0].string.text);
/*
@@ -9047,7 +9097,7 @@
ipp_attribute_t *attr; /* printer-state-message text */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -9129,7 +9179,7 @@
cupsd_printer_t *printer; /* Printer data */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -9202,7 +9252,7 @@
cupsd_job_t *job; /* Job information */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -9339,7 +9389,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"renew_subscription(con=%p[%d], sub_id=%d)",
- con, con->number, sub_id);
+ (void *)con, con->number, sub_id);
/*
* Is the subscription ID valid?
@@ -9426,7 +9476,7 @@
int port; /* Port portion of URI */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -9777,7 +9827,7 @@
int start_job; /* Start the job? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -10289,6 +10339,82 @@
/*
+ * 'send_response()' - Send the IPP response.
+ */
+
+static int /* O - 1 on success, 0 on failure */
+send_response(cupsd_client_t *con) /* I - Client */
+{
+ ipp_attribute_t *uri; /* Target URI */
+ int ret = 0; /* Return value */
+ static _cups_mutex_t mutex = _CUPS_MUTEX_INITIALIZER;
+ /* Mutex for logging/access */
+
+
+ _cupsMutexLock(&mutex);
+
+ if ((uri = ippFindAttribute(con->request, "printer-uri", IPP_TAG_URI)) == NULL)
+ {
+ if ((uri = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI)) == NULL)
+ uri = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME);
+ }
+
+ cupsdLogClient(con, con->response->request.status.status_code >= IPP_STATUS_ERROR_BAD_REQUEST && con->response->request.status.status_code != IPP_STATUS_ERROR_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s.", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", con->http->hostname);
+
+ httpClearFields(con->http);
+
+#ifdef CUPSD_USE_CHUNKING
+ /*
+ * Because older versions of CUPS (1.1.17 and older) and some IPP
+ * clients do not implement chunking properly, we cannot use
+ * chunking by default. This may become the default in future
+ * CUPS releases, or we might add a configuration directive for
+ * it.
+ */
+
+ if (con->http->version == HTTP_1_1)
+ {
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Transfer-Encoding: chunked");
+ cupsdSetLength(con->http, 0);
+ }
+ else
+#endif /* CUPSD_USE_CHUNKING */
+ {
+ size_t length; /* Length of response */
+
+
+ length = ippLength(con->response);
+
+ if (con->file >= 0 && !con->pipe_pid)
+ {
+ struct stat fileinfo; /* File information */
+
+ if (!fstat(con->file, &fileinfo))
+ length += (size_t)fileinfo.st_size;
+ }
+
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Content-Length: " CUPS_LLFMT, CUPS_LLCAST length);
+ httpSetLength(con->http, length);
+ }
+
+ if (cupsdSendHeader(con, HTTP_STATUS_OK, "application/ipp", CUPSD_AUTH_NONE))
+ {
+ /*
+ * Tell the caller the response header was sent successfully...
+ */
+
+ cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, (cupsd_selfunc_t)cupsdWriteClient, con);
+
+ ret = 1;
+ }
+
+ _cupsMutexUnlock(&mutex);
+
+ return (ret);
+}
+
+
+/*
* 'set_default()' - Set the default destination...
*/
@@ -10302,7 +10428,7 @@
*oldprinter; /* Old default printer */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -10384,7 +10510,7 @@
int check_jobs; /* Check jobs? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -10764,7 +10890,7 @@
int changed = 0; /* Was anything changed? */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -11110,7 +11236,7 @@
cupsd_printer_t *printer; /* Printer data */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -11192,7 +11318,7 @@
ipp_attribute_t *attr; /* printer-state-message attribute */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -11434,7 +11560,7 @@
cupsd_printer_t *printer; /* Printer */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", con,
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", (void *)con,
con->number, uri->values[0].string.text);
/*
@@ -11627,7 +11753,7 @@
cupsd_printer_t *printer; /* Printer for job */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", username, CUPS_LLCAST userlen);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", (void *)username, CUPS_LLCAST userlen);
/*
* Validate input...
--- a/scheduler/policy.h
+++ b/scheduler/policy.h
@@ -22,8 +22,6 @@
*ops; /* Operations */
} cupsd_policy_t;
-typedef struct cupsd_printer_s cupsd_printer_t;
-
/*
* Globals...
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -620,7 +620,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)",
- p, p->name, update);
+ (void *)p, p->name, update);
/*
* Save the current position in the Printers array...
@@ -782,11 +782,11 @@
"cupsdDeleteTemporaryPrinters: Removing unused temporary printers");
/*
- * Allow temporary printers to stick around for 60 seconds after the last job
+ * Allow temporary printers to stick around for 5 minutes after the last job
* completes.
*/
- unused_time = time(NULL) - 60;
+ unused_time = time(NULL) - 300;
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers))
{
@@ -2550,7 +2550,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", p, p->name, s);
+ "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", (void *)p, p->name, s);
if (s[0] == '-' || s[0] == '+')
{
@@ -3396,7 +3396,7 @@
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"add_printer_filter(p=%p(%s), filtertype=%p(%s/%s), "
- "filter=\"%s\")", p, p->name, filtertype, filtertype->super,
+ "filter=\"%s\")", (void *)p, p->name, (void *)filtertype, filtertype->super,
filtertype->type, filter);
/*
--- a/scheduler/printers.h
+++ b/scheduler/printers.h
@@ -50,8 +50,6 @@
* Printer/class information structure...
*/
-typedef struct cupsd_job_s cupsd_job_t;
-
struct cupsd_printer_s
{
_cups_rwlock_t lock; /* Concurrency lock for background updates */
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -430,6 +430,14 @@
con->file = -1;
}
+ if (con->bg_pending)
+ {
+ /*
+ * Don't close connection when there is a background thread pending
+ */
+ partial = 1;
+ }
+
/*
* Close the socket and clear the file from the input set for select()...
*/