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