]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpadmin.c
Load cups into easysw/current.
[thirdparty/cups.git] / systemv / lpadmin.c
1 /*
2 * "$Id: lpadmin.c 5545 2006-05-18 21:00:56Z mike $"
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
63 static int add_printer_to_class(http_t *, char *, char *);
64 static int default_printer(http_t *, char *);
65 static int delete_printer(http_t *, char *);
66 static int delete_printer_from_class(http_t *, char *, char *);
67 static int enable_printer(http_t *, char *);
68 static char *get_line(char *, int, FILE *fp);
69 static int set_printer_device(http_t *, char *, char *);
70 static int set_printer_file(http_t *, char *, char *);
71 static int set_printer_info(http_t *, char *, char *);
72 static int set_printer_location(http_t *, char *, char *);
73 static int set_printer_model(http_t *, char *, char *);
74 static int set_printer_options(http_t *, char *, int, cups_option_t *);
75 static int validate_name(const char *);
76
77
78 /*
79 * 'main()' - Parse options and configure the scheduler.
80 */
81
82 int
83 main(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 {
112 _cupsLangPrintf(stderr,
113 _("lpadmin: Unable to connect to server: %s\n"),
114 strerror(errno));
115 return (1);
116 }
117 }
118
119 if (printer == NULL)
120 {
121 _cupsLangPuts(stderr,
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 {
136 _cupsLangPuts(stderr,
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 {
147 _cupsLangPuts(stderr,
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 {
165 _cupsLangPrintf(stderr,
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 {
180 _cupsLangPuts(stderr,
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 {
191 _cupsLangPuts(stderr,
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 {
218 _cupsLangPuts(stderr,
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 {
236 _cupsLangPrintf(stderr,
237 _("lpadmin: Unable to connect to server: %s\n"),
238 strerror(errno));
239 return (1);
240 }
241 }
242
243 if (printer == NULL)
244 {
245 _cupsLangPuts(stderr,
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 {
263 _cupsLangPuts(stderr,
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
283 _cupsLangPrintf(stderr,
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 {
297 _cupsLangPrintf(stderr,
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 {
316 _cupsLangPrintf(stderr,
317 _("lpadmin: Unable to connect to server: %s\n"),
318 strerror(errno));
319 return (1);
320 }
321 }
322
323 if (printer == NULL)
324 {
325 _cupsLangPuts(stderr,
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 {
344 _cupsLangPuts(stderr,
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 {
364 _cupsLangPuts(stderr,
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 {
382 _cupsLangPrintf(stderr,
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 {
397 _cupsLangPuts(stderr,
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 {
408 _cupsLangPuts(stderr,
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 {
423 _cupsLangPrintf(stderr,
424 _("lpadmin: Unable to connect to server: %s\n"),
425 strerror(errno));
426 return (1);
427 }
428 }
429
430 if (printer == NULL)
431 {
432 _cupsLangPuts(stderr,
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 {
448 _cupsLangPuts(stderr,
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 {
459 _cupsLangPuts(stderr,
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' : /* Username */
470 if (argv[i][2] != '\0')
471 cupsSetUser(argv[i] + 2);
472 else
473 {
474 i ++;
475 if (i >= argc)
476 {
477 _cupsLangPrintf(stderr,
478 _("%s: Error - expected username after "
479 "\'-U\' option!\n"),
480 argv[0]);
481 return (1);
482 }
483
484 cupsSetUser(argv[i]);
485 }
486 break;
487
488 case 'u' : /* Allow/deny users */
489 if (argv[i][2])
490 val = argv[i] + 2;
491 else
492 {
493 i ++;
494
495 if (i >= argc)
496 {
497 _cupsLangPuts(stderr,
498 _("lpadmin: Expected allow/deny:userlist after "
499 "\'-u\' option!\n"));
500 return (1);
501 }
502
503 val = argv[i];
504 }
505
506 if (!strncasecmp(val, "allow:", 6))
507 num_options = cupsAddOption("requesting-user-name-allowed",
508 val + 6, num_options, &options);
509 else if (!strncasecmp(val, "deny:", 5))
510 num_options = cupsAddOption("requesting-user-name-denied",
511 val + 5, num_options, &options);
512 else
513 {
514 _cupsLangPrintf(stderr,
515 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
516 val);
517 return (1);
518 }
519 break;
520
521 case 'v' : /* Set the device-uri attribute */
522 if (!http)
523 {
524 http = httpConnectEncrypt(cupsServer(), ippPort(),
525 cupsEncryption());
526
527 if (http == NULL)
528 {
529 _cupsLangPrintf(stderr,
530 _("lpadmin: Unable to connect to server: %s\n"),
531 strerror(errno));
532 return (1);
533 }
534 }
535
536 if (printer == NULL)
537 {
538 _cupsLangPuts(stderr,
539 _("lpadmin: Unable to set the device URI:\n"
540 " You must specify a printer name "
541 "first!\n"));
542 return (1);
543 }
544
545 if (argv[i][2])
546 {
547 if (set_printer_device(http, printer, argv[i] + 2))
548 return (1);
549 }
550 else
551 {
552 i ++;
553
554 if (i >= argc)
555 {
556 _cupsLangPuts(stderr,
557 _("lpadmin: Expected device URI after \'-v\' "
558 "option!\n"));
559 return (1);
560 }
561
562 if (set_printer_device(http, printer, argv[i]))
563 return (1);
564 }
565 break;
566
567 case 'x' : /* Delete a printer */
568 if (!http)
569 {
570 http = httpConnectEncrypt(cupsServer(), ippPort(),
571 cupsEncryption());
572
573 if (http == NULL)
574 {
575 _cupsLangPrintf(stderr,
576 _("lpadmin: Unable to connect to server: %s\n"),
577 strerror(errno));
578 return (1);
579 }
580 }
581
582 if (argv[i][2])
583 printer = argv[i] + 2;
584 else
585 {
586 i ++;
587
588 if (i >= argc)
589 {
590 _cupsLangPuts(stderr,
591 _("lpadmin: Expected printer or class after "
592 "\'-x\' option!\n"));
593 return (1);
594 }
595
596 printer = argv[i];
597 }
598
599 if (!validate_name(printer))
600 {
601 _cupsLangPuts(stderr,
602 _("lpadmin: Printer name can only contain "
603 "printable characters!\n"));
604 return (1);
605 }
606
607 if (delete_printer(http, printer))
608 return (1);
609
610 i = argc;
611 break;
612
613 case 'D' : /* Set the printer-info attribute */
614 if (!http)
615 {
616 http = httpConnectEncrypt(cupsServer(), ippPort(),
617 cupsEncryption());
618
619 if (http == NULL)
620 {
621 _cupsLangPrintf(stderr,
622 _("lpadmin: Unable to connect to server: %s\n"),
623 strerror(errno));
624 return (1);
625 }
626 }
627
628 if (printer == NULL)
629 {
630 _cupsLangPuts(stderr,
631 _("lpadmin: Unable to set the printer "
632 "description:\n"
633 " You must specify a printer name "
634 "first!\n"));
635 return (1);
636 }
637
638 if (argv[i][2])
639 {
640 if (set_printer_info(http, printer, argv[i] + 2))
641 return (1);
642 }
643 else
644 {
645 i ++;
646
647 if (i >= argc)
648 {
649 _cupsLangPuts(stderr,
650 _("lpadmin: Expected description after "
651 "\'-D\' option!\n"));
652 return (1);
653 }
654
655 if (set_printer_info(http, printer, argv[i]))
656 return (1);
657 }
658 break;
659
660 case 'I' : /* Set the supported file types (ignored) */
661 i ++;
662
663 if (i >= argc)
664 {
665 _cupsLangPuts(stderr,
666 _("lpadmin: Expected file type(s) after \'-I\' "
667 "option!\n"));
668 return (1);
669 }
670
671 _cupsLangPuts(stderr,
672 _("lpadmin: Warning - content type list ignored!\n"));
673 break;
674
675 case 'L' : /* Set the printer-location attribute */
676 if (!http)
677 {
678 http = httpConnectEncrypt(cupsServer(), ippPort(),
679 cupsEncryption());
680
681 if (http == NULL)
682 {
683 _cupsLangPrintf(stderr,
684 _("lpadmin: Unable to connect to server: %s\n"),
685 strerror(errno));
686 return (1);
687 }
688 }
689
690 if (printer == NULL)
691 {
692 _cupsLangPuts(stderr,
693 _("lpadmin: Unable to set the printer location:\n"
694 " You must specify a printer name "
695 "first!\n"));
696 return (1);
697 }
698
699 if (argv[i][2])
700 {
701 if (set_printer_location(http, printer, argv[i] + 2))
702 return (1);
703 }
704 else
705 {
706 i ++;
707
708 if (i >= argc)
709 {
710 _cupsLangPuts(stderr,
711 _("lpadmin: Expected location after \'-L\' "
712 "option!\n"));
713 return (1);
714 }
715
716 if (set_printer_location(http, printer, argv[i]))
717 return (1);
718 }
719 break;
720
721 case 'P' : /* Use the specified PPD file */
722 if (!http)
723 {
724 http = httpConnectEncrypt(cupsServer(), ippPort(),
725 cupsEncryption());
726
727 if (http == NULL)
728 {
729 _cupsLangPrintf(stderr,
730 _("lpadmin: Unable to connect to server: %s\n"),
731 strerror(errno));
732 return (1);
733 }
734 }
735
736 if (printer == NULL)
737 {
738 _cupsLangPuts(stderr,
739 _("lpadmin: Unable to set the PPD file:\n"
740 " You must specify a printer name "
741 "first!\n"));
742 return (1);
743 }
744
745 if (argv[i][2])
746 {
747 if (set_printer_file(http, printer, argv[i] + 2))
748 return (1);
749 }
750 else
751 {
752 i ++;
753
754 if (i >= argc)
755 {
756 _cupsLangPuts(stderr,
757 _("lpadmin: Expected PPD after \'-P\' option!\n"));
758 return (1);
759 }
760
761 if (set_printer_file(http, printer, argv[i]))
762 return (1);
763 }
764 break;
765
766 default :
767 _cupsLangPrintf(stderr,
768 _("lpadmin: Unknown option \'%c\'!\n"), argv[i][1]);
769 return (1);
770 }
771 else
772 {
773 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \'%s\'!\n"),
774 argv[i]);
775 return (1);
776 }
777
778 /*
779 * Set options as needed...
780 */
781
782 if (num_options)
783 {
784 if (!http)
785 {
786 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
787
788 if (http == NULL)
789 {
790 _cupsLangPrintf(stderr,
791 _("lpadmin: Unable to connect to server: %s\n"),
792 strerror(errno));
793 return (1);
794 }
795 }
796
797 if (printer == NULL)
798 {
799 _cupsLangPuts(stderr,
800 _("lpadmin: Unable to set the printer options:\n"
801 " You must specify a printer name first!\n"));
802 return (1);
803 }
804
805 if (set_printer_options(http, printer, num_options, options))
806 return (1);
807 }
808
809 if (printer == NULL)
810 {
811 _cupsLangPuts(stdout,
812 _("Usage:\n"
813 "\n"
814 " lpadmin [-h server] -d destination\n"
815 " lpadmin [-h server] -x destination\n"
816 " lpadmin [-h server] -p printer [-c add-class] "
817 "[-i interface] [-m model]\n"
818 " [-r remove-class] [-v device] "
819 "[-D description]\n"
820 " [-P ppd-file] [-o name=value]\n"
821 " [-u allow:user,user] "
822 "[-u deny:user,user]\n"
823 "\n"));
824 }
825
826 if (http)
827 httpClose(http);
828
829 return (0);
830 }
831
832
833 /*
834 * 'add_printer_to_class()' - Add a printer to a class.
835 */
836
837 static int /* O - 0 on success, 1 on fail */
838 add_printer_to_class(http_t *http, /* I - Server connection */
839 char *printer, /* I - Printer to add */
840 char *pclass) /* I - Class to add to */
841 {
842 int i; /* Looping var */
843 ipp_t *request, /* IPP Request */
844 *response; /* IPP Response */
845 ipp_attribute_t *attr, /* Current attribute */
846 *members; /* Members in class */
847 char uri[HTTP_MAX_URI]; /* URI for printer/class */
848
849
850 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
851 printer, pclass));
852
853 /*
854 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
855 * attributes:
856 *
857 * attributes-charset
858 * attributes-natural-language
859 * printer-uri
860 */
861
862 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
863
864 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
865 "localhost", 0, "/classes/%s", pclass);
866 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
867 "printer-uri", NULL, uri);
868
869 /*
870 * Do the request and get back a response...
871 */
872
873 response = cupsDoRequest(http, request, "/");
874
875 /*
876 * Build a CUPS_ADD_CLASS request, which requires the following
877 * attributes:
878 *
879 * attributes-charset
880 * attributes-natural-language
881 * printer-uri
882 * member-uris
883 */
884
885 request = ippNewRequest(CUPS_ADD_CLASS);
886
887 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
888 "printer-uri", NULL, uri);
889
890 /*
891 * See if the printer is already in the class...
892 */
893
894 if (response != NULL &&
895 (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
896 for (i = 0; i < members->num_values; i ++)
897 if (strcasecmp(printer, members->values[i].string.text) == 0)
898 {
899 _cupsLangPrintf(stderr,
900 _("lpadmin: Printer %s is already a member of class %s.\n"),
901 printer, pclass);
902 ippDelete(request);
903 ippDelete(response);
904 return (0);
905 }
906
907 /*
908 * OK, the printer isn't part of the class, so add it...
909 */
910
911 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
912 "localhost", 0, "/printers/%s", printer);
913
914 if (response != NULL &&
915 (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
916 {
917 /*
918 * Add the printer to the existing list...
919 */
920
921 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
922 "member-uris", members->num_values + 1, NULL, NULL);
923 for (i = 0; i < members->num_values; i ++)
924 attr->values[i].string.text = strdup(members->values[i].string.text);
925
926 attr->values[i].string.text = strdup(uri);
927 }
928 else
929 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL, uri);
930
931 /*
932 * Then send the request...
933 */
934
935 ippDelete(response);
936
937 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
938 {
939 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
940
941 return (1);
942 }
943 else if (response->request.status.status_code > IPP_OK_CONFLICT)
944 {
945 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
946
947 ippDelete(response);
948
949 return (1);
950 }
951 else
952 {
953 ippDelete(response);
954
955 return (0);
956 }
957 }
958
959
960 /*
961 * 'default_printer()' - Set the default printing destination.
962 */
963
964 static int /* O - 0 on success, 1 on fail */
965 default_printer(http_t *http, /* I - Server connection */
966 char *printer) /* I - Printer name */
967 {
968 ipp_t *request, /* IPP Request */
969 *response; /* IPP Response */
970 char uri[HTTP_MAX_URI]; /* URI for printer/class */
971
972
973 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
974
975 /*
976 * Build a CUPS_SET_DEFAULT request, which requires the following
977 * attributes:
978 *
979 * attributes-charset
980 * attributes-natural-language
981 * printer-uri
982 */
983
984 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
985 "localhost", 0, "/printers/%s", printer);
986
987 request = ippNewRequest(CUPS_SET_DEFAULT);
988
989 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
990 "printer-uri", NULL, uri);
991
992 /*
993 * Do the request and get back a response...
994 */
995
996 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
997 {
998 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
999
1000 return (1);
1001 }
1002 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1003 {
1004 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1005
1006 ippDelete(response);
1007
1008 return (1);
1009 }
1010 else
1011 {
1012 ippDelete(response);
1013
1014 return (0);
1015 }
1016 }
1017
1018
1019 /*
1020 * 'delete_printer()' - Delete a printer from the system...
1021 */
1022
1023 static int /* O - 0 on success, 1 on fail */
1024 delete_printer(http_t *http, /* I - Server connection */
1025 char *printer) /* I - Printer to delete */
1026 {
1027 ipp_t *request, /* IPP Request */
1028 *response; /* IPP Response */
1029 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1030
1031
1032 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
1033
1034 /*
1035 * Build a CUPS_DELETE_PRINTER request, which requires the following
1036 * attributes:
1037 *
1038 * attributes-charset
1039 * attributes-natural-language
1040 * printer-uri
1041 */
1042
1043 request = ippNewRequest(CUPS_DELETE_PRINTER);
1044
1045 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1046 "localhost", 0, "/printers/%s", printer);
1047 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1048 "printer-uri", NULL, uri);
1049
1050 /*
1051 * Do the request and get back a response...
1052 */
1053
1054 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1055 {
1056 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1057
1058 return (1);
1059 }
1060 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1061 {
1062 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1063
1064 ippDelete(response);
1065
1066 return (1);
1067 }
1068 else
1069 {
1070 ippDelete(response);
1071
1072 return (0);
1073 }
1074 }
1075
1076
1077 /*
1078 * 'delete_printer_from_class()' - Delete a printer from a class.
1079 */
1080
1081 static int /* O - 0 on success, 1 on fail */
1082 delete_printer_from_class(
1083 http_t *http, /* I - Server connection */
1084 char *printer, /* I - Printer to remove */
1085 char *pclass) /* I - Class to remove from */
1086 {
1087 int i, j, k; /* Looping vars */
1088 ipp_t *request, /* IPP Request */
1089 *response; /* IPP Response */
1090 ipp_attribute_t *attr, /* Current attribute */
1091 *members; /* Members in class */
1092 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1093
1094
1095 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
1096 printer, pclass));
1097
1098 /*
1099 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1100 * attributes:
1101 *
1102 * attributes-charset
1103 * attributes-natural-language
1104 * printer-uri
1105 */
1106
1107 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
1108
1109 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1110 "localhost", 0, "/classes/%s", pclass);
1111 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1112 "printer-uri", NULL, uri);
1113
1114 /*
1115 * Do the request and get back a response...
1116 */
1117
1118 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
1119 response->request.status.status_code == IPP_NOT_FOUND)
1120 {
1121 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1122
1123 ippDelete(response);
1124
1125 return (1);
1126 }
1127
1128 /*
1129 * See if the printer is already in the class...
1130 */
1131
1132 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
1133 {
1134 _cupsLangPuts(stderr, _("lpadmin: No member names were seen!\n"));
1135
1136 ippDelete(response);
1137
1138 return (1);
1139 }
1140
1141 for (i = 0; i < members->num_values; i ++)
1142 if (!strcasecmp(printer, members->values[i].string.text))
1143 break;
1144
1145 if (i >= members->num_values)
1146 {
1147 _cupsLangPrintf(stderr,
1148 _("lpadmin: Printer %s is not a member of class %s.\n"),
1149 printer, pclass);
1150
1151 ippDelete(response);
1152
1153 return (1);
1154 }
1155
1156 if (members->num_values == 1)
1157 {
1158 /*
1159 * Build a CUPS_DELETE_CLASS request, which requires the following
1160 * attributes:
1161 *
1162 * attributes-charset
1163 * attributes-natural-language
1164 * printer-uri
1165 */
1166
1167 request = ippNewRequest(CUPS_DELETE_CLASS);
1168
1169 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1170 "printer-uri", NULL, uri);
1171 }
1172 else
1173 {
1174 /*
1175 * Build a CUPS_ADD_CLASS request, which requires the following
1176 * attributes:
1177 *
1178 * attributes-charset
1179 * attributes-natural-language
1180 * printer-uri
1181 * member-uris
1182 */
1183
1184 request = ippNewRequest(CUPS_ADD_CLASS);
1185
1186 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1187 "printer-uri", NULL, uri);
1188
1189 /*
1190 * Delete the printer from the class...
1191 */
1192
1193 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1194 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1195 "member-uris", members->num_values - 1, NULL, NULL);
1196
1197 for (j = 0, k = 0; j < members->num_values; j ++)
1198 if (j != i)
1199 attr->values[k ++].string.text = strdup(members->values[j].string.text);
1200 }
1201
1202 /*
1203 * Then send the request...
1204 */
1205
1206 ippDelete(response);
1207
1208 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1209 {
1210 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1211
1212 return (1);
1213 }
1214 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1215 {
1216 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1217
1218 ippDelete(response);
1219
1220 return (1);
1221 }
1222 else
1223 {
1224 ippDelete(response);
1225
1226 return (0);
1227 }
1228 }
1229
1230
1231 /*
1232 * 'enable_printer()' - Enable a printer...
1233 */
1234
1235 static int /* O - 0 on success, 1 on fail */
1236 enable_printer(http_t *http, /* I - Server connection */
1237 char *printer) /* I - Printer to enable */
1238 {
1239 ipp_t *request, /* IPP Request */
1240 *response; /* IPP Response */
1241 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1242
1243
1244 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1245
1246 /*
1247 * Build a CUPS_ADD_PRINTER request, which requires the following
1248 * attributes:
1249 *
1250 * attributes-charset
1251 * attributes-natural-language
1252 * printer-uri
1253 * printer-state
1254 * printer-is-accepting-jobs
1255 */
1256
1257 request = ippNewRequest(CUPS_ADD_PRINTER);
1258
1259 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1260 "localhost", 0, "/printers/%s", printer);
1261 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1262 "printer-uri", NULL, uri);
1263
1264 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1265 IPP_PRINTER_IDLE);
1266
1267 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1268
1269 /*
1270 * Do the request and get back a response...
1271 */
1272
1273 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1274 {
1275 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1276
1277 return (1);
1278 }
1279 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1280 {
1281 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1282
1283 ippDelete(response);
1284
1285 return (1);
1286 }
1287 else
1288 {
1289 ippDelete(response);
1290
1291 return (0);
1292 }
1293 }
1294
1295
1296 /*
1297 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1298 */
1299
1300 static char * /* O - Pointer to buf or NULL on EOF */
1301 get_line(char *buf, /* I - Line buffer */
1302 int length, /* I - Length of buffer */
1303 FILE *fp) /* I - File to read from */
1304 {
1305 char *bufptr; /* Pointer into buffer */
1306 int ch; /* Character from file */
1307
1308
1309 length --;
1310 bufptr = buf;
1311
1312 while ((ch = getc(fp)) != EOF)
1313 {
1314 if (ch == '\n')
1315 break;
1316 else if (ch == '\r')
1317 {
1318 /*
1319 * Look for LF...
1320 */
1321
1322 ch = getc(fp);
1323 if (ch != '\n' && ch != EOF)
1324 ungetc(ch, fp);
1325
1326 break;
1327 }
1328
1329 *bufptr++ = ch;
1330 length --;
1331 if (length == 0)
1332 break;
1333 }
1334
1335 *bufptr = '\0';
1336
1337 if (ch == EOF)
1338 return (NULL);
1339 else
1340 return (buf);
1341 }
1342
1343
1344 /*
1345 * 'set_printer_device()' - Set the device-uri attribute.
1346 */
1347
1348 static int /* O - 0 on success, 1 on fail */
1349 set_printer_device(http_t *http, /* I - Server connection */
1350 char *printer, /* I - Printer */
1351 char *device) /* I - New device URI */
1352 {
1353 ipp_t *request, /* IPP Request */
1354 *response; /* IPP Response */
1355 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1356
1357
1358 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http, printer,
1359 device));
1360
1361 /*
1362 * Build a CUPS_ADD_PRINTER request, which requires the following
1363 * attributes:
1364 *
1365 * attributes-charset
1366 * attributes-natural-language
1367 * printer-uri
1368 */
1369
1370 request = ippNewRequest(CUPS_ADD_PRINTER);
1371
1372 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1373 "localhost", 0, "/printers/%s", printer);
1374 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1375 "printer-uri", NULL, uri);
1376
1377 /*
1378 * Add the device URI...
1379 */
1380
1381 if (device[0] == '/')
1382 {
1383 /*
1384 * Convert filename to URI...
1385 */
1386
1387 snprintf(uri, sizeof(uri), "file://%s", device);
1388 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1389 uri);
1390 }
1391 else
1392 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1393 device);
1394
1395 /*
1396 * Do the request and get back a response...
1397 */
1398
1399 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1400 {
1401 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1402
1403 return (1);
1404 }
1405 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1406 {
1407 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1408
1409 ippDelete(response);
1410
1411 return (1);
1412 }
1413 else
1414 {
1415 ippDelete(response);
1416
1417 return (0);
1418 }
1419 }
1420
1421
1422 /*
1423 * 'set_printer_file()' - Set the interface script or PPD file.
1424 */
1425
1426 static int /* O - 0 on success, 1 on fail */
1427 set_printer_file(http_t *http, /* I - Server connection */
1428 char *printer, /* I - Printer */
1429 char *file) /* I - PPD file or interface script */
1430 {
1431 ipp_t *request, /* IPP Request */
1432 *response; /* IPP Response */
1433 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1434 #ifdef HAVE_LIBZ
1435 char tempfile[1024]; /* Temporary filename */
1436 int fd; /* Temporary file */
1437 gzFile *gz; /* GZIP'd file */
1438 char buffer[8192]; /* Copy buffer */
1439 int bytes; /* Bytes in buffer */
1440
1441
1442 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http, printer,
1443 file));
1444
1445 /*
1446 * See if the file is gzip'd; if so, unzip it to a temporary file and
1447 * send the uncompressed file.
1448 */
1449
1450 if (!strcmp(file + strlen(file) - 3, ".gz"))
1451 {
1452 /*
1453 * Yes, the file is compressed; uncompress to a temp file...
1454 */
1455
1456 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1457 {
1458 _cupsLangPrintf(stderr,
1459 _("lpadmin: Unable to create temporary file: %s\n"),
1460 strerror(errno));
1461 return (1);
1462 }
1463
1464 if ((gz = gzopen(file, "rb")) == NULL)
1465 {
1466 _cupsLangPrintf(stderr,
1467 _("lpadmin: Unable to open file \"%s\": %s\n"),
1468 file, strerror(errno));
1469 close(fd);
1470 unlink(tempfile);
1471 return (1);
1472 }
1473
1474 while ((bytes = gzread(gz, buffer, sizeof(buffer))) > 0)
1475 write(fd, buffer, bytes);
1476
1477 close(fd);
1478 gzclose(gz);
1479
1480 file = tempfile;
1481 }
1482 #endif /* HAVE_LIBZ */
1483
1484 /*
1485 * Build a CUPS_ADD_PRINTER request, which requires the following
1486 * attributes:
1487 *
1488 * attributes-charset
1489 * attributes-natural-language
1490 * printer-uri
1491 */
1492
1493 request = ippNewRequest(CUPS_ADD_PRINTER);
1494
1495 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1496 "localhost", 0, "/printers/%s", printer);
1497 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1498 "printer-uri", NULL, uri);
1499
1500 /*
1501 * Do the request and get back a response...
1502 */
1503
1504 response = cupsDoFileRequest(http, request, "/admin/", file);
1505 ippDelete(response);
1506
1507 #ifdef HAVE_LIBZ
1508 /*
1509 * Remove the temporary file as needed...
1510 */
1511
1512 if (file == tempfile)
1513 unlink(tempfile);
1514 #endif /* HAVE_LIBZ */
1515
1516 if (cupsLastError() > IPP_OK_CONFLICT)
1517 {
1518 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1519
1520 return (1);
1521 }
1522 else
1523 return (0);
1524 }
1525
1526
1527 /*
1528 * 'set_printer_info()' - Set the printer description string.
1529 */
1530
1531 static int /* O - 0 on success, 1 on fail */
1532 set_printer_info(http_t *http, /* I - Server connection */
1533 char *printer, /* I - Printer */
1534 char *info) /* I - New description string */
1535 {
1536 ipp_t *request, /* IPP Request */
1537 *response; /* IPP Response */
1538 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1539
1540
1541 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http, printer,
1542 info));
1543
1544 /*
1545 * Build a CUPS_ADD_PRINTER request, which requires the following
1546 * attributes:
1547 *
1548 * attributes-charset
1549 * attributes-natural-language
1550 * printer-uri
1551 */
1552
1553 request = ippNewRequest(CUPS_ADD_PRINTER);
1554
1555 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1556 "localhost", 0, "/printers/%s", printer);
1557 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1558 "printer-uri", NULL, uri);
1559
1560 /*
1561 * Add the info string...
1562 */
1563
1564 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL,
1565 info);
1566
1567 /*
1568 * Do the request and get back a response...
1569 */
1570
1571 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1572 {
1573 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1574 return (1);
1575 }
1576 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1577 {
1578 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1579
1580 ippDelete(response);
1581
1582 return (1);
1583 }
1584 else
1585 {
1586 ippDelete(response);
1587
1588 return (0);
1589 }
1590 }
1591
1592
1593 /*
1594 * 'set_printer_location()' - Set the printer location string.
1595 */
1596
1597 static int /* O - 0 on success, 1 on fail */
1598 set_printer_location(http_t *http, /* I - Server connection */
1599 char *printer, /* I - Printer */
1600 char *location) /* I - New location string */
1601 {
1602 ipp_t *request, /* IPP Request */
1603 *response; /* IPP Response */
1604 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1605
1606
1607 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http, printer,
1608 location));
1609
1610 /*
1611 * Build a CUPS_ADD_PRINTER request, which requires the following
1612 * attributes:
1613 *
1614 * attributes-charset
1615 * attributes-natural-language
1616 * printer-uri
1617 */
1618
1619 request = ippNewRequest(CUPS_ADD_PRINTER);
1620
1621 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1622 "localhost", 0, "/printers/%s", printer);
1623 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1624 "printer-uri", NULL, uri);
1625
1626 /*
1627 * Add the location string...
1628 */
1629
1630 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL,
1631 location);
1632
1633 /*
1634 * Do the request and get back a response...
1635 */
1636
1637 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1638 {
1639 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1640
1641 return (1);
1642 }
1643 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1644 {
1645 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1646
1647 ippDelete(response);
1648
1649 return (1);
1650 }
1651 else
1652 {
1653 ippDelete(response);
1654
1655 return (0);
1656 }
1657 }
1658
1659
1660 /*
1661 * 'set_printer_model()' - Set the driver model file.
1662 */
1663
1664 static int /* O - 0 on success, 1 on fail */
1665 set_printer_model(http_t *http, /* I - Server connection */
1666 char *printer, /* I - Printer */
1667 char *model) /* I - Driver model file */
1668 {
1669 ipp_t *request, /* IPP Request */
1670 *response; /* IPP Response */
1671 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1672
1673
1674 /*
1675 * Build a CUPS_ADD_PRINTER request, which requires the following
1676 * attributes:
1677 *
1678 * attributes-charset
1679 * attributes-natural-language
1680 * printer-uri
1681 * ppd-name
1682 */
1683
1684 request = ippNewRequest(CUPS_ADD_PRINTER);
1685
1686 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1687 "localhost", 0, "/printers/%s", printer);
1688 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1689 "printer-uri", NULL, uri);
1690
1691 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1692 "ppd-name", NULL, model);
1693
1694 /*
1695 * Do the request and get back a response...
1696 */
1697
1698 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1699 {
1700 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1701
1702 return (1);
1703 }
1704 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1705 {
1706 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1707
1708 ippDelete(response);
1709
1710 return (1);
1711 }
1712 else
1713 {
1714 ippDelete(response);
1715
1716 return (0);
1717 }
1718 }
1719
1720
1721 /*
1722 * 'set_printer_options()' - Set the printer options.
1723 */
1724
1725 static int /* O - 0 on success, 1 on fail */
1726 set_printer_options(
1727 http_t *http, /* I - Server connection */
1728 char *printer, /* I - Printer */
1729 int num_options, /* I - Number of options */
1730 cups_option_t *options) /* I - Options */
1731 {
1732 ipp_t *request, /* IPP Request */
1733 *response; /* IPP Response */
1734 ipp_attribute_t *attr; /* IPP attribute */
1735 ipp_op_t op; /* Operation to perform */
1736 const char *ppdfile; /* PPD filename */
1737 int ppdchanged; /* PPD changed? */
1738 ppd_file_t *ppd; /* PPD file */
1739 ppd_choice_t *choice; /* Marked choice */
1740 char uri[HTTP_MAX_URI], /* URI for printer/class */
1741 line[1024], /* Line from PPD file */
1742 keyword[1024], /* Keyword from Default line */
1743 *keyptr, /* Pointer into keyword... */
1744 tempfile[1024]; /* Temporary filename */
1745 FILE *in, /* PPD file */
1746 *out; /* Temporary file */
1747 int outfd; /* Temporary file descriptor */
1748 const char *protocol; /* Old protocol option */
1749
1750
1751 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http, printer,
1752 num_options, options));
1753
1754 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1755 "localhost", 0, "/printers/%s", printer);
1756
1757 /*
1758 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1759 * attributes:
1760 *
1761 * attributes-charset
1762 * attributes-natural-language
1763 * printer-uri
1764 * requested-attributes
1765 */
1766
1767 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
1768
1769 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1770 "printer-uri", NULL, uri);
1771
1772 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1773 "requested-attributes", NULL, "printer-type");
1774
1775 /*
1776 * Do the request...
1777 */
1778
1779 op = CUPS_ADD_PRINTER;
1780
1781 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1782 {
1783 /*
1784 * See what kind of printer or class it is...
1785 */
1786
1787 if ((attr = ippFindAttribute(response, "printer-type",
1788 IPP_TAG_ENUM)) != NULL)
1789 {
1790 if (attr->values[0].integer & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
1791 {
1792 op = CUPS_ADD_CLASS;
1793 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1794 "localhost", 0, "/classes/%s", printer);
1795 }
1796 }
1797
1798 ippDelete(response);
1799 }
1800
1801 /*
1802 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1803 * the following attributes:
1804 *
1805 * attributes-charset
1806 * attributes-natural-language
1807 * printer-uri
1808 * other options
1809 */
1810
1811 request = ippNewRequest(op);
1812
1813 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1814 "printer-uri", NULL, uri);
1815
1816 /*
1817 * Add the options...
1818 */
1819
1820 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1821
1822 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1823 {
1824 if (!strcasecmp(protocol, "bcp"))
1825 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "port-monitor",
1826 NULL, "bcp");
1827 else if (!strcasecmp(protocol, "tbcp"))
1828 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "port-monitor",
1829 NULL, "tbcp");
1830 }
1831
1832 if (op == CUPS_ADD_PRINTER)
1833 ppdfile = cupsGetPPD(printer);
1834 else
1835 ppdfile = NULL;
1836
1837 if (ppdfile != NULL)
1838 {
1839 /*
1840 * Set default options in the PPD file...
1841 */
1842
1843 ppd = ppdOpenFile(ppdfile);
1844 ppdMarkDefaults(ppd);
1845 cupsMarkOptions(ppd, num_options, options);
1846
1847 if ((outfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1848 {
1849 _cupsLangPrintf(stderr,
1850 _("lpadmin: Unable to create temporary file - %s\n"),
1851 strerror(errno));
1852 ippDelete(request);
1853 unlink(ppdfile);
1854 return (1);
1855 }
1856
1857 if ((in = fopen(ppdfile, "rb")) == NULL)
1858 {
1859 _cupsLangPrintf(stderr,
1860 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1861 ppdfile, strerror(errno));
1862 ippDelete(request);
1863 unlink(ppdfile);
1864 close(outfd);
1865 unlink(tempfile);
1866 return (1);
1867 }
1868
1869 out = fdopen(outfd, "wb");
1870 ppdchanged = 0;
1871
1872 while (get_line(line, sizeof(line), in) != NULL)
1873 {
1874 if (strncmp(line, "*Default", 8))
1875 fprintf(out, "%s\n", line);
1876 else
1877 {
1878 /*
1879 * Get default option name...
1880 */
1881
1882 strlcpy(keyword, line + 8, sizeof(keyword));
1883
1884 for (keyptr = keyword; *keyptr; keyptr ++)
1885 if (*keyptr == ':' || isspace(*keyptr & 255))
1886 break;
1887
1888 *keyptr++ = '\0';
1889 while (isspace(*keyptr & 255))
1890 keyptr ++;
1891
1892 if (!strcmp(keyword, "PageRegion") ||
1893 !strcmp(keyword, "PageSize") ||
1894 !strcmp(keyword, "PaperDimension") ||
1895 !strcmp(keyword, "ImageableArea"))
1896 {
1897 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1898 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1899 }
1900 else
1901 choice = ppdFindMarkedChoice(ppd, keyword);
1902
1903 if (choice && strcmp(choice->choice, keyptr))
1904 {
1905 fprintf(out, "*Default%s: %s\n", keyword, choice->choice);
1906 ppdchanged = 1;
1907 }
1908 else
1909 fprintf(out, "%s\n", line);
1910 }
1911 }
1912
1913 fclose(in);
1914 fclose(out);
1915 close(outfd);
1916 ppdClose(ppd);
1917
1918 /*
1919 * Do the request...
1920 */
1921
1922 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1923 ppdchanged ? tempfile : NULL));
1924
1925 /*
1926 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1927 * lpadmin)
1928 */
1929
1930 unlink(ppdfile);
1931 unlink(tempfile);
1932 }
1933 else
1934 {
1935 /*
1936 * No PPD file - just set the options...
1937 */
1938
1939 ippDelete(cupsDoRequest(http, request, "/admin/"));
1940 }
1941
1942 /*
1943 * Check the response...
1944 */
1945
1946 if (cupsLastError() > IPP_OK_CONFLICT)
1947 {
1948 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1949
1950 return (1);
1951 }
1952 else
1953 return (0);
1954 }
1955
1956
1957 /*
1958 * 'validate_name()' - Make sure the printer name only contains valid chars.
1959 */
1960
1961 static int /* O - 0 if name is no good, 1 if name is good */
1962 validate_name(const char *name) /* I - Name to check */
1963 {
1964 const char *ptr; /* Pointer into name */
1965
1966
1967 /*
1968 * Scan the whole name...
1969 */
1970
1971 for (ptr = name; *ptr; ptr ++)
1972 if (*ptr == '@')
1973 break;
1974 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1975 *ptr == '#')
1976 return (0);
1977
1978 /*
1979 * All the characters are good; validate the length, too...
1980 */
1981
1982 return ((ptr - name) < 128);
1983 }
1984
1985
1986 /*
1987 * End of "$Id: lpadmin.c 5545 2006-05-18 21:00:56Z mike $".
1988 */