/*
- * "$Id: printers.c 6970 2007-09-17 23:58:28Z mike $"
+ * "$Id: printers.c 7608 2008-05-21 01:37:21Z mike $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* cupsdSaveAllPrinters() - Save all printer definitions to the
* printers.conf file.
* cupsdSetAuthInfoRequired() - Set the required authentication info.
+ * cupsdSetPrinterAttr() - Set a printer attribute.
* cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD
* file.
* cupsdSetPrinterReasons() - Set/update the reasons strings.
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "</Printer>"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!p)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
else if (!strcasecmp(line, "AuthInfoRequired"))
{
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "Option") && value)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "State"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "StateMessage"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "Shared"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "JobSheets"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "AllowUser"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "DenyUser"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "QuotaPeriod"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "PageLimit"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "KLimit"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "OpPolicy"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "ErrorPolicy"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of printers.conf.", linenum);
- return;
+ break;
+ }
+ }
+ else if (!strcasecmp(line, "Attribute") && value)
+ {
+ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (!*valueptr)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Syntax error on line %d of printers.conf.", linenum);
+ else
+ {
+ for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0');
+
+ if (!p->attrs)
+ cupsdSetPrinterAttrs(p);
+
+ cupsdSetPrinterAttr(p, value, valueptr);
+
+ if (!strncmp(value, "marker-", 7))
+ p->marker_time = time(NULL);
}
}
else
struct tm *curdate; /* Current date */
cups_option_t *option; /* Current option */
const char *ptr; /* Pointer into info/location */
+ ipp_attribute_t *marker; /* Current marker attribute */
/*
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]);
+ {
+ if ((ptr = strchr(printer->users[i], '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the user string...
+ */
+
+ cupsFilePrintf(fp, "%sUser ", printer->deny_users ? "Deny" : "Allow");
+ cupsFileWrite(fp, printer->users[i], ptr - printer->users[i]);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "%sUser %s\n",
+ printer->deny_users ? "Deny" : "Allow",
+ printer->users[i]);
+ }
if (printer->op_policy)
cupsFilePrintf(fp, "OpPolicy %s\n", printer->op_policy);
for (i = printer->num_options, option = printer->options;
i > 0;
i --, option ++)
- cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value);
+ {
+ if ((ptr = strchr(option->value, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the option string...
+ */
+
+ cupsFilePrintf(fp, "Option %s ", option->name);
+ cupsFileWrite(fp, option->value, ptr - option->value);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value);
+ }
+
+ if ((marker = ippFindAttribute(printer->attrs, "marker-colors",
+ IPP_TAG_NAME)) != NULL)
+ {
+ cupsFilePrintf(fp, "Attribute %s ", marker->name);
+
+ for (i = 0, ptr = NULL; i < marker->num_values; i ++)
+ {
+ if (i)
+ cupsFilePutChar(fp, ',');
+
+ if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL)
+ {
+ cupsFileWrite(fp, marker->values[i].string.text,
+ ptr - marker->values[i].string.text);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ }
+ else
+ cupsFilePuts(fp, marker->values[i].string.text);
+ }
+
+ cupsFilePuts(fp, "\n");
+ }
+
+ if ((marker = ippFindAttribute(printer->attrs, "marker-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ cupsFilePrintf(fp, "Attribute %s %d", marker->name,
+ marker->values[0].integer);
+ for (i = 1; i < marker->num_values; i ++)
+ cupsFilePrintf(fp, ",%d", marker->values[i].integer);
+ cupsFilePuts(fp, "\n");
+ }
+
+ if ((marker = ippFindAttribute(printer->attrs, "marker-names",
+ IPP_TAG_NAME)) != NULL)
+ {
+ cupsFilePrintf(fp, "Attribute %s ", marker->name);
+
+ for (i = 0, ptr = NULL; i < marker->num_values; i ++)
+ {
+ if (i)
+ cupsFilePutChar(fp, ',');
+
+ if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL)
+ {
+ cupsFileWrite(fp, marker->values[i].string.text,
+ ptr - marker->values[i].string.text);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ }
+ else
+ cupsFilePuts(fp, marker->values[i].string.text);
+ }
+
+ cupsFilePuts(fp, "\n");
+ }
+
+ if ((marker = ippFindAttribute(printer->attrs, "marker-types",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ cupsFilePrintf(fp, "Attribute %s ", marker->name);
+
+ for (i = 0, ptr = NULL; i < marker->num_values; i ++)
+ {
+ if (i)
+ cupsFilePutChar(fp, ',');
+
+ if (!ptr && (ptr = strchr(marker->values[i].string.text, '#')) != NULL)
+ {
+ cupsFileWrite(fp, marker->values[i].string.text,
+ ptr - marker->values[i].string.text);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ }
+ else
+ cupsFilePuts(fp, marker->values[i].string.text);
+ }
+
+ cupsFilePuts(fp, "\n");
+ }
cupsFilePuts(fp, "</Printer>\n");
}
+/*
+ * 'cupsdSetPrinterAttr()' - Set a printer attribute.
+ */
+
+void
+cupsdSetPrinterAttr(
+ cupsd_printer_t *p, /* I - Printer */
+ const char *name, /* I - Attribute name */
+ char *value) /* I - Attribute value string */
+{
+ ipp_attribute_t *attr; /* Attribute */
+ int i, /* Looping var */
+ count; /* Number of values */
+ char *ptr; /* Pointer into value */
+ 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 ++);
+
+ /*
+ * Then add or update the attribute as needed...
+ */
+
+ if (!strcmp(name, "marker-levels"))
+ {
+ /*
+ * Integer values...
+ */
+
+ if ((attr = ippFindAttribute(p->attrs, name, IPP_TAG_INTEGER)) != NULL &&
+ attr->num_values < count)
+ {
+ ippDeleteAttribute(p->attrs, attr);
+ attr = NULL;
+ }
+
+ if (attr)
+ attr->num_values = count;
+ else
+ attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, name,
+ count, NULL);
+
+ if (!attr)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for printer attribute "
+ "(%d values)", count);
+ return;
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ if ((ptr = strchr(value, ',')) != NULL)
+ *ptr++ = '\0';
+
+ attr->values[i].integer = strtol(value, NULL, 10);
+
+ if (ptr)
+ value = ptr;
+ }
+ }
+ else
+ {
+ /*
+ * Name or keyword values...
+ */
+
+ if (!strcmp(name, "marker-types"))
+ value_tag = IPP_TAG_KEYWORD;
+ else
+ value_tag = IPP_TAG_NAME;
+
+ if ((attr = ippFindAttribute(p->attrs, name, value_tag)) != NULL &&
+ attr->num_values < count)
+ {
+ ippDeleteAttribute(p->attrs, attr);
+ attr = NULL;
+ }
+
+ if (attr)
+ attr->num_values = count;
+ else
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, value_tag, name,
+ count, NULL, NULL);
+
+ if (!attr)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate memory for printer attribute "
+ "(%d values)", count);
+ return;
+ }
+
+ for (i = 0; i < count; i ++)
+ {
+ if ((ptr = strchr(value, ',')) != NULL)
+ *ptr++ = '\0';
+
+ _cupsStrFree(attr->values[i].string.text);
+ attr->values[i].string.text = _cupsStrAlloc(value);
+
+ if (ptr)
+ value = ptr;
+ }
+ }
+
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
+}
+
+
/*
* 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
*/
*media_quality, /* EFMediaQualityMode options */
*duplex; /* Duplex options */
ppd_attr_t *ppdattr; /* PPD attribute */
+ ipp_t *oldattrs; /* Old printer attributes */
ipp_attribute_t *attr; /* Attribute data */
ipp_value_t *val; /* Attribute value */
int num_finishings; /* Number of finishings */
"username",
"password"
};
+#ifdef HAVE_GSSAPI
static const char * const air_negotiate[] =
{ /* Kerberos authentication */
"negotiate"
};
+#endif /* HAVE_GSSAPI */
static const char * const air_none[] =
{ /* No authentication */
"none"
};
+ static const char * const standard_commands[] =
+ { /* Standard CUPS commands */
+ "AutoConfigure",
+ "Clean",
+ "PrintSelfTestPage",
+ "ReportLevels"
+ };
DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
snprintf(resource, sizeof(resource), "/printers/%s", p->name);
if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
- auth->type == AUTH_NONE)
+ auth->type == CUPSD_AUTH_NONE)
auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
if (auth)
{
- if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
+ if (auth->type == CUPSD_AUTH_BASIC || auth->type == CUPSD_AUTH_BASICDIGEST)
{
auth_supported = "basic";
num_air = 2;
air = air_userpass;
}
- else if (auth->type == AUTH_DIGEST)
+ else if (auth->type == CUPSD_AUTH_DIGEST)
{
auth_supported = "digest";
num_air = 2;
air = air_userpass;
}
#ifdef HAVE_GSSAPI
- else if (auth->type == AUTH_NEGOTIATE)
+ else if (auth->type == CUPSD_AUTH_NEGOTIATE)
{
auth_supported = "negotiate";
num_air = 1;
}
#endif /* HAVE_GSSAPI */
- if (auth->type != AUTH_NONE)
+ if (auth->type != CUPSD_AUTH_NONE)
p->type |= CUPS_PRINTER_AUTHENTICATED;
else
p->type &= ~CUPS_PRINTER_AUTHENTICATED;
* Create the required IPP attributes for a printer...
*/
- if (p->attrs)
- ippDelete(p->attrs);
-
+ oldattrs = p->attrs;
p->attrs = ippNew();
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
if (ppd->num_filters == 0)
{
/*
- * If there are no filters, add a PostScript printing filter.
+ * If there are no filters, add PostScript printing filters.
*/
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-command 0 commandtops");
add_printer_filter(p, p->filetype,
"application/vnd.cups-postscript 0 -");
+
+ p->type |= CUPS_PRINTER_COMMANDS;
+ }
+ else if (!(p->type & CUPS_PRINTER_COMMANDS))
+ {
+ /*
+ * See if this is a PostScript device without a command filter...
+ */
+
+ for (i = 0; i < ppd->num_filters; i ++)
+ if (!strncasecmp(ppd->filters[i],
+ "application/vnd.cups-postscript", 31))
+ break;
+
+ if (i < ppd->num_filters)
+ {
+ /*
+ * Add the generic PostScript command filter...
+ */
+
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-command 0 commandtops");
+ p->type |= CUPS_PRINTER_COMMANDS;
+ }
+ }
+
+ if (p->type & CUPS_PRINTER_COMMANDS)
+ {
+ char *commands, /* Copy of commands */
+ *start, /* Start of name */
+ *end; /* End of name */
+ int count; /* Number of commands */
+
+
+ if ((ppdattr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL &&
+ ppdattr->value && ppdattr->value[0])
+ {
+ for (count = 0, start = ppdattr->value; *start; count ++)
+ {
+ while (isspace(*start & 255))
+ start ++;
+
+ if (!*start)
+ break;
+
+ while (*start && !isspace(*start & 255))
+ start ++;
+ }
+ }
+ else
+ count = 0;
+
+ if (count > 0)
+ {
+ /*
+ * Make a copy of the commands string and count how many ...
+ */
+
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-commands", count, NULL, NULL);
+
+ commands = strdup(ppdattr->value);
+
+ for (count = 0, start = commands; *start; count ++)
+ {
+ while (isspace(*start & 255))
+ start ++;
+
+ if (!*start)
+ break;
+
+ end = start;
+ while (*end && !isspace(*end & 255))
+ end ++;
+
+ if (*end)
+ *end++ = '\0';
+
+ attr->values[count].string.text = _cupsStrAlloc(start);
+
+ start = end;
+ }
+
+ free(commands);
+ }
+ else
+ {
+ /*
+ * Add the standard list of commands...
+ */
+
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-commands",
+ (int)(sizeof(standard_commands) /
+ sizeof(standard_commands[0])), NULL,
+ standard_commands);
+ }
+ }
+ else
+ {
+ /*
+ * No commands supported...
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-commands", NULL, "none");
}
/*
}
}
+ /*
+ * Copy marker attributes as needed...
+ */
+
+ if (oldattrs)
+ {
+ ipp_attribute_t *oldattr; /* Old attribute */
+
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-colors",
+ IPP_TAG_NAME)) != NULL)
+ {
+ if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "marker-colors", oldattr->num_values, NULL,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].string.text =
+ _cupsStrAlloc(oldattr->values[i].string.text);
+ }
+ }
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-levels",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ if ((attr = ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "marker-levels", oldattr->num_values,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].integer = oldattr->values[i].integer;
+ }
+ }
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-names",
+ IPP_TAG_NAME)) != NULL)
+ {
+ if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "marker-names", oldattr->num_values, NULL,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].string.text =
+ _cupsStrAlloc(oldattr->values[i].string.text);
+ }
+ }
+
+ if ((oldattr = ippFindAttribute(oldattrs, "marker-types",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ if ((attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "marker-types", oldattr->num_values, NULL,
+ NULL)) != NULL)
+ {
+ for (i = 0; i < oldattr->num_values; i ++)
+ attr->values[i].string.text =
+ _cupsStrAlloc(oldattr->values[i].string.text);
+ }
+ }
+
+ ippDelete(oldattrs);
+ }
+
/*
* Force sharing off for remote queues...
*/
if (old_state != s)
{
cupsdAddEvent(s == IPP_PRINTER_STOPPED ? CUPSD_EVENT_PRINTER_STOPPED :
- CUPSD_EVENT_PRINTER_STATE_CHANGED, p, NULL,
+ CUPSD_EVENT_PRINTER_STATE, p, NULL,
"%s \"%s\" state changed.",
(p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
p->name);
* Let the browse protocols reflect the change...
*/
- cupsdRegisterPrinter(p);
+ if (update)
+ cupsdRegisterPrinter(p);
/*
* Save the printer configuration if a printer goes from idle or processing
update)
{
if (p->type & CUPS_PRINTER_CLASS)
- cupsdSaveAllClasses();
+ cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
else
- cupsdSaveAllPrinters();
+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
}
}
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
+ job->dirty = 1;
- cupsdSaveJob(job);
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
"Job stopped due to printer being paused");
}
+/*
+ * 'cupsdUpdatePrinterPPD()' - Update keywords in a printer's PPD file.
+ */
+
+int /* O - 1 if successful, 0 otherwise */
+cupsdUpdatePrinterPPD(
+ cupsd_printer_t *p, /* I - Printer */
+ int num_keywords, /* I - Number of keywords */
+ cups_option_t *keywords) /* I - Keywords */
+{
+ int i; /* Looping var */
+ cups_file_t *src, /* Original file */
+ *dst; /* New file */
+ char srcfile[1024], /* Original filename */
+ dstfile[1024], /* New filename */
+ line[1024], /* Line from file */
+ keystring[41]; /* Keyword from line */
+ cups_option_t *keyword; /* Current keyword */
+
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "Updating keywords in PPD file for %s...",
+ p->name);
+
+ /*
+ * Get the old and new PPD filenames...
+ */
+
+ snprintf(srcfile, sizeof(srcfile), "%s/ppd/%s.ppd.O", ServerRoot, p->name);
+ snprintf(dstfile, sizeof(srcfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
+
+ /*
+ * Rename the old file and open the old and new...
+ */
+
+ if (rename(dstfile, srcfile))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to backup PPD file for %s: %s",
+ p->name, strerror(errno));
+ return (0);
+ }
+
+ if ((src = cupsFileOpen(srcfile, "r")) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open PPD file \"%s\": %s",
+ srcfile, strerror(errno));
+ rename(srcfile, dstfile);
+ return (0);
+ }
+
+ if ((dst = cupsFileOpen(dstfile, "w")) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create PPD file \"%s\": %s",
+ dstfile, strerror(errno));
+ cupsFileClose(src);
+ rename(srcfile, dstfile);
+ return (0);
+ }
+
+ /*
+ * Copy the first line and then write out all of the keywords...
+ */
+
+ if (!cupsFileGets(src, line, sizeof(line)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to read PPD file \"%s\": %s",
+ srcfile, strerror(errno));
+ cupsFileClose(src);
+ cupsFileClose(dst);
+ rename(srcfile, dstfile);
+ return (0);
+ }
+
+ cupsFilePrintf(dst, "%s\n", line);
+
+ for (i = num_keywords, keyword = keywords; i > 0; i --, keyword ++)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "*%s: %s", keyword->name, keyword->value);
+ cupsFilePrintf(dst, "*%s: %s\n", keyword->name, keyword->value);
+ }
+
+ /*
+ * Then copy the rest of the PPD file, dropping any keywords we changed.
+ */
+
+ while (cupsFileGets(src, line, sizeof(line)))
+ {
+ /*
+ * Skip keywords we've already set...
+ */
+
+ if (sscanf(line, "*%40[^:]:", keystring) == 1 &&
+ cupsGetOption(keystring, num_keywords, keywords))
+ continue;
+
+ /*
+ * Otherwise write the line...
+ */
+
+ cupsFilePrintf(dst, "%s\n", line);
+ }
+
+ /*
+ * Close files and return...
+ */
+
+ cupsFileClose(src);
+ cupsFileClose(dst);
+
+ return (1);
+}
+
+
/*
* 'cupsdUpdatePrinters()' - Update printers after a partial reload.
*/
/*
- * End of "$Id: printers.c 6970 2007-09-17 23:58:28Z mike $".
+ * End of "$Id: printers.c 7608 2008-05-21 01:37:21Z mike $".
*/