/*
- * "$Id: printers.c,v 1.93.2.40 2003/03/10 21:22:23 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).
*
*
* 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.
* 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.
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...
}
+/*
+ * '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
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->printers != NULL)
free(p->printers);
+ 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);
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 */
*/
snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot);
- if ((fp = fopen(line, "r")) == NULL)
+ if ((fp = cupsFileOpen(line, "r")) == NULL)
{
LogMessage(L_ERROR, "LoadAllPrinters: Unable to open %s - %s", line,
strerror(errno));
linenum = 0;
p = NULL;
- while (fgets(line, sizeof(line), fp) != NULL)
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
{
linenum ++;
if (p != NULL)
{
SetPrinterAttrs(p);
+ AddPrinterHistory(p);
p = NULL;
}
else
}
}
- fclose(fp);
+ cupsFileClose(fp);
}
SaveAllPrinters(void)
{
int i; /* Looping var */
- FILE *fp; /* printers.conf file */
+ 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 */
if (rename(temp, backup))
LogMessage(L_ERROR, "Unable to backup printers.conf - %s", strerror(errno));
- if ((fp = fopen(temp, "w")) == NULL)
+ if ((fp = cupsFileOpen(temp, "w")) == NULL)
{
LogMessage(L_ERROR, "Unable to save printers.conf - %s", strerror(errno));
* Restrict access to the file...
*/
- fchown(fileno(fp), User, Group);
- fchmod(fileno(fp), 0600);
+ fchown(cupsFileNumber(fp), User, Group);
+ fchmod(cupsFileNumber(fp), ConfigFilePerm);
/*
* Write a small header to the file...
curdate = gmtime(&curtime);
strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate);
- fputs("# Printer configuration file for " CUPS_SVERSION "\n", fp);
- fprintf(fp, "# Written by cupsd on %s\n", temp);
+ 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);
+ cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
if (printer->info)
- fprintf(fp, "Info %s\n", printer->info);
+ cupsFilePrintf(fp, "Info %s\n", printer->info);
if (printer->location)
- fprintf(fp, "Location %s\n", printer->location);
+ cupsFilePrintf(fp, "Location %s\n", printer->location);
if (printer->device_uri)
- fprintf(fp, "DeviceURI %s\n", 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);
+ cupsFilePuts(fp, "Accepting No\n");
- fprintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
+ cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
printer->job_sheets[1]);
- fprintf(fp, "QuotaPeriod %d\n", printer->quota_period);
- fprintf(fp, "PageLimit %d\n", printer->page_limit);
- fprintf(fp, "KLimit %d\n", printer->k_limit);
+ 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 ++)
- fprintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
+ cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
printer->users[i]);
- fputs("</Printer>\n", fp);
+ cupsFilePuts(fp, "</Printer>\n");
#ifdef __sgi
/*
#endif /* __sgi */
}
- fclose(fp);
+ cupsFileClose(fp);
}
*page_size, /* PageSize 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[] = /* number-up-supported values */
"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[] =
"separate-documents-collated-copies"
};
#ifdef __sgi
- FILE *fp; /* Interface script file */
+ cups_file_t *fp; /* Interface script file */
#endif /* __sgi */
ippAddStrings(CommonData, IPP_TAG_PRINTER,
(ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
"document-format-supported", NumMimeTypes, NULL, MimeTypes);
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "compression-supported", NULL, "none");
+ 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,
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);
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
}
+/*
+ * 'SetPrinterReasons()' - Set/update the reasons strings.
+ */
+
+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 */
+
+
+ if (s[0] == '-' || s[0] == '+')
+ {
+ /*
+ * Add/remove reasons...
+ */
+
+ sptr = s + 1;
+ }
+ else
+ {
+ /*
+ * Replace reasons...
+ */
+
+ sptr = s;
+
+ for (i = 0; i < p->num_reasons; i ++)
+ free(p->reasons[i]);
+
+ p->num_reasons = 0;
+ }
+
+ /*
+ * Loop through all of the reasons...
+ */
+
+ while (*sptr)
+ {
+ /*
+ * 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 ++;
+ }
+ }
+ }
+}
+
+
/*
* 'SetPrinterState()' - Update the current state of a printer.
*/
* 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
#endif /* __sgi */
}
+ AddPrinterHistory(p);
+
/*
* Save the printer configuration if a printer goes from idle or processing
* to stopped (or visa-versa)...
void
WritePrintcap(void)
{
- FILE *fp; /* printcap file */
+ cups_file_t *fp; /* printcap file */
printer_t *p; /* Current printer */
* Open the printcap file...
*/
- if ((fp = fopen(Printcap, "w")) == NULL)
+ if ((fp = cupsFileOpen(Printcap, "w")) == NULL)
return;
/*
* data has come from...
*/
- fputs("# This file was automatically generated by cupsd(8) from the\n", fp);
- fprintf(fp, "# %s/printers.conf file. All changes to this file\n",
+ 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);
- fputs("# will be lost.\n", fp);
+ cupsFilePuts(fp, "# will be lost.\n");
/*
* Write a new printcap with the current list of printers.
*/
if (DefaultPrinter)
- fprintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
+ 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)
- fprintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
+ cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
ServerName, p->name);
break;
* :description=Description:
*/
- fputs("_all:all=", fp);
+ cupsFilePuts(fp, "_all:all=");
for (p = Printers; p != NULL; p = p->next)
- fprintf(fp, "%s%c", p->name, p->next ? ',' : '\n');
+ cupsFilePrintf(fp, "%s%c", p->name, p->next ? ',' : '\n');
if (DefaultPrinter)
- fprintf(fp, "_default:use=%s\n", DefaultPrinter->name);
+ cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name);
for (p = Printers; p != NULL; p = p->next)
- fprintf(fp, "%s:\\\n"
+ cupsFilePrintf(fp, "%s:\\\n"
"\t:bsdaddr=%s,%s:\\\n"
"\t:description=%s:\n",
p->name, ServerName, p->name, p->info ? p->info : "");
* Close the file...
*/
- fclose(fp);
+ cupsFileClose(fp);
}
*/
static void
-write_irix_config(printer_t *p) /* I - Printer to update */
+write_irix_config(printer_t *p) /* I - Printer to update */
{
- char filename[1024]; /* Interface script filename */
- FILE *fp; /* Interface script file */
- int tag; /* Status tag value */
+ char filename[1024]; /* Interface script filename */
+ cups_file_t *fp; /* Interface script file */
+ int tag; /* Status tag value */
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fputs("#!/bin/sh\n", fp);
+ cupsFilePuts(fp, "#!/bin/sh\n");
if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
IPP_TAG_TEXT)) != NULL)
- fprintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
+ cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
else if (p->type & CUPS_PRINTER_CLASS)
- fputs("NAME=\"Printer Class\"\n", fp);
+ cupsFilePuts(fp, "NAME=\"Printer Class\"\n");
else
- fputs("NAME=\"Remote Destination\"\n", fp);
+ cupsFilePuts(fp, "NAME=\"Remote Destination\"\n");
if (p->type & CUPS_PRINTER_COLOR)
- fputs("TYPE=ColorPostScript\n", fp);
+ cupsFilePuts(fp, "TYPE=ColorPostScript\n");
else
- fputs("TYPE=MonoPostScript\n", fp);
+ cupsFilePuts(fp, "TYPE=MonoPostScript\n");
- fprintf(fp, "HOSTNAME=%s\n", ServerName);
- fprintf(fp, "HOSTPRINTER=%s\n", p->name);
+ cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName);
+ cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name);
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fputs("/dev/null\n", fp);
+ cupsFilePuts(fp, "/dev/null\n");
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0644);
chown(filename, User, Group);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fputs("#!/bin/sh\n", fp);
- fprintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
+ cupsFilePuts(fp, "#!/bin/sh\n");
+ cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fprintf(fp, "Printer Class | %s\n",
+ cupsFilePrintf(fp, "Printer Class | %s\n",
(p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript");
- fprintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : "");
- fprintf(fp, "Location Code | %s\n", p->location ? p->location : "");
- fprintf(fp, "Physical Location | %s\n", p->info ? p->info : "");
- fprintf(fp, "Port Path | %s\n", p->device_uri ? p->device_uri : "");
- fprintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name);
- fprintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
- fputs("Status Update Wait | 10 seconds\n", fp);
+ 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");
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0664);
chown(filename, User, Group);
*/
static void
-write_irix_state(printer_t *p) /* I - Printer to update */
+write_irix_state(printer_t *p) /* I - Printer to update */
{
- char filename[1024]; /* Interface script filename */
- FILE *fp; /* Interface script file */
- int tag; /* Status tag value */
+ char filename[1024]; /* Interface script filename */
+ cups_file_t *fp; /* Interface script file */
+ int tag; /* Status tag value */
if (p)
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fprintf(fp, "Operational Status | %s\n",
+ cupsFilePrintf(fp, "Operational Status | %s\n",
(p->state == IPP_PRINTER_IDLE) ? "Idle" :
(p->state == IPP_PRINTER_PROCESSING) ? "Busy" :
"Faulted");
- fprintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION);
- fprintf(fp, "Information | 02 00 00 | Device URI: %s\n",
+ 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 : "");
- fprintf(fp, "Information | 03 00 00 | %s jobs\n",
+ cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n",
p->accepting ? "Accepting" : "Not accepting");
- fprintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
+ cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0664);
chown(filename, User, Group);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
- else if ((fp = fopen(filename, "w")) != NULL)
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
if (p->type & CUPS_PRINTER_COLOR)
tag = 66240;
else if (p->state == IPP_PRINTER_STOPPED)
tag |= 2;
- fputs("#!/bin/sh\n", fp);
- fprintf(fp, "#Tag %d\n", tag);
+ cupsFilePuts(fp, "#!/bin/sh\n");
+ cupsFilePrintf(fp, "#Tag %d\n", tag);
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
if (DefaultPrinter != NULL)
{
- if ((fp = fopen(filename, "w")) != NULL)
+ if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
- fprintf(fp, "%s\n", DefaultPrinter->name);
+ cupsFilePrintf(fp, "%s\n", DefaultPrinter->name);
- fclose(fp);
+ cupsFileClose(fp);
chmod(filename, 0644);
chown(filename, User, Group);
/*
- * End of "$Id: printers.c,v 1.93.2.40 2003/03/10 21:22:23 mike Exp $".
+ * End of "$Id: printers.c,v 1.93.2.46 2003/04/03 03:33:41 mike Exp $".
*/