*
* Printer 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
* load_ppd() - Load a cached PPD file, updating the cache as
* needed.
* new_media_col() - Create a media-col collection value.
- * write_irix_config() - Update the config files used by the IRIX
- * desktop tools.
- * write_irix_state() - Update the status files used by IRIX printing
- * desktop tools.
* write_xml_string() - Write a string with XML escaping.
*/
static void log_ipp_conformance(cupsd_printer_t *p, const char *reason);
static ipp_t *new_media_col(_pwg_size_t *size, const char *source,
const char *type);
-#ifdef __sgi
-static void write_irix_config(cupsd_printer_t *p);
-static void write_irix_state(cupsd_printer_t *p);
-#endif /* __sgi */
static void write_xml_string(cups_file_t *fp, const char *s);
"multiple-document-handling",
"number-up",
"output-bin",
- "output-mode",
"orientation-requested",
"page-ranges",
+ "print-color-mode",
"print-quality",
"printer-resolution",
"sides"
"multiple-document-handling",
"number-up",
"output-bin",
- "output-mode",
"orientation-requested",
"page-ranges",
+ "print-color-mode",
"print-quality",
"printer-resolution",
"sides"
/* operations-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "operations-supported",
- sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops);
+ "operations-supported", sizeof(ops) / sizeof(ops[0]), ops);
/* orientation-requested-supported */
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
{
int i, /* Looping var */
changed = 0; /* Class changed? */
-#ifdef __sgi
- char filename[1024]; /* Interface script filename */
-#endif /* __sgi */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)",
"cupsdDeletePrinter: Removing %s from Printers", p->name);
cupsArrayRemove(Printers, p);
- /*
- * Remove the dummy interface/icon/option files under IRIX...
- */
-
-#ifdef __sgi
- snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
- unlink(filename);
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui",
- p->name);
- unlink(filename);
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
- unlink(filename);
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
- unlink(filename);
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
- unlink(filename);
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
- unlink(filename);
-#endif /* __sgi */
-
/*
* If p is the default printer, assign a different one...
*/
cupsdClearString(&p->alert);
cupsdClearString(&p->alert_description);
-#ifdef HAVE_DNSSD
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
cupsdClearString(&p->pdl);
-#endif /* HAVE_DNSSD */
+ cupsdClearString(&p->reg_name);
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
cupsArrayDelete(p->filetypes);
(long)printer->marker_time);
cupsFilePuts(fp, "</Printer>\n");
-
-#ifdef __sgi
- /*
- * Make IRIX desktop & printer status happy
- */
-
- write_irix_state(printer);
-#endif /* __sgi */
}
cupsdCloseCreatedConfFile(fp, filename);
ipp_attribute_t *attr; /* Attribute */
int i, /* Looping var */
count; /* Number of values */
- char *ptr; /* Pointer into value */
+ char *ptr, /* Pointer into value */
+ *start, /* Start of value */
+ quote; /* Quote character */
ipp_tag_t value_tag; /* Value tag for this attribute */
* Count the number of values...
*/
- for (count = 1, ptr = value;
- (ptr = strchr(ptr, ',')) != NULL;
- ptr ++, count ++);
+ for (count = 1, quote = '\0', ptr = value;
+ *ptr;
+ ptr ++)
+ {
+ if (*ptr == quote)
+ quote = '\0';
+ else if (quote)
+ continue;
+ else if (*ptr == '\\' && ptr[1])
+ ptr ++;
+ else if (*ptr == '\'' || *ptr == '\"')
+ quote = *ptr;
+ else if (*ptr == ',')
+ count ++;
+ }
/*
* Then add or update the attribute as needed...
return;
}
- for (i = 0; i < count; i ++)
+ for (i = 0, quote = '\0', ptr = value; i < count; i ++)
{
- if ((ptr = strchr(value, ',')) != NULL)
- *ptr++ = '\0';
+ for (start = ptr; *ptr; ptr ++)
+ {
+ if (*ptr == quote)
+ *ptr = quote = '\0';
+ else if (quote)
+ continue;
+ else if (*ptr == '\\' && ptr[1])
+ _cups_strcpy(ptr, ptr + 1);
+ else if (*ptr == '\'' || *ptr == '\"')
+ {
+ quote = *ptr;
- attr->values[i].string.text = _cupsStrAlloc(value);
+ if (ptr == start)
+ start ++;
+ else
+ _cups_strcpy(ptr, ptr + 1);
+ }
+ else if (*ptr == ',')
+ {
+ *ptr++ = '\0';
+ break;
+ }
+ }
- if (ptr)
- value = ptr;
+ attr->values[i].string.text = _cupsStrAlloc(start);
}
}
}
add_printer_defaults(p);
-#ifdef __sgi
- /*
- * Write the IRIX printer config and status files...
- */
-
- write_irix_config(p);
- write_irix_state(p);
-#endif /* __sgi */
-
/*
* Let the browse protocols reflect the change
*/
ipp_pstate_t s, /* I - New state */
int update) /* I - Update printers.conf? */
{
+ cupsd_job_t *job; /* Current job */
ipp_pstate_t old_state; /* Old printer state */
static const char * const printer_states[] =
{ /* State strings */
*/
p->state_time = time(NULL);
-
-#ifdef __sgi
- write_irix_state(p);
-#endif /* __sgi */
}
/*
else
cupsdSetPrinterReasons(p, "-paused");
+ if (old_state != s)
+ {
+ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
+ job;
+ job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
+ if (job->reasons && job->state_value == IPP_JOB_PENDING &&
+ !_cups_strcasecmp(job->dest, p->name))
+ ippSetString(job->attrs, &job->reasons, 0,
+ s == IPP_PRINTER_STOPPED ? "printer-stopped" : "none");
+ }
+
/*
* Clear the message for the queue when going to processing...
*/
cupsd_printer_t *p; /* Current printer */
-#ifdef __sgi
- /*
- * Update the IRIX printer state for the default printer; if
- * no printers remain, then the default printer file will be
- * removed...
- */
-
- write_irix_state(DefaultPrinter);
-#endif /* __sgi */
-
/*
* See if we have a printcap file; if not, don't bother writing it.
*/
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default"));
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default"));
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-account-id-default"));
+ cupsArrayAdd(CommonDefaults,
+ _cupsStrAlloc("job-accounting-user-id-default"));
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-hold-until-default"));
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-priority-default"));
cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-sheets-default"));
attr->values[i].string.text = _cupsStrAlloc(mimetype);
}
-#ifdef HAVE_DNSSD
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
{
char pdl[1024]; /* Buffer to build pdl list */
mime_filter_t *filter; /* MIME filter looping var */
cupsdSetString(&p->pdl, pdl);
}
-#endif /* HAVE_DNSSD */
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
}
qualities[3]; /* print-quality values */
int num_margins, /* Number of media-*-margin-supported values */
margins[16]; /* media-*-margin-supported values */
- const char *filter; /* Current filter */
+ const char *filter, /* Current filter */
+ *mandatory; /* Current mandatory attribute */
static const char * const sides[3] = /* sides-supported values */
{
"one-sided",
p->pc = _ppdCacheCreateWithPPD(ppd);
+ if (!p->pc)
+ cupsdLogMessage(CUPSD_LOG_WARN, "Unable to create cache of \"%s\": %s",
+ ppd_name, cupsLastErrorString());
+
ppdMarkDefaults(ppd);
if (ppd->color_device)
ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported",
ppd->color_device);
+
+ if (p->pc && p->pc->account_id)
+ ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "job-account-id-supported",
+ 1);
+
+ if (p->pc && p->pc->accounting_user_id)
+ ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER,
+ "job-accounting-user-id-supported", 1);
+
+ if (p->pc && p->pc->password)
+ {
+ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "job-password-encryption-supported", NULL, "none");
+ ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-password-supported", strlen(p->pc->password));
+ }
+
if (ppd->throughput)
{
ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
}
}
+ /*
+ * media-size-supported
+ */
+
+ num_media = p->pc->num_sizes;
+ if (p->pc->custom_min_keyword)
+ num_media ++;
+
+ if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER,
+ "media-size-supported", num_media,
+ NULL)) != NULL)
+ {
+ val = attr->values;
+
+ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes;
+ i > 0;
+ i --, pwgsize ++, val ++)
+ {
+ val->collection = ippNew();
+ ippAddInteger(val->collection, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "x-dimension", pwgsize->width);
+ ippAddInteger(val->collection, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "y-dimension", pwgsize->length);
+ }
+
+ if (p->pc->custom_min_keyword)
+ {
+ val->collection = ippNew();
+ ippAddRange(val->collection, IPP_TAG_PRINTER, "x-dimension",
+ p->pc->custom_min_width, p->pc->custom_max_width);
+ ippAddRange(val->collection, IPP_TAG_PRINTER, "y-dimension",
+ p->pc->custom_min_length, p->pc->custom_max_length);
+ }
+ }
+
/*
* media-source-supported
*/
}
/*
- * output-mode and print-color-mode...
+ * print-color-mode...
*/
if (ppd->color_device)
{
- static const char * const output_modes[] =
+ static const char * const color_modes[] =
{
"monochrome",
"color"
};
ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-mode-supported", 2, NULL, output_modes);
- ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-mode-default", NULL, "color");
-
- ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "print-color-mode-supported", 2, NULL, output_modes);
+ "print-color-mode-supported", 2, NULL, color_modes);
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"print-color-mode-default", NULL, "color");
}
else
{
- ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-mode-supported", NULL, "monochrome");
- ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "output-mode-default", NULL, "monochrome");
-
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"print-color-mode-supported", NULL, "monochrome");
ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"print-color-mode-default", NULL, "monochrome");
}
+ /*
+ * Mandatory job attributes, if any...
+ */
+
+ if (p->pc && cupsArrayCount(p->pc->mandatory) > 0)
+ {
+ int count = cupsArrayCount(p->pc->mandatory);
+ /* Number of mandatory attributes */
+
+ attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-mandatory-job-attributes", count, NULL,
+ NULL);
+
+ for (val = attr->values,
+ mandatory = (char *)cupsArrayFirst(p->pc->mandatory);
+ mandatory;
+ val ++, mandatory = (char *)cupsArrayNext(p->pc->mandatory))
+ val->string.text = _cupsStrRetain(mandatory);
+ }
+
/*
* Printer resolutions...
*/
"printer-make-and-model", NULL,
"Local System V Printer");
}
- else if (!strncmp(p->device_uri, "ipp://", 6) &&
- (strstr(p->device_uri, "/printers/") != NULL ||
- strstr(p->device_uri, "/classes/") != NULL ||
- (strstr(p->device_uri, "._ipp.") != NULL &&
- !strcmp(p->device_uri + strlen(p->device_uri) - 5,
- "/cups"))))
+ else if (((!strncmp(p->device_uri, "ipp://", 6) ||
+ !strncmp(p->device_uri, "ipps://", 7)) &&
+ (strstr(p->device_uri, "/printers/") != NULL ||
+ strstr(p->device_uri, "/classes/") != NULL)) ||
+ ((strstr(p->device_uri, "._ipp.") != NULL ||
+ strstr(p->device_uri, "._ipps.") != NULL) &&
+ !strcmp(p->device_uri + strlen(p->device_uri) - 5, "/cups")))
{
/*
* Tell the client this is really a hard-wired remote printer.
message = "Printer does not support REQUIRED Validate-Job operation.";
else if (!strcmp(reason, "missing-get-printer-attributes"))
message = "Printer does not support REQUIRED Get-Printer-Attributes operation.";
+ else if (!strcmp(reason, "missing-send-document"))
+ message = "Printer supports Create-Job but not Send-Document operation.";
else if (!strcmp(reason, "missing-job-history"))
message = "Printer does not provide REQUIRED job history.";
else if (!strcmp(reason, "missing-job-id"))
}
-#ifdef __sgi
-/*
- * 'write_irix_config()' - Update the config files used by the IRIX
- * desktop tools.
- */
-
-static void
-write_irix_config(cupsd_printer_t *p) /* I - Printer to update */
-{
- char filename[1024]; /* Interface script filename */
- cups_file_t *fp; /* Interface script file */
- ipp_attribute_t *attr; /* Attribute data */
-
-
- /*
- * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
- * tools. First the interface script that tells the tools what kind of
- * printer we have...
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePuts(fp, "#!/bin/sh\n");
-
- if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
- IPP_TAG_TEXT)) != NULL)
- cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
- else if (p->type & CUPS_PRINTER_CLASS)
- cupsFilePuts(fp, "NAME=\"Printer Class\"\n");
- else
- cupsFilePuts(fp, "NAME=\"Remote Destination\"\n");
-
- if (p->type & CUPS_PRINTER_COLOR)
- cupsFilePuts(fp, "TYPE=ColorPostScript\n");
- else
- cupsFilePuts(fp, "TYPE=MonoPostScript\n");
-
- cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName);
- cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name);
-
- cupsFileClose(fp);
-
- chmod(filename, 0755);
- chown(filename, User, Group);
- }
-
- /*
- * Then the member file that tells which device file the queue is connected
- * to... Networked printers use "/dev/null" in this file, so that's what
- * we use (the actual device URI can confuse some apps...)
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePuts(fp, "/dev/null\n");
-
- cupsFileClose(fp);
-
- chmod(filename, 0644);
- chown(filename, User, Group);
- }
-
- /*
- * The gui_interface file is a script or program that launches a GUI
- * option panel for the printer, using options specified on the
- * command-line in the third argument. The option panel must send
- * any printing options to stdout on a single line when the user
- * accepts them, or nothing if the user cancels the dialog.
- *
- * The default options panel program is /usr/bin/glpoptions, from
- * the ESP Print Pro software. You can select another using the
- * PrintcapGUI option.
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePuts(fp, "#!/bin/sh\n");
- cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
-
- cupsFileClose(fp);
-
- chmod(filename, 0755);
- chown(filename, User, Group);
- }
-
- /*
- * The POD config file is needed by the printstatus command to show
- * the printer location and device.
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePrintf(fp, "Printer Class | %s\n",
- (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript");
- cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : "");
- cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : "");
- cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : "");
- cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri);
- cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name);
- cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
- cupsFilePuts(fp, "Status Update Wait | 10 seconds\n");
-
- cupsFileClose(fp);
-
- chmod(filename, 0664);
- chown(filename, User, Group);
- }
-}
-
-
-/*
- * 'write_irix_state()' - Update the status files used by IRIX printing
- * desktop tools.
- */
-
-static void
-write_irix_state(cupsd_printer_t *p) /* I - Printer to update */
-{
- char filename[1024]; /* Interface script filename */
- cups_file_t *fp; /* Interface script file */
- int tag; /* Status tag value */
-
-
- if (p)
- {
- /*
- * The POD status file is needed for the printstatus window to
- * provide the current status of the printer.
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePrintf(fp, "Operational Status | %s\n",
- (p->state == IPP_PRINTER_IDLE) ? "Idle" :
- (p->state == IPP_PRINTER_PROCESSING) ? "Busy" :
- "Faulted");
- cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION);
- cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n",
- p->device_uri);
- cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n",
- p->accepting ? "Accepting" : "Not accepting");
- cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
-
- cupsFileClose(fp);
-
- chmod(filename, 0664);
- chown(filename, User, Group);
- }
-
- /*
- * The activeicons file is needed to provide desktop icons for printers:
- *
- * [ quoted from /usr/lib/print/tagit ]
- *
- * --- Type of printer tags (base values)
- *
- * Dumb=66048 # 0x10200
- * DumbColor=66080 # 0x10220
- * Raster=66112 # 0x10240
- * ColorRaster=66144 # 0x10260
- * Plotter=66176 # 0x10280
- * PostScript=66208 # 0x102A0
- * ColorPostScript=66240 # 0x102C0
- * MonoPostScript=66272 # 0x102E0
- *
- * --- Printer state modifiers for local printers
- *
- * Idle=0 # 0x0
- * Busy=1 # 0x1
- * Faulted=2 # 0x2
- * Unknown=3 # 0x3 (Faulted due to unknown reason)
- *
- * --- Printer state modifiers for network printers
- *
- * NetIdle=8 # 0x8
- * NetBusy=9 # 0x9
- * NetFaulted=10 # 0xA
- * NetUnknown=11 # 0xB (Faulted due to unknown reason)
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
-
- if (p->type & CUPS_PRINTER_CLASS)
- unlink(filename);
- else if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- if (p->type & CUPS_PRINTER_COLOR)
- tag = 66240;
- else
- tag = 66272;
-
- if (p->type & CUPS_PRINTER_REMOTE)
- tag |= 8;
-
- if (p->state == IPP_PRINTER_PROCESSING)
- tag |= 1;
-
- else if (p->state == IPP_PRINTER_STOPPED)
- tag |= 2;
-
- cupsFilePuts(fp, "#!/bin/sh\n");
- cupsFilePrintf(fp, "#Tag %d\n", tag);
-
- cupsFileClose(fp);
-
- chmod(filename, 0755);
- chown(filename, User, Group);
- }
- }
-
- /*
- * The default file is needed by the printers window to show
- * the default printer.
- */
-
- snprintf(filename, sizeof(filename), "/var/spool/lp/default");
-
- if (DefaultPrinter != NULL)
- {
- if ((fp = cupsFileOpen(filename, "w")) != NULL)
- {
- cupsFilePrintf(fp, "%s\n", DefaultPrinter->name);
-
- cupsFileClose(fp);
-
- chmod(filename, 0644);
- chown(filename, User, Group);
- }
- }
- else
- unlink(filename);
-}
-#endif /* __sgi */
-
-
/*
* 'write_xml_string()' - Write a string with XML escaping.
*/