*
* Job management routines for the CUPS scheduler.
*
- * Copyright 2007-2011 by Apple Inc.
+ * Copyright 2007-2012 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
*
* 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.
+* 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.
- * 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.
- * 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.
+ * 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.
*/
/*
#include <grp.h>
#include <cups/backend.h>
#include <cups/dir.h>
+#ifdef __APPLE__
+# include <IOKit/pwr_mgt/IOPMLib.h>
+# ifdef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H
+# include <IOKit/pwr_mgt/IOPMLibPrivate.h>
+# endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */
+#endif /* __APPLE__ */
/*
static void load_job_cache(const char *filename);
static void load_next_job_id(const char *filename);
static void load_request_root(void);
+static void remove_job_files(cupsd_job_t *job);
+static void remove_job_history(cupsd_job_t *job);
static void set_time(cupsd_job_t *job, const char *name);
static void start_job(cupsd_job_t *job, cupsd_printer_t *printer);
static void stop_job(cupsd_job_t *job, cupsd_jobaction_t action);
if (job->kill_time && job->kill_time <= curtime)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job.",
job->id);
stop_job(job, CUPSD_JOB_FORCE);
continue;
}
+ /*
+ * Cancel stuck jobs...
+ */
+
+ if (job->cancel_time && job->cancel_time <= curtime)
+ {
+ cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT,
+ "Canceling stuck job after %d seconds.", MaxJobTime);
+ continue;
+ }
+
/*
* Start held jobs if they are ready...
*/
* Start pending jobs if the destination is available...
*/
- if (job->state_value == IPP_JOB_PENDING && !NeedReload && !Sleeping &&
+ if (job->state_value == IPP_JOB_PENDING && !NeedReload &&
+#ifndef kIOPMAssertionTypeDenySystemSleep
+ !Sleeping &&
+#endif /* !kIOPMAssertionTypeDenySystemSleep */
!DoingShutdown && !job->printer)
{
printer = cupsdFindDest(job->dest);
pclass = NULL;
- while (printer &&
- (printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS)))
+ while (printer && (printer->type & CUPS_PRINTER_CLASS))
{
/*
* If the class is remote, just pass it to the remote server...
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
- if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */
- printer->state == IPP_PRINTER_IDLE) || /* and idle, OR */
- ((printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is remote */
- !printer->job)) /* and not printing */
+ if (printer->state == IPP_PRINTER_IDLE)
{
/*
* Start the job...
cupsdCleanJobs(void)
{
cupsd_job_t *job; /* Current job */
+ time_t curtime; /* Current time */
- if (MaxJobs <= 0 && JobHistory)
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdCleanJobs: MaxJobs=%d, JobHistory=%d, JobFiles=%d",
+ MaxJobs, JobHistory, JobFiles);
+
+ if (MaxJobs <= 0 && JobHistory == INT_MAX && JobFiles == INT_MAX)
return;
+ curtime = time(NULL);
+ JobHistoryUpdate = 0;
+
for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
- job && (cupsArrayCount(Jobs) >= MaxJobs || !JobHistory);
+ job;
job = (cupsd_job_t *)cupsArrayNext(Jobs))
+ {
if (job->state_value >= IPP_JOB_CANCELED && !job->printer)
- cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+ {
+ /*
+ * Expire old jobs (or job files)...
+ */
+
+ if ((MaxJobs > 0 && cupsArrayCount(Jobs) >= MaxJobs) ||
+ (job->history_time && job->history_time <= curtime))
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing from history.");
+ cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+ }
+ else if (job->file_time && job->file_time <= curtime)
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing document files.");
+ remove_job_files(job);
+
+ if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->history_time;
+ }
+ else
+ {
+ if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->history_time;
+
+ if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->file_time;
+ }
+ }
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCleanJobs: JobHistoryUpdate=%ld",
+ (long)JobHistoryUpdate);
}
int filterfds[2][2] = { { -1, -1 }, { -1, -1 } };
/* Pipes used between filters */
int envc; /* Number of environment variables */
+ struct stat fileinfo; /* Job file information */
char **argv = NULL, /* Filter command-line arguments */
filename[1024], /* Job filename */
command[1024], /* Full path to command */
* Local jobs get filtered...
*/
- filters = mimeFilter(MimeDatabase, job->filetypes[job->current_file],
- job->printer->filetype, &(job->cost));
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
+ job->id, job->current_file + 1);
+ if (stat(filename, &fileinfo))
+ fileinfo.st_size = 0;
+
+ filters = mimeFilter2(MimeDatabase, job->filetypes[job->current_file],
+ fileinfo.st_size, job->printer->filetype,
+ &(job->cost));
if (!filters)
{
cupsdLogJob(job, CUPSD_LOG_ERROR,
- "Unable to convert file %d to printable format!",
+ "Unable to convert file %d to printable format.",
job->current_file);
abort_message = "Aborting job because it cannot be printed.";
abort_state = IPP_JOB_ABORTED;
+ ippSetString(job->attrs, &job->reasons, 0, "document-unprintable-error");
goto abort_job;
}
if (cupsArrayCount(filters) > MAX_FILTERS)
{
cupsdLogJob(job, CUPSD_LOG_DEBUG,
- "Too many filters (%d > %d), unable to print!",
+ "Too many filters (%d > %d), unable to print.",
cupsArrayCount(filters), MAX_FILTERS);
abort_message = "Aborting job because it needs too many filters to print.";
abort_state = IPP_JOB_ABORTED;
+ ippSetString(job->attrs, &job->reasons, 0, "document-unprintable-error");
+
goto abort_job;
}
if ((job->job_sheets =
ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
cupsdLogJob(job, CUPSD_LOG_DEBUG,
- "... but someone added one without setting job_sheets!");
+ "... but someone added one without setting job_sheets.");
}
else if (job->job_sheets->num_values == 1)
cupsdLogJob(job, CUPSD_LOG_DEBUG, "job-sheets=%s",
job->job_sheets->values[0].string.text,
job->job_sheets->values[1].string.text);
- if (job->printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+ if (job->printer->type & CUPS_PRINTER_REMOTE)
banner_page = 0;
else if (job->job_sheets == NULL)
banner_page = 0;
- else if (strcasecmp(job->job_sheets->values[0].string.text, "none") != 0 &&
+ else if (_cups_strcasecmp(job->job_sheets->values[0].string.text, "none") != 0 &&
job->current_file == 0)
banner_page = 1;
else if (job->job_sheets->num_values > 1 &&
- strcasecmp(job->job_sheets->values[1].string.text, "none") != 0 &&
+ _cups_strcasecmp(job->job_sheets->values[1].string.text, "none") != 0 &&
job->current_file == (job->num_files - 1))
banner_page = 1;
else
envp[envc ++] = classification;
}
- if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ if (job->dtype & CUPS_PRINTER_CLASS)
{
snprintf(class_name, sizeof(class_name), "CLASS=%s", job->dest);
envp[envc ++] = class_name;
}
envp[envc ++] = auth_info_required;
- 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;
+
+ for (i = 0;
+ i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
+ i ++)
+ if (job->auth_env[i])
+ envp[envc ++] = job->auth_env[i];
+ else
+ break;
+
if (job->auth_uid)
envp[envc ++] = job->auth_uid;
cupsdDeleteJob(cupsd_job_t *job, /* I - Job */
cupsd_jobaction_t action)/* I - Action */
{
- char filename[1024]; /* Job filename */
+ int i; /* Looping var */
if (job->printer)
finalize_job(job, 1);
if (action == CUPSD_JOB_PURGE)
- {
- /*
- * Remove the job info file...
- */
-
- snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot,
- job->id);
- unlink(filename);
- }
+ remove_job_history(job);
cupsdClearString(&job->username);
cupsdClearString(&job->dest);
- cupsdClearString(&job->auth_username);
- cupsdClearString(&job->auth_domain);
- cupsdClearString(&job->auth_password);
+ for (i = 0;
+ i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
+ i ++)
+ cupsdClearString(job->auth_env + i);
cupsdClearString(&job->auth_uid);
- if (job->num_files > 0)
+ if (action == CUPSD_JOB_PURGE)
+ remove_job_files(job);
+ else if (job->num_files > 0)
{
free(job->compressions);
free(job->filetypes);
- while (job->num_files > 0)
- {
- snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
- job->id, job->num_files);
- unlink(filename);
-
- job->num_files --;
- }
+ job->num_files = 0;
}
if (job->history)
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs), count = 0;
job;
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
- if (job->dest && !strcasecmp(job->dest, dest))
+ if (job->dest && !_cups_strcasecmp(job->dest, dest))
count ++;
return (count);
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs), count = 0;
job;
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
- if (!strcasecmp(job->username, username))
+ if (!_cups_strcasecmp(job->username, username))
count ++;
return (count);
int /* O - 1 on success, 0 on failure */
cupsdLoadJob(cupsd_job_t *job) /* I - Job */
{
+ int i; /* Looping var */
char jobfile[1024]; /* Job filename */
cups_file_t *fp; /* Job file */
int fileid; /* Current file ID */
if ((job->attrs = ippNew()) == NULL)
{
- cupsdLogJob(job, CUPSD_LOG_ERROR, "Ran out of memory for job attributes!");
+ cupsdLogJob(job, CUPSD_LOG_ERROR, "Ran out of memory for job attributes.");
return (0);
}
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,
- "[Job %d] Unable to open job control file \"%s\" - %s!",
- job->id, jobfile, strerror(errno));
+ if ((fp = cupsdOpenConfFile(jobfile)) == NULL)
goto error;
- }
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,
+ "[Job %d] Unable to read job control file \"%s\".", job->id,
jobfile);
cupsFileClose(fp);
goto error;
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Job %d] Missing or bad time-at-creation attribute in "
- "control file!", job->id);
+ "control file.", job->id);
goto error;
}
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Job %d] Missing or bad job-state attribute in control "
- "file!", job->id);
+ "file.", job->id);
goto error;
}
- job->state_value = (ipp_jstate_t)job->state->values[0].integer;
+ job->state_value = (ipp_jstate_t)job->state->values[0].integer;
+ job->file_time = 0;
+ job->history_time = 0;
+
+ if (job->state_value >= IPP_JOB_CANCELED &&
+ (attr = ippFindAttribute(job->attrs, "time-at-completed",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ if (JobHistory < INT_MAX)
+ job->history_time = attr->values[0].integer + JobHistory;
+ else
+ job->history_time = INT_MAX;
+
+ if (job->history_time < time(NULL))
+ goto error; /* Expired, remove from history */
+
+ if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->history_time;
+
+ if (JobFiles < INT_MAX)
+ job->file_time = attr->values[0].integer + JobFiles;
+ else
+ job->file_time = INT_MAX;
+
+ if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->file_time;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdLoadJob: JobHistoryUpdate=%ld",
+ (long)JobHistoryUpdate);
+ }
if (!job->dest)
{
IPP_TAG_URI)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] No job-printer-uri attribute in control file!",
+ "[Job %d] No job-printer-uri attribute in control file.",
job->id);
goto error;
}
&destptr)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to queue job for destination \"%s\"!",
+ "[Job %d] Unable to queue job for destination \"%s\".",
job->id, 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 %d] Unable to queue job for destination \"%s\".",
job->id, job->dest);
goto error;
}
+ if ((job->reasons = ippFindAttribute(job->attrs, "job-state-reasons",
+ IPP_TAG_KEYWORD)) == NULL)
+ {
+ const char *reason; /* job-state-reason keyword */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "[Job %d] Adding missing job-state-reasons attribute to "
+ " control file.", job->id);
+
+ switch (job->state_value)
+ {
+ default :
+ case IPP_JOB_PENDING :
+ if (destptr->state == IPP_PRINTER_STOPPED)
+ reason = "printer-stopped";
+ else
+ reason = "none";
+ break;
+
+ case IPP_JOB_HELD :
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
+ IPP_TAG_ZERO)) != NULL &&
+ (attr->value_tag == IPP_TAG_NAME ||
+ attr->value_tag == IPP_TAG_NAMELANG ||
+ attr->value_tag == IPP_TAG_KEYWORD) &&
+ strcmp(attr->values[0].string.text, "no-hold"))
+ reason = "job-hold-until-specified";
+ else
+ reason = "job-incoming";
+ break;
+
+ case IPP_JOB_PROCESSING :
+ reason = "job-printing";
+ break;
+
+ case IPP_JOB_STOPPED :
+ reason = "job-stopped";
+ break;
+
+ case IPP_JOB_CANCELED :
+ reason = "job-canceled-by-user";
+ break;
+
+ case IPP_JOB_ABORTED :
+ reason = "aborted-by-system";
+ break;
+
+ case IPP_JOB_COMPLETED :
+ reason = "job-completed-successfully";
+ break;
+ }
+
+ job->reasons = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, reason);
+ }
+ else if (job->state_value == IPP_JOB_PENDING)
+ {
+ if (destptr->state == IPP_PRINTER_STOPPED)
+ ippSetString(job->attrs, &job->reasons, 0, "printer-stopped");
+ else
+ ippSetString(job->attrs, &job->reasons, 0, "none");
+ }
+
job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed",
IPP_TAG_INTEGER);
job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Job %d] Missing or bad job-priority attribute in "
- "control file!", job->id);
+ "control file.", job->id);
goto error;
}
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Job %d] Missing or bad job-originating-user-name "
- "attribute in control file!", job->id);
+ "attribute in control file.", job->id);
goto error;
}
if (!compressions || !filetypes)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Ran out of memory for job file types!",
+ "[Job %d] Ran out of memory for job file types.",
job->id);
ippDelete(job->attrs);
{
snprintf(jobfile, sizeof(jobfile), "%s/a%05d", RequestRoot, job->id);
- cupsdClearString(&job->auth_username);
- cupsdClearString(&job->auth_domain);
- cupsdClearString(&job->auth_password);
+ for (i = 0;
+ i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
+ i ++)
+ cupsdClearString(job->auth_env + i);
cupsdClearString(&job->auth_uid);
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 */
+ int bytes, /* Size of auth data */
+ linenum = 1; /* Current line number */
+ char line[65536], /* Line from file */
+ *value, /* Value from line */
+ data[65536]; /* Decoded data */
- for (i = 0;
- i < destptr->num_auth_info_required &&
- cupsFileGets(fp, line, sizeof(line));
- i ++)
+ if (cupsFileGets(fp, line, sizeof(line)) &&
+ !strcmp(line, "CUPSD-AUTH-V2"))
{
- 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);
- else if (!strcmp(destptr->auth_info_required[i], "negotiate") &&
- isdigit(line[0] & 255))
- cupsdSetStringf(&job->auth_uid, "AUTH_UID=%s", line);
- }
+ i = 0;
+ while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
+ {
+ /*
+ * Decode value...
+ */
+
+ bytes = sizeof(data);
+ httpDecode64_2(data, &bytes, value);
+
+ /*
+ * Assign environment variables...
+ */
- if (cupsFileGets(fp, line, sizeof(line)) && isdigit(line[0] & 255))
- cupsdSetStringf(&job->auth_uid, "AUTH_UID=%s", line);
+ if (!strcmp(line, "uid"))
+ {
+ cupsdSetStringf(&job->auth_uid, "AUTH_UID=%s", value);
+ continue;
+ }
+ else if (i >= (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0])))
+ break;
+
+ if (!strcmp(line, "username"))
+ cupsdSetStringf(job->auth_env + i, "AUTH_USERNAME=%s", data);
+ else if (!strcmp(line, "domain"))
+ cupsdSetStringf(job->auth_env + i, "AUTH_DOMAIN=%s", data);
+ 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", line);
+ else
+ continue;
+
+ i ++;
+ }
+ }
cupsFileClose(fp);
}
ippDelete(job->attrs);
job->attrs = NULL;
- if (job->compressions)
- {
- free(job->compressions);
- job->compressions = NULL;
- }
-
- if (job->filetypes)
- {
- free(job->filetypes);
- job->filetypes = NULL;
- }
-
- job->num_files = 0;
-
- unlink(jobfile);
+ remove_job_history(job);
+ remove_job_files(job);
return (0);
}
p->name);
cupsdSetString(&job->dest, p->name);
- job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
- CUPS_PRINTER_IMPLICIT);
+ job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
IPP_TAG_URI)) != NULL)
cupsdSaveAllJobs(void)
{
int i; /* Looping var */
- cups_file_t *fp; /* Job cache file */
- char temp[1024]; /* Temporary string */
+ cups_file_t *fp; /* job.cache file */
+ char filename[1024], /* job.cache filename */
+ temp[1024]; /* Temporary string */
cupsd_job_t *job; /* Current job */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
- snprintf(temp, sizeof(temp), "%s/job.cache", CacheDir);
- if ((fp = cupsFileOpen(temp, "w")) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create job cache file \"%s\" - %s",
- temp, strerror(errno));
+ snprintf(filename, sizeof(filename), "%s/job.cache", CacheDir);
+ if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL)
return;
- }
-
- cupsdLogMessage(CUPSD_LOG_INFO, "Saving job cache file \"%s\"...", temp);
-
- /*
- * Restrict access to the file...
- */
- fchown(cupsFileNumber(fp), getuid(), Group);
- fchmod(cupsFileNumber(fp), ConfigFilePerm);
+ cupsdLogMessage(CUPSD_LOG_INFO, "Saving job.cache...");
/*
* Write a small header to the file...
cupsFilePuts(fp, "</Job>\n");
}
- cupsFileClose(fp);
+ cupsdCloseCreatedConfFile(fp, filename);
}
snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id);
- if ((fp = cupsFileOpen(filename, "w")) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unable to create job control file \"%s\" - %s.",
- job->id, filename, strerror(errno));
+ if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm & 0600)) == NULL)
return;
- }
- fchmod(cupsFileNumber(fp), 0600);
fchown(cupsFileNumber(fp), RunUser, Group);
job->attrs->state = IPP_IDLE;
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);
-
- cupsFileClose(fp);
+ "[Job %d] Unable to write job control file.", job->id);
+ cupsFileClose(fp);
+ return;
+ }
- job->dirty = 0;
+ if (!cupsdCloseCreatedConfFile(fp, filename))
+ job->dirty = 0;
}
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
+
+ ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified");
}
/*
* Update the hold time...
*/
+ job->cancel_time = 0;
+
if (!strcmp(when, "indefinite") || !strcmp(when, "auth-info-required"))
{
/*
*/
job->hold_until = 0;
+
+ if (MaxHoldTime > 0)
+ job->cancel_time = time(NULL) + MaxHoldTime;
}
else if (!strcmp(when, "day-time"))
{
if (!cupsdLoadJob(job))
return;
- /*
- * Don't do anything if the state is unchanged and we aren't purging the
- * job...
- */
+ /*
+ * Don't do anything if the state is unchanged and we aren't purging the
+ * job...
+ */
- oldstate = job->state_value;
- if (newstate == oldstate && action != CUPSD_JOB_PURGE)
- return;
+ oldstate = job->state_value;
+ if (newstate == oldstate && action != CUPSD_JOB_PURGE)
+ return;
/*
* Stop any processes that are working on the current job...
case IPP_JOB_CANCELED :
case IPP_JOB_COMPLETED :
set_time(job, "time-at-completed");
+ ippSetString(job->attrs, &job->reasons, 0, "processing-to-stop-point");
break;
}
"Unable to remove authentication cache: %s",
strerror(errno));
- cupsdClearString(&job->auth_username);
- cupsdClearString(&job->auth_domain);
- cupsdClearString(&job->auth_password);
+ for (i = 0;
+ i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
+ i ++)
+ cupsdClearString(job->auth_env + i);
+
cupsdClearString(&job->auth_uid);
/*
*/
if (!JobHistory || !JobFiles || action == CUPSD_JOB_PURGE)
- {
- for (i = 1; i <= job->num_files; i ++)
- {
- snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
- job->id, i);
- unlink(filename);
- }
-
- if (job->num_files > 0)
- {
- free(job->filetypes);
- free(job->compressions);
-
- job->num_files = 0;
- job->filetypes = NULL;
- job->compressions = NULL;
- }
- }
+ remove_job_files(job);
if (JobHistory && action != CUPSD_JOB_PURGE)
{
}
+/*
+ * 'cupsdUpdateJobs()' - Update the history/file files for all jobs.
+ */
+
+void
+cupsdUpdateJobs(void)
+{
+ cupsd_job_t *job; /* Current job */
+ time_t curtime; /* Current time */
+ ipp_attribute_t *attr; /* time-at-completed attribute */
+
+
+ curtime = time(NULL);
+ JobHistoryUpdate = 0;
+
+ for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
+ job;
+ job = (cupsd_job_t *)cupsArrayNext(Jobs))
+ {
+ if (job->state_value >= IPP_JOB_CANCELED &&
+ (attr = ippFindAttribute(job->attrs, "time-at-completed",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ /*
+ * Update history/file expiration times...
+ */
+
+ if (JobHistory < INT_MAX)
+ job->history_time = attr->values[0].integer + JobHistory;
+ else
+ job->history_time = INT_MAX;
+
+ if (job->history_time < curtime)
+ {
+ cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+ continue;
+ }
+
+ if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->history_time;
+
+ if (JobFiles < INT_MAX)
+ job->file_time = attr->values[0].integer + JobFiles;
+ else
+ job->file_time = INT_MAX;
+
+ if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->file_time;
+ }
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdUpdateAllJobs: JobHistoryUpdate=%ld",
+ (long)JobHistoryUpdate);
+}
+
+
/*
* 'compare_active_jobs()' - Compare the job IDs and priorities of two jobs.
*/
int diff; /* Difference */
+ (void)data;
+
if ((diff = ((cupsd_job_t *)second)->priority -
((cupsd_job_t *)first)->priority) != 0)
return (diff);
void *second, /* I - Second job */
void *data) /* I - App data (not used) */
{
+ (void)data;
+
return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id);
}
case IPP_JOB_COMPLETED :
job_state = IPP_JOB_COMPLETED;
message = "Job completed.";
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "job-completed-successfully");
break;
case IPP_JOB_STOPPED :
message = "Job stopped.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "job-stopped");
break;
case IPP_JOB_CANCELED :
message = "Job canceled.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "job-canceled-by-user");
break;
case IPP_JOB_ABORTED :
int exit_code; /* Exit code from backend */
-
/*
* Convert the status to an exit code. Due to the way the W* macros are
* implemented on MacOS X (bug?), we have to store the exit status in a
if (WIFEXITED(exit_code))
exit_code = WEXITSTATUS(exit_code);
else
+ {
+ ippSetString(job->attrs, &job->reasons, 0, "cups-backend-crashed");
exit_code = job->status;
+ }
cupsdLogJob(job, CUPSD_LOG_INFO, "Backend returned status %d (%s)",
exit_code,
* act...
*/
- if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ if (job->dtype & CUPS_PRINTER_CLASS)
{
/*
* Queued on a class - mark the job as pending and we'll retry on
{
job_state = IPP_JOB_PENDING;
message = "Retrying job on another printer.";
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "resources-are-not-ready");
}
}
else if (!strcmp(job->printer->error_policy, "retry-current-job"))
{
job_state = IPP_JOB_PENDING;
message = "Retrying job on same printer.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "none");
}
}
else if ((job->printer->type & CUPS_PRINTER_FAX) ||
JobRetryLimit);
job_state = IPP_JOB_ABORTED;
message = buffer;
+
+ ippSetString(job->attrs, &job->reasons, 0, "aborted-by-system");
}
else
{
job->hold_until = time(NULL) + JobRetryInterval;
job_state = IPP_JOB_HELD;
message = buffer;
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "resources-are-not-ready");
}
}
}
job_state = IPP_JOB_ABORTED;
message = "Job aborted due to backend errors; please consult "
"the error_log file for details.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "aborted-by-system");
}
else if (job->state_value == IPP_JOB_PROCESSING)
{
printer_state = IPP_PRINTER_STOPPED;
message = "Printer stopped due to backend errors; please "
"consult the error_log file for details.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "none");
}
break;
job_state = IPP_JOB_ABORTED;
message = "Job aborted due to backend errors; please consult "
"the error_log file for details.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "aborted-by-system");
}
break;
*/
cupsdSetJobHoldUntil(job, "indefinite", 1);
+ ippSetString(job->attrs, &job->reasons, 0,
+ "job-hold-until-specified");
job_state = IPP_JOB_HELD;
message = "Job held indefinitely due to backend errors; please "
"consult the error_log file for details.";
if (job_state == IPP_JOB_COMPLETED)
+ {
job_state = IPP_JOB_PENDING;
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "resources-are-not-ready");
+ }
break;
case CUPS_BACKEND_AUTH_REQUIRED :
job_state = IPP_JOB_HELD;
message = "Job held for authentication.";
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "cups-held-for-authentication");
}
break;
JobRetryLimit);
job_state = IPP_JOB_ABORTED;
message = buffer;
+
+ ippSetString(job->attrs, &job->reasons, 0, "aborted-by-system");
}
else
{
job->hold_until = time(NULL) + JobRetryInterval;
job_state = IPP_JOB_HELD;
message = buffer;
+
+ ippSetString(job->attrs, &job->reasons, 0,
+ "resources-are-not-ready");
}
}
break;
{
job_state = IPP_JOB_PENDING;
message = "Retrying job on same printer.";
+
+ ippSetString(job->attrs, &job->reasons, 0, "none");
}
break;
}
job_state = IPP_JOB_STOPPED;
message = "Job stopped due to filter errors; please consult the "
"error_log file for details.";
+
+ if (WIFSIGNALED(job->status))
+ ippSetString(job->attrs, &job->reasons, 0, "cups-filter-crashed");
+ else
+ ippSetString(job->attrs, &job->reasons, 0, "job-completed-with-errors");
}
}
* Update the printer and job state.
*/
- if (job_state != job->state_value)
+ if (set_job_state && job_state != job->state_value)
cupsdSetJobState(job, job_state, CUPSD_JOB_DEFAULT, "%s", message);
cupsdSetPrinterState(job->printer, printer_state,
if (job->history)
{
- if (job->status)
+ if (job->status &&
+ (job->state_value == IPP_JOB_ABORTED ||
+ job->state_value == IPP_JOB_STOPPED))
dump_job_history(job);
else
free_job_history(job);
if ((ppd = _ppdCacheGetInputSlot(pc, job->attrs, NULL)) != NULL)
num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds,
&pwgppds);
- else if (!ippFindAttribute(job->attrs, "AP_D_InputSlot", IPP_TAG_ZERO))
- num_pwgppds = cupsAddOption("AP_D_InputSlot", "", num_pwgppds,
- &pwgppds);
}
if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) &&
(ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL)
num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_short,
num_pwgppds, &pwgppds);
}
+
+ /*
+ * Map finishings values...
+ */
+
+ num_pwgppds = _ppdCacheGetFinishingOptions(pc, job->attrs,
+ IPP_FINISHINGS_NONE, num_pwgppds,
+ &pwgppds);
}
/*
* Then allocate/reallocate the option buffer as needed...
*/
+ if (newlength == 0) /* This can never happen, but Clang */
+ newlength = 1; /* thinks it can... */
+
if (newlength > optlength || !options)
{
if (!options)
if (!optptr)
{
cupsdLogJob(job, CUPSD_LOG_CRIT,
- "Unable to allocate " CUPS_LLFMT " bytes for option buffer!",
+ "Unable to allocate " CUPS_LLFMT " bytes for option buffer.",
CUPS_LLCAST newlength);
return (NULL);
}
!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, "com.apple.print.PrintSettings."
+ !_cups_strcasecmp(attr->name, "AP_FIRSTPAGE_InputSlot") ||
+ !_cups_strcasecmp(attr->name, "AP_FIRSTPAGE_ManualFeed") ||
+ !_cups_strcasecmp(attr->name, "com.apple.print.PrintSettings."
"PMTotalSidesImaged..n.") ||
- !strcasecmp(attr->name, "com.apple.print.PrintSettings."
+ !_cups_strcasecmp(attr->name, "com.apple.print.PrintSettings."
"PMTotalBeginPages..n.")) &&
banner_page)
continue;
"%dx%d%s", attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units == IPP_RES_PER_INCH ?
- "dpi" : "dpc");
+ "dpi" : "dpcm");
break;
case IPP_TAG_STRING :
* Open the job.cache file...
*/
- if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ if ((fp = cupsdOpenConfFile(filename)) == NULL)
{
- if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to open job cache file \"%s\": %s",
- filename, strerror(errno));
-
load_request_root();
-
return;
}
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
{
- if (!strcasecmp(line, "NextJobId"))
+ if (!_cups_strcasecmp(line, "NextJobId"))
{
if (value)
NextJobId = atoi(value);
}
- else if (!strcasecmp(line, "<Job"))
+ else if (!_cups_strcasecmp(line, "<Job"))
{
if (job)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d.",
linenum);
continue;
}
if (!value)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d!", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d.", linenum);
continue;
}
if (jobid < 1)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d!", jobid,
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d.", jobid,
linenum);
continue;
}
snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, jobid);
if (access(jobfile, 0))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Files have gone away!",
- jobid);
- continue;
+ snprintf(jobfile, sizeof(jobfile), "%s/c%05d.N", RequestRoot, jobid);
+ if (access(jobfile, 0))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Files have gone away.",
+ jobid);
+ continue;
+ }
}
job = calloc(1, sizeof(cupsd_job_t));
if (!job)
{
cupsdLogMessage(CUPSD_LOG_EMERG,
- "[Job %d] Unable to allocate memory for job!", jobid);
+ "[Job %d] Unable to allocate memory for job.", jobid);
break;
}
else if (!job)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing <Job #> directive on line %d!", linenum);
+ "Missing <Job #> directive on line %d.", linenum);
continue;
}
- else if (!strcasecmp(line, "</Job>"))
+ else if (!_cups_strcasecmp(line, "</Job>"))
{
cupsArrayAdd(Jobs, job);
}
else if (!value)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d!", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum);
continue;
}
- else if (!strcasecmp(line, "State"))
+ else if (!_cups_strcasecmp(line, "State"))
{
job->state_value = (ipp_jstate_t)atoi(value);
else if (job->state_value > IPP_JOB_COMPLETED)
job->state_value = IPP_JOB_COMPLETED;
}
- else if (!strcasecmp(line, "HoldUntil"))
+ else if (!_cups_strcasecmp(line, "HoldUntil"))
{
job->hold_until = atoi(value);
}
- else if (!strcasecmp(line, "Priority"))
+ else if (!_cups_strcasecmp(line, "Priority"))
{
job->priority = atoi(value);
}
- else if (!strcasecmp(line, "Username"))
+ else if (!_cups_strcasecmp(line, "Username"))
{
cupsdSetString(&job->username, value);
}
- else if (!strcasecmp(line, "Destination"))
+ else if (!_cups_strcasecmp(line, "Destination"))
{
cupsdSetString(&job->dest, value);
}
- else if (!strcasecmp(line, "DestType"))
+ else if (!_cups_strcasecmp(line, "DestType"))
{
job->dtype = (cups_ptype_t)atoi(value);
}
- else if (!strcasecmp(line, "NumFiles"))
+ else if (!_cups_strcasecmp(line, "NumFiles"))
{
job->num_files = atoi(value);
if (job->num_files < 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d.",
job->num_files, linenum);
job->num_files = 0;
continue;
job->id);
if (access(jobfile, 0))
{
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Data files have gone away!",
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Data files have gone away.",
job->id);
job->num_files = 0;
continue;
if (!job->filetypes || !job->compressions)
{
cupsdLogMessage(CUPSD_LOG_EMERG,
- "[Job %d] Unable to allocate memory for %d files!",
+ "[Job %d] Unable to allocate memory for %d files.",
job->id, job->num_files);
break;
}
}
}
- else if (!strcasecmp(line, "File"))
+ else if (!_cups_strcasecmp(line, "File"))
{
int number, /* File number */
compression; /* Compression value */
if (sscanf(value, "%d%*[ \t]%15[^/]/%255s%d", &number, super, type,
&compression) != 4)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d!", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d.", linenum);
continue;
}
if (number < 1 || number > job->num_files)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d.",
number, linenum);
continue;
}
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
- "[Job %d] Unknown MIME type %s/%s for file %d!",
+ "[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,
}
}
else
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d.",
line, linenum);
}
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
{
- if (!strcasecmp(line, "NextJobId"))
+ if (!_cups_strcasecmp(line, "NextJobId"))
{
if (value)
{
if ((job = calloc(sizeof(cupsd_job_t), 1)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Ran out of memory for jobs!");
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Ran out of memory for jobs.");
cupsDirClose(dir);
return;
}
}
+/*
+ * 'remove_job_files()' - Remove the document files for a job.
+ */
+
+static void
+remove_job_files(cupsd_job_t *job) /* I - Job */
+{
+ int i; /* Looping var */
+ char filename[1024]; /* Document filename */
+
+
+ if (job->num_files <= 0)
+ return;
+
+ for (i = 1; i <= job->num_files; i ++)
+ {
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
+ job->id, i);
+ if (Classification)
+ cupsdRemoveFile(filename);
+ else
+ unlink(filename);
+ }
+
+ free(job->filetypes);
+ free(job->compressions);
+
+ job->file_time = 0;
+ job->num_files = 0;
+ job->filetypes = NULL;
+ job->compressions = NULL;
+
+ LastEvent |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+}
+
+
+/*
+ * 'remove_job_history()' - Remove the control file for a job.
+ */
+
+static void
+remove_job_history(cupsd_job_t *job) /* I - Job */
+{
+ char filename[1024]; /* Control filename */
+
+
+ /*
+ * Remove the job info file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot,
+ job->id);
+ if (Classification)
+ cupsdRemoveFile(filename);
+ else
+ unlink(filename);
+
+ LastEvent |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+}
+
+
/*
* 'set_time()' - Set one of the "time-at-xyz" attributes.
*/
const char *name) /* I - Name of attribute */
{
ipp_attribute_t *attr; /* Time attribute */
+ time_t curtime; /* Current time */
+ curtime = time(NULL);
+
+ cupsdLogJob(job, CUPSD_LOG_DEBUG, "%s=%ld", name, (long)curtime);
+
if ((attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO)) != NULL)
{
attr->value_tag = IPP_TAG_INTEGER;
- attr->values[0].integer = time(NULL);
+ attr->values[0].integer = curtime;
+ }
+
+ if (!strcmp(name, "time-at-completed"))
+ {
+ if (JobHistory < INT_MAX)
+ job->history_time = attr->values[0].integer + JobHistory;
+ else
+ job->history_time = INT_MAX;
+
+ if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->history_time;
+
+ if (JobFiles < INT_MAX)
+ job->file_time = attr->values[0].integer + JobFiles;
+ else
+ job->file_time = INT_MAX;
+
+ if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+ JobHistoryUpdate = job->file_time;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_time: JobHistoryUpdate=%ld",
+ (long)JobHistoryUpdate);
}
}
if (job->num_files == 0)
{
+ ippSetString(job->attrs, &job->reasons, 0, "aborted-by-system");
cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT,
"Aborting job because it has no files.");
return;
if (!cupsdLoadJob(job))
return;
+ if (!job->printer_message)
+ job->printer_message = ippFindAttribute(job->attrs,
+ "job-printer-state-message",
+ IPP_TAG_TEXT);
+ if (job->printer_message)
+ cupsdSetString(&(job->printer_message->values[0].string.text), "");
+
+ ippSetString(job->attrs, &job->reasons, 0, "job-printing");
cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);
cupsdSetPrinterReasons(printer, "-cups-remote-pending,"
job->cost = 0;
job->current_file = 0;
+ job->file_time = 0;
+ job->history_time = 0;
job->progress = 0;
job->printer = printer;
printer->job = job;
+ if (MaxJobTime > 0)
+ job->cancel_time = time(NULL) + MaxJobTime;
+ else
+ job->cancel_time = 0;
+
/*
* 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...
*/
job->attrs = NULL;
job->state = NULL;
+ job->reasons = NULL;
job->sheets = NULL;
job->job_sheets = NULL;
job->printer_message = NULL;
if (job->sheets)
{
- if (!strncasecmp(message, "total ", 6))
+ if (!_cups_strncasecmp(message, "total ", 6))
{
/*
* Got a total count of pages from a backend or filter...
return;
}
else if (cupsdSetPrinterReasons(job->printer, message))
+ {
event |= CUPSD_EVENT_PRINTER_STATE;
+ if (MaxJobTime > 0 && strstr(message, "connecting-to-device") != NULL)
+ {
+ /*
+ * Reset cancel time after connecting to the device...
+ */
+
+ for (i = 0; i < job->printer->num_reasons; i ++)
+ if (!strcmp(job->printer->reasons[i], "connecting-to-device"))
+ break;
+
+ if (i >= job->printer->num_reasons)
+ job->cancel_time = time(NULL) + MaxJobTime;
+ }
+ }
+
update_job_attrs(job, 0);
}
else if (loglevel == CUPSD_LOG_ATTR)
cupsdSetAuthInfoRequired(job->printer, attr, NULL);
cupsdSetPrinterAttrs(job->printer);
- if (job->printer->type & CUPS_PRINTER_DISCOVERED)
- cupsdMarkDirty(CUPSD_DIRTY_REMOTE);
- else
- cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
if ((attr = cupsGetOption("job-media-progress", num_attrs,
else
ptr = message;
- cupsdLogJob(job, loglevel, "%s", ptr);
+ if (*ptr)
+ cupsdLogJob(job, loglevel, "%s", ptr);
if (loglevel < CUPSD_LOG_DEBUG &&
strcmp(job->printer->state_message, ptr))
if (job->state_value != IPP_JOB_PROCESSING &&
job->status_level == CUPSD_LOG_INFO)
+ {
cupsdSetString(&(job->printer_message->values[0].string.text), "");
+
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+ }
else if (job->printer->state_message[0] && do_message)
+ {
cupsdSetString(&(job->printer_message->values[0].string.text),
job->printer->state_message);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+ }
+
/*
* ... and the printer-state-reasons value...
*/
for (i = 0; i < num_reasons; i ++)
job->printer_reasons->values[i].string.text = _cupsStrAlloc(reasons[i]);
+
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}