]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/dest.c
2 * "$Id: dest.c 6386 2007-03-23 19:03:01Z mike $"
4 * User-defined destination (and option) support for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2007 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
32 * cupsGetDest() - Get the named destination from the list.
33 * cupsGetDests() - Get the list of destinations from the default
35 * cupsGetDests2() - Get the list of destinations from the
37 * cupsRemoveDest() - Remove a destination from the destination list.
38 * cupsDestSetDefaultDest() - Set the default destination.
39 * cupsSetDests() - Set the list of destinations for the default
41 * cupsSetDests2() - Set the list of destinations for the specified
43 * cups_get_dests() - Get destinations from a file.
44 * cups_get_sdests() - Get destinations from a server.
48 * Include necessary headers...
58 #endif /* HAVE_NOTIFY_H */
65 static int cups_get_dests(const char *filename
, int num_dests
,
67 static int cups_get_sdests(http_t
*http
, ipp_op_t op
, int num_dests
,
72 * 'cupsAddDest()' - Add a destination to the list of destinations.
74 * This function cannot be used to add a new class or printer queue,
75 * it only adds a new container of saved options for the named
76 * destination or instance.
78 * If the named destination already exists, the destination list is
79 * returned unchanged. Adding a new instance of a destination creates
80 * a copy of that destination's options.
82 * Use the cupsSaveDests() function to save the updated list of
83 * destinations to the user's lpoptions file.
86 int /* O - New number of destinations */
87 cupsAddDest(const char *name
, /* I - Destination name */
88 const char *instance
, /* I - Instance name or NULL for none/primary */
89 int num_dests
, /* I - Number of destinations */
90 cups_dest_t
**dests
) /* IO - Destinations */
92 int i
; /* Looping var */
93 cups_dest_t
*dest
; /* Destination pointer */
94 cups_dest_t
*parent
; /* Parent destination */
95 cups_option_t
*option
; /* Current option */
101 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
105 * Add new destination...
109 dest
= malloc(sizeof(cups_dest_t
));
111 dest
= realloc(*dests
, sizeof(cups_dest_t
) * (num_dests
+ 1));
119 * Find where to insert the destination...
122 for (i
= num_dests
; i
> 0; i
--, dest
++)
123 if (strcasecmp(name
, dest
->name
) < 0)
125 else if (!instance
&& dest
->instance
)
127 else if (!strcasecmp(name
, dest
->name
) &&
128 instance
&& dest
->instance
&&
129 strcasecmp(instance
, dest
->instance
) < 0)
133 memmove(dest
+ 1, dest
, i
* sizeof(cups_dest_t
));
136 * Initialize the destination...
139 dest
->name
= strdup(name
);
140 dest
->is_default
= 0;
141 dest
->num_options
= 0;
142 dest
->options
= (cups_option_t
*)0;
145 dest
->instance
= NULL
;
149 * Copy options from the primary instance...
152 dest
->instance
= strdup(instance
);
154 if ((parent
= cupsGetDest(name
, NULL
, num_dests
+ 1, *dests
)) != NULL
)
156 for (i
= parent
->num_options
, option
= parent
->options
;
159 dest
->num_options
= cupsAddOption(option
->name
, option
->value
,
165 return (num_dests
+ 1);
170 * 'cupsFreeDests()' - Free the memory used by the list of destinations.
174 cupsFreeDests(int num_dests
, /* I - Number of destinations */
175 cups_dest_t
*dests
) /* I - Destinations */
177 int i
; /* Looping var */
178 cups_dest_t
*dest
; /* Current destination */
181 if (num_dests
== 0 || dests
== NULL
)
184 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
189 free(dest
->instance
);
191 cupsFreeOptions(dest
->num_options
, dest
->options
);
199 * 'cupsGetDest()' - Get the named destination from the list.
201 * Use the cupsGetDests() or cupsGetDests2() functions to get a
202 * list of supported destinations for the current user.
205 cups_dest_t
* /* O - Destination pointer or NULL */
206 cupsGetDest(const char *name
, /* I - Destination name or NULL for the default destination */
207 const char *instance
, /* I - Instance name or NULL */
208 int num_dests
, /* I - Number of destinations */
209 cups_dest_t
*dests
) /* I - Destinations */
211 int comp
; /* Result of comparison */
214 if (num_dests
<= 0 || !dests
)
220 * NULL name for default printer.
223 while (num_dests
> 0)
225 if (dests
->is_default
)
235 * Lookup name and optionally the instance...
238 while (num_dests
> 0)
240 if ((comp
= strcasecmp(name
, dests
->name
)) < 0)
244 if ((!instance
&& !dests
->instance
) ||
245 (instance
!= NULL
&& dests
->instance
!= NULL
&&
246 !strcasecmp(instance
, dests
->instance
)))
260 * 'cupsGetDests()' - Get the list of destinations from the default server.
262 * Starting with CUPS 1.2, the returned list of destinations include the
263 * printer-info, printer-is-accepting-jobs, printer-is-shared,
264 * printer-make-and-model, printer-state, printer-state-change-time,
265 * printer-state-reasons, and printer-type attributes as options.
267 * Use the cupsFreeDests() function to free the destination list and
268 * the cupsGetDest() function to find a particular destination.
271 int /* O - Number of destinations */
272 cupsGetDests(cups_dest_t
**dests
) /* O - Destinations */
274 int num_dests
; /* Number of destinations */
275 http_t
*http
; /* HTTP connection */
279 * Connect to the CUPS server and get the destination list and options...
282 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
284 num_dests
= cupsGetDests2(http
, dests
);
294 * 'cupsGetDests2()' - Get the list of destinations from the specified server.
296 * Starting with CUPS 1.2, the returned list of destinations include the
297 * printer-info, printer-is-accepting-jobs, printer-is-shared,
298 * printer-make-and-model, printer-state, printer-state-change-time,
299 * printer-state-reasons, and printer-type attributes as options.
301 * Use the cupsFreeDests() function to free the destination list and
302 * the cupsGetDest() function to find a particular destination.
304 * @since CUPS 1.1.21@
307 int /* O - Number of destinations */
308 cupsGetDests2(http_t
*http
, /* I - HTTP connection */
309 cups_dest_t
**dests
) /* O - Destinations */
311 int i
; /* Looping var */
312 int num_dests
; /* Number of destinations */
313 cups_dest_t
*dest
; /* Destination pointer */
314 const char *home
; /* HOME environment variable */
315 char filename
[1024]; /* Local ~/.cups/lpoptions file */
316 const char *defprinter
; /* Default printer */
317 char name
[1024], /* Copy of printer name */
318 *instance
; /* Pointer to instance name */
319 int num_reals
; /* Number of real queues */
320 cups_dest_t
*reals
; /* Real queues */
321 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
325 * Range check the input...
332 * Initialize destination array...
336 *dests
= (cups_dest_t
*)0;
339 * Grab the printers and classes...
342 num_dests
= cups_get_sdests(http
, CUPS_GET_PRINTERS
, num_dests
, dests
);
343 num_dests
= cups_get_sdests(http
, CUPS_GET_CLASSES
, num_dests
, dests
);
346 * Make a copy of the "real" queues for a later sanity check...
351 num_reals
= num_dests
;
352 reals
= calloc(num_reals
, sizeof(cups_dest_t
));
355 memcpy(reals
, *dests
, num_reals
* sizeof(cups_dest_t
));
366 * Grab the default destination...
369 if ((defprinter
= cupsGetDefault2(http
)) != NULL
)
372 * Grab printer and instance name...
375 strlcpy(name
, defprinter
, sizeof(name
));
377 if ((instance
= strchr(name
, '/')) != NULL
)
381 * Lookup the printer and instance and make it the default...
384 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
385 dest
->is_default
= 1;
390 * This initialization of "instance" is unnecessary, but avoids a
391 * compiler warning...
398 * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files...
401 snprintf(filename
, sizeof(filename
), "%s/lpoptions", cg
->cups_serverroot
);
402 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
404 if ((home
= getenv("HOME")) != NULL
)
406 snprintf(filename
, sizeof(filename
), "%s/.cups/lpoptions", home
);
407 if (access(filename
, 0))
408 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
410 num_dests
= cups_get_dests(filename
, num_dests
, dests
);
414 * Validate the current default destination - this prevents old
415 * Default lines in /etc/cups/lpoptions and ~/.cups/lpoptions from
416 * pointing to a non-existent printer or class...
422 * See if we have a default printer...
425 if ((dest
= cupsGetDest(NULL
, NULL
, num_dests
, *dests
)) != NULL
)
428 * Have a default; see if it is real...
431 dest
= cupsGetDest(dest
->name
, NULL
, num_reals
, reals
);
435 * If dest is NULL, then no default (that exists) is set, so we
436 * need to set a default if one exists...
439 if (dest
== NULL
&& defprinter
!= NULL
)
441 for (i
= 0; i
< num_dests
; i
++)
442 (*dests
)[i
].is_default
= 0;
444 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) != NULL
)
445 dest
->is_default
= 1;
456 * Return the number of destinations...
464 * 'cupsRemoveDest()' - Remove a destination from the destination list.
466 * Removing a destination/instance does not delete the class or printer
467 * queue, merely the lpoptions for that destination/instance. Use the
468 * cupsSetDests() or cupsSetDests2() functions to save the new options
474 int /* O - New number of destinations */
475 cupsRemoveDest(const char *name
, /* I - Destination name */
476 const char *instance
, /* I - Instance name or NULL */
477 int num_dests
, /* I - Number of destinations */
478 cups_dest_t
**dests
) /* IO - Destinations */
480 int i
; /* Index into destinations */
481 cups_dest_t
*dest
; /* Pointer to destination */
485 * Find the destination...
488 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) == NULL
)
495 cupsFreeOptions(dest
->num_options
, dest
->options
);
498 * Remove the destination from the array...
506 memmove(dest
, dest
+ 1, (num_dests
- i
) * sizeof(cups_dest_t
));
513 * 'cupsDestSetDefaultDest()' - Set the default destination.
520 const char *name
, /* I - Destination name */
521 const char *instance
, /* I - Instance name or NULL */
522 int num_dests
, /* I - Number of destinations */
523 cups_dest_t
*dests
) /* I - Destinations */
525 int i
; /* Looping var */
526 cups_dest_t
*dest
; /* Current destination */
530 * Range check input...
533 if (!name
|| num_dests
<= 0 || !dests
)
537 * Loop through the array and set the "is_default" flag for the matching
541 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
542 dest
->is_default
= !strcasecmp(name
, dest
->name
) &&
543 ((!instance
&& !dest
->instance
) ||
544 (instance
&& dest
->instance
&&
545 !strcasecmp(instance
, dest
->instance
)));
550 * 'cupsSetDests()' - Save the list of destinations for the default server.
552 * This function saves the destinations to /etc/cups/lpoptions when run
553 * as root and ~/.cups/lpoptions when run as a normal user.
557 cupsSetDests(int num_dests
, /* I - Number of destinations */
558 cups_dest_t
*dests
) /* I - Destinations */
560 http_t
*http
; /* HTTP connection */
564 * Connect to the CUPS server and save the destination list and options...
567 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
569 cupsSetDests2(http
, num_dests
, dests
);
577 * 'cupsSetDests2()' - Save the list of destinations for the specified server.
579 * This function saves the destinations to /etc/cups/lpoptions when run
580 * as root and ~/.cups/lpoptions when run as a normal user.
582 * @since CUPS 1.1.21@
585 int /* O - 0 on success, -1 on error */
586 cupsSetDests2(http_t
*http
, /* I - HTTP connection */
587 int num_dests
, /* I - Number of destinations */
588 cups_dest_t
*dests
) /* I - Destinations */
590 int i
, j
; /* Looping vars */
591 int wrote
; /* Wrote definition? */
592 cups_dest_t
*dest
; /* Current destination */
593 cups_option_t
*option
; /* Current option */
594 _ipp_option_t
*match
; /* Matching attribute for option */
595 FILE *fp
; /* File pointer */
597 const char *home
; /* HOME environment variable */
599 char filename
[1024]; /* lpoptions file */
600 int num_temps
; /* Number of temporary destinations */
601 cups_dest_t
*temps
, /* Temporary destinations */
602 *temp
; /* Current temporary dest */
603 const char *val
; /* Value of temporary option */
604 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
608 * Range check the input...
611 if (!http
|| !num_dests
|| !dests
)
615 * Get the server destinations...
618 num_temps
= cups_get_sdests(http
, CUPS_GET_PRINTERS
, 0, &temps
);
619 num_temps
= cups_get_sdests(http
, CUPS_GET_CLASSES
, num_temps
, &temps
);
622 * Figure out which file to write to...
625 snprintf(filename
, sizeof(filename
), "%s/lpoptions", cg
->cups_serverroot
);
631 * Merge in server defaults...
634 num_temps
= cups_get_dests(filename
, num_temps
, &temps
);
637 * Point to user defaults...
640 if ((home
= getenv("HOME")) != NULL
)
643 * Remove the old ~/.lpoptions file...
646 snprintf(filename
, sizeof(filename
), "%s/.lpoptions", home
);
650 * Create ~/.cups subdirectory...
653 snprintf(filename
, sizeof(filename
), "%s/.cups", home
);
654 if (access(filename
, 0))
655 mkdir(filename
, 0700);
657 snprintf(filename
, sizeof(filename
), "%s/.cups/lpoptions", home
);
663 * Try to open the file...
666 if ((fp
= fopen(filename
, "w")) == NULL
)
668 cupsFreeDests(num_temps
, temps
);
674 * Set the permissions to 0644 when saving to the /etc/cups/lpoptions
679 fchmod(fileno(fp
), 0644);
683 * Write each printer; each line looks like:
685 * Dest name[/instance] options
686 * Default name[/instance] options
689 for (i
= num_dests
, dest
= dests
; i
> 0; i
--, dest
++)
690 if (dest
->instance
!= NULL
|| dest
->num_options
!= 0 || dest
->is_default
)
692 if (dest
->is_default
)
694 fprintf(fp
, "Default %s", dest
->name
);
696 fprintf(fp
, "/%s", dest
->instance
);
703 if ((temp
= cupsGetDest(dest
->name
, dest
->instance
, num_temps
, temps
)) == NULL
)
704 temp
= cupsGetDest(dest
->name
, NULL
, num_temps
, temps
);
706 for (j
= dest
->num_options
, option
= dest
->options
; j
> 0; j
--, option
++)
709 * See if this option is a printer attribute; if so, skip it...
712 if ((match
= _ippFindOption(option
->name
)) != NULL
&&
713 match
->group_tag
== IPP_TAG_PRINTER
)
717 * See if the server/global options match these; if so, don't
722 (val
= cupsGetOption(option
->name
, temp
->num_options
,
723 temp
->options
)) != NULL
&&
724 !strcasecmp(val
, option
->value
))
728 * Options don't match, write to the file...
733 fprintf(fp
, "Dest %s", dest
->name
);
735 fprintf(fp
, "/%s", dest
->instance
);
739 if (option
->value
[0])
741 if (strchr(option
->value
, ' ') ||
742 strchr(option
->value
, '\\') ||
743 strchr(option
->value
, '\"') ||
744 strchr(option
->value
, '\''))
750 fprintf(fp
, " %s=\"", option
->name
);
752 for (val
= option
->value
; *val
; val
++)
754 if (strchr("\"\'\\", *val
))
765 * Store the literal value...
768 fprintf(fp
, " %s=%s", option
->name
, option
->value
);
772 fprintf(fp
, " %s", option
->name
);
780 * Free the temporary destinations and close the file...
783 cupsFreeDests(num_temps
, temps
);
787 #ifdef HAVE_NOTIFY_POST
789 * Send a notification so that MacOS X applications can know about the
793 notify_post("com.apple.printerListChange");
794 #endif /* HAVE_NOTIFY_POST */
801 * 'cups_get_dests()' - Get destinations from a file.
804 static int /* O - Number of destinations */
805 cups_get_dests(const char *filename
, /* I - File to read from */
806 int num_dests
, /* I - Number of destinations */
807 cups_dest_t
**dests
) /* IO - Destinations */
809 int i
; /* Looping var */
810 cups_dest_t
*dest
; /* Current destination */
811 FILE *fp
; /* File pointer */
812 char line
[8192], /* Line from file */
813 *lineptr
, /* Pointer into line */
814 *name
, /* Name of destination/option */
815 *instance
; /* Instance of destination */
816 const char *printer
; /* PRINTER or LPDEST */
820 * Check environment variables...
823 if ((printer
= getenv("LPDEST")) == NULL
)
824 if ((printer
= getenv("PRINTER")) != NULL
)
825 if (strcmp(printer
, "lp") == 0)
829 * Try to open the file...
832 if ((fp
= fopen(filename
, "r")) == NULL
)
836 * Read each printer; each line looks like:
838 * Dest name[/instance] options
839 * Default name[/instance] options
842 while (fgets(line
, sizeof(line
), fp
) != NULL
)
845 * See what type of line it is...
848 if (strncasecmp(line
, "dest", 4) == 0 && isspace(line
[4] & 255))
850 else if (strncasecmp(line
, "default", 7) == 0 && isspace(line
[7] & 255))
856 * Skip leading whitespace...
859 while (isspace(*lineptr
& 255))
868 * Search for an instance...
871 while (!isspace(*lineptr
& 255) && *lineptr
&& *lineptr
!= '/')
880 * Found an instance...
887 * Search for an instance...
890 while (!isspace(*lineptr
& 255) && *lineptr
)
899 * See if the primary instance of the destination exists; if not,
900 * ignore this entry and move on...
903 if (cupsGetDest(name
, NULL
, num_dests
, *dests
) == NULL
)
907 * Add the destination...
910 num_dests
= cupsAddDest(name
, instance
, num_dests
, dests
);
912 if ((dest
= cupsGetDest(name
, instance
, num_dests
, *dests
)) == NULL
)
923 * Add options until we hit the end of the line...
926 dest
->num_options
= cupsParseOptions(lineptr
, dest
->num_options
,
930 * Set this as default if needed...
933 if (strncasecmp(line
, "default", 7) == 0 && printer
== NULL
)
935 for (i
= 0; i
< num_dests
; i
++)
936 (*dests
)[i
].is_default
= 0;
938 dest
->is_default
= 1;
943 * Close the file and return...
953 * 'cups_get_sdests()' - Get destinations from a server.
956 static int /* O - Number of destinations */
957 cups_get_sdests(http_t
*http
, /* I - HTTP connection */
958 ipp_op_t op
, /* I - get-printers or get-classes */
959 int num_dests
, /* I - Number of destinations */
960 cups_dest_t
**dests
) /* IO - Destinations */
962 int i
; /* Looping var */
963 cups_dest_t
*dest
; /* Current destination */
964 ipp_t
*request
, /* IPP Request */
965 *response
; /* IPP Response */
966 ipp_attribute_t
*attr
; /* Current attribute */
967 int accepting
, /* printer-is-accepting-jobs attribute */
968 shared
, /* printer-is-shared attribute */
969 state
, /* printer-state attribute */
970 change_time
, /* printer-state-change-time attribute */
971 type
; /* printer-type attribute */
972 const char *info
, /* printer-info attribute */
973 *location
, /* printer-location attribute */
974 *make_model
, /* printer-make-and-model attribute */
975 *name
; /* printer-name attribute */
976 char job_sheets
[1024], /* job-sheets-default attribute */
977 auth_info_req
[1024], /* auth-info-required attribute */
978 reasons
[1024]; /* printer-state-reasons attribute */
979 int num_options
; /* Number of options */
980 cups_option_t
*options
; /* Options */
981 char optname
[1024], /* Option name */
982 value
[2048], /* Option value */
983 *ptr
; /* Pointer into name/value */
984 static const char * const pattrs
[] = /* Attributes we're interested in */
986 "auth-info-required",
987 "job-sheets-default",
989 "printer-is-accepting-jobs",
992 "printer-make-and-model",
995 "printer-state-change-time",
996 "printer-state-reasons",
1003 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
1004 * the following attributes:
1006 * attributes-charset
1007 * attributes-natural-language
1008 * requesting-user-name
1011 request
= ippNewRequest(op
);
1013 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1014 "requested-attributes", sizeof(pattrs
) / sizeof(pattrs
[0]),
1017 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1018 "requesting-user-name", NULL
, cupsUser());
1021 * Do the request and get back a response...
1024 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1026 for (attr
= response
->attrs
; attr
!= NULL
; attr
= attr
->next
)
1029 * Skip leading attributes until we hit a printer...
1032 while (attr
!= NULL
&& attr
->group_tag
!= IPP_TAG_PRINTER
)
1039 * Pull the needed attributes from this printer...
1051 state
= IPP_PRINTER_IDLE
;
1052 type
= CUPS_PRINTER_LOCAL
;
1054 auth_info_req
[0] = '\0';
1055 job_sheets
[0] = '\0';
1058 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_PRINTER
)
1060 if (!strcmp(attr
->name
, "auth-info-required") &&
1061 attr
->value_tag
== IPP_TAG_KEYWORD
)
1063 strlcpy(auth_info_req
, attr
->values
[0].string
.text
,
1064 sizeof(auth_info_req
));
1066 for (i
= 1, ptr
= auth_info_req
+ strlen(auth_info_req
);
1067 i
< attr
->num_values
;
1070 snprintf(ptr
, sizeof(auth_info_req
) - (ptr
- auth_info_req
), ",%s",
1071 attr
->values
[i
].string
.text
);
1075 else if (!strcmp(attr
->name
, "job-sheets-default") &&
1076 (attr
->value_tag
== IPP_TAG_KEYWORD
||
1077 attr
->value_tag
== IPP_TAG_NAME
))
1079 if (attr
->num_values
== 2)
1080 snprintf(job_sheets
, sizeof(job_sheets
), "%s,%s",
1081 attr
->values
[0].string
.text
, attr
->values
[1].string
.text
);
1083 strlcpy(job_sheets
, attr
->values
[0].string
.text
,
1084 sizeof(job_sheets
));
1086 else if (!strcmp(attr
->name
, "printer-info") &&
1087 attr
->value_tag
== IPP_TAG_TEXT
)
1088 info
= attr
->values
[0].string
.text
;
1089 else if (!strcmp(attr
->name
, "printer-is-accepting-jobs") &&
1090 attr
->value_tag
== IPP_TAG_BOOLEAN
)
1091 accepting
= attr
->values
[0].boolean
;
1092 else if (!strcmp(attr
->name
, "printer-is-shared") &&
1093 attr
->value_tag
== IPP_TAG_BOOLEAN
)
1094 shared
= attr
->values
[0].boolean
;
1095 else if (!strcmp(attr
->name
, "printer-location") &&
1096 attr
->value_tag
== IPP_TAG_TEXT
)
1097 location
= attr
->values
[0].string
.text
;
1098 else if (!strcmp(attr
->name
, "printer-make-and-model") &&
1099 attr
->value_tag
== IPP_TAG_TEXT
)
1100 make_model
= attr
->values
[0].string
.text
;
1101 else if (!strcmp(attr
->name
, "printer-name") &&
1102 attr
->value_tag
== IPP_TAG_NAME
)
1103 name
= attr
->values
[0].string
.text
;
1104 else if (!strcmp(attr
->name
, "printer-state") &&
1105 attr
->value_tag
== IPP_TAG_ENUM
)
1106 state
= attr
->values
[0].integer
;
1107 else if (!strcmp(attr
->name
, "printer-state-change-time") &&
1108 attr
->value_tag
== IPP_TAG_INTEGER
)
1109 change_time
= attr
->values
[0].integer
;
1110 else if (!strcmp(attr
->name
, "printer-state-reasons") &&
1111 attr
->value_tag
== IPP_TAG_KEYWORD
)
1113 strlcpy(reasons
, attr
->values
[0].string
.text
, sizeof(reasons
));
1114 for (i
= 1, ptr
= reasons
+ strlen(reasons
);
1115 i
< attr
->num_values
;
1118 snprintf(ptr
, sizeof(reasons
) - (ptr
- reasons
), ",%s",
1119 attr
->values
[i
].string
.text
);
1123 else if (!strcmp(attr
->name
, "printer-type") &&
1124 attr
->value_tag
== IPP_TAG_ENUM
)
1125 type
= attr
->values
[0].integer
;
1126 else if (strncmp(attr
->name
, "notify-", 7) &&
1127 (attr
->value_tag
== IPP_TAG_BOOLEAN
||
1128 attr
->value_tag
== IPP_TAG_ENUM
||
1129 attr
->value_tag
== IPP_TAG_INTEGER
||
1130 attr
->value_tag
== IPP_TAG_KEYWORD
||
1131 attr
->value_tag
== IPP_TAG_NAME
||
1132 attr
->value_tag
== IPP_TAG_RANGE
) &&
1133 strstr(attr
->name
, "-default"))
1135 char *valptr
; /* Pointer into attribute value */
1139 * Add a default option...
1142 strlcpy(optname
, attr
->name
, sizeof(optname
));
1143 if ((ptr
= strstr(optname
, "-default")) != NULL
)
1147 for (i
= 0, ptr
= value
; i
< attr
->num_values
; i
++)
1149 if (ptr
>= (value
+ sizeof(value
) - 1))
1155 switch (attr
->value_tag
)
1157 case IPP_TAG_INTEGER
:
1159 snprintf(ptr
, sizeof(value
) - (ptr
- value
), "%d",
1160 attr
->values
[i
].integer
);
1163 case IPP_TAG_BOOLEAN
:
1164 if (attr
->values
[i
].boolean
)
1165 strlcpy(ptr
, "true", sizeof(value
) - (ptr
- value
));
1167 strlcpy(ptr
, "false", sizeof(value
) - (ptr
- value
));
1170 case IPP_TAG_RANGE
:
1171 if (attr
->values
[i
].range
.lower
==
1172 attr
->values
[i
].range
.upper
)
1173 snprintf(ptr
, sizeof(value
) - (ptr
- value
), "%d",
1174 attr
->values
[i
].range
.lower
);
1176 snprintf(ptr
, sizeof(value
) - (ptr
- value
), "%d-%d",
1177 attr
->values
[i
].range
.lower
,
1178 attr
->values
[i
].range
.upper
);
1182 for (valptr
= attr
->values
[i
].string
.text
;
1183 *valptr
&& ptr
< (value
+ sizeof(value
) - 2);)
1185 if (strchr(" \t\n\\\'\"", *valptr
))
1198 num_options
= cupsAddOption(optname
, value
, num_options
, &options
);
1205 * See if we have everything needed...
1210 cupsFreeOptions(num_options
, options
);
1218 num_dests
= cupsAddDest(name
, NULL
, num_dests
, dests
);
1220 if ((dest
= cupsGetDest(name
, NULL
, num_dests
, *dests
)) != NULL
)
1222 dest
->num_options
= num_options
;
1223 dest
->options
= options
;
1228 if (auth_info_req
[0])
1229 dest
->num_options
= cupsAddOption("auth-info-required", auth_info_req
,
1234 dest
->num_options
= cupsAddOption("job-sheets", job_sheets
,
1239 dest
->num_options
= cupsAddOption("printer-info", info
,
1243 sprintf(value
, "%d", accepting
);
1244 dest
->num_options
= cupsAddOption("printer-is-accepting-jobs", value
,
1248 sprintf(value
, "%d", shared
);
1249 dest
->num_options
= cupsAddOption("printer-is-shared", value
,
1254 dest
->num_options
= cupsAddOption("printer-location",
1255 location
, dest
->num_options
,
1259 dest
->num_options
= cupsAddOption("printer-make-and-model",
1260 make_model
, dest
->num_options
,
1263 sprintf(value
, "%d", state
);
1264 dest
->num_options
= cupsAddOption("printer-state", value
,
1270 sprintf(value
, "%d", change_time
);
1271 dest
->num_options
= cupsAddOption("printer-state-change-time", value
,
1277 dest
->num_options
= cupsAddOption("printer-state-reasons", reasons
,
1281 sprintf(value
, "%d", type
);
1282 dest
->num_options
= cupsAddOption("printer-type", value
,
1287 cupsFreeOptions(num_options
, options
);
1293 ippDelete(response
);
1297 * Return the count...
1305 * End of "$Id: dest.c 6386 2007-03-23 19:03:01Z mike $".