/*
- * "$Id: job.c 6376 2007-03-21 06:39:10Z mike $"
+ * "$Id: job.c 7005 2007-10-01 23:45:48Z mike $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
+ * 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
- * "LICENSE.txt" 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
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
* start_job() - Start a print job.
* unload_job() - Unload a job from memory.
* update_job() - Read a status update from a jobs filters.
+ * update_job_attrs() - Update the job-printer-* attributes.
*/
/*
static void start_job(cupsd_job_t *job, cupsd_printer_t *printer);
static void unload_job(cupsd_job_t *job);
static void update_job(cupsd_job_t *job);
+static void update_job_attrs(cupsd_job_t *job);
/*
case IPP_JOB_COMPLETED :
/*
- * Clear the printer's state_message and state_reasons and move on...
+ * Clear the printer's printer-state-message and move on...
*/
printer->state_message[0] = '\0';
- cupsdSetPrinterReasons(printer, "");
cupsdSetPrinterState(printer, IPP_PRINTER_IDLE, 0);
cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
*/
snprintf(filename, sizeof(filename), "%s/a%05d", RequestRoot, job->id);
- unlink(filename);
+ if (cupsdRemoveFile(filename) && errno != ENOENT)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to remove authentication cache: %s",
+ strerror(errno));
+
+ 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 */
/*
* Remove the print file for good if we aren't preserving jobs or
job->hold_until &&
job->hold_until < time(NULL))
{
+ if (job->pending_timeout)
+ cupsdTimeoutJob(job); /* Add trailing banner as needed */
+
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
}
pclass = printer;
- if (!(pclass->type & CUPS_PRINTER_REMOTE) &&
- pclass->state != IPP_PRINTER_STOPPED)
- printer = cupsdFindAvailablePrinter(job->dest);
- else
+ if (pclass->state == IPP_PRINTER_STOPPED)
printer = NULL;
+ else if (pclass->type & CUPS_PRINTER_REMOTE)
+ break;
+ else
+ printer = cupsdFindAvailablePrinter(printer->name);
}
if (!printer && !pclass)
*/
cupsdLogMessage(CUPSD_LOG_WARN,
- "Printer/class %s has gone away; canceling job %d!",
- job->dest, job->id);
+ "[Job %d] Printer/class %s has gone away; canceling job!",
+ job->id, job->dest);
cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
"Job canceled because the destination printer/class has "
"job-actual-printer-uri", NULL, printer->uri);
}
- if ((!(printer->type & CUPS_PRINTER_REMOTE) && /* Printer is local */
+ if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */
printer->state == IPP_PRINTER_IDLE) || /* and idle */
- ((printer->type & CUPS_PRINTER_REMOTE) && /* Printer is remote */
+ ((printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is remote */
!printer->job)) /* and not printing */
+ {
+ /*
+ * Clear any message and reasons for the queue...
+ */
+
+ printer->state_message[0] = '\0';
+
+ cupsdSetPrinterReasons(printer, "none");
+
+ /*
+ * Start the job...
+ */
+
start_job(job, printer);
+ }
}
}
}
cupsdFinishJob(cupsd_job_t *job) /* I - Job */
{
cupsd_printer_t *printer; /* Current printer */
+ ipp_attribute_t *attr; /* job-hold-until attribute */
cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] File %d is complete.",
job->id, job->current_file - 1);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFinishJob: job->status is %d",
- job->status);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "[Job %d] cupsdFinishJob: job->status is %d",
+ job->id, job->status);
if (job->status_buffer &&
(job->status < 0 || job->current_file >= job->num_files))
cupsdRemoveSelect(job->status_buffer->fd);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdFinishJob: Closing status pipes [ %d %d ]...",
- job->status_pipes[0], job->status_pipes[1]);
+ "[Job %d] cupsdFinishJob: Closing status pipes [ %d %d ]...",
+ job->id, job->status_pipes[0], job->status_pipes[1]);
cupsdClosePipe(job->status_pipes);
cupsdStatBufDelete(job->status_buffer);
printer = job->printer;
+ update_job_attrs(job);
+
if (job->status < 0)
{
/*
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Canceling job %d since it could not be sent "
- "after %d tries.",
+ "[Job %d] Canceling job since it could not be "
+ "sent after %d tries.",
job->id, JobRetryLimit);
cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
case CUPS_BACKEND_AUTH_REQUIRED :
cupsdStopJob(job, 0);
- cupsdSetJobHoldUntil(job, "authenticated");
+ cupsdSetJobHoldUntil(job, "auth-info-required");
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
+ IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr)
+ {
+ attr->value_tag = IPP_TAG_KEYWORD;
+ cupsdSetString(&(attr->values[0].string.text),
+ "auth-info-required");
+ }
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
* Filter had errors; stop job...
*/
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Job stopped due to filter errors.", job->id);
cupsdStopJob(job, 1);
cupsdSaveJob(job);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
* Close out this job...
*/
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Completed successfully.",
+ job->id);
cupsdCancelJob(job, 0, IPP_JOB_COMPLETED);
cupsdCheckJobs();
}
job->state->values[0].integer = IPP_JOB_HELD;
job->state_value = IPP_JOB_HELD;
+ job->current_file = 0;
cupsdSaveJob(job);
cups_file_t *fp; /* Job file */
int fileid; /* Current file ID */
ipp_attribute_t *attr; /* Job attribute */
- const char *dest; /* Destination */
+ const char *dest; /* Destination name */
+ cupsd_printer_t *destptr; /* Pointer to destination */
mime_type_t **filetypes; /* New filetypes array */
int *compressions; /* New compressions array */
if ((job->attrs = ippNew()) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Ran out of memory for job attributes!");
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Ran out of memory for job attributes!", job->id);
return;
}
* Load job attributes...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading attributes for job %d...",
- job->id);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading attributes...", job->id);
snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, job->id);
if ((fp = cupsFileOpen(jobfile, "r")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to open job control file \"%s\" - %s!",
- jobfile, strerror(errno));
+ "[Job %d] Unable to open job control file \"%s\" - %s!",
+ job->id, jobfile, strerror(errno));
ippDelete(job->attrs);
job->attrs = NULL;
return;
if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, job->attrs) != IPP_DATA)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to read job control file \"%s\"!",
- jobfile);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to read job control file \"%s\"!",
+ job->id, jobfile);
cupsFileClose(fp);
ippDelete(job->attrs);
job->attrs = NULL;
IPP_TAG_ENUM)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing or bad job-state attribute in control "
- "file \"%s\"!",
- jobfile);
+ "[Job %d] Missing or bad job-state attribute in "
+ "control file!",
+ job->id);
ippDelete(job->attrs);
job->attrs = NULL;
unlink(jobfile);
IPP_TAG_URI)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "No job-printer-uri attribute in control file \"%s\"!",
- jobfile);
+ "[Job %d] No job-printer-uri attribute in control file!",
+ job->id);
ippDelete(job->attrs);
job->attrs = NULL;
unlink(jobfile);
}
if ((dest = cupsdValidateDest(attr->values[0].string.text, &(job->dtype),
- NULL)) == NULL)
+ &destptr)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to queue job for destination \"%s\"!",
- attr->values[0].string.text);
+ "[Job %d] Unable to queue job for destination \"%s\"!",
+ job->id, attr->values[0].string.text);
ippDelete(job->attrs);
job->attrs = NULL;
unlink(jobfile);
cupsdSetString(&job->dest, dest);
}
+ else if ((destptr = cupsdFindDest(job->dest)) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to queue job for destination \"%s\"!",
+ job->id, job->dest);
+ ippDelete(job->attrs);
+ job->attrs = NULL;
+ unlink(jobfile);
+ return;
+ }
job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed",
IPP_TAG_INTEGER);
IPP_TAG_INTEGER)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing or bad job-priority attribute in control "
- "file \"%s\"!", jobfile);
+ "[Job %d] Missing or bad job-priority attribute in "
+ "control file!", job->id);
ippDelete(job->attrs);
job->attrs = NULL;
unlink(jobfile);
IPP_TAG_NAME)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing or bad job-originating-user-name attribute "
- "in control file \"%s\"!", jobfile);
+ "[Job %d] Missing or bad job-originating-user-name "
+ "attribute in control file!", job->id);
ippDelete(job->attrs);
job->attrs = NULL;
unlink(jobfile);
if (access(jobfile, 0))
break;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Auto-typing document file \"%s\"...",
- jobfile);
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Job %d] Auto-typing document file \"%s\"...",
+ job->id, jobfile);
if (fileid > job->num_files)
{
if (!compressions || !filetypes)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Ran out of memory for job file types!");
+ "[Job %d] Ran out of memory for job file types!",
+ job->id);
return;
}
}
}
+ /*
+ * Load authentication information as needed...
+ */
+
+ if (job->state_value < IPP_JOB_STOPPED)
+ {
+ snprintf(jobfile, sizeof(jobfile), "%s/a%05d", RequestRoot, job->id);
+
+ cupsdClearString(&job->auth_username);
+ cupsdClearString(&job->auth_domain);
+ cupsdClearString(&job->auth_password);
+
+ if ((fp = cupsFileOpen(jobfile, "r")) != NULL)
+ {
+ int i, /* Looping var */
+ bytes; /* Size of auth data */
+ char line[255], /* Line from file */
+ data[255]; /* Decoded data */
+
+
+ for (i = 0;
+ i < destptr->num_auth_info_required &&
+ cupsFileGets(fp, line, sizeof(line));
+ i ++)
+ {
+ bytes = sizeof(data);
+ httpDecode64_2(data, &bytes, line);
+
+ if (!strcmp(destptr->auth_info_required[i], "username"))
+ cupsdSetStringf(&job->auth_username, "AUTH_USERNAME=%s", data);
+ else if (!strcmp(destptr->auth_info_required[i], "domain"))
+ cupsdSetStringf(&job->auth_domain, "AUTH_DOMAIN=%s", data);
+ else if (!strcmp(destptr->auth_info_required[i], "password"))
+ cupsdSetStringf(&job->auth_password, "AUTH_PASSWORD=%s", data);
+ }
+
+ cupsFileClose(fp);
+ }
+ }
job->access_time = time(NULL);
}
* Change the destination information...
*/
- cupsdLoadJob(job);
+ if (job->state_value == IPP_JOB_PROCESSING)
+ cupsdStopJob(job, 0);
+ else
+ cupsdLoadJob(job);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, oldp, job,
"Job #%d moved from %s to %s.", job->id, olddest,
if ((fp = cupsFileOpen(filename, "w")) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create job control file \"%s\" - %s.",
- filename, strerror(errno));
+ "[Job %d] Unable to create job control file \"%s\" - %s.",
+ job->id, filename, strerror(errno));
return;
}
if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL,
job->attrs) != IPP_DATA)
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to write job control file \"%s\"!",
- filename);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to write job control file!", job->id);
cupsFileClose(fp);
}
second = 0;
- if (!strcmp(when, "indefinite") || !strcmp(when, "authenticated"))
+ if (!strcmp(when, "indefinite") || !strcmp(when, "auth-info-required"))
{
/*
* Hold indefinitely...
int i; /* Looping var */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopJob: id = %d, force = %d",
- job->id, force);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "[Job %d] cupsdStopJob: force = %d", job->id, force);
if (job->state_value != IPP_JOB_PROCESSING)
return;
job->backend = 0;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopJob: Closing print pipes [ %d %d ]...",
- job->print_pipes[0], job->print_pipes[1]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] Closing print pipes [ %d %d ]...",
+ job->id, job->print_pipes[0], job->print_pipes[1]);
cupsdClosePipe(job->print_pipes);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopJob: Closing back pipes [ %d %d ]...",
- job->back_pipes[0], job->back_pipes[1]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] Closing back pipes [ %d %d ]...",
+ job->id, job->back_pipes[0], job->back_pipes[1]);
cupsdClosePipe(job->back_pipes);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopJob: Closing side pipes [ %d %d ]...",
- job->side_pipes[0], job->side_pipes[1]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] Closing side pipes [ %d %d ]...",
+ job->id, job->side_pipes[0], job->side_pipes[1]);
cupsdClosePipe(job->side_pipes);
cupsdRemoveSelect(job->status_buffer->fd);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopJob: Closing status pipes [ %d %d ]...",
+ "[Job %d] Closing status pipes [ %d %d ]...", job->id,
job->status_pipes[0], job->status_pipes[1]);
cupsdClosePipe(job->status_pipes);
{
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 */
snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, jobid);
if (access(jobfile, 0))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Job %d files have gone away!", jobid);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Files have gone away!",
+ jobid);
continue;
}
if (!job)
{
cupsdLogMessage(CUPSD_LOG_EMERG,
- "Unable to allocate memory for job %d!", jobid);
+ "[Job %d] Unable to allocate memory for job!", jobid);
break;
}
job->status_pipes[0] = -1;
job->status_pipes[1] = -1;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading job %d from cache...", job->id);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading from cache...", job->id);
}
else if (!job)
{
if (access(jobfile, 0))
{
cupsdLogMessage(CUPSD_LOG_INFO,
- "Data files for job %d have gone away!", job->id);
+ "[Job %d] Data files have gone away!", job->id);
job->num_files = 0;
continue;
}
if (!job->filetypes || !job->compressions)
{
cupsdLogMessage(CUPSD_LOG_EMERG,
- "Unable to allocate memory for %d files!",
- job->num_files);
+ "[Job %d] Unable to allocate memory for %d files!",
+ job->id, job->num_files);
break;
}
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unknown MIME type %s/%s for file %d of job %d!",
- super, type, number + 1, job->id);
+ "[Job %d] Unknown MIME type %s/%s for file %d!",
+ job->id, super, type, number + 1);
snprintf(jobfile, sizeof(jobfile), "%s/d%05d-%03d", RequestRoot,
job->id, number + 1);
title[IPP_MAX_NAME],
/* Job title string */
copies[255], /* # copies string */
- *envp[MAX_ENV + 12],
+ *envp[MAX_ENV + 15],
/* Environment variables */
charset[255], /* CHARSET env variable */
class_name[255],/* CLASS env variable */
static int optlength = 0; /* Length of option buffer */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job: id = %d, file = %d/%d",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] start_job: file = %d/%d",
job->id, job->current_file, job->num_files);
if (job->num_files == 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Job ID %d has no files! Canceling it!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] No files, canceling job!",
job->id);
cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
if (!filters)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to convert file %d to printable format for "
- "job %d!",
+ "[Job %d] Unable to convert file %d to printable format!",
job->current_file, job->id);
cupsdLogMessage(CUPSD_LOG_INFO,
"Hint: Do you have ESP Ghostscript installed?");
cupsArrayDelete(filters);
cupsdLogMessage(CUPSD_LOG_INFO,
- "Holding job %d because filter limit has been reached.",
+ "[Job %d] Holding because filter limit has been reached.",
job->id);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: id=%d, file=%d, cost=%d, level=%d, "
- "limit=%d",
+ "[Job %d] start_job: file=%d, cost=%d, level=%d, limit=%d",
job->id, job->current_file, job->cost, FilterLevel,
FilterLimit);
return;
if (!cupsArrayInsert(filters, &gziptoany_filter))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to add decompression filter - %s",
- strerror(errno));
+ "[Job %d] Unable to add decompression filter - %s",
+ job->id, strerror(errno));
cupsArrayDelete(filters);
if (!cupsArrayAdd(filters, &port_monitor))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to add port monitor - %s",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to add port monitor - %s",
+ job->id, strerror(errno));
cupsArrayDelete(filters);
if (job->job_sheets == NULL)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG, "No job-sheets attribute.");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] No job-sheets attribute.",
+ job->id);
if ((job->job_sheets =
ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "... but someone added one without setting job_sheets!");
+ "[Job %d] ... but someone added one without setting "
+ "job_sheets!", job->id);
}
else if (job->job_sheets->num_values == 1)
- cupsdLogMessage(CUPSD_LOG_DEBUG, "job-sheets=%s",
- job->job_sheets->values[0].string.text);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] job-sheets=%s", job->id,
+ job->job_sheets->values[0].string.text);
else
- cupsdLogMessage(CUPSD_LOG_DEBUG, "job-sheets=%s,%s",
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] job-sheets=%s,%s", job->id,
job->job_sheets->values[0].string.text,
job->job_sheets->values[1].string.text);
else
banner_page = 0;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "banner_page = %d", banner_page);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] banner_page = %d", job->id,
+ banner_page);
/*
* Building the options string is harder than it needs to be, but
if (optptr == NULL)
{
cupsdLogMessage(CUPSD_LOG_CRIT,
- "Unable to allocate %d bytes for option buffer for "
- "job %d!", i, job->id);
+ "[Job %d] Unable to allocate %d bytes for option buffer!",
+ job->id, i);
cupsArrayDelete(filters);
if ((!strcmp(attr->name, "page-label") ||
!strcmp(attr->name, "page-border") ||
!strncmp(attr->name, "number-up", 9) ||
+ !strcmp(attr->name, "page-ranges") ||
!strcmp(attr->name, "page-set") ||
!strcasecmp(attr->name, "AP_FIRSTPAGE_InputSlot") ||
- !strcasecmp(attr->name, "AP_FIRSTPAGE_ManualFeed")) &&
+ !strcasecmp(attr->name, "AP_FIRSTPAGE_ManualFeed") ||
+ !strcasecmp(attr->name, "com.apple.print.PrintSettings."
+ "PMTotalSidesImaged..n.") ||
+ !strcasecmp(attr->name, "com.apple.print.PrintSettings."
+ "PMTotalBeginPages..n.")) &&
banner_page)
continue;
* Just the language code (ll)...
*/
- snprintf(lang, sizeof(lang), "LANG=%s",
+ snprintf(lang, sizeof(lang), "LANG=%s.UTF8",
attr->values[0].string.text);
break;
* Language and country code (ll-cc)...
*/
- snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c",
+ snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF8",
attr->values[0].string.text[0],
attr->values[0].string.text[1],
toupper(attr->values[0].string.text[3] & 255),
envp[envc ++] = printer_name;
if (!printer->remote && !printer->raw &&
- (filter = (mime_filter_t *)cupsArrayLast(filters)) != NULL)
+ (filter = (mime_filter_t *)cupsArrayLast(filters)) != NULL &&
+ filter->dst)
{
snprintf(final_content_type, sizeof(final_content_type),
"FINAL_CONTENT_TYPE=%s/%s",
envp[envc ++] = class_name;
}
+ if (job->auth_username)
+ envp[envc ++] = job->auth_username;
+ if (job->auth_domain)
+ envp[envc ++] = job->auth_domain;
+ if (job->auth_password)
+ envp[envc ++] = job->auth_password;
+
#ifdef HAVE_GSSAPI
if (job->ccname)
envp[envc ++] = job->ccname;
envp[envc] = NULL;
for (i = 0; i < envc; i ++)
- if (strncmp(envp[i], "DEVICE_URI=", 11))
+ if (!strncmp(envp[i], "AUTH_", 5))
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] envp[%d]=\"AUTH_%c****\"",
+ job->id, i, envp[i][5]);
+ else if (strncmp(envp[i], "DEVICE_URI=", 11))
cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] envp[%d]=\"%s\"",
job->id, i, envp[i]);
else
{
if (cupsdOpenPipe(job->status_pipes))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create job status pipes - %s.",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to create job status pipes - %s.",
+ job->id, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to create status pipes - %s.", strerror(errno));
goto abort_job;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job: status_pipes = [ %d %d ]",
- job->status_pipes[0], job->status_pipes[1]);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "[Job %d] start_job: status_pipes = [ %d %d ]",
+ job->id, job->status_pipes[0], job->status_pipes[1]);
job->status_buffer = cupsdStatBufNew(job->status_pipes[0], "[Job %d]",
job->id);
+ job->status_level = CUPSD_LOG_INFO;
}
job->status = 0;
if (cupsdOpenPipe(filterfds[slot]))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create job filter pipes - %s.",
- strerror(errno));
+ "[Job %d] Unable to create job filter pipes - %s.",
+ job->id, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to create filter pipes - %s.", strerror(errno));
cupsdAddPrinterHistory(printer);
if (cupsdOpenPipe(job->print_pipes))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create job backend pipes - %s.",
- strerror(errno));
+ "[Job %d] Unable to create job backend pipes - %s.",
+ job->id, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to create backend pipes - %s.", strerror(errno));
cupsdAddPrinterHistory(printer);
if (job->print_pipes[1] < 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to open output file \"%s\" - %s.",
- printer->device_uri, strerror(errno));
+ "[Job %d] Unable to open output file \"%s\" - %s.",
+ job->id, printer->device_uri, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to open output file \"%s\" - %s.",
printer->device_uri, strerror(errno));
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: print_pipes = [ %d %d ]",
- job->print_pipes[0], job->print_pipes[1]);
+ "[Job %d] start_job: print_pipes = [ %d %d ]",
+ job->id, job->print_pipes[0], job->print_pipes[1]);
}
filterfds[slot][0] = job->print_pipes[0];
filterfds[slot][1] = job->print_pipes[1];
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job: filter=\"%s\"",
- command);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] start_job: filter=\"%s\"",
+ job->id, command);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: filterfds[%d]=[ %d %d ]",
- slot, filterfds[slot][0], filterfds[slot][1]);
+ "[Job %d] start_job: filterfds[%d]=[ %d %d ]",
+ job->id, slot, filterfds[slot][0], filterfds[slot][1]);
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
job->filters + i);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing filter pipes for slot %d "
+ "[Job %d] start_job: Closing filter pipes for slot %d "
"[ %d %d ]...",
- !slot, filterfds[!slot][0], filterfds[!slot][1]);
+ job->id, !slot, filterfds[!slot][0], filterfds[!slot][1]);
cupsdClosePipe(filterfds[!slot]);
if (pid == 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to start filter \"%s\" - %s.",
- filter->filter, strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to start filter \"%s\" - %s.",
+ job->id, filter->filter, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to start filter \"%s\" - %s.",
filter->filter, strerror(errno));
goto abort_job;
}
- cupsdLogMessage(CUPSD_LOG_INFO, "Started filter %s (PID %d) for job %d.",
- command, pid, job->id);
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Started filter %s (PID %d)",
+ job->id, command, pid);
argv[6] = NULL;
slot = !slot;
filterfds[slot][0] = -1;
filterfds[slot][1] = -1;
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job: backend=\"%s\"",
- command);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] start_job: backend=\"%s\"",
+ job->id, command);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: filterfds[%d] = [ %d %d ]",
+ "[Job %d] start_job: filterfds[%d] = [ %d %d ]", job->id,
slot, filterfds[slot][0], filterfds[slot][1]);
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
if (pid == 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to start backend \"%s\" - %s.",
- method, strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "[Job %d] Unable to start backend \"%s\" - %s.",
+ job->id, method, strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to start backend \"%s\" - %s.", method,
strerror(errno));
}
else
{
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Started backend %s (PID %d) for job %d.",
- command, pid, job->id);
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Started backend %s (PID %d)",
+ job->id, command, pid);
}
}
if (job->current_file == job->num_files)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing print pipes [ %d %d ]...",
- job->print_pipes[0], job->print_pipes[1]);
+ "[Job %d] start_job: Closing print pipes [ %d %d ]...",
+ job->id, job->print_pipes[0], job->print_pipes[1]);
cupsdClosePipe(job->print_pipes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing back pipes [ %d %d ]...",
- job->back_pipes[0], job->back_pipes[1]);
+ "[Job %d] start_job: Closing back pipes [ %d %d ]...",
+ job->id, job->back_pipes[0], job->back_pipes[1]);
cupsdClosePipe(job->back_pipes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing side pipes [ %d %d ]...",
- job->side_pipes[0], job->side_pipes[1]);
+ "[Job %d] start_job: Closing side pipes [ %d %d ]...",
+ job->id, job->side_pipes[0], job->side_pipes[1]);
cupsdClosePipe(job->side_pipes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing status output pipe %d...",
- job->status_pipes[1]);
+ "[Job %d] start_job: Closing status output pipe %d...",
+ job->id, job->status_pipes[1]);
close(job->status_pipes[1]);
job->status_pipes[1] = -1;
if (job->current_file == job->num_files)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing print pipes [ %d %d ]...",
- job->print_pipes[0], job->print_pipes[1]);
+ "[Job %d] start_job: Closing print pipes [ %d %d ]...",
+ job->id, job->print_pipes[0], job->print_pipes[1]);
cupsdClosePipe(job->print_pipes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing status output pipe %d...",
- job->status_pipes[1]);
+ "[Job %d] start_job: Closing status output pipe %d...",
+ job->id, job->status_pipes[1]);
close(job->status_pipes[1]);
job->status_pipes[1] = -1;
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing filter pipes for slot %d "
+ "[Job %d] start_job: Closing filter pipes for slot %d "
"[ %d %d ]...",
- slot, filterfds[slot][0], filterfds[slot][1]);
+ job->id, slot, filterfds[slot][0], filterfds[slot][1]);
cupsdClosePipe(filterfds[slot]);
if (printer->remote && job->num_files > 1)
for (slot = 0; slot < 2; slot ++)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing filter pipes for slot %d "
+ "[Job %d] start_job: Closing filter pipes for slot %d "
"[ %d %d ]...",
- slot, filterfds[slot][0], filterfds[slot][1]);
+ job->id, slot, filterfds[slot][0], filterfds[slot][1]);
cupsdClosePipe(filterfds[slot]);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Closing status pipes [ %d %d ]...",
- job->status_pipes[0], job->status_pipes[1]);
+ "[Job %d] start_job: Closing status pipes [ %d %d ]...",
+ job->id, job->status_pipes[0], job->status_pipes[1]);
cupsdClosePipe(job->status_pipes);
cupsdStatBufDelete(job->status_buffer);
+ job->status_buffer = NULL;
+
cupsArrayDelete(filters);
if (printer->remote && job->num_files > 1)
if (!job->attrs)
return;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Unloading job %d...", job->id);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Unloading...", job->id);
ippDelete(job->attrs);
- job->attrs = NULL;
- job->state = NULL;
- job->sheets = NULL;
- job->job_sheets = NULL;
+ job->attrs = NULL;
+ job->state = NULL;
+ job->sheets = NULL;
+ job->job_sheets = NULL;
+ job->printer_message = NULL;
+ job->printer_reasons = NULL;
}
*/
void
-update_job(cupsd_job_t *job) /* I - Job to check */
+update_job(cupsd_job_t *job) /* I - Job to check */
{
int i; /* Looping var */
int copies; /* Number of copies printed */
*/
cupsdLogMessage(CUPSD_LOG_INFO,
- "Job %d canceled: pages exceed user %s quota "
- "limit on printer %s (%s).",
+ "[Job %d] Canceled because pages exceed user %s "
+ "quota limit on printer %s (%s).",
job->id, job->username, job->printer->name,
job->printer->info);
}
else if (loglevel == CUPSD_LOG_STATE)
{
- cupsdSetPrinterReasons(job->printer, message);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ if (!strcmp(message, "paused"))
+ {
+ cupsdStopPrinter(job->printer, 1);
+ return;
+ }
+ else
+ {
+ cupsdSetPrinterReasons(job->printer, message);
+ cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+
+ update_job_attrs(job);
}
else if (loglevel == CUPSD_LOG_ATTR)
{
if ((attr = cupsGetOption("auth-info-required", num_attrs,
attrs)) != NULL)
+ {
cupsdSetAuthInfoRequired(job->printer, attr, NULL);
+ cupsdSetPrinterAttrs(job->printer);
+ cupsdSaveAllPrinters();
+ }
+
+ if ((attr = cupsGetOption("printer-alert", num_attrs, attrs)) != NULL)
+ {
+ cupsdSetString(&job->printer->alert, attr);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
+
+ if ((attr = cupsGetOption("printer-alert-description", num_attrs,
+ attrs)) != NULL)
+ {
+ cupsdSetString(&job->printer->alert_description, attr);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+ }
cupsFreeOptions(num_attrs, attrs);
}
event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
}
#endif /* __APPLE__ */
- else if (loglevel <= CUPSD_LOG_INFO)
+ else if (loglevel <= job->status_level)
{
/*
* Some message to show in the printer-state-message attribute...
*/
+ if (loglevel != CUPSD_LOG_NOTICE)
+ job->status_level = loglevel;
+
strlcpy(job->printer->state_message, message,
sizeof(job->printer->state_message));
cupsdAddPrinterHistory(job->printer);
event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+
+ update_job_attrs(job);
}
if (!strchr(job->status_buffer->buffer, '\n'))
/*
- * End of "$Id: job.c 6376 2007-03-21 06:39:10Z mike $".
+ * 'update_job_attrs()' - Update the job-printer-* attributes.
+ */
+
+void
+update_job_attrs(cupsd_job_t *job) /* I - Job to update */
+{
+ int i; /* Looping var */
+ int num_reasons; /* Actual number of reasons */
+ const char * const *reasons; /* Reasons */
+ static const char *none = "none", /* "none" */
+ *paused = "paused";
+ /* "paused" */
+
+
+ /*
+ * Get/create the job-printer-state-* attributes...
+ */
+
+ if (!job->printer_message)
+ {
+ if ((job->printer_message = ippFindAttribute(job->attrs,
+ "job-printer-state-message",
+ IPP_TAG_TEXT)) == NULL)
+ job->printer_message = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_TEXT,
+ "job-printer-state-message",
+ NULL, "");
+ }
+
+ if (!job->printer_reasons)
+ job->printer_reasons = ippFindAttribute(job->attrs,
+ "job-printer-state-reasons",
+ IPP_TAG_KEYWORD);
+
+ /*
+ * If the job isn't printing, return now...
+ */
+
+ if (!job->printer)
+ return;
+
+ /*
+ * Otherwise copy the printer-state-message value...
+ */
+
+ if (job->printer->state_message[0])
+ cupsdSetString(&(job->printer_message->values[0].string.text),
+ job->printer->state_message);
+
+ /*
+ * ... and the printer-state-reasons value...
+ */
+
+ if (job->printer->num_reasons == 0)
+ {
+ num_reasons = 1;
+ reasons = job->printer->state == IPP_PRINTER_STOPPED ? &paused : &none;
+ }
+ else
+ {
+ num_reasons = job->printer->num_reasons;
+ reasons = (const char * const *)job->printer->reasons;
+ }
+
+ if (!job->printer_reasons || job->printer_reasons->num_values != num_reasons)
+ {
+ ippDeleteAttribute(job->attrs, job->printer_reasons);
+
+ job->printer_reasons = ippAddStrings(job->attrs,
+ IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-printer-state-reasons",
+ num_reasons, NULL, NULL);
+ }
+
+ for (i = 0; i < num_reasons; i ++)
+ cupsdSetString(&(job->printer_reasons->values[i].string.text), reasons[i]);
+}
+
+
+/*
+ * End of "$Id: job.c 7005 2007-10-01 23:45:48Z mike $".
*/