* 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);
ipp_attribute_t *attr; /* Current attribute */
const char *ptr, /* Pointer into value */
*abort_message; /* Abort message */
- ipp_jstate_t abort_state = IPP_JOB_ABORTED;
+ 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? */
job->current_file);
abort_message = "Aborting job because it cannot be printed.";
+ abort_state = IPP_JOB_ABORTED;
+
goto abort_job;
}
cupsArrayDelete(filters);
- abort_state = IPP_JOB_STOPPED;
abort_message = "Stopping job because the scheduler ran out of memory.";
goto abort_job;
cupsdLogJob(job, CUPSD_LOG_DEBUG,
"Unable to add port monitor - %s", strerror(errno));
- abort_state = IPP_JOB_STOPPED;
abort_message = "Stopping job because the scheduler ran out of memory.";
goto abort_job;
cupsArrayCount(filters), MAX_FILTERS);
abort_message = "Aborting job because it needs too many filters to print.";
+ abort_state = IPP_JOB_ABORTED;
+
goto abort_job;
}
if ((options = get_options(job, banner_page, copies, sizeof(copies), title,
sizeof(title))) == NULL)
{
- abort_state = IPP_JOB_STOPPED;
abort_message = "Stopping job because the scheduler ran out of memory.";
goto abort_job;
cupsdLogMessage(CUPSD_LOG_DEBUG, "Unable to allocate argument array - %s",
strerror(errno));
- abort_state = IPP_JOB_STOPPED;
abort_message = "Stopping job because the scheduler ran out of memory.";
goto abort_job;
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;
cupsdSetPrinterState(job->printer, IPP_PRINTER_IDLE, 0);
update_job_attrs(job, 0);
+ if (job->history)
+ free_job_history(job);
+
cupsArrayRemove(PrintingJobs, job);
/*
job->num_files = 0;
}
+ if (job->history)
+ free_job_history(job);
+
unload_job(job);
cupsArrayRemove(Jobs, job);
case IPP_JOB_ABORTED :
case IPP_JOB_CANCELED :
case IPP_JOB_COMPLETED :
- /*
- * Expire job subscriptions since the job is now "completed"...
- */
+ if (newstate == IPP_JOB_CANCELED)
+ {
+ /*
+ * Remove the job from the active list if there are no processes still
+ * running for it...
+ */
- cupsdExpireSubscriptions(NULL, job);
+ for (i = 0; job->filters[i] < 0; i++);
+
+ if (!job->filters[i] && job->backend <= 0)
+ cupsArrayRemove(ActiveJobs, job);
+ }
+ else
+ {
+ /*
+ * Otherwise just remove the job from the active list immediately...
+ */
+
+ cupsArrayRemove(ActiveJobs, job);
+ }
/*
- * Remove the job from the active list...
+ * Expire job subscriptions since the job is now "completed"...
*/
- cupsArrayRemove(ActiveJobs, job);
+ cupsdExpireSubscriptions(NULL, job);
#ifdef __APPLE__
/*
}
+/*
+ * '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.
*/
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...
+ * Clear the "connecting-to-device" reason, which is only valid when a printer
+ * is processing...
*/
cupsdSetPrinterReasons(job->printer, "-connecting-to-device");
default :
case IPP_JOB_PROCESSING :
case IPP_JOB_COMPLETED :
- job_state = IPP_JOB_COMPLETED;
- message = "Job completed.";
+ job_state = IPP_JOB_COMPLETED;
+ message = "Job completed.";
break;
case IPP_JOB_STOPPED :
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;
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;
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);
/*
attr->value_tag == IPP_TAG_BEGIN_COLLECTION) /* Not yet supported */
continue;
- if (!strncmp(attr->name, "time-", 5))
+ if (!strncmp(attr->name, "time-", 5) ||
+ !strcmp(attr->name, "job-hold-until"))
continue;
if (!strncmp(attr->name, "job-", 4) &&
{
cupsArrayAdd(Jobs, job);
- if (job->state_value <= IPP_JOB_STOPPED)
- {
- cupsArrayAdd(ActiveJobs, job);
- cupsdLoadJob(job);
- }
+ if (job->state_value <= IPP_JOB_STOPPED && cupsdLoadJob(job))
+ cupsArrayAdd(ActiveJobs, job);
job = NULL;
}
* Load the job...
*/
- cupsdLoadJob(job);
-
- /*
- * Insert the job into the array, sorting by job priority and ID...
- */
+ if (cupsdLoadJob(job))
+ {
+ /*
+ * Insert the job into the array, sorting by job priority and ID...
+ */
- cupsArrayAdd(Jobs, job);
+ cupsArrayAdd(Jobs, job);
- if (job->state_value <= IPP_JOB_STOPPED)
- cupsArrayAdd(ActiveJobs, job);
- else
- unload_job(job);
+ if (job->state_value <= IPP_JOB_STOPPED)
+ cupsArrayAdd(ActiveJobs, job);
+ else
+ unload_job(job);
+ }
}
cupsDirClose(dir);
fcntl(job->side_pipes[1], F_SETFL,
fcntl(job->side_pipes[1], F_GETFL) | O_NONBLOCK);
+ fcntl(job->side_pipes[0], F_SETFD,
+ fcntl(job->side_pipes[0], F_GETFD) | FD_CLOEXEC);
+ fcntl(job->side_pipes[1], F_SETFD,
+ fcntl(job->side_pipes[1], F_GETFD) | FD_CLOEXEC);
+
/*
* Now start the first file in the job...
*/
{
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? */
cupsdStopPrinter(job->printer, 1);
return;
}
- else
+ else if (cupsdSetPrinterReasons(job->printer, message))
{
- cupsdSetPrinterReasons(job->printer, message);
cupsdAddPrinterHistory(job->printer);
event |= CUPSD_EVENT_PRINTER_STATE;
}
cupsFreeOptions(num_keywords, keywords);
}
-#ifdef __APPLE__
- else if (!strncmp(message, "recoverable:", 12))
+ else
{
- ptr = message + 12;
- while (isspace(*ptr & 255))
- ptr ++;
+ /*
+ * Strip legacy message prefix...
+ */
- if (*ptr)
+ if (!strncmp(message, "recoverable:", 12))
{
- cupsdSetPrinterReasons(job->printer,
- "+com.apple.print.recoverable-warning");
- cupsdSetString(&(job->printer->recoverable), ptr);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE;
+ ptr = message + 12;
+ while (isspace(*ptr & 255))
+ ptr ++;
}
- }
- else if (!strncmp(message, "recovered:", 10))
- {
- cupsdSetPrinterReasons(job->printer,
- "-com.apple.print.recoverable-warning");
-
- ptr = message + 10;
- while (isspace(*ptr & 255))
- ptr ++;
+ else if (!strncmp(message, "recovered:", 10))
+ {
+ ptr = message + 10;
+ while (isspace(*ptr & 255))
+ ptr ++;
+ }
+ else
+ ptr = message;
- cupsdSetString(&(job->printer->recoverable), ptr);
- cupsdAddPrinterHistory(job->printer);
- event |= CUPSD_EVENT_PRINTER_STATE;
- }
-#endif /* __APPLE__ */
- else
- {
- cupsdLogJob(job, loglevel, "%s", message);
+ cupsdLogJob(job, loglevel, "%s", ptr);
if (loglevel < CUPSD_LOG_DEBUG)
{
- strlcpy(job->printer->state_message, message,
+ strlcpy(job->printer->state_message, ptr,
sizeof(job->printer->state_message));
cupsdAddPrinterHistory(job->printer);