]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/dest.c
2 * "$Id: dest.c 4918 2006-01-12 05:14:40Z mike $"
4 * User-defined destination (and option) support for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2006 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 USA
21 * Voice: (301) 373-9600
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 from the default server.
33 * cupsGetDests2() - Get the list of destinations from the specified server.
34 * cupsSetDests() - Set the list of destinations for the default server.
35 * cupsSetDests2() - Set the list of destinations for the specified server.
36 * cups_get_dests() - Get destinations from a file.
37 * cups_get_sdests() - Get destinations from a server.
41 * Include necessary headers...
53 static int cups_get_dests(const char *filename
, int num_dests
,
55 static int cups_get_sdests(http_t
*http
, ipp_op_t op
, int num_dests
,
60 * 'cupsAddDest()' - Add a destination to the list of destinations.
62 * Use the cupsSaveDests() function to save the updated list of destinations
63 * to the user's lpoptions file.
66 int /* O - New number of destinations */
67 cupsAddDest(const char *name
, /* I - Name of destination */
68 const char *instance
, /* I - Instance of destination or NULL for none/primary */
69 int num_dests
, /* I - Number of destinations */
70 cups_dest_t
**dests
) /* IO - Destinations */
72 int i
; /* Looping var */
73 cups_dest_t
*dest
; /* Destination pointer */
76 if (name
== NULL
|| dests
== NULL
)
79 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
83 * Add new destination...
87 dest
= malloc(sizeof(cups_dest_t
));
89 dest
= realloc(*dests
, sizeof(cups_dest_t
) * (num_dests
+ 1));
96 for (i
= num_dests
; i
> 0; i
--, dest
++)
97 if (strcasecmp(name
, dest
->name
) < 0)
99 else if (strcasecmp(name
, dest
->name
) == 0 &&
100 instance
!= NULL
&& dest
->instance
!= NULL
&&
101 strcasecmp(instance
, dest
->instance
) < 0)
105 memmove(dest
+ 1, dest
, i
* sizeof(cups_dest_t
));
107 dest
->name
= strdup(name
);
108 dest
->is_default
= 0;
109 dest
->num_options
= 0;
110 dest
->options
= (cups_option_t
*)0;
112 if (instance
== NULL
)
113 dest
->instance
= NULL
;
115 dest
->instance
= strdup(instance
);
117 return (num_dests
+ 1);
122 * 'cupsFreeDests()' - Free the memory used by the list of destinations.
126 cupsFreeDests(int num_dests
, /* I - Number of destinations */
127 cups_dest_t
*dests
) /* I - Destinations */
129 int i
; /* Looping var */
130 cups_dest_t
*dest
; /* Current destination */
133 if (num_dests
== 0 || dests
== NULL
)
136 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
141 free(dest
->instance
);
143 cupsFreeOptions(dest
->num_options
, dest
->options
);
151 * 'cupsGetDest()' - Get the named destination from the list.
153 * Use the cupsGetDests() or cupsGetDests2() functions to get a
154 * list of supported destinations for the current user.
157 cups_dest_t
* /* O - Destination pointer or NULL */
158 cupsGetDest(const char *name
, /* I - Name of destination */
159 const char *instance
, /* I - Instance of destination */
160 int num_dests
, /* I - Number of destinations */
161 cups_dest_t
*dests
) /* I - Destinations */
163 int comp
; /* Result of comparison */
166 if (num_dests
== 0 || dests
== NULL
)
172 * NULL name for default printer.
175 while (num_dests
> 0)
177 if (dests
->is_default
)
187 * Lookup name and optionally the instance...
190 while (num_dests
> 0)
192 if ((comp
= strcasecmp(name
, dests
->name
)) < 0)
196 if ((instance
== NULL
&& dests
->instance
== NULL
) ||
197 (instance
!= NULL
&& dests
->instance
!= NULL
&&
198 strcasecmp(instance
, dests
->instance
) == 0))
212 * 'cupsGetDests()' - Get the list of destinations from the default server.
215 int /* O - Number of destinations */
216 cupsGetDests(cups_dest_t
**dests
) /* O - Destinations */
218 int num_dests
; /* Number of destinations */
219 http_t
*http
; /* HTTP connection */
223 * Connect to the CUPS server and get the destination list and options...
226 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
228 num_dests
= cupsGetDests2(http
, dests
);
238 * 'cupsGetDests2()' - Get the list of destinations from the specified server.
240 * @since CUPS 1.1.21@
243 int /* O - Number of destinations */
244 cupsGetDests2(http_t
*http
, /* I - HTTP connection */
245 cups_dest_t
**dests
) /* O - Destinations */
247 int i
; /* Looping var */
248 int num_dests
; /* Number of destinations */
249 cups_dest_t
*dest
; /* Destination pointer */
250 const char *home
; /* HOME environment variable */
251 char filename
[1024]; /* Local ~/.lpoptions file */
252 const char *defprinter
; /* Default printer */
253 char name
[1024], /* Copy of printer name */
254 *instance
; /* Pointer to instance name */
255 int num_reals
; /* Number of real queues */
256 cups_dest_t
*reals
; /* Real queues */
257 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
261 * Range check the input...
268 * Initialize destination array...
272 *dests
= (cups_dest_t
*)0;
275 * Grab the printers and classes...
278 num_dests
= cups_get_sdests(http
, CUPS_GET_PRINTERS
, num_dests
, dests
);
279 num_dests
= cups_get_sdests(http
, CUPS_GET_CLASSES
, num_dests
, dests
);
282 * Make a copy of the "real" queues for a later sanity check...
287 num_reals
= num_dests
;
288 reals
= calloc(num_reals
, sizeof(cups_dest_t
));
291 memcpy(reals
, *dests
, num_reals
* sizeof(cups_dest_t
));
302 * Grab the default destination...
305 if ((defprinter
= cupsGetDefault2(http
)) != NULL
)
308 * Grab printer and instance name...
311 strlcpy(name
, defprinter
, sizeof(name
));
313 if ((instance
= strchr(name
, '/')) != NULL
)
317 * Lookup the printer and instance and make it the default...
320 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
321 dest
->is_default
= 1;
326 * This initialization of "instance" is unnecessary, but avoids a
327 * compiler warning...
334 * Load the /etc/cups/lpoptions and ~/.lpoptions files...
337 snprintf(filename
, sizeof(filename
), "%s/lpoptions", cg
->cups_serverroot
);
338 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
340 if ((home
= getenv("HOME")) != NULL
)
342 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
343 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
347 * Validate the current default destination - this prevents old
348 * Default lines in /etc/cups/lpoptions and ~/.lpoptions from
349 * pointing to a non-existent printer or class...
355 * See if we have a default printer...
358 if ((dest
= cupsGetDest(NULL
, NULL
, num_dests
, *dests
)) != NULL
)
361 * Have a default; see if it is real...
364 dest
= cupsGetDest(dest
->name
, NULL
, num_reals
, reals
);
368 * If dest is NULL, then no default (that exists) is set, so we
369 * need to set a default if one exists...
372 if (dest
== NULL
&& defprinter
!= NULL
)
374 for (i
= 0; i
< num_dests
; i
++)
375 (*dests
)[i
].is_default
= 0;
377 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
378 dest
->is_default
= 1;
389 * Return the number of destinations...
397 * 'cupsSetDests()' - Save the list of destinations for the default server.
399 * This function saves the destinations to /etc/cups/lpoptions when run
400 * as root and ~/.lpoptions when run as a normal user.
404 cupsSetDests(int num_dests
, /* I - Number of destinations */
405 cups_dest_t
*dests
) /* I - Destinations */
407 http_t
*http
; /* HTTP connection */
411 * Connect to the CUPS server and save the destination list and options...
414 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
416 cupsSetDests2(http
, num_dests
, dests
);
424 * 'cupsSetDests2()' - Save the list of destinations for the specified server.
426 * This function saves the destinations to /etc/cups/lpoptions when run
427 * as root and ~/.lpoptions when run as a normal user.
429 * @since CUPS 1.1.21@
432 int /* O - 0 on success, -1 on error */
433 cupsSetDests2(http_t
*http
, /* I - HTTP connection */
434 int num_dests
, /* I - Number of destinations */
435 cups_dest_t
*dests
) /* I - Destinations */
437 int i
, j
; /* Looping vars */
438 int wrote
; /* Wrote definition? */
439 cups_dest_t
*dest
; /* Current destination */
440 cups_option_t
*option
; /* Current option */
441 FILE *fp
; /* File pointer */
442 const char *home
; /* HOME environment variable */
443 char filename
[1024]; /* lpoptions file */
444 int num_temps
; /* Number of temporary destinations */
445 cups_dest_t
*temps
, /* Temporary destinations */
446 *temp
; /* Current temporary dest */
447 const char *val
; /* Value of temporary option */
448 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
452 * Range check the input...
455 if (!http
|| !num_dests
|| !dests
)
459 * Get the server destinations...
462 num_temps
= cups_get_sdests(http
, CUPS_GET_PRINTERS
, 0, &temps
);
463 num_temps
= cups_get_sdests(http
, CUPS_GET_CLASSES
, num_temps
, &temps
);
466 * Figure out which file to write to...
469 snprintf(filename
, sizeof(filename
), "%s/lpoptions", cg
->cups_serverroot
);
475 * Merge in server defaults...
478 num_temps
= cups_get_dests(filename
, num_temps
, &temps
);
481 * Point to user defaults...
484 if ((home
= getenv("HOME")) != NULL
)
485 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
490 * Try to open the file...
493 if ((fp
= fopen(filename
, "w")) == NULL
)
495 cupsFreeDests(num_temps
, temps
);
500 * Write each printer; each line looks like:
502 * Dest name[/instance] options
503 * Default name[/instance] options
506 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
507 if (dest
->instance
!= NULL
|| dest
->num_options
!= 0 || dest
->is_default
)
509 if (dest
->is_default
)
511 fprintf(fp
, "Default %s", dest
->name
);
513 fprintf(fp
, "/%s", dest
->instance
);
520 if ((temp
= cupsGetDest(dest
->name
, dest
->instance
, num_temps
, temps
)) == NULL
)
521 temp
= cupsGetDest(dest
->name
, NULL
, num_temps
, temps
);
523 for (j
= dest
->num_options
, option
= dest
->options
; j
> 0; j
--, option
++)
526 * See if the server/global options match these; if so, don't
530 if (temp
&& (val
= cupsGetOption(option
->name
, temp
->num_options
,
531 temp
->options
)) != NULL
)
533 if (strcasecmp(val
, option
->value
) == 0)
538 * Options don't match, write to the file...
543 fprintf(fp
, "Dest %s", dest
->name
);
545 fprintf(fp
, "/%s", dest
->instance
);
549 if (option
->value
[0])
551 if (strchr(option
->value
, ' ') != NULL
)
552 fprintf(fp
, " %s=\"%s\"", option
->name
, option
->value
);
554 fprintf(fp
, " %s=%s", option
->name
, option
->value
);
557 fprintf(fp
, " %s", option
->name
);
565 * Free the temporary destinations...
568 cupsFreeDests(num_temps
, temps
);
571 * Close the file and return...
581 * 'cups_get_dests()' - Get destinations from a file.
584 static int /* O - Number of destinations */
585 cups_get_dests(const char *filename
, /* I - File to read from */
586 int num_dests
, /* I - Number of destinations */
587 cups_dest_t
**dests
) /* IO - Destinations */
589 int i
; /* Looping var */
590 cups_dest_t
*dest
; /* Current destination */
591 FILE *fp
; /* File pointer */
592 char line
[8192], /* Line from file */
593 *lineptr
, /* Pointer into line */
594 *name
, /* Name of destination/option */
595 *instance
; /* Instance of destination */
596 const char *printer
; /* PRINTER or LPDEST */
600 * Check environment variables...
603 if ((printer
= getenv("LPDEST")) == NULL
)
604 if ((printer
= getenv("PRINTER")) != NULL
)
605 if (strcmp(printer
, "lp") == 0)
609 * Try to open the file...
612 if ((fp
= fopen(filename
, "r")) == NULL
)
616 * Read each printer; each line looks like:
618 * Dest name[/instance] options
619 * Default name[/instance] options
622 while (fgets(line
, sizeof(line
), fp
) != NULL
)
625 * See what type of line it is...
628 if (strncasecmp(line
, "dest", 4) == 0 && isspace(line
[4] & 255))
630 else if (strncasecmp(line
, "default", 7) == 0 && isspace(line
[7] & 255))
636 * Skip leading whitespace...
639 while (isspace(*lineptr
& 255))
648 * Search for an instance...
651 while (!isspace(*lineptr
& 255) && *lineptr
&& *lineptr
!= '/')
660 * Found an instance...
667 * Search for an instance...
670 while (!isspace(*lineptr
& 255) && *lineptr
)
679 * See if the primary instance of the destination exists; if not,
680 * ignore this entry and move on...
683 if (cupsGetDest(name
, NULL
, num_dests
, *dests
) == NULL
)
687 * Add the destination...
690 num_dests
= cupsAddDest(name
, instance
, num_dests
, dests
);
692 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) == NULL
)
703 * Add options until we hit the end of the line...
706 dest
->num_options
= cupsParseOptions(lineptr
, dest
->num_options
,
710 * Set this as default if needed...
713 if (strncasecmp(line
, "default", 7) == 0 && printer
== NULL
)
715 for (i
= 0; i
< num_dests
; i
++)
716 (*dests
)[i
].is_default
= 0;
718 dest
->is_default
= 1;
723 * Close the file and return...
733 * 'cups_get_sdests()' - Get destinations from a server.
736 static int /* O - Number of destinations */
737 cups_get_sdests(http_t
*http
, /* I - HTTP connection */
738 ipp_op_t op
, /* I - get-printers or get-classes */
739 int num_dests
, /* I - Number of destinations */
740 cups_dest_t
**dests
) /* IO - Destinations */
742 cups_dest_t
*dest
; /* Current destination */
743 ipp_t
*request
, /* IPP Request */
744 *response
; /* IPP Response */
745 ipp_attribute_t
*attr
; /* Current attribute */
746 cups_lang_t
*language
; /* Default language */
747 const char *name
; /* printer-name attribute */
748 char job_sheets
[1024]; /* job-sheets option */
749 static const char * const pattrs
[] = /* Attributes we're interested in */
757 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
758 * the following attributes:
761 * attributes-natural-language
766 request
->request
.op
.operation_id
= op
;
767 request
->request
.op
.request_id
= 1;
769 language
= cupsLangDefault();
771 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
772 "attributes-charset", NULL
, cupsLangEncoding(language
));
774 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
775 "attributes-natural-language", NULL
, language
->language
);
777 cupsLangFree(language
);
779 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
780 "requested-attributes", sizeof(pattrs
) / sizeof(pattrs
[0]),
784 * Do the request and get back a response...
787 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
789 for (attr
= response
->attrs
; attr
!= NULL
; attr
= attr
->next
)
792 * Skip leading attributes until we hit a printer...
795 while (attr
!= NULL
&& attr
->group_tag
!= IPP_TAG_PRINTER
)
802 * Pull the needed attributes from this job...
807 strcpy(job_sheets
, "");
809 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_PRINTER
)
811 if (strcmp(attr
->name
, "printer-name") == 0 &&
812 attr
->value_tag
== IPP_TAG_NAME
)
813 name
= attr
->values
[0].string
.text
;
815 if (strcmp(attr
->name
, "job-sheets-default") == 0 &&
816 (attr
->value_tag
== IPP_TAG_KEYWORD
||
817 attr
->value_tag
== IPP_TAG_NAME
))
819 if (attr
->num_values
== 2)
820 snprintf(job_sheets
, sizeof(job_sheets
), "%s,%s",
821 attr
->values
[0].string
.text
, attr
->values
[1].string
.text
);
823 strcpy(job_sheets
, attr
->values
[0].string
.text
);
830 * See if we have everything needed...
841 num_dests
= cupsAddDest(name
, NULL
, num_dests
, dests
);
843 if ((dest
= cupsGetDest(name
, NULL
, num_dests
, *dests
)) != NULL
)
845 dest
->num_options
= cupsAddOption("job-sheets", job_sheets
, 0,
856 * Return the count...
864 * End of "$Id: dest.c 4918 2006-01-12 05:14:40Z mike $".