]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpadmin.c
Load cups into easysw/current.
[thirdparty/cups.git] / systemv / lpadmin.c
CommitLineData
ef416fc2 1/*
b423cd4c 2 * "$Id: lpadmin.c 5154 2006-02-23 01:36:15Z mike $"
ef416fc2 3 *
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * main() - Parse options and configure the scheduler.
27 * add_printer_to_class() - Add a printer to a class.
28 * default_printer() - Set the default printing destination.
29 * delete_printer() - Delete a printer from the system...
30 * delete_printer_from_class() - Delete a printer from a class.
31 * enable_printer() - Enable a printer...
32 * set_printer_device() - Set the device-uri attribute.
33 * set_printer_file() - Set the interface script or PPD file.
34 * set_printer_info() - Set the printer description string.
35 * set_printer_location() - Set the printer location string.
36 * set_printer_model() - Set the driver model file.
37 * set_printer_options() - Set the printer options.
38 * validate_name() - Make sure the printer name only contains
39 * valid chars...
40 */
41
42/*
43 * Include necessary headers...
44 */
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <ctype.h>
49#include <errno.h>
50#include <cups/string.h>
51#include <cups/cups.h>
52#include <cups/i18n.h>
53#include <cups/debug.h>
54#ifdef HAVE_LIBZ
55# include <zlib.h>
56#endif /* HAVE_LIBZ */
57
58
59/*
60 * Local functions...
61 */
62
63static int add_printer_to_class(http_t *, char *, char *);
64static int default_printer(http_t *, char *);
65static int delete_printer(http_t *, char *);
66static int delete_printer_from_class(http_t *, char *, char *);
67static int enable_printer(http_t *, char *);
68static char *get_line(char *, int, FILE *fp);
69static int set_printer_device(http_t *, char *, char *);
70static int set_printer_file(http_t *, char *, char *);
71static int set_printer_info(http_t *, char *, char *);
72static int set_printer_location(http_t *, char *, char *);
73static int set_printer_model(http_t *, char *, char *);
74static int set_printer_options(http_t *, char *, int, cups_option_t *);
75static int validate_name(const char *);
76
77
78/*
79 * 'main()' - Parse options and configure the scheduler.
80 */
81
82int
83main(int argc, /* I - Number of command-line arguments */
84 char *argv[]) /* I - Command-line arguments */
85{
86 int i; /* Looping var */
87 http_t *http; /* Connection to server */
88 char *printer, /* Destination printer */
89 *pclass, /* Printer class name */
90 *val; /* Pointer to allow/deny value */
91 int num_options; /* Number of options */
92 cups_option_t *options; /* Options */
93
94
95 http = NULL;
96 printer = NULL;
97 num_options = 0;
98 options = NULL;
99
100 for (i = 1; i < argc; i ++)
101 if (argv[i][0] == '-')
102 switch (argv[i][1])
103 {
104 case 'c' : /* Add printer to class */
105 if (!http)
106 {
107 http = httpConnectEncrypt(cupsServer(), ippPort(),
108 cupsEncryption());
109
110 if (http == NULL)
111 {
fa73b229 112 _cupsLangPrintf(stderr,
ef416fc2 113 _("lpadmin: Unable to connect to server: %s\n"),
114 strerror(errno));
115 return (1);
116 }
117 }
118
119 if (printer == NULL)
120 {
fa73b229 121 _cupsLangPuts(stderr,
ef416fc2 122 _("lpadmin: Unable to add a printer to the class:\n"
123 " You must specify a printer name "
124 "first!\n"));
125 return (1);
126 }
127
128 if (argv[i][2])
129 pclass = argv[i] + 2;
130 else
131 {
132 i ++;
133
134 if (i >= argc)
135 {
fa73b229 136 _cupsLangPuts(stderr,
ef416fc2 137 _("lpadmin: Expected class name after \'-c\' "
138 "option!\n"));
139 return (1);
140 }
141
142 pclass = argv[i];
143 }
144
145 if (!validate_name(pclass))
146 {
fa73b229 147 _cupsLangPuts(stderr,
ef416fc2 148 _("lpadmin: Class name can only contain printable "
149 "characters!\n"));
150 return (1);
151 }
152
153 if (add_printer_to_class(http, printer, pclass))
154 return (1);
155 break;
156
157 case 'd' : /* Set as default destination */
158 if (!http)
159 {
160 http = httpConnectEncrypt(cupsServer(), ippPort(),
161 cupsEncryption());
162
163 if (http == NULL)
164 {
fa73b229 165 _cupsLangPrintf(stderr,
ef416fc2 166 _("lpadmin: Unable to connect to server: %s\n"),
167 strerror(errno));
168 return (1);
169 }
170 }
171
172 if (argv[i][2])
173 printer = argv[i] + 2;
174 else
175 {
176 i ++;
177
178 if (i >= argc)
179 {
fa73b229 180 _cupsLangPuts(stderr,
ef416fc2 181 _("lpadmin: Expected printer name after \'-d\' "
182 "option!\n"));
183 return (1);
184 }
185
186 printer = argv[i];
187 }
188
189 if (!validate_name(printer))
190 {
fa73b229 191 _cupsLangPuts(stderr,
ef416fc2 192 _("lpadmin: Printer name can only contain "
193 "printable characters!\n"));
194 return (1);
195 }
196
197 if (default_printer(http, printer))
198 return (1);
199
200 i = argc;
201 break;
202
203 case 'h' : /* Connect to host */
204 if (http)
205 {
206 httpClose(http);
207 http = NULL;
208 }
209
210 if (argv[i][2] != '\0')
211 cupsSetServer(argv[i] + 2);
212 else
213 {
214 i ++;
215
216 if (i >= argc)
217 {
fa73b229 218 _cupsLangPuts(stderr,
ef416fc2 219 _("lpadmin: Expected hostname after \'-h\' "
220 "option!\n"));
221 return (1);
222 }
223
224 cupsSetServer(argv[i]);
225 }
226 break;
227
228 case 'i' : /* Use the specified interface script */
229 if (!http)
230 {
231 http = httpConnectEncrypt(cupsServer(), ippPort(),
232 cupsEncryption());
233
234 if (http == NULL)
235 {
fa73b229 236 _cupsLangPrintf(stderr,
ef416fc2 237 _("lpadmin: Unable to connect to server: %s\n"),
238 strerror(errno));
239 return (1);
240 }
241 }
242
243 if (printer == NULL)
244 {
fa73b229 245 _cupsLangPuts(stderr,
ef416fc2 246 _("lpadmin: Unable to set the interface script:\n"
247 " You must specify a printer name "
248 "first!\n"));
249 return (1);
250 }
251
252 if (argv[i][2])
253 {
254 if (set_printer_file(http, printer, argv[i] + 2))
255 return (1);
256 }
257 else
258 {
259 i ++;
260
261 if (i >= argc)
262 {
fa73b229 263 _cupsLangPuts(stderr,
ef416fc2 264 _("lpadmin: Expected interface after \'-i\' "
265 "option!\n"));
266 return (1);
267 }
268
269 if (set_printer_file(http, printer, argv[i]))
270 return (1);
271 }
272 break;
273
274 case 'E' : /* Enable the printer */
275 if (printer == NULL)
276 {
277#ifdef HAVE_SSL
278 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
279
280 if (http)
281 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
282#else
fa73b229 283 _cupsLangPrintf(stderr,
ef416fc2 284 _("%s: Sorry, no encryption support compiled in!\n"),
285 argv[0]);
286#endif /* HAVE_SSL */
287 break;
288 }
289
290 if (!http)
291 {
292 http = httpConnectEncrypt(cupsServer(), ippPort(),
293 cupsEncryption());
294
295 if (http == NULL)
296 {
fa73b229 297 _cupsLangPrintf(stderr,
ef416fc2 298 _("lpadmin: Unable to connect to server: %s\n"),
299 strerror(errno));
300 return (1);
301 }
302 }
303
304 if (enable_printer(http, printer))
305 return (1);
306 break;
307
308 case 'm' : /* Use the specified standard script/PPD file */
309 if (!http)
310 {
311 http = httpConnectEncrypt(cupsServer(), ippPort(),
312 cupsEncryption());
313
314 if (http == NULL)
315 {
fa73b229 316 _cupsLangPrintf(stderr,
ef416fc2 317 _("lpadmin: Unable to connect to server: %s\n"),
318 strerror(errno));
319 return (1);
320 }
321 }
322
323 if (printer == NULL)
324 {
fa73b229 325 _cupsLangPuts(stderr,
ef416fc2 326 _("lpadmin: Unable to set the interface script or "
327 "PPD file:\n"
328 " You must specify a printer name "
329 "first!\n"));
330 return (1);
331 }
332
333 if (argv[i][2])
334 {
335 if (set_printer_model(http, printer, argv[i] + 2))
336 return (1);
337 }
338 else
339 {
340 i ++;
341
342 if (i >= argc)
343 {
fa73b229 344 _cupsLangPuts(stderr,
ef416fc2 345 _("lpadmin: Expected model after \'-m\' "
346 "option!\n"));
347 return (1);
348 }
349
350 if (set_printer_model(http, printer, argv[i]))
351 return (1);
352 }
353 break;
354
355 case 'o' : /* Set option */
356 if (argv[i][2])
357 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
358 else
359 {
360 i ++;
361
362 if (i >= argc)
363 {
fa73b229 364 _cupsLangPuts(stderr,
ef416fc2 365 _("lpadmin: Expected name=value after \'-o\' "
366 "option!\n"));
367 return (1);
368 }
369
370 num_options = cupsParseOptions(argv[i], num_options, &options);
371 }
372 break;
373
374 case 'p' : /* Add/modify a printer */
375 if (!http)
376 {
377 http = httpConnectEncrypt(cupsServer(), ippPort(),
378 cupsEncryption());
379
380 if (http == NULL)
381 {
fa73b229 382 _cupsLangPrintf(stderr,
ef416fc2 383 _("lpadmin: Unable to connect to server: %s\n"),
384 strerror(errno));
385 return (1);
386 }
387 }
388
389 if (argv[i][2])
390 printer = argv[i] + 2;
391 else
392 {
393 i ++;
394
395 if (i >= argc)
396 {
fa73b229 397 _cupsLangPuts(stderr,
ef416fc2 398 _("lpadmin: Expected printer after \'-p\' "
399 "option!\n"));
400 return (1);
401 }
402
403 printer = argv[i];
404 }
405
406 if (!validate_name(printer))
407 {
fa73b229 408 _cupsLangPuts(stderr,
ef416fc2 409 _("lpadmin: Printer name can only contain "
410 "printable characters!\n"));
411 return (1);
412 }
413 break;
414
415 case 'r' : /* Remove printer from class */
416 if (!http)
417 {
418 http = httpConnectEncrypt(cupsServer(), ippPort(),
419 cupsEncryption());
420
421 if (http == NULL)
422 {
fa73b229 423 _cupsLangPrintf(stderr,
ef416fc2 424 _("lpadmin: Unable to connect to server: %s\n"),
425 strerror(errno));
426 return (1);
427 }
428 }
429
430 if (printer == NULL)
431 {
fa73b229 432 _cupsLangPuts(stderr,
ef416fc2 433 _("lpadmin: Unable to remove a printer from the "
434 "class:\n"
435 " You must specify a printer name "
436 "first!\n"));
437 return (1);
438 }
439
440 if (argv[i][2])
441 pclass = argv[i] + 2;
442 else
443 {
444 i ++;
445
446 if (i >= argc)
447 {
fa73b229 448 _cupsLangPuts(stderr,
ef416fc2 449 _("lpadmin: Expected class after \'-r\' "
450 "option!\n"));
451 return (1);
452 }
453
454 pclass = argv[i];
455 }
456
457 if (!validate_name(pclass))
458 {
fa73b229 459 _cupsLangPuts(stderr,
ef416fc2 460 _("lpadmin: Class name can only contain printable "
461 "characters!\n"));
462 return (1);
463 }
464
465 if (delete_printer_from_class(http, printer, pclass))
466 return (1);
467 break;
468
469 case 'u' : /* Allow/deny users */
470 if (argv[i][2])
471 val = argv[i] + 2;
472 else
473 {
474 i ++;
475
476 if (i >= argc)
477 {
fa73b229 478 _cupsLangPuts(stderr,
ef416fc2 479 _("lpadmin: Expected allow/deny:userlist after "
480 "\'-u\' option!\n"));
481 return (1);
482 }
483
484 val = argv[i];
485 }
486
487 if (!strncasecmp(val, "allow:", 6))
488 num_options = cupsAddOption("requesting-user-name-allowed",
489 val + 6, num_options, &options);
490 else if (!strncasecmp(val, "deny:", 5))
491 num_options = cupsAddOption("requesting-user-name-denied",
492 val + 5, num_options, &options);
493 else
494 {
fa73b229 495 _cupsLangPrintf(stderr,
ef416fc2 496 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
497 val);
498 return (1);
499 }
500 break;
501
502 case 'v' : /* Set the device-uri attribute */
503 if (!http)
504 {
505 http = httpConnectEncrypt(cupsServer(), ippPort(),
506 cupsEncryption());
507
508 if (http == NULL)
509 {
fa73b229 510 _cupsLangPrintf(stderr,
ef416fc2 511 _("lpadmin: Unable to connect to server: %s\n"),
512 strerror(errno));
513 return (1);
514 }
515 }
516
517 if (printer == NULL)
518 {
fa73b229 519 _cupsLangPuts(stderr,
ef416fc2 520 _("lpadmin: Unable to set the device URI:\n"
521 " You must specify a printer name "
522 "first!\n"));
523 return (1);
524 }
525
526 if (argv[i][2])
527 {
528 if (set_printer_device(http, printer, argv[i] + 2))
529 return (1);
530 }
531 else
532 {
533 i ++;
534
535 if (i >= argc)
536 {
fa73b229 537 _cupsLangPuts(stderr,
ef416fc2 538 _("lpadmin: Expected device URI after \'-v\' "
539 "option!\n"));
540 return (1);
541 }
542
543 if (set_printer_device(http, printer, argv[i]))
544 return (1);
545 }
546 break;
547
548 case 'x' : /* Delete a printer */
549 if (!http)
550 {
551 http = httpConnectEncrypt(cupsServer(), ippPort(),
552 cupsEncryption());
553
554 if (http == NULL)
555 {
fa73b229 556 _cupsLangPrintf(stderr,
ef416fc2 557 _("lpadmin: Unable to connect to server: %s\n"),
558 strerror(errno));
559 return (1);
560 }
561 }
562
563 if (argv[i][2])
564 printer = argv[i] + 2;
565 else
566 {
567 i ++;
568
569 if (i >= argc)
570 {
fa73b229 571 _cupsLangPuts(stderr,
ef416fc2 572 _("lpadmin: Expected printer or class after "
573 "\'-x\' option!\n"));
574 return (1);
575 }
576
577 printer = argv[i];
578 }
579
580 if (!validate_name(printer))
581 {
fa73b229 582 _cupsLangPuts(stderr,
ef416fc2 583 _("lpadmin: Printer name can only contain "
584 "printable characters!\n"));
585 return (1);
586 }
587
588 if (delete_printer(http, printer))
589 return (1);
590
591 i = argc;
592 break;
593
594 case 'D' : /* Set the printer-info attribute */
595 if (!http)
596 {
597 http = httpConnectEncrypt(cupsServer(), ippPort(),
598 cupsEncryption());
599
600 if (http == NULL)
601 {
fa73b229 602 _cupsLangPrintf(stderr,
ef416fc2 603 _("lpadmin: Unable to connect to server: %s\n"),
604 strerror(errno));
605 return (1);
606 }
607 }
608
609 if (printer == NULL)
610 {
fa73b229 611 _cupsLangPuts(stderr,
ef416fc2 612 _("lpadmin: Unable to set the printer "
613 "description:\n"
614 " You must specify a printer name "
615 "first!\n"));
616 return (1);
617 }
618
619 if (argv[i][2])
620 {
621 if (set_printer_info(http, printer, argv[i] + 2))
622 return (1);
623 }
624 else
625 {
626 i ++;
627
628 if (i >= argc)
629 {
fa73b229 630 _cupsLangPuts(stderr,
ef416fc2 631 _("lpadmin: Expected description after "
632 "\'-D\' option!\n"));
633 return (1);
634 }
635
636 if (set_printer_info(http, printer, argv[i]))
637 return (1);
638 }
639 break;
640
641 case 'I' : /* Set the supported file types (ignored) */
642 i ++;
643
644 if (i >= argc)
645 {
fa73b229 646 _cupsLangPuts(stderr,
ef416fc2 647 _("lpadmin: Expected file type(s) after \'-I\' "
648 "option!\n"));
649 return (1);
650 }
651
fa73b229 652 _cupsLangPuts(stderr,
ef416fc2 653 _("lpadmin: Warning - content type list ignored!\n"));
654 break;
655
656 case 'L' : /* Set the printer-location attribute */
657 if (!http)
658 {
659 http = httpConnectEncrypt(cupsServer(), ippPort(),
660 cupsEncryption());
661
662 if (http == NULL)
663 {
fa73b229 664 _cupsLangPrintf(stderr,
ef416fc2 665 _("lpadmin: Unable to connect to server: %s\n"),
666 strerror(errno));
667 return (1);
668 }
669 }
670
671 if (printer == NULL)
672 {
fa73b229 673 _cupsLangPuts(stderr,
ef416fc2 674 _("lpadmin: Unable to set the printer location:\n"
675 " You must specify a printer name "
676 "first!\n"));
677 return (1);
678 }
679
680 if (argv[i][2])
681 {
682 if (set_printer_location(http, printer, argv[i] + 2))
683 return (1);
684 }
685 else
686 {
687 i ++;
688
689 if (i >= argc)
690 {
fa73b229 691 _cupsLangPuts(stderr,
ef416fc2 692 _("lpadmin: Expected location after \'-L\' "
693 "option!\n"));
694 return (1);
695 }
696
697 if (set_printer_location(http, printer, argv[i]))
698 return (1);
699 }
700 break;
701
702 case 'P' : /* Use the specified PPD file */
703 if (!http)
704 {
705 http = httpConnectEncrypt(cupsServer(), ippPort(),
706 cupsEncryption());
707
708 if (http == NULL)
709 {
fa73b229 710 _cupsLangPrintf(stderr,
ef416fc2 711 _("lpadmin: Unable to connect to server: %s\n"),
712 strerror(errno));
713 return (1);
714 }
715 }
716
717 if (printer == NULL)
718 {
fa73b229 719 _cupsLangPuts(stderr,
ef416fc2 720 _("lpadmin: Unable to set the PPD file:\n"
721 " You must specify a printer name "
722 "first!\n"));
723 return (1);
724 }
725
726 if (argv[i][2])
727 {
728 if (set_printer_file(http, printer, argv[i] + 2))
729 return (1);
730 }
731 else
732 {
733 i ++;
734
735 if (i >= argc)
736 {
fa73b229 737 _cupsLangPuts(stderr,
ef416fc2 738 _("lpadmin: Expected PPD after \'-P\' option!\n"));
739 return (1);
740 }
741
742 if (set_printer_file(http, printer, argv[i]))
743 return (1);
744 }
745 break;
746
747 default :
fa73b229 748 _cupsLangPrintf(stderr,
ef416fc2 749 _("lpadmin: Unknown option \'%c\'!\n"), argv[i][1]);
750 return (1);
751 }
752 else
753 {
fa73b229 754 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \'%s\'!\n"),
ef416fc2 755 argv[i]);
756 return (1);
757 }
758
759 /*
760 * Set options as needed...
761 */
762
763 if (num_options)
764 {
765 if (!http)
766 {
767 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
768
769 if (http == NULL)
770 {
fa73b229 771 _cupsLangPrintf(stderr,
ef416fc2 772 _("lpadmin: Unable to connect to server: %s\n"),
773 strerror(errno));
774 return (1);
775 }
776 }
777
778 if (printer == NULL)
779 {
fa73b229 780 _cupsLangPuts(stderr,
ef416fc2 781 _("lpadmin: Unable to set the printer options:\n"
782 " You must specify a printer name first!\n"));
783 return (1);
784 }
785
786 if (set_printer_options(http, printer, num_options, options))
787 return (1);
788 }
789
790 if (printer == NULL)
791 {
fa73b229 792 _cupsLangPuts(stdout,
ef416fc2 793 _("Usage:\n"
794 "\n"
795 " lpadmin [-h server] -d destination\n"
796 " lpadmin [-h server] -x destination\n"
797 " lpadmin [-h server] -p printer [-c add-class] "
798 "[-i interface] [-m model]\n"
799 " [-r remove-class] [-v device] "
800 "[-D description]\n"
801 " [-P ppd-file] [-o name=value]\n"
802 " [-u allow:user,user] "
803 "[-u deny:user,user]\n"
804 "\n"));
805 }
806
807 if (http)
808 httpClose(http);
809
810 return (0);
811}
812
813
814/*
815 * 'add_printer_to_class()' - Add a printer to a class.
816 */
817
818static int /* O - 0 on success, 1 on fail */
819add_printer_to_class(http_t *http, /* I - Server connection */
820 char *printer, /* I - Printer to add */
821 char *pclass) /* I - Class to add to */
822{
823 int i; /* Looping var */
824 ipp_t *request, /* IPP Request */
825 *response; /* IPP Response */
826 ipp_attribute_t *attr, /* Current attribute */
827 *members; /* Members in class */
ef416fc2 828 char uri[HTTP_MAX_URI]; /* URI for printer/class */
829
830
831 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
832 printer, pclass));
833
834 /*
835 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
836 * attributes:
837 *
838 * attributes-charset
839 * attributes-natural-language
840 * printer-uri
841 */
842
fa73b229 843 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
844
a4d04587 845 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
846 "localhost", 0, "/classes/%s", pclass);
ef416fc2 847 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
848 "printer-uri", NULL, uri);
849
850 /*
851 * Do the request and get back a response...
852 */
853
854 response = cupsDoRequest(http, request, "/");
855
856 /*
857 * Build a CUPS_ADD_CLASS request, which requires the following
858 * attributes:
859 *
860 * attributes-charset
861 * attributes-natural-language
862 * printer-uri
863 * member-uris
864 */
865
fa73b229 866 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 867
868 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
869 "printer-uri", NULL, uri);
870
871 /*
872 * See if the printer is already in the class...
873 */
874
875 if (response != NULL &&
876 (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
877 for (i = 0; i < members->num_values; i ++)
878 if (strcasecmp(printer, members->values[i].string.text) == 0)
879 {
fa73b229 880 _cupsLangPrintf(stderr,
881 _("lpadmin: Printer %s is already a member of class %s.\n"),
882 printer, pclass);
ef416fc2 883 ippDelete(request);
884 ippDelete(response);
885 return (0);
886 }
887
888 /*
889 * OK, the printer isn't part of the class, so add it...
890 */
891
a4d04587 892 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
893 "localhost", 0, "/printers/%s", printer);
ef416fc2 894
895 if (response != NULL &&
896 (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
897 {
898 /*
899 * Add the printer to the existing list...
900 */
901
902 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
903 "member-uris", members->num_values + 1, NULL, NULL);
904 for (i = 0; i < members->num_values; i ++)
905 attr->values[i].string.text = strdup(members->values[i].string.text);
906
907 attr->values[i].string.text = strdup(uri);
908 }
909 else
910 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL, uri);
911
912 /*
913 * Then send the request...
914 */
915
916 ippDelete(response);
917
918 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
919 {
fa73b229 920 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 921
922 return (1);
923 }
924 else if (response->request.status.status_code > IPP_OK_CONFLICT)
925 {
fa73b229 926 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 927
928 ippDelete(response);
929
930 return (1);
931 }
932 else
933 {
934 ippDelete(response);
935
936 return (0);
937 }
938}
939
940
941/*
942 * 'default_printer()' - Set the default printing destination.
943 */
944
945static int /* O - 0 on success, 1 on fail */
946default_printer(http_t *http, /* I - Server connection */
947 char *printer) /* I - Printer name */
948{
949 ipp_t *request, /* IPP Request */
950 *response; /* IPP Response */
ef416fc2 951 char uri[HTTP_MAX_URI]; /* URI for printer/class */
952
953
954 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
955
956 /*
957 * Build a CUPS_SET_DEFAULT request, which requires the following
958 * attributes:
959 *
960 * attributes-charset
961 * attributes-natural-language
962 * printer-uri
963 */
964
a4d04587 965 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
966 "localhost", 0, "/printers/%s", printer);
ef416fc2 967
fa73b229 968 request = ippNewRequest(CUPS_SET_DEFAULT);
ef416fc2 969
970 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
971 "printer-uri", NULL, uri);
972
973 /*
974 * Do the request and get back a response...
975 */
976
977 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
978 {
fa73b229 979 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 980
981 return (1);
982 }
983 else if (response->request.status.status_code > IPP_OK_CONFLICT)
984 {
fa73b229 985 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 986
987 ippDelete(response);
988
989 return (1);
990 }
991 else
992 {
993 ippDelete(response);
994
995 return (0);
996 }
997}
998
999
1000/*
1001 * 'delete_printer()' - Delete a printer from the system...
1002 */
1003
1004static int /* O - 0 on success, 1 on fail */
1005delete_printer(http_t *http, /* I - Server connection */
1006 char *printer) /* I - Printer to delete */
1007{
1008 ipp_t *request, /* IPP Request */
1009 *response; /* IPP Response */
ef416fc2 1010 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1011
1012
1013 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
1014
1015 /*
1016 * Build a CUPS_DELETE_PRINTER request, which requires the following
1017 * attributes:
1018 *
1019 * attributes-charset
1020 * attributes-natural-language
1021 * printer-uri
1022 */
1023
fa73b229 1024 request = ippNewRequest(CUPS_DELETE_PRINTER);
1025
a4d04587 1026 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1027 "localhost", 0, "/printers/%s", printer);
ef416fc2 1028 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1029 "printer-uri", NULL, uri);
1030
1031 /*
1032 * Do the request and get back a response...
1033 */
1034
1035 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1036 {
fa73b229 1037 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1038
1039 return (1);
1040 }
1041 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1042 {
fa73b229 1043 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1044
1045 ippDelete(response);
1046
1047 return (1);
1048 }
1049 else
1050 {
1051 ippDelete(response);
1052
1053 return (0);
1054 }
1055}
1056
1057
1058/*
1059 * 'delete_printer_from_class()' - Delete a printer from a class.
1060 */
1061
1062static int /* O - 0 on success, 1 on fail */
fa73b229 1063delete_printer_from_class(
1064 http_t *http, /* I - Server connection */
1065 char *printer, /* I - Printer to remove */
1066 char *pclass) /* I - Class to remove from */
ef416fc2 1067{
1068 int i, j, k; /* Looping vars */
1069 ipp_t *request, /* IPP Request */
1070 *response; /* IPP Response */
1071 ipp_attribute_t *attr, /* Current attribute */
1072 *members; /* Members in class */
ef416fc2 1073 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1074
1075
1076 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
1077 printer, pclass));
1078
1079 /*
1080 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1081 * attributes:
1082 *
1083 * attributes-charset
1084 * attributes-natural-language
1085 * printer-uri
1086 */
1087
fa73b229 1088 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
1089
a4d04587 1090 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1091 "localhost", 0, "/classes/%s", pclass);
ef416fc2 1092 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1093 "printer-uri", NULL, uri);
1094
1095 /*
1096 * Do the request and get back a response...
1097 */
1098
1099 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
1100 response->request.status.status_code == IPP_NOT_FOUND)
1101 {
fa73b229 1102 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1103
ef416fc2 1104 ippDelete(response);
fa73b229 1105
ef416fc2 1106 return (1);
1107 }
1108
1109 /*
1110 * See if the printer is already in the class...
1111 */
1112
1113 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
1114 {
fa73b229 1115 _cupsLangPuts(stderr, _("lpadmin: No member names were seen!\n"));
1116
ef416fc2 1117 ippDelete(response);
fa73b229 1118
ef416fc2 1119 return (1);
1120 }
1121
1122 for (i = 0; i < members->num_values; i ++)
fa73b229 1123 if (!strcasecmp(printer, members->values[i].string.text))
ef416fc2 1124 break;
1125
1126 if (i >= members->num_values)
1127 {
fa73b229 1128 _cupsLangPrintf(stderr,
1129 _("lpadmin: Printer %s is not a member of class %s.\n"),
1130 printer, pclass);
1131
ef416fc2 1132 ippDelete(response);
fa73b229 1133
ef416fc2 1134 return (1);
1135 }
1136
1137 if (members->num_values == 1)
1138 {
1139 /*
1140 * Build a CUPS_DELETE_CLASS request, which requires the following
1141 * attributes:
1142 *
1143 * attributes-charset
1144 * attributes-natural-language
1145 * printer-uri
1146 */
1147
fa73b229 1148 request = ippNewRequest(CUPS_DELETE_CLASS);
ef416fc2 1149
1150 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1151 "printer-uri", NULL, uri);
1152 }
1153 else
1154 {
1155 /*
1156 * Build a CUPS_ADD_CLASS request, which requires the following
1157 * attributes:
1158 *
1159 * attributes-charset
1160 * attributes-natural-language
1161 * printer-uri
1162 * member-uris
1163 */
1164
fa73b229 1165 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 1166
1167 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1168 "printer-uri", NULL, uri);
1169
1170 /*
1171 * Delete the printer from the class...
1172 */
1173
1174 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1175 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1176 "member-uris", members->num_values - 1, NULL, NULL);
1177
1178 for (j = 0, k = 0; j < members->num_values; j ++)
1179 if (j != i)
1180 attr->values[k ++].string.text = strdup(members->values[j].string.text);
1181 }
1182
1183 /*
1184 * Then send the request...
1185 */
1186
1187 ippDelete(response);
1188
1189 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1190 {
fa73b229 1191 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1192
ef416fc2 1193 return (1);
1194 }
1195 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1196 {
fa73b229 1197 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1198
1199 ippDelete(response);
1200
1201 return (1);
1202 }
1203 else
1204 {
1205 ippDelete(response);
1206
1207 return (0);
1208 }
1209}
1210
1211
1212/*
1213 * 'enable_printer()' - Enable a printer...
1214 */
1215
1216static int /* O - 0 on success, 1 on fail */
1217enable_printer(http_t *http, /* I - Server connection */
1218 char *printer) /* I - Printer to enable */
1219{
1220 ipp_t *request, /* IPP Request */
1221 *response; /* IPP Response */
ef416fc2 1222 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1223
1224
1225 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1226
1227 /*
1228 * Build a CUPS_ADD_PRINTER request, which requires the following
1229 * attributes:
1230 *
1231 * attributes-charset
1232 * attributes-natural-language
1233 * printer-uri
1234 * printer-state
1235 * printer-is-accepting-jobs
1236 */
1237
fa73b229 1238 request = ippNewRequest(CUPS_ADD_PRINTER);
1239
a4d04587 1240 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1241 "localhost", 0, "/printers/%s", printer);
ef416fc2 1242 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1243 "printer-uri", NULL, uri);
1244
1245 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1246 IPP_PRINTER_IDLE);
1247
1248 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1249
1250 /*
1251 * Do the request and get back a response...
1252 */
1253
1254 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1255 {
fa73b229 1256 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1257
ef416fc2 1258 return (1);
1259 }
1260 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1261 {
fa73b229 1262 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1263
1264 ippDelete(response);
1265
1266 return (1);
1267 }
1268 else
1269 {
1270 ippDelete(response);
1271
1272 return (0);
1273 }
1274}
1275
1276
1277/*
1278 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1279 */
1280
1281static char * /* O - Pointer to buf or NULL on EOF */
1282get_line(char *buf, /* I - Line buffer */
1283 int length, /* I - Length of buffer */
1284 FILE *fp) /* I - File to read from */
1285{
1286 char *bufptr; /* Pointer into buffer */
1287 int ch; /* Character from file */
1288
1289
1290 length --;
1291 bufptr = buf;
1292
1293 while ((ch = getc(fp)) != EOF)
1294 {
1295 if (ch == '\n')
1296 break;
1297 else if (ch == '\r')
1298 {
1299 /*
1300 * Look for LF...
1301 */
1302
1303 ch = getc(fp);
1304 if (ch != '\n' && ch != EOF)
1305 ungetc(ch, fp);
1306
1307 break;
1308 }
1309
1310 *bufptr++ = ch;
1311 length --;
1312 if (length == 0)
1313 break;
1314 }
1315
1316 *bufptr = '\0';
1317
1318 if (ch == EOF)
1319 return (NULL);
1320 else
1321 return (buf);
1322}
1323
1324
1325/*
1326 * 'set_printer_device()' - Set the device-uri attribute.
1327 */
1328
1329static int /* O - 0 on success, 1 on fail */
1330set_printer_device(http_t *http, /* I - Server connection */
1331 char *printer, /* I - Printer */
1332 char *device) /* I - New device URI */
1333{
1334 ipp_t *request, /* IPP Request */
1335 *response; /* IPP Response */
ef416fc2 1336 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1337
1338
1339 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http, printer,
1340 device));
1341
1342 /*
1343 * Build a CUPS_ADD_PRINTER request, which requires the following
1344 * attributes:
1345 *
1346 * attributes-charset
1347 * attributes-natural-language
1348 * printer-uri
1349 */
1350
fa73b229 1351 request = ippNewRequest(CUPS_ADD_PRINTER);
1352
a4d04587 1353 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1354 "localhost", 0, "/printers/%s", printer);
ef416fc2 1355 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1356 "printer-uri", NULL, uri);
1357
1358 /*
1359 * Add the device URI...
1360 */
1361
1362 if (device[0] == '/')
1363 {
1364 /*
1365 * Convert filename to URI...
1366 */
1367
fa73b229 1368 snprintf(uri, sizeof(uri), "file://%s", device);
ef416fc2 1369 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1370 uri);
1371 }
1372 else
1373 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1374 device);
1375
1376 /*
1377 * Do the request and get back a response...
1378 */
1379
1380 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1381 {
fa73b229 1382 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1383
ef416fc2 1384 return (1);
1385 }
1386 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1387 {
fa73b229 1388 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1389
1390 ippDelete(response);
1391
1392 return (1);
1393 }
1394 else
1395 {
1396 ippDelete(response);
1397
1398 return (0);
1399 }
1400}
1401
1402
1403/*
1404 * 'set_printer_file()' - Set the interface script or PPD file.
1405 */
1406
1407static int /* O - 0 on success, 1 on fail */
1408set_printer_file(http_t *http, /* I - Server connection */
1409 char *printer, /* I - Printer */
1410 char *file) /* I - PPD file or interface script */
1411{
ef416fc2 1412 ipp_t *request, /* IPP Request */
1413 *response; /* IPP Response */
ef416fc2 1414 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1415#ifdef HAVE_LIBZ
1416 char tempfile[1024]; /* Temporary filename */
1417 int fd; /* Temporary file */
1418 gzFile *gz; /* GZIP'd file */
1419 char buffer[8192]; /* Copy buffer */
1420 int bytes; /* Bytes in buffer */
1421
1422
1423 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http, printer,
1424 file));
1425
1426 /*
1427 * See if the file is gzip'd; if so, unzip it to a temporary file and
1428 * send the uncompressed file.
1429 */
1430
1431 if (!strcmp(file + strlen(file) - 3, ".gz"))
1432 {
1433 /*
1434 * Yes, the file is compressed; uncompress to a temp file...
1435 */
1436
1437 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1438 {
fa73b229 1439 _cupsLangPrintf(stderr,
ef416fc2 1440 _("lpadmin: Unable to create temporary file: %s\n"),
1441 strerror(errno));
1442 return (1);
1443 }
1444
1445 if ((gz = gzopen(file, "rb")) == NULL)
1446 {
fa73b229 1447 _cupsLangPrintf(stderr,
ef416fc2 1448 _("lpadmin: Unable to open file \"%s\": %s\n"),
1449 file, strerror(errno));
1450 close(fd);
1451 unlink(tempfile);
1452 return (1);
1453 }
1454
1455 while ((bytes = gzread(gz, buffer, sizeof(buffer))) > 0)
1456 write(fd, buffer, bytes);
1457
1458 close(fd);
1459 gzclose(gz);
1460
1461 file = tempfile;
1462 }
1463#endif /* HAVE_LIBZ */
1464
1465 /*
1466 * Build a CUPS_ADD_PRINTER request, which requires the following
1467 * attributes:
1468 *
1469 * attributes-charset
1470 * attributes-natural-language
1471 * printer-uri
1472 */
1473
fa73b229 1474 request = ippNewRequest(CUPS_ADD_PRINTER);
1475
a4d04587 1476 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1477 "localhost", 0, "/printers/%s", printer);
ef416fc2 1478 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1479 "printer-uri", NULL, uri);
1480
1481 /*
1482 * Do the request and get back a response...
1483 */
1484
fa73b229 1485 response = cupsDoFileRequest(http, request, "/admin/", file);
1486 ippDelete(response);
ef416fc2 1487
1488#ifdef HAVE_LIBZ
1489 /*
1490 * Remove the temporary file as needed...
1491 */
1492
1493 if (file == tempfile)
1494 unlink(tempfile);
1495#endif /* HAVE_LIBZ */
1496
fa73b229 1497 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1498 {
fa73b229 1499 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1500
1501 return (1);
1502 }
1503 else
1504 return (0);
1505}
1506
1507
1508/*
1509 * 'set_printer_info()' - Set the printer description string.
1510 */
1511
1512static int /* O - 0 on success, 1 on fail */
1513set_printer_info(http_t *http, /* I - Server connection */
1514 char *printer, /* I - Printer */
1515 char *info) /* I - New description string */
1516{
1517 ipp_t *request, /* IPP Request */
1518 *response; /* IPP Response */
ef416fc2 1519 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1520
1521
1522 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http, printer,
1523 info));
1524
1525 /*
1526 * Build a CUPS_ADD_PRINTER request, which requires the following
1527 * attributes:
1528 *
1529 * attributes-charset
1530 * attributes-natural-language
1531 * printer-uri
1532 */
1533
fa73b229 1534 request = ippNewRequest(CUPS_ADD_PRINTER);
1535
a4d04587 1536 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1537 "localhost", 0, "/printers/%s", printer);
ef416fc2 1538 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1539 "printer-uri", NULL, uri);
1540
1541 /*
1542 * Add the info string...
1543 */
1544
1545 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL,
1546 info);
1547
1548 /*
1549 * Do the request and get back a response...
1550 */
1551
1552 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1553 {
fa73b229 1554 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1555 return (1);
1556 }
1557 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1558 {
fa73b229 1559 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1560
1561 ippDelete(response);
1562
1563 return (1);
1564 }
1565 else
1566 {
1567 ippDelete(response);
1568
1569 return (0);
1570 }
1571}
1572
1573
1574/*
1575 * 'set_printer_location()' - Set the printer location string.
1576 */
1577
1578static int /* O - 0 on success, 1 on fail */
1579set_printer_location(http_t *http, /* I - Server connection */
1580 char *printer, /* I - Printer */
1581 char *location) /* I - New location string */
1582{
1583 ipp_t *request, /* IPP Request */
1584 *response; /* IPP Response */
ef416fc2 1585 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1586
1587
1588 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http, printer,
1589 location));
1590
1591 /*
1592 * Build a CUPS_ADD_PRINTER request, which requires the following
1593 * attributes:
1594 *
1595 * attributes-charset
1596 * attributes-natural-language
1597 * printer-uri
1598 */
1599
fa73b229 1600 request = ippNewRequest(CUPS_ADD_PRINTER);
1601
a4d04587 1602 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1603 "localhost", 0, "/printers/%s", printer);
ef416fc2 1604 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1605 "printer-uri", NULL, uri);
1606
1607 /*
1608 * Add the location string...
1609 */
1610
1611 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL,
1612 location);
1613
1614 /*
1615 * Do the request and get back a response...
1616 */
1617
1618 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1619 {
fa73b229 1620 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1621
1622 return (1);
1623 }
1624 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1625 {
fa73b229 1626 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1627
1628 ippDelete(response);
1629
1630 return (1);
1631 }
1632 else
1633 {
1634 ippDelete(response);
1635
1636 return (0);
1637 }
1638}
1639
1640
1641/*
1642 * 'set_printer_model()' - Set the driver model file.
1643 */
1644
1645static int /* O - 0 on success, 1 on fail */
1646set_printer_model(http_t *http, /* I - Server connection */
1647 char *printer, /* I - Printer */
1648 char *model) /* I - Driver model file */
1649{
1650 ipp_t *request, /* IPP Request */
1651 *response; /* IPP Response */
ef416fc2 1652 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1653
1654
1655 /*
1656 * Build a CUPS_ADD_PRINTER request, which requires the following
1657 * attributes:
1658 *
1659 * attributes-charset
1660 * attributes-natural-language
1661 * printer-uri
1662 * ppd-name
1663 */
1664
fa73b229 1665 request = ippNewRequest(CUPS_ADD_PRINTER);
1666
a4d04587 1667 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1668 "localhost", 0, "/printers/%s", printer);
ef416fc2 1669 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1670 "printer-uri", NULL, uri);
1671
1672 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1673 "ppd-name", NULL, model);
1674
1675 /*
1676 * Do the request and get back a response...
1677 */
1678
1679 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1680 {
fa73b229 1681 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1682
1683 return (1);
1684 }
1685 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1686 {
fa73b229 1687 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1688
1689 ippDelete(response);
1690
1691 return (1);
1692 }
1693 else
1694 {
1695 ippDelete(response);
1696
1697 return (0);
1698 }
1699}
1700
1701
1702/*
1703 * 'set_printer_options()' - Set the printer options.
1704 */
1705
1706static int /* O - 0 on success, 1 on fail */
fa73b229 1707set_printer_options(
1708 http_t *http, /* I - Server connection */
1709 char *printer, /* I - Printer */
1710 int num_options, /* I - Number of options */
1711 cups_option_t *options) /* I - Options */
ef416fc2 1712{
1713 ipp_t *request, /* IPP Request */
1714 *response; /* IPP Response */
1715 ipp_attribute_t *attr; /* IPP attribute */
ef416fc2 1716 ipp_op_t op; /* Operation to perform */
b423cd4c 1717 const char *ppdfile; /* PPD filename */
1718 int ppdchanged; /* PPD changed? */
1719 ppd_file_t *ppd; /* PPD file */
1720 ppd_choice_t *choice; /* Marked choice */
ef416fc2 1721 char uri[HTTP_MAX_URI], /* URI for printer/class */
1722 line[1024], /* Line from PPD file */
1723 keyword[1024], /* Keyword from Default line */
1724 *keyptr, /* Pointer into keyword... */
1725 tempfile[1024]; /* Temporary filename */
1726 FILE *in, /* PPD file */
1727 *out; /* Temporary file */
1728 int outfd; /* Temporary file descriptor */
b423cd4c 1729 const char *protocol; /* Old protocol option */
ef416fc2 1730
1731
1732 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http, printer,
1733 num_options, options));
1734
a4d04587 1735 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1736 "localhost", 0, "/printers/%s", printer);
ef416fc2 1737
1738 /*
1739 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1740 * attributes:
1741 *
1742 * attributes-charset
1743 * attributes-natural-language
1744 * printer-uri
1745 * requested-attributes
1746 */
1747
fa73b229 1748 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 1749
1750 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1751 "printer-uri", NULL, uri);
1752
1753 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1754 "requested-attributes", NULL, "printer-type");
1755
1756 /*
1757 * Do the request...
1758 */
1759
1760 op = CUPS_ADD_PRINTER;
1761
1762 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1763 {
1764 /*
1765 * See what kind of printer or class it is...
1766 */
1767
b423cd4c 1768 if ((attr = ippFindAttribute(response, "printer-type",
1769 IPP_TAG_ENUM)) != NULL)
ef416fc2 1770 {
1771 if (attr->values[0].integer & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
1772 {
1773 op = CUPS_ADD_CLASS;
a4d04587 1774 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1775 "localhost", 0, "/classes/%s", printer);
ef416fc2 1776 }
1777 }
1778
1779 ippDelete(response);
1780 }
1781
1782 /*
1783 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1784 * the following attributes:
1785 *
1786 * attributes-charset
1787 * attributes-natural-language
1788 * printer-uri
1789 * other options
1790 */
1791
fa73b229 1792 request = ippNewRequest(op);
ef416fc2 1793
1794 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1795 "printer-uri", NULL, uri);
1796
1797 /*
1798 * Add the options...
1799 */
1800
b423cd4c 1801 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1802
1803 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1804 {
1805 if (!strcasecmp(protocol, "bcp"))
1806 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "port-monitor",
1807 NULL, "bcp");
1808 else if (!strcasecmp(protocol, "tbcp"))
1809 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "port-monitor",
1810 NULL, "tbcp");
1811 }
ef416fc2 1812
1813 if (op == CUPS_ADD_PRINTER)
1814 ppdfile = cupsGetPPD(printer);
1815 else
1816 ppdfile = NULL;
1817
1818 if (ppdfile != NULL)
1819 {
1820 /*
1821 * Set default options in the PPD file...
1822 */
1823
b423cd4c 1824 ppd = ppdOpenFile(ppdfile);
1825 ppdMarkDefaults(ppd);
1826 cupsMarkOptions(ppd, num_options, options);
1827
ef416fc2 1828 if ((outfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1829 {
fa73b229 1830 _cupsLangPrintf(stderr,
ef416fc2 1831 _("lpadmin: Unable to create temporary file - %s\n"),
1832 strerror(errno));
1833 ippDelete(request);
1834 unlink(ppdfile);
1835 return (1);
1836 }
1837
1838 if ((in = fopen(ppdfile, "rb")) == NULL)
1839 {
fa73b229 1840 _cupsLangPrintf(stderr,
ef416fc2 1841 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1842 ppdfile, strerror(errno));
1843 ippDelete(request);
1844 unlink(ppdfile);
1845 close(outfd);
1846 unlink(tempfile);
1847 return (1);
1848 }
1849
b423cd4c 1850 out = fdopen(outfd, "wb");
1851 ppdchanged = 0;
ef416fc2 1852
1853 while (get_line(line, sizeof(line), in) != NULL)
1854 {
b423cd4c 1855 if (strncmp(line, "*Default", 8))
ef416fc2 1856 fprintf(out, "%s\n", line);
1857 else
1858 {
1859 /*
1860 * Get default option name...
1861 */
1862
1863 strlcpy(keyword, line + 8, sizeof(keyword));
1864
1865 for (keyptr = keyword; *keyptr; keyptr ++)
1866 if (*keyptr == ':' || isspace(*keyptr & 255))
1867 break;
1868
b423cd4c 1869 *keyptr++ = '\0';
1870 while (isspace(*keyptr & 255))
1871 keyptr ++;
1872
1873 if (!strcmp(keyword, "PageRegion") ||
1874 !strcmp(keyword, "PageSize") ||
1875 !strcmp(keyword, "PaperDimension") ||
1876 !strcmp(keyword, "ImageableArea"))
1877 {
1878 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1879 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1880 }
ef416fc2 1881 else
b423cd4c 1882 choice = ppdFindMarkedChoice(ppd, keyword);
ef416fc2 1883
b423cd4c 1884 if (choice && strcmp(choice->choice, keyptr))
1885 {
1886 fprintf(out, "*Default%s: %s\n", keyword, choice->choice);
1887 ppdchanged = 1;
1888 }
ef416fc2 1889 else
1890 fprintf(out, "%s\n", line);
1891 }
1892 }
1893
ef416fc2 1894 fclose(in);
1895 fclose(out);
1896 close(outfd);
b423cd4c 1897 ppdClose(ppd);
ef416fc2 1898
1899 /*
1900 * Do the request...
1901 */
1902
b423cd4c 1903 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1904 ppdchanged ? tempfile : NULL));
ef416fc2 1905
1906 /*
1907 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1908 * lpadmin)
1909 */
1910
1911 unlink(ppdfile);
1912 unlink(tempfile);
1913 }
1914 else
1915 {
1916 /*
1917 * No PPD file - just set the options...
1918 */
1919
b423cd4c 1920 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1921 }
1922
1923 /*
1924 * Check the response...
1925 */
1926
fa73b229 1927 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1928 {
fa73b229 1929 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1930
1931 return (1);
1932 }
1933 else
ef416fc2 1934 return (0);
ef416fc2 1935}
1936
1937
1938/*
1939 * 'validate_name()' - Make sure the printer name only contains valid chars.
1940 */
1941
fa73b229 1942static int /* O - 0 if name is no good, 1 if name is good */
1943validate_name(const char *name) /* I - Name to check */
ef416fc2 1944{
fa73b229 1945 const char *ptr; /* Pointer into name */
ef416fc2 1946
1947
1948 /*
1949 * Scan the whole name...
1950 */
1951
1952 for (ptr = name; *ptr; ptr ++)
1953 if (*ptr == '@')
1954 break;
1955 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1956 *ptr == '#')
1957 return (0);
1958
1959 /*
1960 * All the characters are good; validate the length, too...
1961 */
1962
1963 return ((ptr - name) < 128);
1964}
1965
1966
1967/*
b423cd4c 1968 * End of "$Id: lpadmin.c 5154 2006-02-23 01:36:15Z mike $".
ef416fc2 1969 */