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