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