/*
- * "$Id: printers.c,v 1.72 2000/09/06 19:40:12 mike Exp $"
+ * "$Id: printers.c,v 1.93.2.46 2003/04/03 03:33:41 mike Exp $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2000 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2003 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
*
* Contents:
*
- * AddPrinter() - Add a printer to the system.
- * DeleteAllPrinters() - Delete all printers from the system.
- * DeletePrinter() - Delete a printer from the system.
- * FindPrinter() - Find a printer in the list.
- * LoadAllPrinters() - Load printers from the printers.conf file.
- * SaveAllPrinters() - Save all printer definitions to the printers.conf
- * SetPrinterAttrs() - Set printer attributes based upon the PPD file.
- * SetPrinterState() - Update the current state of a printer.
- * SortPrinters() - Sort the printer list when a printer name is
- * changed.
- * StopPrinter() - Stop a printer from printing any jobs...
- * ValidateDest() - Validate a printer/class destination.
- * write_printcap() - Write a pseudo-printcap file for older applications
- * that need it...
+ * AddPrinter() - Add a printer to the system.
+ * AddPrinterFilter() - Add a MIME filter for a printer.
+ * AddPrinterHistory() - Add the current printer state to the history.
+ * AddPrinterUser() - Add a user to the ACL.
+ * DeleteAllPrinters() - Delete all printers from the system.
+ * DeletePrinter() - Delete a printer from the system.
+ * DeletePrinterFilters() - Delete all MIME filters for a printer.
+ * FindPrinter() - Find a printer in the list.
+ * FreePrinterUsers() - Free allow/deny users.
+ * LoadAllPrinters() - Load printers from the printers.conf file.
+ * SaveAllPrinters() - Save all printer definitions to the printers.conf
+ * SetPrinterAttrs() - Set printer attributes based upon the PPD file.
+ * SetPrinterReasons() - Set/update the reasons strings.
+ * SetPrinterState() - Update the current state of a printer.
+ * SortPrinters() - Sort the printer list when a printer name is
+ * changed.
+ * StopPrinter() - Stop a printer from printing any jobs...
+ * ValidateDest() - Validate a printer/class destination.
+ * WritePrintcap() - Write a pseudo-printcap file for older
+ * applications that need it...
+ * 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.
*/
/*
* Local functions...
*/
-static void write_printcap(void);
+#ifdef __sgi
+static void write_irix_state(printer_t *p);
+#endif /* __sgi */
/*
*prev; /* Previous printer in list */
- DEBUG_printf(("AddPrinter(\"%s\")\n", name));
-
/*
* Range check input...
*/
+ LogMessage(L_DEBUG2, "AddPrinter(\"%s\")", name ? name : "(null)");
+
if (name == NULL)
return (NULL);
* Create a new printer entity...
*/
- if ((p = calloc(sizeof(printer_t), 1)) == NULL)
+ if ((p = calloc(1, sizeof(printer_t))) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to allocate memory for printer - %s",
+ strerror(errno));
return (NULL);
+ }
- strcpy(p->name, name);
- strcpy(p->hostname, ServerName);
- sprintf(p->uri, "ipp://%s:%d/printers/%s", ServerName,
- ntohs(Listeners[0].address.sin_port), name);
- strcpy(p->more_info, p->uri);
+ SetString(&p->name, name);
+ SetString(&p->info, name);
+ SetString(&p->hostname, ServerName);
+
+#ifdef AF_INET6
+ if (Listeners[0].address.addr.sa_family == AF_INET6)
+ SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName,
+ ntohs(Listeners[0].address.ipv6.sin6_port), name);
+ else
+#endif /* AF_INET6 */
+ SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName,
+ ntohs(Listeners[0].address.ipv4.sin_port), name);
+ SetStringf(&p->device_uri, "file:/dev/null");
p->state = IPP_PRINTER_STOPPED;
p->accepting = 0;
p->filetype = mimeAddType(MimeDatabase, "printer", name);
- strcpy(p->job_sheets[0], "none");
- strcpy(p->job_sheets[1], "none");
-
- /*
- * Setup required filters and IPP attributes...
- */
-
- SetPrinterAttrs(p);
+ SetString(&p->job_sheets[0], "none");
+ SetString(&p->job_sheets[1], "none");
+
+ if (MaxPrinterHistory)
+ p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *));
/*
* Insert the printer in the printer list alphabetically...
* Write a new /etc/printcap or /var/spool/lp/pstatus file.
*/
- write_printcap();
+ WritePrintcap();
return (p);
}
*/
void
-AddPrinterFilter(printer_t *p, /* I - Printer to add to */
- char *filter) /* I - Filter to add */
+AddPrinterFilter(printer_t *p, /* I - Printer to add to */
+ const char *filter) /* I - Filter to add */
{
int i; /* Looping var */
char super[MIME_MAX_SUPER], /* Super-type for filter */
* Range check input...
*/
- if (p == NULL || filter == NULL)
+ if (p == NULL || p->filetype == NULL || filter == NULL)
return;
/*
for (temptype = MimeDatabase->types, i = MimeDatabase->num_types;
i > 0;
i --, temptype ++)
- if (((super[0] == '*' && strcmp((*temptype)->super, "printer") != 0) ||
- strcmp((*temptype)->super, super) == 0) &&
- (type[0] == '*' || strcmp((*temptype)->type, type) == 0))
+ if (((super[0] == '*' && strcasecmp((*temptype)->super, "printer") != 0) ||
+ strcasecmp((*temptype)->super, super) == 0) &&
+ (type[0] == '*' || strcasecmp((*temptype)->type, type) == 0))
{
- LogMessage(L_DEBUG, "Adding filter %s/%s %s/%s %d %s",
+ LogMessage(L_DEBUG2, "Adding filter %s/%s %s/%s %d %s",
(*temptype)->super, (*temptype)->type,
p->filetype->super, p->filetype->type,
cost, program);
}
+/*
+ * 'AddPrinterHistory()' - Add the current printer state to the history.
+ */
+
+void
+AddPrinterHistory(printer_t *p) /* I - Printer */
+{
+ ipp_t *history; /* History collection */
+
+
+ /*
+ * Stop early if we aren't keeping history data...
+ */
+
+ if (MaxPrinterHistory <= 0)
+ return;
+
+ /*
+ * Retire old history data as needed...
+ */
+
+ if (p->num_history >= MaxPrinterHistory)
+ {
+ p->num_history --;
+ ippDelete(p->history[0]);
+ memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *));
+ }
+
+ /*
+ * Create a collection containing the current printer-state, printer-up-time,
+ * printer-state-message, and printer-state-reasons attributes.
+ */
+
+ history = ippNew();
+ ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ p->state);
+ ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message",
+ NULL, p->state_message);
+ if (p->num_reasons == 0)
+ ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", NULL,
+ p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
+ else
+ ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", p->num_reasons, NULL,
+ (const char * const *)p->reasons);
+ ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state-time",
+ p->state_time);
+
+ p->history[p->num_history] = history;
+ p->num_history ++;
+}
+
+
+/*
+ * 'AddPrinterUser()' - Add a user to the ACL.
+ */
+
+void
+AddPrinterUser(printer_t *p, /* I - Printer */
+ const char *username) /* I - User */
+{
+ const char **temp; /* Temporary array pointer */
+
+
+ if (!p || !username)
+ return;
+
+ if (p->num_users == 0)
+ temp = malloc(sizeof(char **));
+ else
+ temp = realloc(p->users, sizeof(char **) * (p->num_users + 1));
+
+ if (!temp)
+ return;
+
+ p->users = temp;
+ temp += p->num_users;
+
+ if ((*temp = strdup(username)) != NULL)
+ p->num_users ++;
+}
+
+
/*
* 'DeleteAllPrinters()' - Delete all printers from the system.
*/
if (!(p->type & CUPS_PRINTER_CLASS))
DeletePrinter(p);
}
+
+ if (CommonData)
+ {
+ ippDelete(CommonData);
+ CommonData = NULL;
+ }
}
void
DeletePrinter(printer_t *p) /* I - Printer to delete */
{
+ int i; /* Looping var */
printer_t *current, /* Current printer in list */
*prev; /* Previous printer in list */
#ifdef __sgi
if (p == NULL)
return;
- /*
- * Stop printing on this printer...
- */
-
- StopPrinter(p);
-
/*
* Remove the printer from the list...
*/
else
prev->next = p->next;
- if (p->printers != NULL)
- free(p->printers);
+ /*
+ * Stop printing on this printer...
+ */
- ippDelete(p->attrs);
+ StopPrinter(p);
- free(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 the next one...
*/
if (p == DefaultPrinter)
+ {
DefaultPrinter = Printers;
+ WritePrintcap();
+ }
+
/*
- * Write a new /etc/printcap file, and delete the dummy interface and GUI
- * scripts to fool SGI's stupid printing tools.
+ * Remove this printer from any classes...
*/
- write_printcap();
+ if (!(p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
+ DeletePrinterFromClasses(p);
-#ifdef __sgi
- sprintf(filename, "/var/spool/lp/interface/%s", p->name);
- unlink(filename);
+ /*
+ * Free all memory used by the printer...
+ */
- sprintf(filename, "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
- unlink(filename);
+ if (p->printers != NULL)
+ free(p->printers);
- sprintf(filename, "/var/spool/lp/activeicons/%s", p->name);
- unlink(filename);
-#endif /* __sgi */
+ if (MaxPrinterHistory)
+ {
+ for (i = 0; i < p->num_history; i ++)
+ ippDelete(p->history[i]);
+
+ free(p->history);
+ }
+
+ for (i = 0; i < p->num_reasons; i ++)
+ free(p->reasons[i]);
+
+ ippDelete(p->attrs);
+
+ DeletePrinterFilters(p);
+
+ FreePrinterUsers(p);
+ FreeQuotas(p);
+
+ ClearString(&p->uri);
+ ClearString(&p->hostname);
+ ClearString(&p->name);
+ ClearString(&p->location);
+ ClearString(&p->make_model);
+ ClearString(&p->info);
+ ClearString(&p->job_sheets[0]);
+ ClearString(&p->job_sheets[1]);
+ ClearString(&p->device_uri);
+
+ free(p);
+
+ /*
+ * Write a new /etc/printcap file...
+ */
+
+ WritePrintcap();
}
/*
- * 'AddPrinterFilter()' - Add a MIME filter for a printer.
+ * 'DeletePrinterFilters()' - Delete all MIME filters for a printer.
*/
void
}
+/*
+ * 'FindDest()' - Find a destination in the list.
+ */
+
+printer_t * /* O - Destination in list */
+FindDest(const char *name) /* I - Name of printer or class to find */
+{
+ printer_t *p; /* Current destination */
+ int diff; /* Difference */
+
+
+ for (p = Printers; p != NULL; p = p->next)
+ if ((diff = strcasecmp(name, p->name)) == 0)/* name == p->name */
+ return (p);
+ else if (diff < 0) /* name < p->name */
+ return (NULL);
+
+ return (NULL);
+}
+
+
/*
* 'FindPrinter()' - Find a printer in the list.
*/
FindPrinter(const char *name) /* I - Name of printer to find */
{
printer_t *p; /* Current printer */
+ int diff; /* Difference */
for (p = Printers; p != NULL; p = p->next)
- switch (strcasecmp(name, p->name))
- {
- case 0 : /* name == p->name */
- if (!(p->type & CUPS_PRINTER_CLASS))
- return (p);
- case 1 : /* name > p->name */
- break;
- case -1 : /* name < p->name */
- return (NULL);
- }
+ if ((diff = strcasecmp(name, p->name)) == 0 &&
+ !(p->type & CUPS_PRINTER_CLASS)) /* name == p->name */
+ return (p);
+ else if (diff < 0) /* name < p->name */
+ return (NULL);
return (NULL);
}
+/*
+ * 'FreePrinterUsers()' - Free allow/deny users.
+ */
+
+void
+FreePrinterUsers(printer_t *p) /* I - Printer */
+{
+ int i; /* Looping var */
+
+
+ if (!p || !p->num_users)
+ return;
+
+ for (i = 0; i < p->num_users; i ++)
+ free((void *)p->users[i]);
+
+ free(p->users);
+
+ p->num_users = 0;
+ p->users = NULL;
+}
+
+
/*
* 'LoadAllPrinters()' - Load printers from the printers.conf file.
*/
void
LoadAllPrinters(void)
{
- FILE *fp; /* printers.conf file */
+ cups_file_t *fp; /* printers.conf file */
int linenum; /* Current line number */
int len; /* Length of line */
char line[1024], /* Line from file */
/*
- * Open the printer.conf file...
+ * Open the printers.conf file...
*/
- sprintf(line, "%s/printers.conf", ServerRoot);
- if ((fp = fopen(line, "r")) == NULL)
+ snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot);
+ if ((fp = cupsFileOpen(line, "r")) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllPrinters: Unable to open %s - %s", line,
+ strerror(errno));
return;
+ }
/*
* Read printer configurations until we hit EOF...
linenum = 0;
p = NULL;
- while (fgets(line, sizeof(line), fp) != NULL)
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
{
linenum ++;
continue;
/*
- * Strip trailing newline, if any...
+ * Strip trailing whitespace, if any...
*/
len = strlen(line);
- if (line[len - 1] == '\n')
+ while (len > 0 && isspace(line[len - 1]))
{
len --;
line[len] = '\0';
for (value = line; isspace(*value); value ++);
- for (nameptr = name; *value != '\0' && !isspace(*value);)
+ for (nameptr = name; *value != '\0' && !isspace(*value) &&
+ nameptr < (name + sizeof(name) - 1);)
*nameptr++ = *value++;
*nameptr = '\0';
line[len - 1] = '\0';
+ LogMessage(L_DEBUG, "LoadAllPrinters: Loading printer %s...", value);
+
p = AddPrinter(value);
p->accepting = 1;
p->state = IPP_PRINTER_IDLE;
if (p != NULL)
{
SetPrinterAttrs(p);
+ AddPrinterHistory(p);
p = NULL;
}
else
linenum);
return;
}
-
else if (strcmp(name, "Info") == 0)
- strncpy(p->info, value, sizeof(p->info) - 1);
+ SetString(&p->info, value);
else if (strcmp(name, "Location") == 0)
- strncpy(p->location, value, sizeof(p->location) - 1);
+ SetString(&p->location, value);
else if (strcmp(name, "DeviceURI") == 0)
- strncpy(p->device_uri, value, sizeof(p->device_uri) - 1);
+ SetString(&p->device_uri, value);
else if (strcmp(name, "State") == 0)
{
/*
while (isspace(*value))
value ++;
- strcpy(p->state_message, value);
+ strlcpy(p->state_message, value, sizeof(p->state_message));
}
else if (strcmp(name, "Accepting") == 0)
{
if (*valueptr)
*valueptr++ = '\0';
- strncpy(p->job_sheets[0], value, sizeof(p->job_sheets[0]) - 1);
+ SetString(&p->job_sheets[0], value);
while (isspace(*valueptr))
valueptr ++;
if (*valueptr)
*valueptr++ = '\0';
- strncpy(p->job_sheets[1], value, sizeof(p->job_sheets[1]) - 1);
+ SetString(&p->job_sheets[1], value);
}
}
+ else if (strcmp(name, "AllowUser") == 0)
+ {
+ p->deny_users = 0;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "DenyUser") == 0)
+ {
+ p->deny_users = 1;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "QuotaPeriod") == 0)
+ p->quota_period = atoi(value);
+ else if (strcmp(name, "PageLimit") == 0)
+ p->page_limit = atoi(value);
+ else if (strcmp(name, "KLimit") == 0)
+ p->k_limit = atoi(value);
else
{
/*
}
}
- fclose(fp);
+ cupsFileClose(fp);
}
void
SaveAllPrinters(void)
{
- FILE *fp; /* printers.conf file */
+ int i; /* Looping var */
+ cups_file_t *fp; /* printers.conf file */
char temp[1024]; /* Temporary string */
+ char backup[1024]; /* printers.conf.O file */
printer_t *printer; /* Current printer class */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
* Create the printers.conf file...
*/
- sprintf(temp, "%s/printers.conf", ServerRoot);
- if ((fp = fopen(temp, "w")) == NULL)
+ snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot);
+ snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot);
+
+ if (rename(temp, backup))
+ LogMessage(L_ERROR, "Unable to backup printers.conf - %s", strerror(errno));
+
+ if ((fp = cupsFileOpen(temp, "w")) == NULL)
{
LogMessage(L_ERROR, "Unable to save printers.conf - %s", strerror(errno));
+
+ if (rename(backup, temp))
+ LogMessage(L_ERROR, "Unable to restore printers.conf - %s", strerror(errno));
return;
}
else
LogMessage(L_INFO, "Saving printers.conf...");
+ /*
+ * Restrict access to the file...
+ */
+
+ fchown(cupsFileNumber(fp), User, Group);
+ fchmod(cupsFileNumber(fp), ConfigFilePerm);
+
/*
* Write a small header to the file...
*/
curtime = time(NULL);
curdate = gmtime(&curtime);
- strftime(temp, sizeof(temp) - 1, "# Written by cupsd on %c\n", curdate);
+ strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate);
- fputs("# Printer configuration file for " CUPS_SVERSION "\n", fp);
- fputs(temp, fp);
+ cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n");
+ cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
/*
* Write each local printer known to the system...
*/
if (printer == DefaultPrinter)
- fprintf(fp, "<DefaultPrinter %s>\n", printer->name);
+ cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name);
else
- fprintf(fp, "<Printer %s>\n", printer->name);
-
- if (printer->info[0])
- fprintf(fp, "Info %s\n", printer->info);
- if (printer->more_info[0])
- fprintf(fp, "Location %s\n", printer->location);
- if (printer->device_uri[0])
- fprintf(fp, "DeviceURI %s\n", printer->device_uri);
+ cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
+
+ if (printer->info)
+ cupsFilePrintf(fp, "Info %s\n", printer->info);
+
+ if (printer->location)
+ cupsFilePrintf(fp, "Location %s\n", printer->location);
+
+ if (printer->device_uri)
+ cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
+
if (printer->state == IPP_PRINTER_STOPPED)
{
- fputs("State Stopped\n", fp);
- fprintf(fp, "StateMessage %s\n", printer->state_message);
+ cupsFilePuts(fp, "State Stopped\n");
+ cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message);
}
else
- fputs("State Idle\n", fp);
+ cupsFilePuts(fp, "State Idle\n");
+
if (printer->accepting)
- fputs("Accepting Yes\n", fp);
+ cupsFilePuts(fp, "Accepting Yes\n");
else
- fputs("Accepting No\n", fp);
- fprintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
+ cupsFilePuts(fp, "Accepting No\n");
+
+ cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
printer->job_sheets[1]);
- fputs("</Printer>\n", fp);
+ cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period);
+ cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit);
+ cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit);
+
+ for (i = 0; i < printer->num_users; i ++)
+ cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
+ printer->users[i]);
+
+ cupsFilePuts(fp, "</Printer>\n");
+
+#ifdef __sgi
+ /*
+ * Make IRIX desktop & printer status happy
+ */
+
+ write_irix_state(printer);
+#endif /* __sgi */
}
- fclose(fp);
+ cupsFileClose(fp);
}
char filename[1024]; /* Name of PPD file */
int num_media; /* Number of media options */
location_t *auth; /* Pointer to authentication element */
- int auth_len; /* Length of class or printer resource */
const char *auth_supported; /* Authentication supported */
+ cups_ptype_t printer_type; /* Printer type data */
ppd_file_t *ppd; /* PPD file data */
ppd_option_t *input_slot, /* InputSlot options */
*media_type, /* MediaType options */
*page_size, /* PageSize options */
- *output_bin; /* OutputBin options */
+ *output_bin, /* OutputBin options */
+ *media_quality; /* EFMediaQualityMode options */
+ ppd_attr_t *ppdattr; /* PPD attribute */
ipp_attribute_t *attr; /* Attribute data */
ipp_value_t *val; /* Attribute value */
- int nups[3] = /* number-up-supported values */
- { 1, 2, 4 };
+ int nups[] = /* number-up-supported values */
+ { 1, 2, 4, 6, 9, 16 };
ipp_orient_t orients[4] = /* orientation-requested-supported values */
{
IPP_PORTRAIT,
IPP_RESUME_PRINTER,
IPP_PURGE_JOBS,
IPP_SET_JOB_ATTRIBUTES,
+ IPP_ENABLE_PRINTER,
+ IPP_DISABLE_PRINTER,
CUPS_GET_DEFAULT,
CUPS_GET_PRINTERS,
CUPS_ADD_PRINTER,
"iso-8859-8",
"iso-8859-9",
"iso-8859-10",
- "utf-8"
+ "iso-8859-13",
+ "iso-8859-14",
+ "iso-8859-15",
+ "utf-8",
+ "windows-874",
+ "windows-1250",
+ "windows-1251",
+ "windows-1252",
+ "windows-1253",
+ "windows-1254",
+ "windows-1255",
+ "windows-1256",
+ "windows-1257",
+ "windows-1258",
+ "koi8-r",
+ "koi8-u",
+ };
+ const char *compressions[] =
+ {
+#ifdef HAVE_LIBZ
+ "none",
+ "gzip"
+#else
+ "none"
+#endif /* HAVE_LIBZ */
};
int num_finishings;
ipp_finish_t finishings[5];
const char *multiple_document_handling[] =
{
- "single-document",
"separate-documents-uncollated-copies",
- "separate-documents-collated-copies",
- "single-document-new-sheet"
+ "separate-documents-collated-copies"
};
#ifdef __sgi
- FILE *fp; /* Interface script file */
+ cups_file_t *fp; /* Interface script file */
#endif /* __sgi */
DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p->name,
p->type));
+ /*
+ * Make sure that we have the common attributes defined...
+ */
+
+ if (!CommonData)
+ {
+ CommonData = ippNew();
+
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "pdl-override-supported", NULL, "not-attempted");
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
+ NULL, versions);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported",
+ sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
+ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "multiple-document-jobs-supported", 1);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "multiple-operation-time-out", 60);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "multiple-document-handling-supported",
+ sizeof(multiple_document_handling) /
+ sizeof(multiple_document_handling[0]), NULL,
+ multiple_document_handling);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-configured",
+ NULL, DefaultCharset);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-supported",
+ sizeof(charsets) / sizeof(charsets[0]), NULL, charsets);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "natural-language-configured", NULL, DefaultLanguage);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "generated-natural-language-supported", NULL, DefaultLanguage);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+ "document-format-default", NULL, "application/octet-stream");
+ ippAddStrings(CommonData, IPP_TAG_PRINTER,
+ (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
+ "document-format-supported", NumMimeTypes, NULL, MimeTypes);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "compression-supported",
+ sizeof(compressions) / sizeof(compressions[0]),
+ NULL, compressions);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-priority-supported", 100);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-priority-default", 50);
+ ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "copies-default", 1);
+ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "number-up-default", 1);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "orientation-requested-supported", 4, (int *)orients);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "orientation-requested-default", IPP_PORTRAIT);
+
+ if (NumBanners > 0)
+ {
+ /*
+ * Setup the job-sheets-supported and job-sheets-default attributes...
+ */
+
+ if (Classification && !ClassifyOverride)
+ attr = ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-supported", NULL, Classification);
+ else
+ attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-supported", NumBanners + 1, NULL, NULL);
+
+ if (attr == NULL)
+ LogMessage(L_EMERG, "SetPrinterAttrs: Unable to allocate memory for "
+ "job-sheets-supported attribute: %s!",
+ strerror(errno));
+ else if (!Classification || ClassifyOverride)
+ {
+ attr->values[0].string.text = strdup("none");
+
+ for (i = 0; i < NumBanners; i ++)
+ attr->values[i + 1].string.text = strdup(Banners[i].name);
+ }
+ }
+ }
+
/*
* Clear out old filters and add a filter from application/vnd.cups-raw to
* printer/name to handle "raw" printing by users.
if (!(p->type & CUPS_PRINTER_REMOTE))
{
if (p->type & CUPS_PRINTER_CLASS)
- {
- auth_len = 8;
- sprintf(resource, "/classes/%s", p->name);
- }
+ snprintf(resource, sizeof(resource), "/classes/%s", p->name);
else
+ snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+
+ if ((auth = FindBest(resource, HTTP_POST)) != NULL)
{
- auth_len = 9;
- sprintf(resource, "/printers/%s", p->name);
+ if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
+ auth_supported = "basic";
+ else if (auth->type == AUTH_DIGEST)
+ auth_supported = "digest";
}
-
- for (i = NumLocations, auth = Locations; i > 0; i --, auth ++)
- if (strcmp(auth->location, resource) == 0)
- {
- /*
- * Exact match...
- */
-
- if (auth->type == AUTH_BASIC)
- auth_supported = "basic";
- else if (auth->type == AUTH_DIGEST)
- auth_supported = "digest";
- break;
- }
- else if (strcmp(auth->location, "/") == 0 ||
- (strncmp(auth->location, resource, auth_len) == 0 &&
- (strlen(auth->location) == auth_len ||
- strlen(auth->location) == (auth_len + 1))))
- {
- /*
- * Matches base printer or class resources...
- */
-
- if (auth->type == AUTH_BASIC)
- auth_supported = "basic";
- else if (auth->type == AUTH_DIGEST)
- auth_supported = "digest";
- }
}
/*
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL,
p->name);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
- NULL, p->location);
+ NULL, p->location ? p->location : "");
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
- NULL, p->info);
+ NULL, p->info ? p->info : "");
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
- NULL, p->more_info);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "pdl-override-supported", NULL, "not-attempted");
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
- NULL, versions);
- ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported",
- sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
- ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "multiple-document-jobs-supported", 1);
- ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "multiple-operation-time-out", 60);
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "multiple-document-handling-supported",
- sizeof(multiple_document_handling) /
- sizeof(multiple_document_handling[0]), NULL,
- multiple_document_handling);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-configured",
- NULL, DefaultCharset);
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-supported",
- sizeof(charsets) / sizeof(charsets[0]), NULL, charsets);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
- "natural-language-configured", NULL, DefaultLanguage);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
- "generated-natural-language-supported", NULL, DefaultLanguage);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
- "document-format-default", NULL, "application/octet-stream");
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
- "document-format-supported", NULL, "application/octet-stream");
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "compression-supported", NULL, "none");
- ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "job-priority-supported", 100);
+ NULL, p->uri);
+
+ if (p->num_users)
+ {
+ if (p->deny_users)
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-denied", p->num_users, NULL,
+ p->users);
+ else
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-allowed", p->num_users, NULL,
+ p->users);
+ }
+
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "job-priority-default", 50);
- ippAddRange(p->attrs, IPP_TAG_PRINTER, "copies-supported", 1, 65535);
+ "job-quota-period", p->quota_period);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "copies-default", 1);
- ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "page-ranges-supported", 1);
- ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "number-up-supported", 3, nups);
+ "job-k-limit", p->k_limit);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "number-up-default", 1);
- ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "orientation-requested-supported", 4, (int *)orients);
- ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "orientation-requested-default", IPP_PORTRAIT);
+ "job-page-limit", p->page_limit);
- if (NumBanners > 0)
+ if (NumBanners > 0 && !(p->type & CUPS_PRINTER_REMOTE))
{
/*
- * Setup the job-sheets-supported and job-sheets-default attributes...
+ * Setup the job-sheets-default attribute...
*/
- attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "job-sheets-supported", NumBanners + 1, NULL, NULL);
- attr->values[0].string.text = strdup("none");
- for (i = 0; i < NumBanners; i ++)
- attr->values[i + 1].string.text = strdup(Banners[i].name);
-
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"job-sheets-default", 2, NULL, NULL);
- attr->values[0].string.text = strdup(p->job_sheets[0]);
- attr->values[1].string.text = strdup(p->job_sheets[1]);
+
+ if (attr != NULL)
+ {
+ attr->values[0].string.text = strdup(Classification ?
+ Classification : p->job_sheets[0]);
+ attr->values[1].string.text = strdup(Classification ?
+ Classification : p->job_sheets[1]);
+ }
}
+ printer_type = p->type;
+
+ p->raw = 0;
+
if (p->type & CUPS_PRINTER_REMOTE)
{
/*
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, p->make_model);
+
+ p->raw = 1;
}
else
{
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
"member-uris", p->num_printers, NULL, NULL);
-
p->type |= CUPS_PRINTER_OPTIONS;
for (i = 0; i < p->num_printers; i ++)
{
- attr->values[i].string.text = strdup(p->printers[i]->uri);
+ if (attr != NULL)
+ attr->values[i].string.text = strdup(p->printers[i]->uri);
p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
}
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"member-names", p->num_printers, NULL, NULL);
- for (i = 0; i < p->num_printers; i ++)
- attr->values[i].string.text = strdup(p->printers[i]->name);
+ if (attr != NULL)
+ {
+ for (i = 0; i < p->num_printers; i ++)
+ attr->values[i].string.text = strdup(p->printers[i]->name);
+ }
}
}
else
* URI so it doesn't have a username or password in it...
*/
- if (strstr(p->device_uri, "://") != NULL)
+ if (!p->device_uri)
+ strcpy(uri, "file:/dev/null");
+ else if (strstr(p->device_uri, "://") != NULL)
{
/*
* http://..., ipp://..., etc.
httpSeparate(p->device_uri, method, username, host, &port, resource);
if (port)
- sprintf(uri, "%s://%s:%d%s", method, host, port, resource);
+ snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, host, port,
+ resource);
else
- sprintf(uri, "%s://%s%s", method, host, resource);
+ snprintf(uri, sizeof(uri), "%s://%s%s", method, host, resource);
}
else
{
* file:..., serial:..., etc.
*/
- strcpy(uri, p->device_uri);
+ strlcpy(uri, p->device_uri, sizeof(uri));
}
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
*/
p->type |= CUPS_PRINTER_BW;
- finishings[0] = IPP_FINISH_NONE;
+ finishings[0] = IPP_FINISHINGS_NONE;
num_finishings = 1;
- sprintf(filename, "%s/ppd/%s.ppd", ServerRoot, p->name);
+ snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
+ p->name);
+
if ((ppd = ppdOpenFile(filename)) != NULL)
{
/*
p->type |= CUPS_PRINTER_VARIABLE;
if (!ppd->manual_copies)
p->type |= CUPS_PRINTER_COPIES;
+ if ((ppdattr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL)
+ if (ppdattr->value && !strcasecmp(ppdattr->value, "true"))
+ p->type |= CUPS_PRINTER_FAX;
ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported",
ppd->color_device);
if (ppd->throughput)
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"pages-per-minute", ppd->throughput);
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "printer-make-and-model", NULL, ppd->nickname);
- strncpy(p->make_model, ppd->nickname, sizeof(p->make_model) - 1);
+ if (ppd->nickname)
+ SetString(&p->make_model, ppd->nickname);
+ else if (ppd->modelname)
+ SetString(&p->make_model, ppd->modelname);
+ else
+ SetString(&p->make_model, "Bad PPD File");
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, p->make_model);
/*
* Add media options from the PPD file...
if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL)
num_media += page_size->num_choices;
- attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "media-supported", num_media, NULL, NULL);
- val = attr->values;
+ if ((media_quality = ppdFindOption(ppd, "EFMediaQualityMode")) != NULL)
+ num_media += media_quality->num_choices;
- if (input_slot != NULL)
- for (i = 0; i < input_slot->num_choices; i ++, val ++)
- val->string.text = strdup(input_slot->choices[i].choice);
-
- if (media_type != NULL)
- for (i = 0; i < media_type->num_choices; i ++, val ++)
- val->string.text = strdup(media_type->choices[i].choice);
-
- if (page_size != NULL)
+ if (num_media == 0)
{
- for (i = 0; i < page_size->num_choices; i ++, val ++)
- val->string.text = strdup(page_size->choices[i].choice);
-
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, page_size->defchoice);
- }
- else if (input_slot != NULL)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, input_slot->defchoice);
- else if (media_type != NULL)
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, media_type->defchoice);
+ LogMessage(L_CRIT, "SetPrinterAttrs: The PPD file for printer %s "
+ "contains no media options and is therefore "
+ "invalid!", p->name);
+ }
else
- ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
- NULL, "none");
+ {
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-supported", num_media, NULL, NULL);
+ if (attr != NULL)
+ {
+ val = attr->values;
+
+ if (input_slot != NULL)
+ for (i = 0; i < input_slot->num_choices; i ++, val ++)
+ val->string.text = strdup(input_slot->choices[i].choice);
+
+ if (media_type != NULL)
+ for (i = 0; i < media_type->num_choices; i ++, val ++)
+ val->string.text = strdup(media_type->choices[i].choice);
+
+ if (media_quality != NULL)
+ for (i = 0; i < media_quality->num_choices; i ++, val ++)
+ val->string.text = strdup(media_quality->choices[i].choice);
+
+ if (page_size != NULL)
+ {
+ for (i = 0; i < page_size->num_choices; i ++, val ++)
+ val->string.text = strdup(page_size->choices[i].choice);
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, page_size->defchoice);
+ }
+ else if (input_slot != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, input_slot->defchoice);
+ else if (media_type != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, media_type->defchoice);
+ else if (media_quality != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, media_quality->defchoice);
+ else
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, "none");
+ }
+ }
/*
* Output bin...
"output-bin-supported", output_bin->num_choices,
NULL, NULL);
- for (i = 0, val = attr->values;
- i < output_bin->num_choices;
- i ++, val ++)
- val->string.text = strdup(output_bin->choices[i].choice);
- }
+ if (attr != NULL)
+ {
+ for (i = 0, val = attr->values;
+ i < output_bin->num_choices;
+ i ++, val ++)
+ val->string.text = strdup(output_bin->choices[i].choice);
+ }
+ }
/*
* Duplexing, etc...
if (ppdFindOption(ppd, "StapleLocation") != NULL)
{
p->type |= CUPS_PRINTER_STAPLE;
- finishings[num_finishings++] = IPP_FINISH_STAPLE;
+ finishings[num_finishings++] = IPP_FINISHINGS_STAPLE;
}
if (ppdFindOption(ppd, "BindEdge") != NULL)
{
p->type |= CUPS_PRINTER_BIND;
- finishings[num_finishings++] = IPP_FINISH_BIND;
+ finishings[num_finishings++] = IPP_FINISHINGS_BIND;
}
for (i = 0; i < ppd->num_sizes; i ++)
AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
ppdClose(ppd);
+
+ printer_type = p->type;
}
else if (access(filename, 0) == 0)
{
+ int pline; /* PPD line number */
+ ppd_status_t pstatus; /* PPD load status */
+
+
+ pstatus = ppdLastError(&pline);
+
LogMessage(L_ERROR, "PPD file for %s cannot be loaded!", p->name);
+ if (pstatus <= PPD_ALLOC_ERROR)
+ LogMessage(L_ERROR, "%s", strerror(errno));
+ else
+ LogMessage(L_ERROR, "%s on line %d.", ppdErrorString(pstatus),
+ pline);
+
+ LogMessage(L_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.",
+ filename);
+
AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
}
else
* If we have an interface script, add a filter entry for it...
*/
- sprintf(filename, "%s/interfaces/%s", ServerRoot, p->name);
+ snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
+ p->name);
if (access(filename, X_OK) == 0)
{
/*
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Local System V Printer");
- sprintf(filename, "*/* 0 %s/interfaces/%s", ServerRoot, p->name);
+ snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
+ ServerRoot, p->name);
AddPrinterFilter(p, filename);
}
+ else if (p->device_uri &&
+ strncmp(p->device_uri, "ipp://", 6) == 0 &&
+ (strstr(p->device_uri, "/printers/") != NULL ||
+ strstr(p->device_uri, "/classes/") != NULL))
+ {
+ /*
+ * Tell the client this is really a hard-wired remote printer.
+ */
+
+ printer_type |= CUPS_PRINTER_REMOTE;
+
+ /*
+ * Reset the printer-uri-supported attribute to point at the
+ * remote printer...
+ */
+
+ attr = ippFindAttribute(p->attrs, "printer-uri-supported", IPP_TAG_URI);
+ free(attr->values[0].string.text);
+ attr->values[0].string.text = strdup(p->device_uri);
+
+ /*
+ * Then set the make-and-model accordingly...
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, "Remote Printer");
+
+ /*
+ * Print all files directly...
+ */
+
+ p->raw = 1;
+ }
else
{
/*
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Local Raw Printer");
- AddPrinterFilter(p, "*/* 0 -");
+ p->raw = 1;
}
}
ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-supported", num_finishings, (int *)finishings);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
- "finishings-default", IPP_FINISH_NONE);
+ "finishings-default", IPP_FINISHINGS_NONE);
}
}
* Add the CUPS-specific printer-type attribute...
*/
- ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", p->type);
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type",
+ printer_type);
DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
p->type));
#ifdef __sgi
/*
- * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
- * tools.
+ * Write the IRIX printer config and status files...
*/
- sprintf(filename, "/var/spool/lp/interface/%s", p->name);
- if ((fp = fopen(filename, "w")) != NULL)
- {
- fputs("#!/bin/sh\n", fp);
+ write_irix_config(p);
+ write_irix_state(p);
+#endif /* __sgi */
+}
- if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
- IPP_TAG_TEXT)) != NULL)
- fprintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
- else if (p->type & CUPS_PRINTER_CLASS)
- fputs("NAME=\"Printer Class\"\n", fp);
- else
- fputs("NAME=\"Remote Destination\"\n", fp);
- if (p->type & CUPS_PRINTER_COLOR)
- fputs("TYPE=ColorPostScript\n", fp);
- else
- fputs("TYPE=PostScript\n", fp);
+/*
+ * 'SetPrinterReasons()' - Set/update the reasons strings.
+ */
- fclose(fp);
- chmod(filename, 0755);
- }
+void
+SetPrinterReasons(printer_t *p, /* I - Printer */
+ const char *s) /* I - Reasons strings */
+{
+ int i; /* Looping var */
+ const char *sptr; /* Pointer into reasons */
+ char reason[255], /* Reason string */
+ *rptr; /* Pointer into reason */
- sprintf(filename, "/var/spool/lp/member/%s", p->name);
- if ((fp = fopen(filename, "w")) != NULL)
+
+ if (s[0] == '-' || s[0] == '+')
{
- fputs("/dev/null\n", fp);
- fclose(fp);
- chmod(filename, 0644);
- }
+ /*
+ * Add/remove reasons...
+ */
- sprintf(filename, "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
- if ((fp = fopen(filename, "w")) != NULL)
+ sptr = s + 1;
+ }
+ else
{
- fputs("#!/bin/sh\n", fp);
- fprintf(fp, "/usr/bin/glpoptions -d %s -o \"$3\"\n", p->name);
- fclose(fp);
- chmod(filename, 0755);
+ /*
+ * Replace reasons...
+ */
+
+ sptr = s;
+
+ for (i = 0; i < p->num_reasons; i ++)
+ free(p->reasons[i]);
+
+ p->num_reasons = 0;
}
- sprintf(filename, "/var/spool/lp/activeicons/%s", p->name);
- if ((fp = fopen(filename, "w")) != NULL)
+ /*
+ * Loop through all of the reasons...
+ */
+
+ while (*sptr)
{
- fputs("#!/bin/sh\n", fp);
- if (p->type & CUPS_PRINTER_COLOR)
- fputs("#Tag 66240\n", fp);
- else
- fputs("#Tag 66208\n", fp);
- fclose(fp);
- chmod(filename, 0755);
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*sptr) || *sptr == ',')
+ sptr ++;
+
+ for (rptr = reason; *sptr && !isspace(*sptr) && *sptr != ','; sptr ++)
+ if (rptr < (reason + sizeof(reason) - 1))
+ *rptr++ = *sptr;
+
+ if (rptr == reason)
+ break;
+
+ *rptr = '\0';
+
+ if (s[0] == '-')
+ {
+ /*
+ * Remove reason...
+ */
+
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcasecmp(reason, p->reasons[i]))
+ {
+ /*
+ * Found a match, so remove it...
+ */
+
+ p->num_reasons --;
+ free(p->reasons[i]);
+
+ if (i < p->num_reasons)
+ memmove(p->reasons + i, p->reasons + i + 1,
+ (p->num_reasons - i) * sizeof(char *));
+
+ i --;
+ }
+ }
+ else if (s[0] == '+' &&
+ p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+ {
+ /*
+ * Add reason...
+ */
+
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcasecmp(reason, p->reasons[i]))
+ break;
+
+ if (i >= p->num_reasons)
+ {
+ p->reasons[i] = strdup(reason);
+ p->num_reasons ++;
+ }
+ }
}
-#endif /* __sgi */
}
* Set the new state...
*/
- old_state = p->state;
- p->state = s;
- p->state_time = time(NULL);
+ old_state = p->state;
+ p->state = s;
if (old_state != s)
+ {
+ p->state_time = time(NULL);
p->browse_time = 0;
+#ifdef __sgi
+ write_irix_state(p);
+#endif /* __sgi */
+ }
+
+ AddPrinterHistory(p);
+
/*
* Save the printer configuration if a printer goes from idle or processing
* to stopped (or visa-versa)...
if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED))
SaveAllPrinters();
-
- /*
- * Check to see if any pending jobs can now be printed...
- */
-
- CheckJobs();
}
next = current->next;
current->next = next->next;
next->next = current;
+ prev = next;
}
else
+ {
+ prev = current;
current = current->next;
+ }
}
while (did_swap);
}
void
StopPrinter(printer_t *p) /* I - Printer to stop */
{
+ job_t *job; /* Active print job */
+
+
+ /*
+ * Set the printer state...
+ */
+
+ p->state = IPP_PRINTER_STOPPED;
+
+ /*
+ * See if we have a job printing on this printer...
+ */
+
if (p->job)
{
- StopJob(((job_t *)p->job)->id);
- ((job_t *)p->job)->state->values[0].integer = IPP_JOB_PENDING;
- SaveJob(((job_t *)p->job)->id);
- }
+ /*
+ * Get pointer to job...
+ */
- p->state = IPP_PRINTER_STOPPED;
+ job = (job_t *)p->job;
+
+ /*
+ * Stop it...
+ */
+
+ StopJob(job->id, 0);
+
+ /*
+ * Reset the state to pending...
+ */
+
+ job->state->values[0].integer = IPP_JOB_PENDING;
+
+ SaveJob(job->id);
+ }
}
}
/*
- * See if the printer or class name is dest@server; if so, just lookup the
- * name instead...
+ * See if the printer or class name exists...
*/
- if (strchr(resource, '@') != NULL)
- {
- if ((p = FindPrinter(resource)) == NULL)
- p = FindClass(resource);
-
- if (p == NULL)
- return (NULL);
+ if ((p = FindPrinter(resource)) == NULL)
+ p = FindClass(resource);
- *dtype = p->type & CUPS_PRINTER_CLASS;
+ if (p == NULL && strchr(resource, '@') == NULL)
+ return (NULL);
+ else if (p != NULL)
+ {
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
return (p->name);
}
if (strcasecmp(hostname, "localhost") == 0)
hostname = ServerName;
- strncpy(localname, hostname, sizeof(localname) - 1);
- localname[sizeof(localname) - 1] = '\0';
+ strlcpy(localname, hostname, sizeof(localname));
if (strcasecmp(hostname, ServerName) != 0)
{
if (strcasecmp(p->hostname, localname) == 0 &&
strcasecmp(p->name, resource) == 0)
{
- *dtype = p->type & CUPS_PRINTER_CLASS;
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
return (p->name);
}
/*
- * 'write_printcap()' - Write a pseudo-printcap file for older applications
- * that need it...
+ * 'WritePrintcap()' - Write a pseudo-printcap file for older applications
+ * that need it...
*/
-static void
-write_printcap(void)
+void
+WritePrintcap(void)
{
- FILE *fp; /* printcap file */
+ cups_file_t *fp; /* printcap file */
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.
*/
return;
/*
- * Write a new printcap with the current list of printers. Each printer
- * is put in the file as:
- *
- * Printer1:
- * Printer2:
- * Printer3:
- * ...
- * PrinterN:
+ * Open the printcap file...
*/
- if ((fp = fopen(Printcap, "w")) == NULL)
+ if ((fp = cupsFileOpen(Printcap, "w")) == NULL)
return;
- for (p = Printers; p != NULL; p = p->next)
- fprintf(fp, "%s:\n", p->name);
+ /*
+ * Put a comment header at the top so that users will know where the
+ * data has come from...
+ */
+
+ cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n");
+ cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n",
+ ServerRoot);
+ cupsFilePuts(fp, "# will be lost.\n");
+
+ /*
+ * Write a new printcap with the current list of printers.
+ */
+
+ switch (PrintcapFormat)
+ {
+ case PRINTCAP_BSD:
+ /*
+ * Each printer is put in the file as:
+ *
+ * Printer1:
+ * Printer2:
+ * Printer3:
+ * ...
+ * PrinterN:
+ */
+
+ if (DefaultPrinter)
+ cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
+ DefaultPrinter->info, ServerName, DefaultPrinter->name);
+
+ for (p = Printers; p != NULL; p = p->next)
+ if (p != DefaultPrinter)
+ cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
+ ServerName, p->name);
+ break;
+
+ case PRINTCAP_SOLARIS:
+ /*
+ * Each printer is put in the file as:
+ *
+ * _all:all=Printer1,Printer2,Printer3,...,PrinterN
+ * _default:use=DefaultPrinter
+ * Printer1:\
+ * :bsdaddr=ServerName,Printer1:\
+ * :description=Description:
+ * Printer2:
+ * :bsdaddr=ServerName,Printer2:\
+ * :description=Description:
+ * Printer3:
+ * :bsdaddr=ServerName,Printer3:\
+ * :description=Description:
+ * ...
+ * PrinterN:
+ * :bsdaddr=ServerName,PrinterN:\
+ * :description=Description:
+ */
+
+ cupsFilePuts(fp, "_all:all=");
+ for (p = Printers; p != NULL; p = p->next)
+ cupsFilePrintf(fp, "%s%c", p->name, p->next ? ',' : '\n');
+
+ if (DefaultPrinter)
+ cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name);
+
+ for (p = Printers; p != NULL; p = p->next)
+ cupsFilePrintf(fp, "%s:\\\n"
+ "\t:bsdaddr=%s,%s:\\\n"
+ "\t:description=%s:\n",
+ p->name, ServerName, p->name, p->info ? p->info : "");
+ break;
+ }
/*
* Close the file...
*/
- fclose(fp);
+ cupsFileClose(fp);
+}
+
+
+#ifdef __sgi
+/*
+ * 'write_irix_config()' - Update the config files used by the IRIX
+ * desktop tools.
+ */
+
+static void
+write_irix_config(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 */
+
+
+
+ /*
+ * 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 ? 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(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 ? 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 */
/*
- * End of "$Id: printers.c,v 1.72 2000/09/06 19:40:12 mike Exp $".
+ * End of "$Id: printers.c,v 1.93.2.46 2003/04/03 03:33:41 mike Exp $".
*/