]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/dest.c
0c7144e48e9c4dff8adfc16b389763ca0da20bbd
2 * "$Id: dest.c,v 1.18.2.11 2003/01/07 18:26:24 mike Exp $"
4 * User-defined destination (and option) support for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2003 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Easy Software Products and are protected by Federal
11 * copyright law. Distribution and use rights are outlined in the file
12 * "LICENSE.txt" which should have been included with this file. If this
13 * file is missing or damaged please contact Easy Software Products
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636-3111 USA
21 * Voice: (301) 373-9603
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
25 * This file is subject to the Apple OS-Developed Software exception.
29 * cupsAddDest() - Add a destination to the list of destinations.
30 * cupsFreeDests() - Free the memory used by the list of destinations.
31 * cupsGetDest() - Get the named destination from the list.
32 * cupsGetDests() - Get the list of destinations.
33 * cupsSetDests() - Set the list of destinations.
34 * cups_get_dests() - Get destinations from a file.
35 * cups_get_sdests() - Get destinations from a server.
39 * Include necessary headers...
53 static int cups_get_dests(const char *filename
, int num_dests
,
55 static int cups_get_sdests(ipp_op_t op
, int num_dests
,
60 * 'cupsAddDest()' - Add a destination to the list of destinations.
63 int /* O - New number of destinations */
64 cupsAddDest(const char *name
, /* I - Name of destination */
65 const char *instance
, /* I - Instance of destination */
66 int num_dests
, /* I - Number of destinations */
67 cups_dest_t
**dests
) /* IO - Destinations */
69 int i
; /* Looping var */
70 cups_dest_t
*dest
; /* Destination pointer */
73 if (name
== NULL
|| dests
== NULL
)
76 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
80 * Add new destination...
84 dest
= malloc(sizeof(cups_dest_t
));
86 dest
= realloc(*dests
, sizeof(cups_dest_t
) * (num_dests
+ 1));
93 for (i
= num_dests
; i
> 0; i
--, dest
++)
94 if (strcasecmp(name
, dest
->name
) < 0)
96 else if (strcasecmp(name
, dest
->name
) == 0 &&
97 instance
!= NULL
&& dest
->instance
!= NULL
&&
98 strcasecmp(instance
, dest
->instance
) < 0)
102 memmove(dest
+ 1, dest
, i
* sizeof(cups_dest_t
));
104 dest
->name
= strdup(name
);
105 dest
->is_default
= 0;
106 dest
->num_options
= 0;
107 dest
->options
= (cups_option_t
*)0;
109 if (instance
== NULL
)
110 dest
->instance
= NULL
;
112 dest
->instance
= strdup(instance
);
114 return (num_dests
+ 1);
119 * 'cupsFreeDests()' - Free the memory used by the list of destinations.
123 cupsFreeDests(int num_dests
, /* I - Number of destinations */
124 cups_dest_t
*dests
) /* I - Destinations */
126 int i
; /* Looping var */
127 cups_dest_t
*dest
; /* Current destination */
130 if (num_dests
== 0 || dests
== NULL
)
133 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
138 free(dest
->instance
);
140 cupsFreeOptions(dest
->num_options
, dest
->options
);
148 * 'cupsGetDest()' - Get the named destination from the list.
151 cups_dest_t
* /* O - Destination pointer or NULL */
152 cupsGetDest(const char *name
, /* I - Name of destination */
153 const char *instance
, /* I - Instance of destination */
154 int num_dests
, /* I - Number of destinations */
155 cups_dest_t
*dests
) /* I - Destinations */
157 int comp
; /* Result of comparison */
160 if (num_dests
== 0 || dests
== NULL
)
166 * NULL name for default printer.
169 while (num_dests
> 0)
171 if (dests
->is_default
)
181 * Lookup name and optionally the instance...
184 while (num_dests
> 0)
186 if ((comp
= strcasecmp(name
, dests
->name
)) < 0)
190 if ((instance
== NULL
&& dests
->instance
== NULL
) ||
191 (instance
!= NULL
&& dests
->instance
!= NULL
&&
192 strcasecmp(instance
, dests
->instance
) == 0))
206 * 'cupsGetDests()' - Get the list of destinations.
209 int /* O - Number of destinations */
210 cupsGetDests(cups_dest_t
**dests
) /* O - Destinations */
212 int i
; /* Looping var */
213 int num_dests
; /* Number of destinations */
214 cups_dest_t
*dest
; /* Destination pointer */
215 const char *home
; /* HOME environment variable */
216 char filename
[1024]; /* Local ~/.lpoptions file */
217 const char *defprinter
; /* Default printer */
218 char name
[1024], /* Copy of printer name */
219 *instance
; /* Pointer to instance name */
220 int num_reals
; /* Number of real queues */
221 cups_dest_t
*reals
; /* Real queues */
225 * Initialize destination array...
229 *dests
= (cups_dest_t
*)0;
232 * Grab the printers and classes...
235 num_dests
= cups_get_sdests(CUPS_GET_PRINTERS
, num_dests
, dests
);
236 num_dests
= cups_get_sdests(CUPS_GET_CLASSES
, num_dests
, dests
);
239 * Make a copy of the "real" queues for a later sanity check...
244 num_reals
= num_dests
;
245 reals
= calloc(num_reals
, sizeof(cups_dest_t
));
248 memcpy(reals
, *dests
, num_reals
* sizeof(cups_dest_t
));
259 * Grab the default destination...
262 if ((defprinter
= cupsGetDefault()) != NULL
)
265 * Grab printer and instance name...
268 strlcpy(name
, defprinter
, sizeof(name
));
270 if ((instance
= strchr(name
, '/')) != NULL
)
274 * Lookup the printer and instance and make it the default...
277 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
278 dest
->is_default
= 1;
283 * This initialization of "instance" is unnecessary, but avoids a
284 * compiler warning...
291 * Load the /etc/cups/lpoptions and ~/.lpoptions files...
294 if ((home
= getenv("CUPS_SERVERROOT")) != NULL
)
296 snprintf(filename
, sizeof(filename
), "%s/lpoptions", home
);
297 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
300 num_dests
= cups_get_dests(CUPS_SERVERROOT
"/lpoptions", num_dests
, dests
);
302 if ((home
= getenv("HOME")) != NULL
)
304 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
305 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
309 * Validate the current default destination - this prevents old
310 * Default lines in /etc/cups/lpoptions and ~/.lpoptions from
311 * pointing to a non-existent printer or class...
317 * See if we have a default printer...
320 if ((dest
= cupsGetDest(NULL
, NULL
, num_dests
, *dests
)) != NULL
)
323 * Have a default; see if it is real...
326 dest
= cupsGetDest(dest
->name
, NULL
, num_reals
, reals
);
330 * If dest is NULL, then no default (that exists) is set, so we
331 * need to set a default if one exists...
334 if (dest
== NULL
&& defprinter
!= NULL
)
336 for (i
= 0; i
< num_dests
; i
++)
337 (*dests
)[i
].is_default
= 0;
339 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
340 dest
->is_default
= 1;
351 * Return the number of destinations...
359 * 'cupsSetDests()' - Set the list of destinations.
363 cupsSetDests(int num_dests
, /* I - Number of destinations */
364 cups_dest_t
*dests
) /* I - Destinations */
366 int i
, j
; /* Looping vars */
367 int wrote
; /* Wrote definition? */
368 cups_dest_t
*dest
; /* Current destination */
369 cups_option_t
*option
; /* Current option */
370 FILE *fp
; /* File pointer */
371 const char *home
; /* HOME environment variable */
372 char filename
[1024]; /* lpoptions file */
373 int num_temps
; /* Number of temporary destinations */
374 cups_dest_t
*temps
, /* Temporary destinations */
375 *temp
; /* Current temporary dest */
376 const char *val
; /* Value of temporary option */
380 * Get the server destinations...
383 num_temps
= cups_get_sdests(CUPS_GET_PRINTERS
, 0, &temps
);
384 num_temps
= cups_get_sdests(CUPS_GET_CLASSES
, num_temps
, &temps
);
387 * Figure out which file to write to...
390 if ((home
= getenv("CUPS_SERVERROOT")) != NULL
)
391 snprintf(filename
, sizeof(filename
), "%s/lpoptions", home
);
393 strcpy(filename
, CUPS_SERVERROOT
"/lpoptions");
399 * Merge in server defaults...
402 num_temps
= cups_get_dests(filename
, num_temps
, &temps
);
405 * Point to user defaults...
408 if ((home
= getenv("HOME")) != NULL
)
409 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
414 * Try to open the file...
417 if ((fp
= fopen(filename
, "w")) == NULL
)
419 cupsFreeDests(num_temps
, temps
);
424 * Write each printer; each line looks like:
426 * Dest name[/instance] options
427 * Default name[/instance] options
430 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
431 if (dest
->instance
!= NULL
|| dest
->num_options
!= 0 || dest
->is_default
)
433 if (dest
->is_default
)
435 fprintf(fp
, "Default %s", dest
->name
);
437 fprintf(fp
, "/%s", dest
->instance
);
444 if ((temp
= cupsGetDest(dest
->name
, dest
->instance
, num_temps
, temps
)) == NULL
)
445 temp
= cupsGetDest(dest
->name
, NULL
, num_temps
, temps
);
447 for (j
= dest
->num_options
, option
= dest
->options
; j
> 0; j
--, option
++)
450 * See if the server/global options match these; if so, don't
454 if (temp
&& (val
= cupsGetOption(option
->name
, temp
->num_options
,
455 temp
->options
)) != NULL
)
457 if (strcasecmp(val
, option
->value
) == 0)
462 * Options don't match, write to the file...
467 fprintf(fp
, "Dest %s", dest
->name
);
469 fprintf(fp
, "/%s", dest
->instance
);
473 if (option
->value
[0])
475 if (strchr(option
->value
, ' ') != NULL
)
476 fprintf(fp
, " %s=\"%s\"", option
->name
, option
->value
);
478 fprintf(fp
, " %s=%s", option
->name
, option
->value
);
481 fprintf(fp
, " %s", option
->name
);
489 * Free the temporary destinations...
492 cupsFreeDests(num_temps
, temps
);
495 * Close the file and return...
503 * 'cups_get_dests()' - Get destinations from a file.
506 static int /* O - Number of destinations */
507 cups_get_dests(const char *filename
, /* I - File to read from */
508 int num_dests
, /* I - Number of destinations */
509 cups_dest_t
**dests
) /* IO - Destinations */
511 int i
; /* Looping var */
512 cups_dest_t
*dest
; /* Current destination */
513 FILE *fp
; /* File pointer */
514 char line
[8192], /* Line from file */
515 *lineptr
, /* Pointer into line */
516 *name
, /* Name of destination/option */
517 *instance
; /* Instance of destination */
518 const char *printer
; /* PRINTER or LPDEST */
522 * Check environment variables...
525 if ((printer
= getenv("LPDEST")) == NULL
)
526 if ((printer
= getenv("PRINTER")) != NULL
)
527 if (strcmp(printer
, "lp") == 0)
531 * Try to open the file...
534 if ((fp
= fopen(filename
, "r")) == NULL
)
538 * Read each printer; each line looks like:
540 * Dest name[/instance] options
541 * Default name[/instance] options
544 while (fgets(line
, sizeof(line
), fp
) != NULL
)
547 * See what type of line it is...
550 if (strncasecmp(line
, "dest", 4) == 0 && isspace(line
[4]))
552 else if (strncasecmp(line
, "default", 7) == 0 && isspace(line
[7]))
558 * Skip leading whitespace...
561 while (isspace(*lineptr
))
570 * Search for an instance...
573 while (!isspace(*lineptr
) && *lineptr
&& *lineptr
!= '/')
582 * Found an instance...
589 * Search for an instance...
592 while (!isspace(*lineptr
) && *lineptr
)
601 * See if the primary instance of the destination exists; if not,
602 * ignore this entry and move on...
605 if (cupsGetDest(name
, NULL
, num_dests
, *dests
) == NULL
)
609 * Add the destination...
612 num_dests
= cupsAddDest(name
, instance
, num_dests
, dests
);
614 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) == NULL
)
625 * Add options until we hit the end of the line...
628 dest
->num_options
= cupsParseOptions(lineptr
, dest
->num_options
,
632 * Set this as default if needed...
635 if (strncasecmp(line
, "default", 7) == 0 && printer
== NULL
)
637 for (i
= 0; i
< num_dests
; i
++)
638 (*dests
)[i
].is_default
= 0;
640 dest
->is_default
= 1;
645 * Close the file and return...
655 * 'cups_get_sdests()' - Get destinations from a server.
658 static int /* O - Number of destinations */
659 cups_get_sdests(ipp_op_t op
, /* I - get-printers or get-classes */
660 int num_dests
, /* I - Number of destinations */
661 cups_dest_t
**dests
) /* IO - Destinations */
663 cups_dest_t
*dest
; /* Current destination */
664 http_t
*http
; /* HTTP connection */
665 ipp_t
*request
, /* IPP Request */
666 *response
; /* IPP Response */
667 ipp_attribute_t
*attr
; /* Current attribute */
668 cups_lang_t
*language
; /* Default language */
669 const char *name
; /* printer-name attribute */
670 char job_sheets
[1024]; /* job-sheets option */
671 static const char *pattrs
[] = /* Attributes we're interested in */
679 * Connect to the CUPS server...
682 if ((http
= httpConnect(cupsServer(), ippPort())) == NULL
)
686 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
687 * the following attributes:
690 * attributes-natural-language
695 request
->request
.op
.operation_id
= op
;
696 request
->request
.op
.request_id
= 1;
698 language
= cupsLangDefault();
700 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
701 "attributes-charset", NULL
, cupsLangEncoding(language
));
703 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
704 "attributes-natural-language", NULL
, language
->language
);
706 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
707 "requested-attributes", sizeof(pattrs
) / sizeof(pattrs
[0]),
711 * Do the request and get back a response...
714 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
716 for (attr
= response
->attrs
; attr
!= NULL
; attr
= attr
->next
)
719 * Skip leading attributes until we hit a printer...
722 while (attr
!= NULL
&& attr
->group_tag
!= IPP_TAG_PRINTER
)
729 * Pull the needed attributes from this job...
734 strcpy(job_sheets
, "");
736 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_PRINTER
)
738 if (strcmp(attr
->name
, "printer-name") == 0 &&
739 attr
->value_tag
== IPP_TAG_NAME
)
740 name
= attr
->values
[0].string
.text
;
742 if (strcmp(attr
->name
, "job-sheets-default") == 0 &&
743 (attr
->value_tag
== IPP_TAG_KEYWORD
||
744 attr
->value_tag
== IPP_TAG_NAME
))
746 if (attr
->num_values
== 2)
747 snprintf(job_sheets
, sizeof(job_sheets
), "%s,%s",
748 attr
->values
[0].string
.text
, attr
->values
[1].string
.text
);
750 strcpy(job_sheets
, attr
->values
[0].string
.text
);
757 * See if we have everything needed...
768 num_dests
= cupsAddDest(name
, NULL
, num_dests
, dests
);
770 if ((dest
= cupsGetDest(name
, NULL
, num_dests
, *dests
)) != NULL
)
772 dest
->num_options
= cupsAddOption("job-sheets", job_sheets
, 0,
783 * Close the server connection...
789 * Return the count...
797 * End of "$Id: dest.c,v 1.18.2.11 2003/01/07 18:26:24 mike Exp $".