]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/dest.c
Remove svn:keywords since they cause svn_load_dirs.pl to complain about every file.
[thirdparty/cups.git] / cups / dest.c
CommitLineData
ef416fc2 1/*
c07d5b2d 2 * "$Id: dest.c 177 2006-06-21 00:20:03Z jlovell $"
ef416fc2 3 *
4 * User-defined destination (and option) support for the Common UNIX
5 * Printing System (CUPS).
6 *
7 * Copyright 1997-2006 by Easy Software Products.
8 *
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
14 * at:
15 *
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
20 *
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
24 *
25 * This file is subject to the Apple OS-Developed Software exception.
26 *
27 * Contents:
28 *
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.
38 */
39
40/*
41 * Include necessary headers...
42 */
43
44#include "globals.h"
45#include <stdlib.h>
46#include <ctype.h>
b423cd4c 47#include <sys/stat.h>
ef416fc2 48
fa73b229 49#ifdef HAVE_NOTIFY_H
50# include <notify.h>
51#endif /* HAVE_NOTIFY_H */
52
ef416fc2 53
54/*
55 * Local functions...
56 */
57
58static int cups_get_dests(const char *filename, int num_dests,
59 cups_dest_t **dests);
60static int cups_get_sdests(http_t *http, ipp_op_t op, int num_dests,
61 cups_dest_t **dests);
62
63
64/*
65 * 'cupsAddDest()' - Add a destination to the list of destinations.
66 *
67 * Use the cupsSaveDests() function to save the updated list of destinations
68 * to the user's lpoptions file.
69 */
70
71int /* O - New number of destinations */
72cupsAddDest(const char *name, /* I - Name of destination */
73 const char *instance, /* I - Instance of destination or NULL for none/primary */
74 int num_dests, /* I - Number of destinations */
75 cups_dest_t **dests) /* IO - Destinations */
76{
77 int i; /* Looping var */
78 cups_dest_t *dest; /* Destination pointer */
79
80
81 if (name == NULL || dests == NULL)
82 return (0);
83
84 if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
85 return (num_dests);
86
87 /*
88 * Add new destination...
89 */
90
91 if (num_dests == 0)
92 dest = malloc(sizeof(cups_dest_t));
93 else
94 dest = realloc(*dests, sizeof(cups_dest_t) * (num_dests + 1));
95
96 if (dest == NULL)
97 return (num_dests);
98
99 *dests = dest;
100
101 for (i = num_dests; i > 0; i --, dest ++)
102 if (strcasecmp(name, dest->name) < 0)
103 break;
b423cd4c 104 else if (!strcasecmp(name, dest->name) &&
ef416fc2 105 instance != NULL && dest->instance != NULL &&
106 strcasecmp(instance, dest->instance) < 0)
107 break;
108
109 if (i > 0)
110 memmove(dest + 1, dest, i * sizeof(cups_dest_t));
111
112 dest->name = strdup(name);
113 dest->is_default = 0;
114 dest->num_options = 0;
115 dest->options = (cups_option_t *)0;
116
117 if (instance == NULL)
118 dest->instance = NULL;
119 else
120 dest->instance = strdup(instance);
121
122 return (num_dests + 1);
123}
124
125
126/*
127 * 'cupsFreeDests()' - Free the memory used by the list of destinations.
128 */
129
130void
131cupsFreeDests(int num_dests, /* I - Number of destinations */
132 cups_dest_t *dests) /* I - Destinations */
133{
134 int i; /* Looping var */
135 cups_dest_t *dest; /* Current destination */
136
137
138 if (num_dests == 0 || dests == NULL)
139 return;
140
141 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
142 {
143 free(dest->name);
144
145 if (dest->instance)
146 free(dest->instance);
147
148 cupsFreeOptions(dest->num_options, dest->options);
149 }
150
151 free(dests);
152}
153
154
155/*
156 * 'cupsGetDest()' - Get the named destination from the list.
157 *
158 * Use the cupsGetDests() or cupsGetDests2() functions to get a
159 * list of supported destinations for the current user.
160 */
161
162cups_dest_t * /* O - Destination pointer or NULL */
163cupsGetDest(const char *name, /* I - Name of destination */
164 const char *instance, /* I - Instance of destination */
165 int num_dests, /* I - Number of destinations */
166 cups_dest_t *dests) /* I - Destinations */
167{
168 int comp; /* Result of comparison */
169
170
171 if (num_dests == 0 || dests == NULL)
172 return (NULL);
173
174 if (name == NULL)
175 {
176 /*
177 * NULL name for default printer.
178 */
179
180 while (num_dests > 0)
181 {
182 if (dests->is_default)
183 return (dests);
184
185 num_dests --;
186 dests ++;
187 }
188 }
189 else
190 {
191 /*
192 * Lookup name and optionally the instance...
193 */
194
195 while (num_dests > 0)
196 {
197 if ((comp = strcasecmp(name, dests->name)) < 0)
198 return (NULL);
199 else if (comp == 0)
200 {
201 if ((instance == NULL && dests->instance == NULL) ||
202 (instance != NULL && dests->instance != NULL &&
203 strcasecmp(instance, dests->instance) == 0))
204 return (dests);
205 }
206
207 num_dests --;
208 dests ++;
209 }
210 }
211
212 return (NULL);
213}
214
215
216/*
217 * 'cupsGetDests()' - Get the list of destinations from the default server.
ecdc0628 218 *
219 * Starting with CUPS 1.2, the returned list of destinations include the
220 * printer-info, printer-is-accepting-jobs, printer-is-shared,
221 * printer-make-and-model, printer-state, printer-state-change-time,
222 * printer-state-reasons, and printer-type attributes as options.
ef416fc2 223 */
224
225int /* O - Number of destinations */
226cupsGetDests(cups_dest_t **dests) /* O - Destinations */
227{
228 int num_dests; /* Number of destinations */
229 http_t *http; /* HTTP connection */
230
231
232 /*
233 * Connect to the CUPS server and get the destination list and options...
234 */
235
236 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
237
238 num_dests = cupsGetDests2(http, dests);
239
240 if (http)
241 httpClose(http);
242
243 return (num_dests);
244}
245
246
247/*
248 * 'cupsGetDests2()' - Get the list of destinations from the specified server.
249 *
ecdc0628 250 * Starting with CUPS 1.2, the returned list of destinations include the
251 * printer-info, printer-is-accepting-jobs, printer-is-shared,
252 * printer-make-and-model, printer-state, printer-state-change-time,
253 * printer-state-reasons, and printer-type attributes as options.
254 *
ef416fc2 255 * @since CUPS 1.1.21@
256 */
257
258int /* O - Number of destinations */
259cupsGetDests2(http_t *http, /* I - HTTP connection */
260 cups_dest_t **dests) /* O - Destinations */
261{
262 int i; /* Looping var */
263 int num_dests; /* Number of destinations */
264 cups_dest_t *dest; /* Destination pointer */
265 const char *home; /* HOME environment variable */
b423cd4c 266 char filename[1024]; /* Local ~/.cups/lpoptions file */
ef416fc2 267 const char *defprinter; /* Default printer */
268 char name[1024], /* Copy of printer name */
269 *instance; /* Pointer to instance name */
270 int num_reals; /* Number of real queues */
271 cups_dest_t *reals; /* Real queues */
272 _cups_globals_t *cg = _cupsGlobals(); /* Global data */
273
274
275 /*
276 * Range check the input...
277 */
278
279 if (!http || !dests)
280 return (0);
281
282 /*
283 * Initialize destination array...
284 */
285
286 num_dests = 0;
287 *dests = (cups_dest_t *)0;
288
289 /*
290 * Grab the printers and classes...
291 */
292
293 num_dests = cups_get_sdests(http, CUPS_GET_PRINTERS, num_dests, dests);
294 num_dests = cups_get_sdests(http, CUPS_GET_CLASSES, num_dests, dests);
295
296 /*
297 * Make a copy of the "real" queues for a later sanity check...
298 */
299
300 if (num_dests > 0)
301 {
302 num_reals = num_dests;
303 reals = calloc(num_reals, sizeof(cups_dest_t));
304
305 if (reals)
306 memcpy(reals, *dests, num_reals * sizeof(cups_dest_t));
307 else
308 num_reals = 0;
309 }
310 else
311 {
312 num_reals = 0;
313 reals = NULL;
314 }
315
316 /*
317 * Grab the default destination...
318 */
319
320 if ((defprinter = cupsGetDefault2(http)) != NULL)
321 {
322 /*
323 * Grab printer and instance name...
324 */
325
326 strlcpy(name, defprinter, sizeof(name));
327
328 if ((instance = strchr(name, '/')) != NULL)
329 *instance++ = '\0';
330
331 /*
332 * Lookup the printer and instance and make it the default...
333 */
334
335 if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
336 dest->is_default = 1;
337 }
338 else
339 {
340 /*
341 * This initialization of "instance" is unnecessary, but avoids a
342 * compiler warning...
343 */
344
345 instance = NULL;
346 }
347
348 /*
b423cd4c 349 * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files...
ef416fc2 350 */
351
352 snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
353 num_dests = cups_get_dests(filename, num_dests, dests);
354
355 if ((home = getenv("HOME")) != NULL)
356 {
b423cd4c 357 snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
358 if (access(filename, 0))
359 snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
360
ef416fc2 361 num_dests = cups_get_dests(filename, num_dests, dests);
362 }
363
364 /*
365 * Validate the current default destination - this prevents old
b423cd4c 366 * Default lines in /etc/cups/lpoptions and ~/.cups/lpoptions from
ef416fc2 367 * pointing to a non-existent printer or class...
368 */
369
370 if (num_reals)
371 {
372 /*
373 * See if we have a default printer...
374 */
375
376 if ((dest = cupsGetDest(NULL, NULL, num_dests, *dests)) != NULL)
377 {
378 /*
379 * Have a default; see if it is real...
380 */
381
382 dest = cupsGetDest(dest->name, NULL, num_reals, reals);
383 }
384
385 /*
386 * If dest is NULL, then no default (that exists) is set, so we
387 * need to set a default if one exists...
388 */
389
390 if (dest == NULL && defprinter != NULL)
391 {
392 for (i = 0; i < num_dests; i ++)
393 (*dests)[i].is_default = 0;
394
395 if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
396 dest->is_default = 1;
397 }
398
399 /*
400 * Free memory...
401 */
402
403 free(reals);
404 }
405
406 /*
407 * Return the number of destinations...
408 */
409
410 return (num_dests);
411}
412
413
414/*
415 * 'cupsSetDests()' - Save the list of destinations for the default server.
416 *
417 * This function saves the destinations to /etc/cups/lpoptions when run
b423cd4c 418 * as root and ~/.cups/lpoptions when run as a normal user.
ef416fc2 419 */
420
421void
422cupsSetDests(int num_dests, /* I - Number of destinations */
423 cups_dest_t *dests) /* I - Destinations */
424{
425 http_t *http; /* HTTP connection */
426
427
428 /*
429 * Connect to the CUPS server and save the destination list and options...
430 */
431
432 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
433
434 cupsSetDests2(http, num_dests, dests);
435
436 if (http)
437 httpClose(http);
438}
439
440
441/*
442 * 'cupsSetDests2()' - Save the list of destinations for the specified server.
443 *
444 * This function saves the destinations to /etc/cups/lpoptions when run
b423cd4c 445 * as root and ~/.cups/lpoptions when run as a normal user.
ef416fc2 446 *
447 * @since CUPS 1.1.21@
448 */
449
450int /* O - 0 on success, -1 on error */
451cupsSetDests2(http_t *http, /* I - HTTP connection */
452 int num_dests, /* I - Number of destinations */
453 cups_dest_t *dests) /* I - Destinations */
454{
455 int i, j; /* Looping vars */
456 int wrote; /* Wrote definition? */
457 cups_dest_t *dest; /* Current destination */
458 cups_option_t *option; /* Current option */
459 FILE *fp; /* File pointer */
460 const char *home; /* HOME environment variable */
461 char filename[1024]; /* lpoptions file */
462 int num_temps; /* Number of temporary destinations */
463 cups_dest_t *temps, /* Temporary destinations */
464 *temp; /* Current temporary dest */
465 const char *val; /* Value of temporary option */
466 _cups_globals_t *cg = _cupsGlobals(); /* Global data */
467
468
469 /*
470 * Range check the input...
471 */
472
473 if (!http || !num_dests || !dests)
474 return (-1);
475
476 /*
477 * Get the server destinations...
478 */
479
480 num_temps = cups_get_sdests(http, CUPS_GET_PRINTERS, 0, &temps);
481 num_temps = cups_get_sdests(http, CUPS_GET_CLASSES, num_temps, &temps);
482
483 /*
484 * Figure out which file to write to...
485 */
486
487 snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
488
489#ifndef WIN32
490 if (getuid())
491 {
492 /*
493 * Merge in server defaults...
494 */
495
496 num_temps = cups_get_dests(filename, num_temps, &temps);
497
498 /*
499 * Point to user defaults...
500 */
501
502 if ((home = getenv("HOME")) != NULL)
b423cd4c 503 {
504 /*
505 * Remove the old ~/.lpoptions file...
506 */
507
ef416fc2 508 snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
b423cd4c 509 unlink(filename);
510
511 /*
512 * Create ~/.cups subdirectory...
513 */
514
515 snprintf(filename, sizeof(filename), "%s/.cups", home);
516 if (access(filename, 0))
517 mkdir(filename, 0700);
518
519 snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
520 }
ef416fc2 521 }
522#endif /* !WIN32 */
523
524 /*
525 * Try to open the file...
526 */
527
528 if ((fp = fopen(filename, "w")) == NULL)
529 {
530 cupsFreeDests(num_temps, temps);
531 return (-1);
532 }
533
d6ae789d 534#ifndef WIN32
535 /*
536 * Set the permissions to 0644 when saving to the /etc/cups/lpoptions
537 * file...
538 */
539
540 if (!getuid())
541 fchmod(fileno(fp), 0644);
542#endif /* !WIN32 */
543
ef416fc2 544 /*
545 * Write each printer; each line looks like:
546 *
547 * Dest name[/instance] options
548 * Default name[/instance] options
549 */
550
551 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
552 if (dest->instance != NULL || dest->num_options != 0 || dest->is_default)
553 {
554 if (dest->is_default)
555 {
556 fprintf(fp, "Default %s", dest->name);
557 if (dest->instance)
558 fprintf(fp, "/%s", dest->instance);
559
560 wrote = 1;
561 }
562 else
563 wrote = 0;
564
565 if ((temp = cupsGetDest(dest->name, dest->instance, num_temps, temps)) == NULL)
566 temp = cupsGetDest(dest->name, NULL, num_temps, temps);
567
568 for (j = dest->num_options, option = dest->options; j > 0; j --, option ++)
569 {
570 /*
571 * See if the server/global options match these; if so, don't
572 * write 'em.
573 */
574
575 if (temp && (val = cupsGetOption(option->name, temp->num_options,
576 temp->options)) != NULL)
577 {
b423cd4c 578 if (!strcasecmp(val, option->value))
ef416fc2 579 continue;
580 }
581
582 /*
583 * Options don't match, write to the file...
584 */
585
586 if (!wrote)
587 {
588 fprintf(fp, "Dest %s", dest->name);
589 if (dest->instance)
590 fprintf(fp, "/%s", dest->instance);
591 wrote = 1;
592 }
593
594 if (option->value[0])
595 {
596 if (strchr(option->value, ' ') != NULL)
597 fprintf(fp, " %s=\"%s\"", option->name, option->value);
598 else
599 fprintf(fp, " %s=%s", option->name, option->value);
600 }
601 else
602 fprintf(fp, " %s", option->name);
603 }
604
605 if (wrote)
606 fputs("\n", fp);
607 }
608
609 /*
fa73b229 610 * Free the temporary destinations and close the file...
ef416fc2 611 */
612
613 cupsFreeDests(num_temps, temps);
614
fa73b229 615 fclose(fp);
616
617#ifdef HAVE_NOTIFY_POST
ef416fc2 618 /*
fa73b229 619 * Send a notification so that MacOS X applications can know about the
620 * change, too.
ef416fc2 621 */
622
fa73b229 623 notify_post("com.apple.printerListChange");
624#endif /* HAVE_NOTIFY_POST */
ef416fc2 625
626 return (0);
627}
628
629
630/*
631 * 'cups_get_dests()' - Get destinations from a file.
632 */
633
634static int /* O - Number of destinations */
635cups_get_dests(const char *filename, /* I - File to read from */
636 int num_dests, /* I - Number of destinations */
637 cups_dest_t **dests) /* IO - Destinations */
638{
639 int i; /* Looping var */
640 cups_dest_t *dest; /* Current destination */
641 FILE *fp; /* File pointer */
642 char line[8192], /* Line from file */
643 *lineptr, /* Pointer into line */
644 *name, /* Name of destination/option */
645 *instance; /* Instance of destination */
646 const char *printer; /* PRINTER or LPDEST */
647
648
649 /*
650 * Check environment variables...
651 */
652
653 if ((printer = getenv("LPDEST")) == NULL)
654 if ((printer = getenv("PRINTER")) != NULL)
655 if (strcmp(printer, "lp") == 0)
656 printer = NULL;
657
658 /*
659 * Try to open the file...
660 */
661
662 if ((fp = fopen(filename, "r")) == NULL)
663 return (num_dests);
664
665 /*
666 * Read each printer; each line looks like:
667 *
668 * Dest name[/instance] options
669 * Default name[/instance] options
670 */
671
672 while (fgets(line, sizeof(line), fp) != NULL)
673 {
674 /*
675 * See what type of line it is...
676 */
677
678 if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4] & 255))
679 lineptr = line + 4;
680 else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7] & 255))
681 lineptr = line + 7;
682 else
683 continue;
684
685 /*
686 * Skip leading whitespace...
687 */
688
689 while (isspace(*lineptr & 255))
690 lineptr ++;
691
692 if (!*lineptr)
693 continue;
694
695 name = lineptr;
696
697 /*
698 * Search for an instance...
699 */
700
701 while (!isspace(*lineptr & 255) && *lineptr && *lineptr != '/')
702 lineptr ++;
703
704 if (!*lineptr)
705 continue;
706
707 if (*lineptr == '/')
708 {
709 /*
710 * Found an instance...
711 */
712
713 *lineptr++ = '\0';
714 instance = lineptr;
715
716 /*
717 * Search for an instance...
718 */
719
720 while (!isspace(*lineptr & 255) && *lineptr)
721 lineptr ++;
722 }
723 else
724 instance = NULL;
725
726 *lineptr++ = '\0';
727
728 /*
729 * See if the primary instance of the destination exists; if not,
730 * ignore this entry and move on...
731 */
732
733 if (cupsGetDest(name, NULL, num_dests, *dests) == NULL)
734 continue;
735
736 /*
737 * Add the destination...
738 */
739
740 num_dests = cupsAddDest(name, instance, num_dests, dests);
741
742 if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL)
743 {
744 /*
745 * Out of memory!
746 */
747
748 fclose(fp);
749 return (num_dests);
750 }
751
752 /*
753 * Add options until we hit the end of the line...
754 */
755
756 dest->num_options = cupsParseOptions(lineptr, dest->num_options,
757 &(dest->options));
758
759 /*
760 * Set this as default if needed...
761 */
762
763 if (strncasecmp(line, "default", 7) == 0 && printer == NULL)
764 {
765 for (i = 0; i < num_dests; i ++)
766 (*dests)[i].is_default = 0;
767
768 dest->is_default = 1;
769 }
770 }
771
772 /*
773 * Close the file and return...
774 */
775
776 fclose(fp);
777
778 return (num_dests);
779}
780
781
782/*
783 * 'cups_get_sdests()' - Get destinations from a server.
784 */
785
786static int /* O - Number of destinations */
787cups_get_sdests(http_t *http, /* I - HTTP connection */
788 ipp_op_t op, /* I - get-printers or get-classes */
789 int num_dests, /* I - Number of destinations */
790 cups_dest_t **dests) /* IO - Destinations */
791{
fa73b229 792 int i; /* Looping var */
ef416fc2 793 cups_dest_t *dest; /* Current destination */
794 ipp_t *request, /* IPP Request */
795 *response; /* IPP Response */
796 ipp_attribute_t *attr; /* Current attribute */
fa73b229 797 int accepting, /* printer-is-accepting-jobs attribute */
798 shared, /* printer-is-shared attribute */
799 state, /* printer-state attribute */
800 change_time, /* printer-state-change-time attribute */
801 type; /* printer-type attribute */
802 const char *info, /* printer-info attribute */
803 *make_model, /* printer-make-and-model attribute */
804 *name; /* printer-name attribute */
805 char job_sheets[1024], /* job-sheets option */
806 reasons[1024], /* printer-state-reasons attribute */
807 *rptr, /* Pointer into reasons string */
808 temp[255]; /* Temporary string for numbers */
ef416fc2 809 static const char * const pattrs[] = /* Attributes we're interested in */
810 {
fa73b229 811 "job-sheets-default",
812 "printer-info",
813 "printer-is-accepting-jobs",
814 "printer-is-shared",
815 "printer-make-and-model",
ef416fc2 816 "printer-name",
fa73b229 817 "printer-state",
818 "printer-state-change-time",
819 "printer-state-reasons",
820 "printer-type"
ef416fc2 821 };
822
823
824 /*
825 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
826 * the following attributes:
827 *
828 * attributes-charset
829 * attributes-natural-language
fa73b229 830 * requesting-user-name
ef416fc2 831 */
832
fa73b229 833 request = ippNewRequest(op);
ef416fc2 834
835 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
836 "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
837 NULL, pattrs);
838
fa73b229 839 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
840 "requesting-user-name", NULL, cupsUser());
841
ef416fc2 842 /*
843 * Do the request and get back a response...
844 */
845
846 if ((response = cupsDoRequest(http, request, "/")) != NULL)
847 {
848 for (attr = response->attrs; attr != NULL; attr = attr->next)
849 {
850 /*
851 * Skip leading attributes until we hit a printer...
852 */
853
854 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
855 attr = attr->next;
856
857 if (attr == NULL)
858 break;
859
860 /*
861 * Pull the needed attributes from this job...
862 */
863
fa73b229 864 accepting = 0;
865 change_time = 0;
866 info = NULL;
867 make_model = NULL;
868 name = NULL;
869 shared = 1;
870 state = IPP_PRINTER_IDLE;
871 type = CUPS_PRINTER_LOCAL;
ef416fc2 872
873 strcpy(job_sheets, "");
fa73b229 874 strcpy(reasons, "");
ef416fc2 875
876 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
877 {
fa73b229 878 if (!strcmp(attr->name, "job-sheets-default") &&
ef416fc2 879 (attr->value_tag == IPP_TAG_KEYWORD ||
880 attr->value_tag == IPP_TAG_NAME))
881 {
882 if (attr->num_values == 2)
883 snprintf(job_sheets, sizeof(job_sheets), "%s,%s",
884 attr->values[0].string.text, attr->values[1].string.text);
885 else
fa73b229 886 strlcpy(job_sheets, attr->values[0].string.text,
887 sizeof(job_sheets));
ef416fc2 888 }
fa73b229 889 else if (!strcmp(attr->name, "printer-info") &&
890 attr->value_tag == IPP_TAG_TEXT)
891 info = attr->values[0].string.text;
892 else if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
893 attr->value_tag == IPP_TAG_BOOLEAN)
894 accepting = attr->values[0].boolean;
895 else if (!strcmp(attr->name, "printer-is-shared") &&
896 attr->value_tag == IPP_TAG_BOOLEAN)
897 shared = attr->values[0].boolean;
898 else if (!strcmp(attr->name, "printer-make-and-model") &&
899 attr->value_tag == IPP_TAG_TEXT)
900 make_model = attr->values[0].string.text;
901 else if (!strcmp(attr->name, "printer-name") &&
902 attr->value_tag == IPP_TAG_NAME)
903 name = attr->values[0].string.text;
904 else if (!strcmp(attr->name, "printer-state") &&
905 attr->value_tag == IPP_TAG_ENUM)
906 state = attr->values[0].integer;
907 else if (!strcmp(attr->name, "printer-state-change-time") &&
908 attr->value_tag == IPP_TAG_INTEGER)
909 change_time = attr->values[0].integer;
910 else if (!strcmp(attr->name, "printer-state-reasons") &&
911 attr->value_tag == IPP_TAG_KEYWORD)
912 {
913 strlcpy(reasons, attr->values[0].string.text, sizeof(reasons));
914 for (i = 1, rptr = reasons + strlen(reasons);
915 i < attr->num_values;
916 i ++)
917 {
918 snprintf(rptr, sizeof(reasons) - (rptr - reasons), ",%s",
919 attr->values[i].string.text);
920 rptr += strlen(rptr);
921 }
922 }
923 else if (!strcmp(attr->name, "printer-type") &&
924 attr->value_tag == IPP_TAG_ENUM)
925 type = attr->values[0].integer;
ef416fc2 926
927 attr = attr->next;
928 }
929
930 /*
931 * See if we have everything needed...
932 */
933
934 if (!name)
935 {
936 if (attr == NULL)
937 break;
938 else
939 continue;
940 }
941
942 num_dests = cupsAddDest(name, NULL, num_dests, dests);
943
944 if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL)
fa73b229 945 {
ef416fc2 946 if (job_sheets[0])
fa73b229 947 dest->num_options = cupsAddOption("job-sheets", job_sheets,
948 dest->num_options,
949 &(dest->options));
950
951 if (info)
952 dest->num_options = cupsAddOption("printer-info", info,
953 dest->num_options,
954 &(dest->options));
955
956 sprintf(temp, "%d", accepting);
957 dest->num_options = cupsAddOption("printer-is-accepting-jobs", temp,
958 dest->num_options,
959 &(dest->options));
960
961 sprintf(temp, "%d", shared);
962 dest->num_options = cupsAddOption("printer-is-shared", temp,
963 dest->num_options,
964 &(dest->options));
965
966 if (make_model)
967 dest->num_options = cupsAddOption("printer-make-and-model",
968 make_model, dest->num_options,
ef416fc2 969 &(dest->options));
970
fa73b229 971 sprintf(temp, "%d", state);
972 dest->num_options = cupsAddOption("printer-state", temp,
973 dest->num_options,
974 &(dest->options));
975
976 if (change_time)
977 {
978 sprintf(temp, "%d", change_time);
979 dest->num_options = cupsAddOption("printer-state-change-time", temp,
980 dest->num_options,
981 &(dest->options));
982 }
983
984 if (reasons[0])
985 dest->num_options = cupsAddOption("printer-state-reasons", reasons,
986 dest->num_options,
987 &(dest->options));
988
989 sprintf(temp, "%d", type);
990 dest->num_options = cupsAddOption("printer-type", temp,
991 dest->num_options,
992 &(dest->options));
993 }
994
ef416fc2 995 if (attr == NULL)
996 break;
997 }
998
999 ippDelete(response);
1000 }
1001
1002 /*
1003 * Return the count...
1004 */
1005
1006 return (num_dests);
1007}
1008
1009
1010/*
c07d5b2d 1011 * End of "$Id: dest.c 177 2006-06-21 00:20:03Z jlovell $".
ef416fc2 1012 */