* cupsdCleanJobs() - Clean out old jobs.
* cupsdContinueJob() - Continue printing with the next file in a job.
* cupsdDeleteJob() - Free all memory used by a job.
- * cupsdFinishJob() - Finish a job.
* cupsdFreeAllJobs() - Free all jobs from memory.
* cupsdFindJob() - Find the specified job.
* cupsdGetPrinterJobCount() - Get the number of pending, processing, or held
* compare_active_jobs() - Compare the job IDs and priorities of two
* jobs.
* compare_jobs() - Compare the job IDs of two jobs.
+ * dump_job_history() - Dump any debug messages for a job.
+ * free_job_history() - Free any log history.
* finalize_job() - Cleanup after job filter processes and support
* data.
* get_options() - Get a string containing the job options.
static int compare_active_jobs(void *first, void *second, void *data);
static int compare_jobs(void *first, void *second, void *data);
+static void dump_job_history(cupsd_job_t *job);
static void finalize_job(cupsd_job_t *job);
+static void free_job_history(cupsd_job_t *job);
static char *get_options(cupsd_job_t *job, int banner_page, char *copies,
size_t copies_size, char *title,
size_t title_size);
cupsd_printer_t *printer, /* Printer destination */
*pclass; /* Printer class destination */
ipp_attribute_t *attr; /* Job attribute */
+ time_t curtime; /* Current time */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdCheckJobs: %d active jobs, sleeping=%d, reload=%d",
cupsArrayCount(ActiveJobs), Sleeping, NeedReload);
+ curtime = time(NULL);
+
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
job;
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
{
+ /*
+ * Kill jobs if they are unresponsive...
+ */
+
+ if (job->kill_time && job->kill_time <= curtime)
+ {
+ stop_job(job, CUPSD_JOB_FORCE);
+ continue;
+ }
+
/*
* Start held jobs if they are ready...
*/
if (job->state_value == IPP_JOB_HELD &&
job->hold_until &&
- job->hold_until < time(NULL))
+ job->hold_until < curtime)
{
if (job->pending_timeout)
{
"Job submission timed out.");
}
+ /*
+ * Continue jobs that are waiting on the FilterLimit...
+ */
+
+ if (job->pending_cost > 0 &&
+ ((FilterLevel + job->pending_cost) < FilterLimit || FilterLevel == 0))
+ cupsdContinueJob(job);
+
/*
* Start pending jobs if the destination is available...
*/
{
int i; /* Looping var */
int slot; /* Pipe slot */
- cups_array_t *filters, /* Filters for job */
+ cups_array_t *filters = NULL,/* Filters for job */
*prefilters; /* Filters with prefilters */
mime_filter_t *filter, /* Current filter */
*prefilter, /* Prefilter */
ipp_attribute_t *attr; /* Current attribute */
const char *ptr, /* Pointer into value */
*abort_message; /* Abort message */
+ ipp_jstate_t abort_state = IPP_JOB_STOPPED;
+ /* New job state on abort */
struct stat backinfo; /* Backend file information */
int backroot; /* Run backend as root? */
int pid; /* Process ID of new filter process */
int banner_page; /* 1 if banner page, 0 otherwise */
- int filterfds[2][2];/* Pipes used between filters */
+ int filterfds[2][2] = { { -1, -1 }, { -1, -1 } };
+ /* Pipes used between filters */
int envc; /* Number of environment variables */
- char **argv, /* Filter command-line arguments */
+ char **argv = NULL, /* Filter command-line arguments */
filename[1024], /* Job filename */
command[1024], /* Full path to command */
jobid[255], /* Job ID string */
FilterLevel -= job->cost;
- filters = NULL;
+ job->cost = 0;
+ job->pending_cost = 0;
+
+ memset(job->filters, 0, sizeof(job->filters));
+
if (job->printer->raw)
{
*/
cupsdLogJob(job, CUPSD_LOG_DEBUG, "Sending job to queue tagged as raw...");
-
- filters = NULL;
}
else
{
"Unable to convert file %d to printable format!",
job->current_file);
- job->current_file ++;
+ abort_message = "Aborting job because it cannot be printed.";
+ abort_state = IPP_JOB_ABORTED;
- if (job->current_file == job->num_files)
- cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT,
- "Aborting job because it cannot be printed.");
-
- return;
+ goto abort_job;
}
/*
"cupsdContinueJob: file=%d, cost=%d, level=%d, limit=%d",
job->current_file, job->cost, FilterLevel,
FilterLimit);
+
+ job->pending_cost = job->cost;
+ job->cost = 0;
return;
}
cupsArrayDelete(filters);
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT,
- "Stopping job because the scheduler ran out of "
- "memory.");
+ abort_message = "Stopping job because the scheduler ran out of memory.";
- FilterLevel -= job->cost;
- return;
+ goto abort_job;
}
}
cupsdLogJob(job, CUPSD_LOG_DEBUG,
"Unable to add port monitor - %s", strerror(errno));
- cupsArrayDelete(filters);
-
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT,
- "Stopping job because the scheduler ran out of "
- "memory.");
+ abort_message = "Stopping job because the scheduler ran out of memory.";
- FilterLevel -= job->cost;
- return;
+ goto abort_job;
}
}
"Too many filters (%d > %d), unable to print!",
cupsArrayCount(filters), MAX_FILTERS);
- cupsArrayDelete(filters);
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT,
- "Stopping job because it needs too many filters to "
- "print.");
+ abort_message = "Aborting job because it needs too many filters to print.";
+ abort_state = IPP_JOB_ABORTED;
- FilterLevel -= job->cost;
- return;
+ goto abort_job;
}
/*
if ((options = get_options(job, banner_page, copies, sizeof(copies), title,
sizeof(title))) == NULL)
{
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT,
- "Stopping job because the scheduler ran out of memory.");
- cupsArrayDelete(filters);
+ abort_message = "Stopping job because the scheduler ran out of memory.";
- FilterLevel -= job->cost;
- return;
+ goto abort_job;
}
/*
{
cupsdLogMessage(CUPSD_LOG_DEBUG, "Unable to allocate argument array - %s",
strerror(errno));
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT,
- "Stopping job because the scheduler ran out of memory.");
- cupsArrayDelete(filters);
- FilterLevel -= job->cost;
- return;
+ abort_message = "Stopping job because the scheduler ran out of memory.";
+
+ goto abort_job;
}
sprintf(jobid, "%d", job->id);
* Just the language code (ll)...
*/
- snprintf(lang, sizeof(lang), "LANG=%s.UTF8",
+ snprintf(lang, sizeof(lang), "LANG=%s.UTF-8",
attr->values[0].string.text);
break;
* Language and country code (ll-cc)...
*/
- snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF8",
+ snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF-8",
attr->values[0].string.text[0],
attr->values[0].string.text[1],
toupper(attr->values[0].string.text[3] & 255),
* Now create processes for all of the filters...
*/
- filterfds[0][0] = -1;
- filterfds[0][1] = -1;
- filterfds[1][0] = -1;
- filterfds[1][1] = -1;
-
- memset(job->filters, 0, sizeof(job->filters));
-
for (i = 0, slot = 0, filter = (mime_filter_t *)cupsArrayFirst(filters);
filter;
i ++, filter = (mime_filter_t *)cupsArrayNext(filters))
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
job->back_pipes[0], job->side_pipes[0], 0,
- job->profile, job->id, job->filters + i);
+ job->profile, job, job->filters + i);
cupsdClosePipe(filterfds[!slot]);
cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to start filter \"%s\" - %s.",
filter->filter, strerror(errno));
- abort_message = "Stopped job because the scheduler could not execute a "
+ abort_message = "Stopping job because the scheduler could not execute a "
"filter.";
goto abort_job;
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
job->back_pipes[1], job->side_pipes[1],
- backroot, job->profile, job->id, &(job->backend));
+ backroot, job->profile, job, &(job->backend));
if (pid == 0)
{
cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job, "Job #%d started.",
job->id);
+ /*
+ * If we get here than we are able to run the printer driver filters, so clear
+ * the missing and insecure warnings...
+ */
+
+ if (cupsdSetPrinterReasons(job->printer, "-cups-missing-filter-warning,"
+ "cups-insecure-filter-warning"))
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL,
+ "Printer drivers now functional.");
+
return;
abort_job:
+ FilterLevel -= job->cost;
+ job->cost = 0;
+
for (slot = 0; slot < 2; slot ++)
cupsdClosePipe(filterfds[slot]);
+ cupsArrayDelete(filters);
+
+ if (argv)
+ {
+ if (job->printer->remote && job->num_files > 1)
+ {
+ for (i = 0; i < job->num_files; i ++)
+ free(argv[i + 6]);
+ }
+
+ free(argv);
+ }
+
+ cupsdClosePipe(job->print_pipes);
+ cupsdClosePipe(job->back_pipes);
+ cupsdClosePipe(job->side_pipes);
+
+ cupsdRemoveSelect(job->status_pipes[0]);
cupsdClosePipe(job->status_pipes);
cupsdStatBufDelete(job->status_buffer);
job->status_buffer = NULL;
- cupsArrayDelete(filters);
+ /*
+ * Update the printer and job state.
+ */
- if (job->printer->remote && job->num_files > 1)
- {
- for (i = 0; i < job->num_files; i ++)
- free(argv[i + 6]);
- }
+ cupsdSetJobState(job, abort_state, CUPSD_JOB_DEFAULT, "%s", abort_message);
+ cupsdSetPrinterState(job->printer, IPP_PRINTER_IDLE, 0);
+ update_job_attrs(job, 0);
- free(argv);
+ if (job->history)
+ free_job_history(job);
- cupsdSetJobState(job, IPP_JOB_STOPPED, CUPSD_JOB_DEFAULT, "%s",
- abort_message);
+ cupsArrayRemove(PrintingJobs, job);
+
+ /*
+ * Clear the printer <-> job association...
+ */
+
+ job->printer->job = NULL;
+ job->printer = NULL;
}
job->num_files = 0;
}
+ if (job->history)
+ free_job_history(job);
+
unload_job(job);
cupsArrayRemove(Jobs, job);
cupsdHoldSignals();
- cupsdStopAllJobs(1);
+ cupsdStopAllJobs(CUPSD_JOB_FORCE, 0);
cupsdSaveAllJobs();
for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
cupsFilePrintf(fp, "<Job %d>\n", job->id);
cupsFilePrintf(fp, "State %d\n", job->state_value);
cupsFilePrintf(fp, "Priority %d\n", job->priority);
+ cupsFilePrintf(fp, "HoldUntil %d\n", (int)job->hold_until);
cupsFilePrintf(fp, "Username %s\n", job->username);
cupsFilePrintf(fp, "Destination %s\n", job->dest);
cupsFilePrintf(fp, "DestType %d\n", job->dtype);
break;
}
+ /*
+ * Finalize the job immediately if we forced things...
+ */
+
+ if (action == CUPSD_JOB_FORCE)
+ finalize_job(job);
+
/*
* Update the server "busy" state...
*/
void
cupsdStopAllJobs(
- cupsd_jobaction_t action) /* I - Action */
+ cupsd_jobaction_t action, /* I - Action */
+ int kill_delay) /* I - Number of seconds before we kill */
{
cupsd_job_t *job; /* Current job */
for (job = (cupsd_job_t *)cupsArrayFirst(PrintingJobs);
job;
job = (cupsd_job_t *)cupsArrayNext(PrintingJobs))
+ {
+ if (kill_delay)
+ job->kill_time = time(NULL) + kill_delay;
+
cupsdSetJobState(job, IPP_JOB_PENDING, action, NULL);
+ }
}
}
+/*
+ * 'dump_job_history()' - Dump any debug messages for a job.
+ */
+
+static void
+dump_job_history(cupsd_job_t *job) /* I - Job */
+{
+ int i, /* Looping var */
+ oldsize; /* Current MaxLogSize */
+ struct tm *date; /* Date/time value */
+ cupsd_joblog_t *message; /* Current message */
+ char temp[2048], /* Log message */
+ *ptr, /* Pointer into log message */
+ start[256], /* Start time */
+ end[256]; /* End time */
+ cupsd_printer_t *printer; /* Printer for job */
+
+
+ /*
+ * See if we have anything to dump...
+ */
+
+ if (!job->history)
+ return;
+
+ /*
+ * Disable log rotation temporarily...
+ */
+
+ oldsize = MaxLogSize;
+ MaxLogSize = 0;
+
+ /*
+ * Copy the debug messages to the log...
+ */
+
+ message = (cupsd_joblog_t *)cupsArrayFirst(job->history);
+ date = localtime(&(message->time));
+ strftime(start, sizeof(start), "%X", date);
+
+ message = (cupsd_joblog_t *)cupsArrayLast(job->history);
+ date = localtime(&(message->time));
+ strftime(end, sizeof(end), "%X", date);
+
+ snprintf(temp, sizeof(temp),
+ "[Job %d] The following messages were recorded from %s to %s",
+ job->id, start, end);
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, temp);
+
+ for (message = (cupsd_joblog_t *)cupsArrayFirst(job->history);
+ message;
+ message = (cupsd_joblog_t *)cupsArrayNext(job->history))
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, message->message);
+
+ snprintf(temp, sizeof(temp), "[Job %d] End of messages", job->id);
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, temp);
+
+ /*
+ * Log the printer state values...
+ */
+
+ if ((printer = job->printer) == NULL)
+ printer = cupsdFindDest(job->dest);
+
+ if (printer)
+ {
+ snprintf(temp, sizeof(temp), "[Job %d] printer-state=%d(%s)", job->id,
+ printer->state,
+ printer->state == IPP_PRINTER_IDLE ? "idle" :
+ printer->state == IPP_PRINTER_PROCESSING ? "processing" :
+ "stopped");
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, temp);
+
+ snprintf(temp, sizeof(temp), "[Job %d] printer-state-message=\"%s\"",
+ job->id, printer->state_message);
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, temp);
+
+ snprintf(temp, sizeof(temp), "[Job %d] printer-state-reasons=", job->id);
+ ptr = temp + strlen(temp);
+ if (printer->num_reasons == 0)
+ strlcpy(ptr, "none", sizeof(temp) - (ptr - temp));
+ else
+ {
+ for (i = 0;
+ i < printer->num_reasons && ptr < (temp + sizeof(temp) - 2);
+ i ++)
+ {
+ if (i)
+ *ptr++ = ',';
+
+ strlcpy(ptr, printer->reasons[i], sizeof(temp) - (ptr - temp));
+ ptr += strlen(ptr);
+ }
+ }
+ cupsdWriteErrorLog(CUPSD_LOG_DEBUG, temp);
+ }
+
+ /*
+ * Restore log file rotation...
+ */
+
+ MaxLogSize = oldsize;
+
+ /*
+ * Free all messages...
+ */
+
+ free_job_history(job);
+}
+
+
+/*
+ * 'free_job_history()' - Free any log history.
+ */
+
+static void
+free_job_history(cupsd_job_t *job) /* I - Job */
+{
+ char *message; /* Current message */
+
+
+ if (!job->history)
+ return;
+
+ for (message = (char *)cupsArrayFirst(job->history);
+ message;
+ message = (char *)cupsArrayNext(job->history))
+ free(message);
+
+ cupsArrayDelete(job->history);
+ job->history = NULL;
+}
+
+
/*
* 'finalize_job()' - Cleanup after job filter processes and support data.
*/
* Close pipes and status buffer...
*/
- cupsdRemoveSelect(job->status_buffer->fd);
-
cupsdClosePipe(job->print_pipes);
cupsdClosePipe(job->back_pipes);
cupsdClosePipe(job->side_pipes);
- cupsdClosePipe(job->status_pipes);
+ cupsdRemoveSelect(job->status_pipes[0]);
+ cupsdClosePipe(job->status_pipes);
cupsdStatBufDelete(job->status_buffer);
job->status_buffer = NULL;
* Process the exit status...
*/
- printer_state = IPP_PRINTER_IDLE;
- job_state = IPP_JOB_COMPLETED;
- message = "Job completed.";
+ if (job->printer->state == IPP_PRINTER_PROCESSING)
+ printer_state = IPP_PRINTER_IDLE;
+ else
+ printer_state = job->printer->state;
+
+ switch (job_state = job->state_value)
+ {
+ case IPP_JOB_PENDING :
+ message = "Job paused.";
+ break;
+
+ case IPP_JOB_HELD :
+ message = "Job held.";
+ break;
+
+ default :
+ case IPP_JOB_PROCESSING :
+ case IPP_JOB_COMPLETED :
+ job_state = IPP_JOB_COMPLETED;
+ message = "Job completed.";
+ break;
+
+ case IPP_JOB_STOPPED :
+ message = "Job stopped.";
+ break;
+
+ case IPP_JOB_CANCELED :
+ message = "Job canceled.";
+ break;
+
+ case IPP_JOB_ABORTED :
+ message = "Job aborted.";
+ break;
+ }
if (job->status < 0)
{
* another printer...
*/
- job_state = IPP_JOB_PENDING;
- message = "Retrying job on another printer.";
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ job_state = IPP_JOB_PENDING;
+ message = "Retrying job on another printer.";
+ }
}
else if (!strcmp(job->printer->error_policy, "retry-current-job"))
{
* and we'll retry on the same printer...
*/
- job_state = IPP_JOB_PENDING;
- message = "Retrying job on same printer.";
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ job_state = IPP_JOB_PENDING;
+ message = "Retrying job on same printer.";
+ }
}
else if ((job->printer->type & CUPS_PRINTER_FAX) ||
!strcmp(job->printer->error_policy, "retry-job"))
{
- /*
- * The job was queued on a fax or the error policy is "retry-job" -
- * hold the job if the number of retries is less than the
- * JobRetryLimit, otherwise abort the job.
- */
-
- job->tries ++;
-
- if (job->tries >= JobRetryLimit)
+ if (job_state == IPP_JOB_COMPLETED)
{
/*
- * Too many tries...
+ * The job was queued on a fax or the error policy is "retry-job" -
+ * hold the job if the number of retries is less than the
+ * JobRetryLimit, otherwise abort the job.
*/
- snprintf(buffer, sizeof(buffer),
- "Job aborted after %d unsuccessful attempts.",
- JobRetryLimit);
- job_state = IPP_JOB_ABORTED;
- message = buffer;
- }
- else
- {
- /*
- * Try again in N seconds...
- */
+ job->tries ++;
- set_hold_until(job, time(NULL) + JobRetryInterval);
+ if (job->tries >= JobRetryLimit)
+ {
+ /*
+ * Too many tries...
+ */
+
+ snprintf(buffer, sizeof(buffer),
+ "Job aborted after %d unsuccessful attempts.",
+ JobRetryLimit);
+ job_state = IPP_JOB_ABORTED;
+ message = buffer;
+ }
+ else
+ {
+ /*
+ * Try again in N seconds...
+ */
- snprintf(buffer, sizeof(buffer),
- "Job held for %d seconds since it could not be sent.",
- JobRetryInterval);
- job_state = IPP_JOB_HELD;
- message = buffer;
- }
+ set_hold_until(job, time(NULL) + JobRetryInterval);
+
+ snprintf(buffer, sizeof(buffer),
+ "Job held for %d seconds since it could not be sent.",
+ JobRetryInterval);
+ job_state = IPP_JOB_HELD;
+ message = buffer;
+ }
+ }
}
- else if (!strcmp(job->printer->error_policy, "abort-job"))
+ else if (!strcmp(job->printer->error_policy, "abort-job") &&
+ job_state == IPP_JOB_COMPLETED)
{
job_state = IPP_JOB_ABORTED;
message = "Job aborted due to backend errors; please consult "
"the error_log file for details.";
}
- else
+ else if (job->state_value == IPP_JOB_PROCESSING)
{
+ job_state = IPP_JOB_PENDING;
printer_state = IPP_PRINTER_STOPPED;
- job_state = IPP_JOB_PENDING;
message = "Printer stopped due to backend errors; please "
- "consult the error_log file for details.";
+ "consult the error_log file for details.";
}
break;
* Abort the job...
*/
- job_state = IPP_JOB_ABORTED;
- message = "Job aborted due to backend errors; please consult "
- "the error_log file for details.";
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ job_state = IPP_JOB_ABORTED;
+ message = "Job aborted due to backend errors; please consult "
+ "the error_log file for details.";
+ }
break;
case CUPS_BACKEND_HOLD :
- /*
- * Hold the job...
- */
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ /*
+ * Hold the job...
+ */
- cupsdSetJobHoldUntil(job, "indefinite", 1);
+ cupsdSetJobHoldUntil(job, "indefinite", 1);
- job_state = IPP_JOB_HELD;
- message = "Job held indefinitely due to backend errors; please "
- "consult the error_log file for details.";
+ job_state = IPP_JOB_HELD;
+ message = "Job held indefinitely due to backend errors; please "
+ "consult the error_log file for details.";
+ }
break;
case CUPS_BACKEND_STOP :
*/
printer_state = IPP_PRINTER_STOPPED;
- job_state = IPP_JOB_PENDING;
message = "Printer stopped due to backend errors; please "
"consult the error_log file for details.";
+
+ if (job_state == IPP_JOB_COMPLETED)
+ job_state = IPP_JOB_PENDING;
break;
case CUPS_BACKEND_AUTH_REQUIRED :
* Hold the job for authentication...
*/
- cupsdSetJobHoldUntil(job, "auth-info-required", 1);
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ cupsdSetJobHoldUntil(job, "auth-info-required", 1);
- job_state = IPP_JOB_HELD;
- message = "Job held for authentication.";
+ job_state = IPP_JOB_HELD;
+ message = "Job held for authentication.";
+ }
break;
}
}
* Filter had errors; stop job...
*/
- job_state = IPP_JOB_STOPPED;
- message = "Job stopped due to filter errors; please consult the "
- "error_log file for details.";
+ if (job_state == IPP_JOB_COMPLETED)
+ {
+ job_state = IPP_JOB_STOPPED;
+ message = "Job stopped due to filter errors; please consult the "
+ "error_log file for details.";
+ }
}
/*
printer_state == IPP_PRINTER_STOPPED);
update_job_attrs(job, 0);
+ if (job->history)
+ {
+ if (job->status)
+ dump_job_history(job);
+ else
+ free_job_history(job);
+ }
+
cupsArrayRemove(PrintingJobs, job);
/*
optptr = options;
*optptr = '\0';
- snprintf(title, sizeof(title), "%s-%d", job->printer->name, job->id);
- strcpy(copies, "1");
+ snprintf(title, title_size, "%s-%d", job->printer->name, job->id);
+ strlcpy(copies, "1", copies_size);
for (attr = job->attrs->attrs; attr != NULL; attr = attr->next)
{
*/
if (!banner_page)
- sprintf(copies, "%d", attr->values[0].integer);
+ snprintf(copies, copies_size, "%d", attr->values[0].integer);
}
else if (!strcmp(attr->name, "job-name") &&
(attr->value_tag == IPP_TAG_NAME ||
attr->value_tag == IPP_TAG_NAMELANG))
- strlcpy(title, attr->values[0].string.text, sizeof(title));
+ strlcpy(title, attr->values[0].string.text, title_size);
else if (attr->group_tag == IPP_TAG_JOB)
{
/*
else if (job->state_value > IPP_JOB_COMPLETED)
job->state_value = IPP_JOB_COMPLETED;
}
+ else if (!strcasecmp(line, "HoldUntil"))
+ {
+ job->hold_until = atoi(value);
+ }
else if (!strcasecmp(line, "Priority"))
{
job->priority = atoi(value);
cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);
- job->cost = 0;
- job->progress = 0;
- job->printer = printer;
- printer->job = job;
+ job->cost = 0;
+ job->current_file = 0;
+ job->progress = 0;
+ job->printer = printer;
+ printer->job = job;
/*
* Setup the last exit status and security profiles...
job->status_buffer = cupsdStatBufNew(job->status_pipes[0], NULL);
job->status_level = CUPSD_LOG_INFO;
+ if (job->printer_message)
+ cupsdSetString(&(job->printer_message->values[0].string.text), "");
+
/*
* Create the backchannel pipes and make them non-blocking...
*/
FilterLevel -= job->cost;
job->cost = 0;
+ if (action == CUPSD_JOB_DEFAULT && !job->kill_time)
+ job->kill_time = time(NULL) + JobKillDelay;
+ else if (action == CUPSD_JOB_FORCE)
+ job->kill_time = 0;
+
for (i = 0; job->filters[i]; i ++)
if (job->filters[i] > 0)
cupsdEndProcess(job->filters[i], action == CUPSD_JOB_FORCE);
{
int i; /* Looping var */
int copies; /* Number of copies printed */
- char message[1024], /* Message text */
+ char message[CUPSD_SB_BUFFER_SIZE],
+ /* Message text */
*ptr; /* Pointer update... */
int loglevel, /* Log level for message */
event = 0; /* Events? */
#endif /* __APPLE__ */
else
{
- if (loglevel != CUPSD_LOG_INFO && loglevel > LogLevel)
- cupsdLogJob(job, loglevel, "%d %s", loglevel, message);
+ cupsdLogJob(job, loglevel, "%s", message);
if (loglevel < CUPSD_LOG_DEBUG)
{
sizeof(job->printer->state_message));
cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE;
+ event |= CUPSD_EVENT_PRINTER_STATE | CUPSD_EVENT_JOB_PROGRESS;
- if (loglevel <= job->status_level)
+ if (loglevel < job->status_level)
{
/*
* Some messages show in the job-printer-state-message attribute...
"Printer \"%s\" state changed.",
job->printer->name);
+ if (event & CUPSD_EVENT_JOB_PROGRESS)
+ cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
+ "%s", job->printer->state_message);
+
if (ptr == NULL && !job->status_buffer->bufused)
{
/*
for (i = 0; job->filters[i] < 0; i ++);
if (job->filters[i])
+ {
+ /*
+ * EOF but we haven't collected the exit status of all filters...
+ */
+
+ cupsdCheckProcess();
return;
+ }
if (job->current_file >= job->num_files && job->backend > 0)
+ {
+ /*
+ * EOF but we haven't collected the exit status of the backend...
+ */
+
+ cupsdCheckProcess();
return;
+ }
/*
* Handle the end of job stuff...