/*
- * "$Id: job.c 7902 2008-09-03 14:20:17Z mike $"
+ * "$Id$"
*
- * Job management routines for the CUPS scheduler.
+ * Job management routines for the CUPS scheduler.
*
- * Copyright 2007-2012 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2013 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
- * These coded instructions, statements, and computer programs are the
- * 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:
- *
- * cupsdAddJob() - Add a new job to the job queue.
- * cupsdCancelJobs() - Cancel all jobs for the given
- * destination/user.
- * cupsdCheckJobs() - Check the pending jobs and start any if the
- * destination is available.
- * cupsdCleanJobs() - Clean out old jobs.
- * cupsdContinueJob() - Continue printing with the next file in a
- * job.
- * cupsdDeleteJob() - Free all memory used by a job.
- * cupsdFreeAllJobs() - Free all jobs from memory.
- * cupsdFindJob() - Find the specified job.
- * cupsdGetPrinterJobCount() - Get the number of pending, processing, or
- * held jobs in a printer or class.
- * cupsdGetUserJobCount() - Get the number of pending, processing, or
- * held jobs for a user.
- * cupsdLoadAllJobs() - Load all jobs from disk.
- * cupsdLoadJob() - Load a single job.
- * cupsdMoveJob() - Move the specified job to a different
- * destination.
- * cupsdReleaseJob() - Release the specified job.
- * cupsdRestartJob() - Restart the specified job.
- * cupsdSaveAllJobs() - Save a summary of all jobs to disk.
- * cupsdSaveJob() - Save a job to disk.
- * cupsdSetJobHoldUntil() - Set the hold time for a job.
- * cupsdSetJobPriority() - Set the priority of a job, moving it up/down
- * in the list as needed.
- * cupsdSetJobState() - Set the state of the specified print job.
- * cupsdStopAllJobs() - Stop all print jobs.
- * cupsdUnloadCompletedJobs() - Flush completed job history from memory.
- * cupsdUpdateJobs() - Update the history/file files for all jobs.
- * 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.
- * 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.
- * load_next_job_id() - Load the NextJobId value from the job.cache
- * file.
- * load_request_root() - Load jobs from the RequestRoot directory.
- * remove_job_files() - Remove the document files for a job.
- * remove_job_history() - Remove the control file for a job.
- * set_time() - Set one of the "time-at-xyz" attributes.
- * start_job() - Start a print job.
- * stop_job() - Stop a print job.
- * unload_job() - Unload a job from memory.
- * update_job() - Read a status update from a job's filters.
- * update_job_attrs() - Update the job-printer-* attributes.
+ * These coded instructions, statements, and computer programs are the
+ * 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/".
*/
/*
if (job->kill_time && job->kill_time <= curtime)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job.",
- job->id);
+ if (!job->completed)
+ cupsdLogJob(job, CUPSD_LOG_ERROR, "Stopping unresponsive job.");
stop_job(job, CUPSD_JOB_FORCE);
continue;
if (job->cancel_time && job->cancel_time <= curtime)
{
- cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT,
- "Canceling stuck job after %d seconds.", MaxJobTime);
+ if (job->completed)
+ cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_FORCE,
+ "Marking stuck job as completed after %d seconds.", MaxJobTime);
+ else
+ cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT,
+ "Canceling stuck job after %d seconds.", MaxJobTime);
continue;
}
*/
if (job->state_value == IPP_JOB_PENDING && !NeedReload &&
-#ifndef kIOPMAssertionTypeDenySystemSleep
- !Sleeping &&
-#endif /* !kIOPMAssertionTypeDenySystemSleep */
- !DoingShutdown && !job->printer)
+ !Sleeping && !DoingShutdown && !job->printer)
{
printer = cupsdFindDest(job->dest);
pclass = NULL;
"FINAL_CONTENT_TYPE=%s/%s", filter->dst->super,
filter->dst->type);
}
+ else
+ snprintf(final_content_type, sizeof(final_content_type),
+ "FINAL_CONTENT_TYPE=printer/%s", job->printer->name);
}
/*
* Add decompression/raw filter as needed...
*/
- if ((!job->printer->raw && job->compressions[job->current_file]) ||
- (!filters && !job->printer->remote &&
- (job->num_files > 1 || !strncmp(job->printer->device_uri, "file:", 5))))
+ if (job->compressions[job->current_file] &&
+ (!job->printer->remote || job->num_files == 1))
{
/*
* Add gziptoany filter to the front of the list...
{
snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
job->id, job->current_file + 1);
- argv[6] = filename;
+ argv[6] = strdup(filename);
}
for (i = 0; argv[i]; i ++)
cupsdClosePipe(filterfds[slot]);
- if (job->printer->remote && job->num_files > 1)
- {
- for (i = 0; i < job->num_files; i ++)
- free(argv[i + 6]);
- }
+ for (i = 0; i < job->num_files; i ++)
+ free(argv[i + 6]);
free(argv);
+
if (printer_state_reasons)
free(printer_state_reasons);
* Load job attributes...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading attributes...", job->id);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Loading attributes...");
snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, job->id);
if ((fp = cupsdOpenConfFile(jobfile)) == NULL)
if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, job->attrs) != IPP_DATA)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to read job control file \"%s\".", job->id,
- jobfile);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Unable to read job control file \"%s\".", jobfile);
cupsFileClose(fp);
goto error;
}
if (!ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER))
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Missing or bad time-at-creation attribute in "
- "control file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Missing or bad time-at-creation attribute in control file.");
goto error;
}
if ((job->state = ippFindAttribute(job->attrs, "job-state",
IPP_TAG_ENUM)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Missing or bad job-state attribute in control "
- "file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Missing or bad job-state attribute in control file.");
goto error;
}
if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
IPP_TAG_URI)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] No job-printer-uri attribute in control file.",
- job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "No job-printer-uri attribute in control file.");
goto error;
}
if ((dest = cupsdValidateDest(attr->values[0].string.text, &(job->dtype),
&destptr)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to queue job for destination \"%s\".",
- job->id, attr->values[0].string.text);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Unable to queue job for destination \"%s\".",
+ attr->values[0].string.text);
goto error;
}
}
else if ((destptr = cupsdFindDest(job->dest)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to queue job for destination \"%s\".",
- job->id, job->dest);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Unable to queue job for destination \"%s\".",
+ job->dest);
goto error;
}
{
const char *reason; /* job-state-reason keyword */
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "[Job %d] Adding missing job-state-reasons attribute to "
- " control file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
+ "Adding missing job-state-reasons attribute to control file.");
switch (job->state_value)
{
if ((attr = ippFindAttribute(job->attrs, "job-priority",
IPP_TAG_INTEGER)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Missing or bad job-priority attribute in "
- "control file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Missing or bad job-priority attribute in control file.");
goto error;
}
if ((attr = ippFindAttribute(job->attrs, "job-originating-user-name",
IPP_TAG_NAME)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Missing or bad job-originating-user-name "
- "attribute in control file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Missing or bad job-originating-user-name "
+ "attribute in control file.");
goto error;
}
if (access(jobfile, 0))
break;
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "[Job %d] Auto-typing document file \"%s\"...", job->id,
- jobfile);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG,
+ "Auto-typing document file \"%s\"...", jobfile);
if (fileid > job->num_files)
{
if (!compressions || !filetypes)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Ran out of memory for job file types.",
- job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Ran out of memory for job file types.");
ippDelete(job->attrs);
job->attrs = NULL;
if (cupsFileGets(fp, line, sizeof(line)) &&
- !strcmp(line, "CUPSD-AUTH-V2"))
+ !strcmp(line, "CUPSD-AUTH-V3"))
{
i = 0;
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
* Decode value...
*/
- bytes = sizeof(data);
- httpDecode64_2(data, &bytes, value);
+ if (strcmp(line, "negotiate") && strcmp(line, "uid"))
+ {
+ bytes = sizeof(data);
+ httpDecode64_2(data, &bytes, value);
+ }
/*
* Assign environment variables...
else if (!strcmp(line, "password"))
cupsdSetStringf(job->auth_env + i, "AUTH_PASSWORD=%s", data);
else if (!strcmp(line, "negotiate"))
- cupsdSetStringf(job->auth_env + i, "AUTH_NEGOTIATE=%s", data);
+ cupsdSetStringf(job->auth_env + i, "AUTH_NEGOTIATE=%s", value);
else
continue;
if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL,
job->attrs) != IPP_DATA)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to write job control file.", job->id);
+ cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to write job control file.");
cupsFileClose(fp);
return;
}
job;
job = (cupsd_job_t *)cupsArrayNext(PrintingJobs))
{
- if (kill_delay)
- job->kill_time = time(NULL) + kill_delay;
+ if (job->completed)
+ {
+ cupsdSetJobState(job, IPP_JOB_COMPLETED, CUPSD_JOB_FORCE, NULL);
+ }
+ else
+ {
+ if (kill_delay)
+ job->kill_time = time(NULL) + kill_delay;
- cupsdSetJobState(job, IPP_JOB_PENDING, action, NULL);
+ cupsdSetJobState(job, IPP_JOB_PENDING, action, NULL);
+ }
}
}
cupsdLogMessage(CUPSD_LOG_DEBUG2, "finalize_job(job=%p(%d))", job, job->id);
/*
- * Clear the "connecting-to-device" reason, which is only valid when a printer
- * is processing, along with any remote printing job state...
+ * Clear the "connecting-to-device" and "cups-waiting-for-job-completed"
+ * reasons, which are only valid when a printer is processing, along with any
+ * remote printing job state...
*/
cupsdSetPrinterReasons(job->printer, "-connecting-to-device,"
+ "cups-waiting-for-job-completed,"
"cups-remote-pending,"
"cups-remote-pending-held,"
"cups-remote-processing,"
job->status_pipes[0] = -1;
job->status_pipes[1] = -1;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading from cache...",
- job->id);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Loading from cache...");
}
else if (!job)
{
job->id);
if (access(jobfile, 0))
{
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Data files have gone away.",
- job->id);
+ cupsdLogJob(job, CUPSD_LOG_INFO, "Data files have gone away.");
job->num_files = 0;
continue;
}
if (!job->filetypes || !job->compressions)
{
- cupsdLogMessage(CUPSD_LOG_EMERG,
- "[Job %d] Unable to allocate memory for %d files.",
- job->id, job->num_files);
+ cupsdLogJob(job, CUPSD_LOG_EMERG,
+ "Unable to allocate memory for %d files.",
+ job->num_files);
break;
}
}
* If the original MIME type is unknown, auto-type it!
*/
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unknown MIME type %s/%s for file %d.",
- job->id, super, type, number + 1);
+ cupsdLogJob(job, CUPSD_LOG_ERROR,
+ "Unknown MIME type %s/%s for file %d.",
+ super, type, number + 1);
snprintf(jobfile, sizeof(jobfile), "%s/d%05d-%03d", RequestRoot,
job->id, number + 1);
cupsd_printer_t *printer) /* I - Printer to print job */
{
const char *filename; /* Support filename */
+ ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
+ "job-cancel-after",
+ IPP_TAG_INTEGER);
+ /* job-cancel-after attribute */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job(job=%p(%d), printer=%p(%s))",
job->printer = printer;
printer->job = job;
- if (MaxJobTime > 0)
+ if (cancel_after)
+ job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0);
+ else if (MaxJobTime > 0)
job->cancel_time = time(NULL) + MaxJobTime;
else
job->cancel_time = 0;
if (!job->attrs)
return;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Unloading...", job->id);
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Unloading...");
ippDelete(job->attrs);
{
event |= CUPSD_EVENT_PRINTER_STATE;
- if (MaxJobTime > 0 && strstr(message, "connecting-to-device") != NULL)
+ if (MaxJobTime > 0)
{
/*
* Reset cancel time after connecting to the device...
break;
if (i >= job->printer->num_reasons)
- job->cancel_time = time(NULL) + MaxJobTime;
+ {
+ ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs,
+ "job-cancel-after",
+ IPP_TAG_INTEGER);
+ /* job-cancel-after attribute */
+
+ if (cancel_after)
+ job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0);
+ else
+ job->cancel_time = time(NULL) + MaxJobTime;
+ }
}
}
/*
- * End of "$Id: job.c 7902 2008-09-03 14:20:17Z mike $".
+ * End of "$Id$".
*/