/*
- * "$Id: dest.c 5346 2006-03-28 16:05:19Z mike $"
+ * "$Id: dest.c 6265 2007-02-11 19:42:42Z mike $"
*
* User-defined destination (and option) support for the Common UNIX
* Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
*
* Contents:
*
- * cupsAddDest() - Add a destination to the list of destinations.
- * cupsFreeDests() - Free the memory used by the list of destinations.
- * cupsGetDest() - Get the named destination from the list.
- * cupsGetDests() - Get the list of destinations from the default server.
- * cupsGetDests2() - Get the list of destinations from the specified server.
- * cupsSetDests() - Set the list of destinations for the default server.
- * cupsSetDests2() - Set the list of destinations for the specified server.
- * cups_get_dests() - Get destinations from a file.
- * cups_get_sdests() - Get destinations from a server.
+ * cupsAddDest() - Add a destination to the list of destinations.
+ * cupsFreeDests() - Free the memory used by the list of
+ * destinations.
+ * cupsGetDest() - Get the named destination from the list.
+ * cupsGetDests() - Get the list of destinations from the default
+ * server.
+ * cupsGetDests2() - Get the list of destinations from the
+ * specified server.
+ * cupsRemoveDest() - Remove a destination from the destination list.
+ * cupsDestSetDefaultDest() - Set the default destination.
+ * cupsSetDests() - Set the list of destinations for the default
+ * server.
+ * cupsSetDests2() - Set the list of destinations for the specified
+ * server.
+ * cups_get_dests() - Get destinations from a file.
+ * cups_get_sdests() - Get destinations from a server.
*/
/*
/*
* 'cupsAddDest()' - Add a destination to the list of destinations.
*
- * Use the cupsSaveDests() function to save the updated list of destinations
- * to the user's lpoptions file.
+ * This function cannot be used to add a new class or printer queue,
+ * it only adds a new container of saved options for the named
+ * destination or instance.
+ *
+ * If the named destination already exists, the destination list is
+ * returned unchanged. Adding a new instance of a destination creates
+ * a copy of that destination's options.
+ *
+ * Use the cupsSaveDests() function to save the updated list of
+ * destinations to the user's lpoptions file.
*/
int /* O - New number of destinations */
-cupsAddDest(const char *name, /* I - Name of destination */
- const char *instance, /* I - Instance of destination or NULL for none/primary */
+cupsAddDest(const char *name, /* I - Destination name */
+ const char *instance, /* I - Instance name or NULL for none/primary */
int num_dests, /* I - Number of destinations */
cups_dest_t **dests) /* IO - Destinations */
{
int i; /* Looping var */
cups_dest_t *dest; /* Destination pointer */
+ cups_dest_t *parent; /* Parent destination */
+ cups_option_t *option; /* Current option */
- if (name == NULL || dests == NULL)
+ if (!name || !dests)
return (0);
if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
*dests = dest;
+ /*
+ * Find where to insert the destination...
+ */
+
for (i = num_dests; i > 0; i --, dest ++)
if (strcasecmp(name, dest->name) < 0)
break;
+ else if (!instance && dest->instance)
+ break;
else if (!strcasecmp(name, dest->name) &&
- instance != NULL && dest->instance != NULL &&
+ instance && dest->instance &&
strcasecmp(instance, dest->instance) < 0)
break;
if (i > 0)
memmove(dest + 1, dest, i * sizeof(cups_dest_t));
+ /*
+ * Initialize the destination...
+ */
+
dest->name = strdup(name);
dest->is_default = 0;
dest->num_options = 0;
dest->options = (cups_option_t *)0;
- if (instance == NULL)
+ if (!instance)
dest->instance = NULL;
else
+ {
+ /*
+ * Copy options from the primary instance...
+ */
+
dest->instance = strdup(instance);
+ if ((parent = cupsGetDest(name, NULL, num_dests + 1, *dests)) != NULL)
+ {
+ for (i = parent->num_options, option = parent->options;
+ i > 0;
+ i --, option ++)
+ dest->num_options = cupsAddOption(option->name, option->value,
+ dest->num_options,
+ &(dest->options));
+ }
+ }
+
return (num_dests + 1);
}
*/
cups_dest_t * /* O - Destination pointer or NULL */
-cupsGetDest(const char *name, /* I - Name of destination */
- const char *instance, /* I - Instance of destination */
+cupsGetDest(const char *name, /* I - Destination name or NULL for the default destination */
+ const char *instance, /* I - Instance name or NULL */
int num_dests, /* I - Number of destinations */
cups_dest_t *dests) /* I - Destinations */
{
int comp; /* Result of comparison */
- if (num_dests == 0 || dests == NULL)
+ if (num_dests <= 0 || !dests)
return (NULL);
- if (name == NULL)
+ if (!name)
{
/*
* NULL name for default printer.
return (NULL);
else if (comp == 0)
{
- if ((instance == NULL && dests->instance == NULL) ||
+ if ((!instance && !dests->instance) ||
(instance != NULL && dests->instance != NULL &&
- strcasecmp(instance, dests->instance) == 0))
+ !strcasecmp(instance, dests->instance)))
return (dests);
}
* printer-info, printer-is-accepting-jobs, printer-is-shared,
* printer-make-and-model, printer-state, printer-state-change-time,
* printer-state-reasons, and printer-type attributes as options.
+ *
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
*/
int /* O - Number of destinations */
* printer-make-and-model, printer-state, printer-state-change-time,
* printer-state-reasons, and printer-type attributes as options.
*
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
+ *
* @since CUPS 1.1.21@
*/
}
+/*
+ * 'cupsRemoveDest()' - Remove a destination from the destination list.
+ *
+ * Removing a destination/instance does not delete the class or printer
+ * queue, merely the lpoptions for that destination/instance. Use the
+ * cupsSetDests() or cupsSetDests2() functions to save the new options
+ * for the user.
+ *
+ * @since CUPS 1.3@
+ */
+
+int /* O - New number of destinations */
+cupsRemoveDest(const char *name, /* I - Destination name */
+ const char *instance, /* I - Instance name or NULL */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
+{
+ int i; /* Index into destinations */
+ cups_dest_t *dest; /* Pointer to destination */
+
+
+ /*
+ * Find the destination...
+ */
+
+ if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL)
+ return (num_dests);
+
+ /*
+ * Free memory...
+ */
+
+ cupsFreeOptions(dest->num_options, dest->options);
+
+ /*
+ * Remove the destination from the array...
+ */
+
+ num_dests --;
+
+ i = dest - *dests;
+
+ if (i < num_dests)
+ memmove(dest, dest + 1, (num_dests - i) * sizeof(cups_dest_t));
+
+ return (num_dests);
+}
+
+
+/*
+ * 'cupsDestSetDefaultDest()' - Set the default destination.
+ *
+ * @since CUPS 1.3@
+ */
+
+void
+cupsSetDefaultDest(
+ const char *name, /* I - Destination name */
+ const char *instance, /* I - Instance name or NULL */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t *dests) /* I - Destinations */
+{
+ int i; /* Looping var */
+ cups_dest_t *dest; /* Current destination */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!name || num_dests <= 0 || !dests)
+ return;
+
+ /*
+ * Loop through the array and set the "is_default" flag for the matching
+ * destination...
+ */
+
+ for (i = num_dests, dest = dests; i > 0; i --, dest ++)
+ dest->is_default = !strcasecmp(name, dest->name) &&
+ ((!instance && !dest->instance) ||
+ (instance && dest->instance &&
+ !strcasecmp(instance, dest->instance)));
+}
+
+
/*
* 'cupsSetDests()' - Save the list of destinations for the default server.
*
int wrote; /* Wrote definition? */
cups_dest_t *dest; /* Current destination */
cups_option_t *option; /* Current option */
+ _ipp_option_t *match; /* Matching attribute for option */
FILE *fp; /* File pointer */
+#ifndef WIN32
const char *home; /* HOME environment variable */
+#endif /* WIN32 */
char filename[1024]; /* lpoptions file */
int num_temps; /* Number of temporary destinations */
cups_dest_t *temps, /* Temporary destinations */
for (j = dest->num_options, option = dest->options; j > 0; j --, option ++)
{
+ /*
+ * See if this option is a printer attribute; if so, skip it...
+ */
+
+ if ((match = _ippFindOption(option->name)) != NULL &&
+ match->group_tag == IPP_TAG_PRINTER)
+ continue;
+
/*
* See if the server/global options match these; if so, don't
* write 'em.
*/
- if (temp && (val = cupsGetOption(option->name, temp->num_options,
- temp->options)) != NULL)
- {
- if (!strcasecmp(val, option->value))
- continue;
- }
+ if (temp &&
+ (val = cupsGetOption(option->name, temp->num_options,
+ temp->options)) != NULL &&
+ !strcasecmp(val, option->value))
+ continue;
/*
* Options don't match, write to the file...
if (option->value[0])
{
- if (strchr(option->value, ' ') != NULL)
- fprintf(fp, " %s=\"%s\"", option->name, option->value);
- else
+ if (strchr(option->value, ' ') ||
+ strchr(option->value, '\\') ||
+ strchr(option->value, '\"') ||
+ strchr(option->value, '\''))
+ {
+ /*
+ * Quote the value...
+ */
+
+ fprintf(fp, " %s=\"", option->name);
+
+ for (val = option->value; *val; val ++)
+ {
+ if (strchr("\"\'\\", *val))
+ putc('\\', fp);
+
+ putc(*val, fp);
+ }
+
+ putc('\"', fp);
+ }
+ else
+ {
+ /*
+ * Store the literal value...
+ */
+
fprintf(fp, " %s=%s", option->name, option->value);
+ }
}
else
fprintf(fp, " %s", option->name);
const char *info, /* printer-info attribute */
*make_model, /* printer-make-and-model attribute */
*name; /* printer-name attribute */
- char job_sheets[1024], /* job-sheets option */
- reasons[1024], /* printer-state-reasons attribute */
- *rptr, /* Pointer into reasons string */
- temp[255]; /* Temporary string for numbers */
+ char job_sheets[1024], /* job-sheets-default attribute */
+ reasons[1024]; /* printer-state-reasons attribute */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ char optname[1024], /* Option name */
+ value[2048], /* Option value */
+ *ptr; /* Pointer into name/value */
static const char * const pattrs[] = /* Attributes we're interested in */
{
"job-sheets-default",
"printer-state",
"printer-state-change-time",
"printer-state-reasons",
- "printer-type"
+ "printer-type",
+ "printer-defaults"
};
break;
/*
- * Pull the needed attributes from this job...
+ * Pull the needed attributes from this printer...
*/
accepting = 0;
info = NULL;
make_model = NULL;
name = NULL;
+ num_options = 0;
+ options = NULL;
shared = 1;
state = IPP_PRINTER_IDLE;
type = CUPS_PRINTER_LOCAL;
attr->value_tag == IPP_TAG_KEYWORD)
{
strlcpy(reasons, attr->values[0].string.text, sizeof(reasons));
- for (i = 1, rptr = reasons + strlen(reasons);
+ for (i = 1, ptr = reasons + strlen(reasons);
i < attr->num_values;
i ++)
{
- snprintf(rptr, sizeof(reasons) - (rptr - reasons), ",%s",
+ snprintf(ptr, sizeof(reasons) - (ptr - reasons), ",%s",
attr->values[i].string.text);
- rptr += strlen(rptr);
+ ptr += strlen(ptr);
}
}
else if (!strcmp(attr->name, "printer-type") &&
attr->value_tag == IPP_TAG_ENUM)
type = attr->values[0].integer;
+ else if (strncmp(attr->name, "notify-", 7) &&
+ (attr->value_tag == IPP_TAG_BOOLEAN ||
+ attr->value_tag == IPP_TAG_ENUM ||
+ attr->value_tag == IPP_TAG_INTEGER ||
+ attr->value_tag == IPP_TAG_KEYWORD ||
+ attr->value_tag == IPP_TAG_NAME ||
+ attr->value_tag == IPP_TAG_RANGE) &&
+ strstr(attr->name, "-default"))
+ {
+ char *valptr; /* Pointer into attribute value */
+
+
+ /*
+ * Add a default option...
+ */
+
+ strlcpy(optname, attr->name, sizeof(optname));
+ if ((ptr = strstr(optname, "-default")) != NULL)
+ *ptr = '\0';
+
+ value[0] = '\0';
+ for (i = 0, ptr = value; i < attr->num_values; i ++)
+ {
+ if (ptr >= (value + sizeof(value) - 1))
+ break;
+
+ if (i)
+ *ptr++ = ',';
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ snprintf(ptr, sizeof(value) - (ptr - value), "%d",
+ attr->values[i].integer);
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ if (attr->values[i].boolean)
+ strlcpy(ptr, "true", sizeof(value) - (ptr - value));
+ else
+ strlcpy(ptr, "false", sizeof(value) - (ptr - value));
+ break;
+
+ case IPP_TAG_RANGE :
+ if (attr->values[i].range.lower ==
+ attr->values[i].range.upper)
+ snprintf(ptr, sizeof(value) - (ptr - value), "%d",
+ attr->values[i].range.lower);
+ else
+ snprintf(ptr, sizeof(value) - (ptr - value), "%d-%d",
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
+
+ default :
+ for (valptr = attr->values[i].string.text;
+ *valptr && ptr < (value + sizeof(value) - 2);)
+ {
+ if (strchr(" \t\n\\\'\"", *valptr))
+ *ptr++ = '\\';
+
+ *ptr++ = *valptr++;
+ }
+
+ *ptr = '\0';
+ break;
+ }
+
+ ptr += strlen(ptr);
+ }
+
+ num_options = cupsAddOption(optname, value, num_options, &options);
+ }
attr = attr->next;
}
if (!name)
{
+ cupsFreeOptions(num_options, options);
+
if (attr == NULL)
break;
else
if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL)
{
+ dest->num_options = num_options;
+ dest->options = options;
+
+ num_options = 0;
+ options = NULL;
+
if (job_sheets[0])
dest->num_options = cupsAddOption("job-sheets", job_sheets,
dest->num_options,
dest->num_options,
&(dest->options));
- sprintf(temp, "%d", accepting);
- dest->num_options = cupsAddOption("printer-is-accepting-jobs", temp,
+ sprintf(value, "%d", accepting);
+ dest->num_options = cupsAddOption("printer-is-accepting-jobs", value,
dest->num_options,
&(dest->options));
- sprintf(temp, "%d", shared);
- dest->num_options = cupsAddOption("printer-is-shared", temp,
+ sprintf(value, "%d", shared);
+ dest->num_options = cupsAddOption("printer-is-shared", value,
dest->num_options,
&(dest->options));
make_model, dest->num_options,
&(dest->options));
- sprintf(temp, "%d", state);
- dest->num_options = cupsAddOption("printer-state", temp,
+ sprintf(value, "%d", state);
+ dest->num_options = cupsAddOption("printer-state", value,
dest->num_options,
&(dest->options));
if (change_time)
{
- sprintf(temp, "%d", change_time);
- dest->num_options = cupsAddOption("printer-state-change-time", temp,
+ sprintf(value, "%d", change_time);
+ dest->num_options = cupsAddOption("printer-state-change-time", value,
dest->num_options,
&(dest->options));
}
dest->num_options,
&(dest->options));
- sprintf(temp, "%d", type);
- dest->num_options = cupsAddOption("printer-type", temp,
+ sprintf(value, "%d", type);
+ dest->num_options = cupsAddOption("printer-type", value,
dest->num_options,
&(dest->options));
}
+ cupsFreeOptions(num_options, options);
+
if (attr == NULL)
break;
}
/*
- * End of "$Id: dest.c 5346 2006-03-28 16:05:19Z mike $".
+ * End of "$Id: dest.c 6265 2007-02-11 19:42:42Z mike $".
*/