]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpadmin.c
Fix lpadmin when both -m and -o are used (STR #4578)
[thirdparty/cups.git] / systemv / lpadmin.c
1 /*
2 * "$Id$"
3 *
4 * "lpadmin" command for CUPS.
5 *
6 * Copyright 2007-2015 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 */
15
16 /*
17 * Include necessary headers...
18 */
19
20 #define _CUPS_NO_DEPRECATED
21 #define _PPD_DEPRECATED
22 #include <cups/cups-private.h>
23
24
25 /*
26 * Local functions...
27 */
28
29 static int add_printer_to_class(http_t *http, char *printer, char *pclass);
30 static int default_printer(http_t *http, char *printer);
31 static int delete_printer(http_t *http, char *printer);
32 static int delete_printer_from_class(http_t *http, char *printer,
33 char *pclass);
34 static int delete_printer_option(http_t *http, char *printer,
35 char *option);
36 static int enable_printer(http_t *http, char *printer);
37 static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize);
38 static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri,
39 size_t urisize);
40 static int set_printer_options(http_t *http, char *printer,
41 int num_options, cups_option_t *options,
42 char *file);
43 static int validate_name(const char *name);
44
45
46 /*
47 * 'main()' - Parse options and configure the scheduler.
48 */
49
50 int
51 main(int argc, /* I - Number of command-line arguments */
52 char *argv[]) /* I - Command-line arguments */
53 {
54 int i; /* Looping var */
55 http_t *http; /* Connection to server */
56 char *printer, /* Destination printer */
57 *pclass, /* Printer class name */
58 *val; /* Pointer to allow/deny value */
59 int num_options; /* Number of options */
60 cups_option_t *options; /* Options */
61 char *file, /* New PPD file/interface script */
62 evefile[1024] = "";
63 /* IPP Everywhere PPD */
64 const char *ppd_name, /* ppd-name value */
65 *device_uri; /* device-uri value */
66
67
68 _cupsSetLocale(argv);
69
70 http = NULL;
71 printer = NULL;
72 num_options = 0;
73 options = NULL;
74 file = NULL;
75
76 for (i = 1; i < argc; i ++)
77 if (argv[i][0] == '-')
78 switch (argv[i][1])
79 {
80 case 'c' : /* Add printer to class */
81 if (!http)
82 {
83 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
84
85 if (http == NULL)
86 {
87 _cupsLangPrintf(stderr,
88 _("lpadmin: Unable to connect to server: %s"),
89 strerror(errno));
90 return (1);
91 }
92 }
93
94 if (printer == NULL)
95 {
96 _cupsLangPuts(stderr,
97 _("lpadmin: Unable to add a printer to the class:\n"
98 " You must specify a printer name "
99 "first."));
100 return (1);
101 }
102
103 if (argv[i][2])
104 pclass = argv[i] + 2;
105 else
106 {
107 i ++;
108
109 if (i >= argc)
110 {
111 _cupsLangPuts(stderr,
112 _("lpadmin: Expected class name after \"-c\" "
113 "option."));
114 return (1);
115 }
116
117 pclass = argv[i];
118 }
119
120 if (!validate_name(pclass))
121 {
122 _cupsLangPuts(stderr,
123 _("lpadmin: Class name can only contain printable "
124 "characters."));
125 return (1);
126 }
127
128 if (add_printer_to_class(http, printer, pclass))
129 return (1);
130 break;
131
132 case 'd' : /* Set as default destination */
133 if (!http)
134 {
135 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
136
137 if (http == NULL)
138 {
139 _cupsLangPrintf(stderr,
140 _("lpadmin: Unable to connect to server: %s"),
141 strerror(errno));
142 return (1);
143 }
144 }
145
146 if (argv[i][2])
147 printer = argv[i] + 2;
148 else
149 {
150 i ++;
151
152 if (i >= argc)
153 {
154 _cupsLangPuts(stderr,
155 _("lpadmin: Expected printer name after \"-d\" "
156 "option."));
157 return (1);
158 }
159
160 printer = argv[i];
161 }
162
163 if (!validate_name(printer))
164 {
165 _cupsLangPuts(stderr,
166 _("lpadmin: Printer name can only contain "
167 "printable characters."));
168 return (1);
169 }
170
171 if (default_printer(http, printer))
172 return (1);
173
174 i = argc;
175 break;
176
177 case 'h' : /* Connect to host */
178 if (http)
179 {
180 httpClose(http);
181 http = NULL;
182 }
183
184 if (argv[i][2] != '\0')
185 cupsSetServer(argv[i] + 2);
186 else
187 {
188 i ++;
189
190 if (i >= argc)
191 {
192 _cupsLangPuts(stderr,
193 _("lpadmin: Expected hostname after \"-h\" "
194 "option."));
195 return (1);
196 }
197
198 cupsSetServer(argv[i]);
199 }
200 break;
201
202 case 'i' : /* Use the specified interface script */
203 if (argv[i][2])
204 file = argv[i] + 2;
205 else
206 {
207 i ++;
208
209 if (i >= argc)
210 {
211 _cupsLangPuts(stderr,
212 _("lpadmin: Expected interface after \"-i\" "
213 "option."));
214 return (1);
215 }
216
217 file = argv[i];
218 }
219 break;
220
221 case 'E' : /* Enable the printer */
222 if (printer == NULL)
223 {
224 #ifdef HAVE_SSL
225 cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
226
227 if (http)
228 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
229 #else
230 _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
231 argv[0]);
232 #endif /* HAVE_SSL */
233 break;
234 }
235
236 if (!http)
237 {
238 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
239
240 if (http == NULL)
241 {
242 _cupsLangPrintf(stderr,
243 _("lpadmin: Unable to connect to server: %s"),
244 strerror(errno));
245 return (1);
246 }
247 }
248
249 if (enable_printer(http, printer))
250 return (1);
251 break;
252
253 case 'm' : /* Use the specified standard script/PPD file */
254 if (argv[i][2])
255 num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options,
256 &options);
257 else
258 {
259 i ++;
260
261 if (i >= argc)
262 {
263 _cupsLangPuts(stderr,
264 _("lpadmin: Expected model after \"-m\" "
265 "option."));
266 return (1);
267 }
268
269 num_options = cupsAddOption("ppd-name", argv[i], num_options,
270 &options);
271 }
272 break;
273
274 case 'o' : /* Set option */
275 if (argv[i][2])
276 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
277 else
278 {
279 i ++;
280
281 if (i >= argc)
282 {
283 _cupsLangPuts(stderr,
284 _("lpadmin: Expected name=value after \"-o\" "
285 "option."));
286 return (1);
287 }
288
289 num_options = cupsParseOptions(argv[i], num_options, &options);
290 }
291 break;
292
293 case 'p' : /* Add/modify a printer */
294 if (argv[i][2])
295 printer = argv[i] + 2;
296 else
297 {
298 i ++;
299
300 if (i >= argc)
301 {
302 _cupsLangPuts(stderr,
303 _("lpadmin: Expected printer after \"-p\" "
304 "option."));
305 return (1);
306 }
307
308 printer = argv[i];
309 }
310
311 if (!validate_name(printer))
312 {
313 _cupsLangPuts(stderr,
314 _("lpadmin: Printer name can only contain "
315 "printable characters."));
316 return (1);
317 }
318 break;
319
320 case 'r' : /* Remove printer from class */
321 if (!http)
322 {
323 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
324
325 if (http == NULL)
326 {
327 _cupsLangPrintf(stderr,
328 _("lpadmin: Unable to connect to server: %s"),
329 strerror(errno));
330 return (1);
331 }
332 }
333
334 if (printer == NULL)
335 {
336 _cupsLangPuts(stderr,
337 _("lpadmin: Unable to remove a printer from the "
338 "class:\n"
339 " You must specify a printer name "
340 "first."));
341 return (1);
342 }
343
344 if (argv[i][2])
345 pclass = argv[i] + 2;
346 else
347 {
348 i ++;
349
350 if (i >= argc)
351 {
352 _cupsLangPuts(stderr,
353 _("lpadmin: Expected class after \"-r\" "
354 "option."));
355 return (1);
356 }
357
358 pclass = argv[i];
359 }
360
361 if (!validate_name(pclass))
362 {
363 _cupsLangPuts(stderr,
364 _("lpadmin: Class name can only contain printable "
365 "characters."));
366 return (1);
367 }
368
369 if (delete_printer_from_class(http, printer, pclass))
370 return (1);
371 break;
372
373 case 'R' : /* Remove option */
374 if (!http)
375 {
376 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
377
378 if (http == NULL)
379 {
380 _cupsLangPrintf(stderr,
381 _("lpadmin: Unable to connect to server: %s"),
382 strerror(errno));
383 return (1);
384 }
385 }
386
387 if (printer == NULL)
388 {
389 _cupsLangPuts(stderr,
390 _("lpadmin: Unable to delete option:\n"
391 " You must specify a printer name "
392 "first."));
393 return (1);
394 }
395
396 if (argv[i][2])
397 val = argv[i] + 2;
398 else
399 {
400 i ++;
401
402 if (i >= argc)
403 {
404 _cupsLangPuts(stderr,
405 _("lpadmin: Expected name after \"-R\" "
406 "option."));
407 return (1);
408 }
409
410 val = argv[i];
411 }
412
413 if (delete_printer_option(http, printer, val))
414 return (1);
415 break;
416
417 case 'U' : /* Username */
418 if (argv[i][2] != '\0')
419 cupsSetUser(argv[i] + 2);
420 else
421 {
422 i ++;
423 if (i >= argc)
424 {
425 _cupsLangPrintf(stderr,
426 _("%s: Error - expected username after "
427 "\"-U\" option."), argv[0]);
428 return (1);
429 }
430
431 cupsSetUser(argv[i]);
432 }
433 break;
434
435 case 'u' : /* Allow/deny users */
436 if (argv[i][2])
437 val = argv[i] + 2;
438 else
439 {
440 i ++;
441
442 if (i >= argc)
443 {
444 _cupsLangPuts(stderr,
445 _("lpadmin: Expected allow/deny:userlist after "
446 "\"-u\" option."));
447 return (1);
448 }
449
450 val = argv[i];
451 }
452
453 if (!_cups_strncasecmp(val, "allow:", 6))
454 num_options = cupsAddOption("requesting-user-name-allowed",
455 val + 6, num_options, &options);
456 else if (!_cups_strncasecmp(val, "deny:", 5))
457 num_options = cupsAddOption("requesting-user-name-denied",
458 val + 5, num_options, &options);
459 else
460 {
461 _cupsLangPrintf(stderr,
462 _("lpadmin: Unknown allow/deny option \"%s\"."),
463 val);
464 return (1);
465 }
466 break;
467
468 case 'v' : /* Set the device-uri attribute */
469 if (argv[i][2])
470 num_options = cupsAddOption("device-uri", argv[i] + 2,
471 num_options, &options);
472 else
473 {
474 i ++;
475
476 if (i >= argc)
477 {
478 _cupsLangPuts(stderr,
479 _("lpadmin: Expected device URI after \"-v\" "
480 "option."));
481 return (1);
482 }
483
484 num_options = cupsAddOption("device-uri", argv[i],
485 num_options, &options);
486 }
487 break;
488
489 case 'x' : /* Delete a printer */
490 if (!http)
491 {
492 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
493
494 if (http == NULL)
495 {
496 _cupsLangPrintf(stderr,
497 _("lpadmin: Unable to connect to server: %s"),
498 strerror(errno));
499 return (1);
500 }
501 }
502
503 if (argv[i][2])
504 printer = argv[i] + 2;
505 else
506 {
507 i ++;
508
509 if (i >= argc)
510 {
511 _cupsLangPuts(stderr,
512 _("lpadmin: Expected printer or class after "
513 "\"-x\" option."));
514 return (1);
515 }
516
517 printer = argv[i];
518 }
519
520 if (!validate_name(printer))
521 {
522 _cupsLangPuts(stderr,
523 _("lpadmin: Printer name can only contain "
524 "printable characters."));
525 return (1);
526 }
527
528 if (delete_printer(http, printer))
529 return (1);
530
531 i = argc;
532 break;
533
534 case 'D' : /* Set the printer-info attribute */
535 if (argv[i][2])
536 num_options = cupsAddOption("printer-info", argv[i] + 2,
537 num_options, &options);
538 else
539 {
540 i ++;
541
542 if (i >= argc)
543 {
544 _cupsLangPuts(stderr,
545 _("lpadmin: Expected description after "
546 "\"-D\" option."));
547 return (1);
548 }
549
550 num_options = cupsAddOption("printer-info", argv[i],
551 num_options, &options);
552 }
553 break;
554
555 case 'I' : /* Set the supported file types (ignored) */
556 i ++;
557
558 if (i >= argc)
559 {
560 _cupsLangPuts(stderr,
561 _("lpadmin: Expected file type(s) after \"-I\" "
562 "option."));
563 return (1);
564 }
565
566 _cupsLangPuts(stderr,
567 _("lpadmin: Warning - content type list ignored."));
568 break;
569
570 case 'L' : /* Set the printer-location attribute */
571 if (argv[i][2])
572 num_options = cupsAddOption("printer-location", argv[i] + 2,
573 num_options, &options);
574 else
575 {
576 i ++;
577
578 if (i >= argc)
579 {
580 _cupsLangPuts(stderr,
581 _("lpadmin: Expected location after \"-L\" "
582 "option."));
583 return (1);
584 }
585
586 num_options = cupsAddOption("printer-location", argv[i],
587 num_options, &options);
588 }
589 break;
590
591 case 'P' : /* Use the specified PPD file */
592 if (argv[i][2])
593 file = argv[i] + 2;
594 else
595 {
596 i ++;
597
598 if (i >= argc)
599 {
600 _cupsLangPuts(stderr,
601 _("lpadmin: Expected PPD after \"-P\" option."));
602 return (1);
603 }
604
605 file = argv[i];
606 }
607 break;
608
609 default :
610 _cupsLangPrintf(stderr,
611 _("lpadmin: Unknown option \"%c\"."), argv[i][1]);
612 return (1);
613 }
614 else
615 {
616 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."),
617 argv[i]);
618 return (1);
619 }
620
621 /*
622 * Set options as needed...
623 */
624
625 if ((ppd_name = cupsGetOption("ppd-name", num_options, options)) != NULL && !strcmp(ppd_name, "everywhere") && (device_uri = cupsGetOption("device-uri", num_options, options)) != NULL)
626 {
627 if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile))) == NULL)
628 return (1);
629
630 num_options = cupsRemoveOption("ppd-name", num_options, &options);
631 }
632
633 if (num_options || file)
634 {
635 if (!http)
636 {
637 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
638
639 if (http == NULL)
640 {
641 _cupsLangPrintf(stderr,
642 _("lpadmin: Unable to connect to server: %s"),
643 strerror(errno));
644 return (1);
645 }
646 }
647
648 if (printer == NULL)
649 {
650 _cupsLangPuts(stderr,
651 _("lpadmin: Unable to set the printer options:\n"
652 " You must specify a printer name first."));
653 return (1);
654 }
655
656 if (set_printer_options(http, printer, num_options, options, file))
657 return (1);
658 }
659
660 if (evefile[0])
661 unlink(evefile);
662
663 if (printer == NULL)
664 {
665 _cupsLangPuts(stdout,
666 _("Usage:\n"
667 "\n"
668 " lpadmin [-h server] -d destination\n"
669 " lpadmin [-h server] -x destination\n"
670 " lpadmin [-h server] -p printer [-c add-class] "
671 "[-i interface] [-m model]\n"
672 " [-r remove-class] [-v device] "
673 "[-D description]\n"
674 " [-P ppd-file] [-o name=value]\n"
675 " [-u allow:user,user] "
676 "[-u deny:user,user]"));
677 }
678
679 if (http)
680 httpClose(http);
681
682 return (0);
683 }
684
685
686 /*
687 * 'add_printer_to_class()' - Add a printer to a class.
688 */
689
690 static int /* O - 0 on success, 1 on fail */
691 add_printer_to_class(http_t *http, /* I - Server connection */
692 char *printer, /* I - Printer to add */
693 char *pclass) /* I - Class to add to */
694 {
695 int i; /* Looping var */
696 ipp_t *request, /* IPP Request */
697 *response; /* IPP Response */
698 ipp_attribute_t *attr, /* Current attribute */
699 *members; /* Members in class */
700 char uri[HTTP_MAX_URI]; /* URI for printer/class */
701
702
703 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
704 printer, pclass));
705
706 /*
707 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
708 * attributes:
709 *
710 * attributes-charset
711 * attributes-natural-language
712 * printer-uri
713 * requesting-user-name
714 */
715
716 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
717
718 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
719 "localhost", 0, "/classes/%s", pclass);
720 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
721 "printer-uri", NULL, uri);
722 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
723 NULL, cupsUser());
724
725 /*
726 * Do the request and get back a response...
727 */
728
729 response = cupsDoRequest(http, request, "/");
730
731 /*
732 * Build a CUPS-Add-Modify-Class request, which requires the following
733 * attributes:
734 *
735 * attributes-charset
736 * attributes-natural-language
737 * printer-uri
738 * requesting-user-name
739 * member-uris
740 */
741
742 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
743
744 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
745 "printer-uri", NULL, uri);
746 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
747 NULL, cupsUser());
748
749 /*
750 * See if the printer is already in the class...
751 */
752
753 if (response != NULL &&
754 (members = ippFindAttribute(response, "member-names",
755 IPP_TAG_NAME)) != NULL)
756 for (i = 0; i < members->num_values; i ++)
757 if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
758 {
759 _cupsLangPrintf(stderr,
760 _("lpadmin: Printer %s is already a member of class "
761 "%s."), printer, pclass);
762 ippDelete(request);
763 ippDelete(response);
764 return (0);
765 }
766
767 /*
768 * OK, the printer isn't part of the class, so add it...
769 */
770
771 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
772 "localhost", 0, "/printers/%s", printer);
773
774 if (response != NULL &&
775 (members = ippFindAttribute(response, "member-uris",
776 IPP_TAG_URI)) != NULL)
777 {
778 /*
779 * Add the printer to the existing list...
780 */
781
782 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
783 "member-uris", members->num_values + 1, NULL, NULL);
784 for (i = 0; i < members->num_values; i ++)
785 attr->values[i].string.text =
786 _cupsStrAlloc(members->values[i].string.text);
787
788 attr->values[i].string.text = _cupsStrAlloc(uri);
789 }
790 else
791 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
792 uri);
793
794 /*
795 * Then send the request...
796 */
797
798 ippDelete(response);
799
800 ippDelete(cupsDoRequest(http, request, "/admin/"));
801 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
802 {
803 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
804
805 return (1);
806 }
807 else
808 return (0);
809 }
810
811
812 /*
813 * 'default_printer()' - Set the default printing destination.
814 */
815
816 static int /* O - 0 on success, 1 on fail */
817 default_printer(http_t *http, /* I - Server connection */
818 char *printer) /* I - Printer name */
819 {
820 ipp_t *request; /* IPP Request */
821 char uri[HTTP_MAX_URI]; /* URI for printer/class */
822
823
824 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
825
826 /*
827 * Build a CUPS-Set-Default request, which requires the following
828 * attributes:
829 *
830 * attributes-charset
831 * attributes-natural-language
832 * printer-uri
833 * requesting-user-name
834 */
835
836 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
837 "localhost", 0, "/printers/%s", printer);
838
839 request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
840
841 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
842 "printer-uri", NULL, uri);
843 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
844 NULL, cupsUser());
845
846 /*
847 * Do the request and get back a response...
848 */
849
850 ippDelete(cupsDoRequest(http, request, "/admin/"));
851
852 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
853 {
854 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
855
856 return (1);
857 }
858 else
859 return (0);
860 }
861
862
863 /*
864 * 'delete_printer()' - Delete a printer from the system...
865 */
866
867 static int /* O - 0 on success, 1 on fail */
868 delete_printer(http_t *http, /* I - Server connection */
869 char *printer) /* I - Printer to delete */
870 {
871 ipp_t *request; /* IPP Request */
872 char uri[HTTP_MAX_URI]; /* URI for printer/class */
873
874
875 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
876
877 /*
878 * Build a CUPS-Delete-Printer request, which requires the following
879 * attributes:
880 *
881 * attributes-charset
882 * attributes-natural-language
883 * printer-uri
884 * requesting-user-name
885 */
886
887 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
888
889 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
890 "localhost", 0, "/printers/%s", printer);
891 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
892 "printer-uri", NULL, uri);
893 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
894 NULL, cupsUser());
895
896 /*
897 * Do the request and get back a response...
898 */
899
900 ippDelete(cupsDoRequest(http, request, "/admin/"));
901
902 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
903 {
904 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
905
906 return (1);
907 }
908 else
909 return (0);
910 }
911
912
913 /*
914 * 'delete_printer_from_class()' - Delete a printer from a class.
915 */
916
917 static int /* O - 0 on success, 1 on fail */
918 delete_printer_from_class(
919 http_t *http, /* I - Server connection */
920 char *printer, /* I - Printer to remove */
921 char *pclass) /* I - Class to remove from */
922 {
923 int i, j, k; /* Looping vars */
924 ipp_t *request, /* IPP Request */
925 *response; /* IPP Response */
926 ipp_attribute_t *attr, /* Current attribute */
927 *members; /* Members in class */
928 char uri[HTTP_MAX_URI]; /* URI for printer/class */
929
930
931 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
932 printer, pclass));
933
934 /*
935 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
936 * attributes:
937 *
938 * attributes-charset
939 * attributes-natural-language
940 * printer-uri
941 * requesting-user-name
942 */
943
944 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
945
946 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
947 "localhost", 0, "/classes/%s", pclass);
948 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
949 "printer-uri", NULL, uri);
950 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
951 NULL, cupsUser());
952
953 /*
954 * Do the request and get back a response...
955 */
956
957 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
958 response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND)
959 {
960 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
961
962 ippDelete(response);
963
964 return (1);
965 }
966
967 /*
968 * See if the printer is already in the class...
969 */
970
971 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
972 {
973 _cupsLangPuts(stderr, _("lpadmin: No member names were seen."));
974
975 ippDelete(response);
976
977 return (1);
978 }
979
980 for (i = 0; i < members->num_values; i ++)
981 if (!_cups_strcasecmp(printer, members->values[i].string.text))
982 break;
983
984 if (i >= members->num_values)
985 {
986 _cupsLangPrintf(stderr,
987 _("lpadmin: Printer %s is not a member of class %s."),
988 printer, pclass);
989
990 ippDelete(response);
991
992 return (1);
993 }
994
995 if (members->num_values == 1)
996 {
997 /*
998 * Build a CUPS-Delete-Class request, which requires the following
999 * attributes:
1000 *
1001 * attributes-charset
1002 * attributes-natural-language
1003 * printer-uri
1004 * requesting-user-name
1005 */
1006
1007 request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS);
1008
1009 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1010 "printer-uri", NULL, uri);
1011 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1012 "requesting-user-name", NULL, cupsUser());
1013 }
1014 else
1015 {
1016 /*
1017 * Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following
1018 * attributes:
1019 *
1020 * attributes-charset
1021 * attributes-natural-language
1022 * printer-uri
1023 * requesting-user-name
1024 * member-uris
1025 */
1026
1027 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1028
1029 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1030 "printer-uri", NULL, uri);
1031 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1032 "requesting-user-name", NULL, cupsUser());
1033
1034 /*
1035 * Delete the printer from the class...
1036 */
1037
1038 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1039 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1040 "member-uris", members->num_values - 1, NULL, NULL);
1041
1042 for (j = 0, k = 0; j < members->num_values; j ++)
1043 if (j != i)
1044 attr->values[k ++].string.text =
1045 _cupsStrAlloc(members->values[j].string.text);
1046 }
1047
1048 /*
1049 * Then send the request...
1050 */
1051
1052 ippDelete(response);
1053
1054 ippDelete(cupsDoRequest(http, request, "/admin/"));
1055
1056 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1057 {
1058 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1059
1060 return (1);
1061 }
1062 else
1063 return (0);
1064 }
1065
1066
1067 /*
1068 * 'delete_printer_option()' - Delete a printer option.
1069 */
1070
1071 static int /* O - 0 on success, 1 on fail */
1072 delete_printer_option(http_t *http, /* I - Server connection */
1073 char *printer, /* I - Printer */
1074 char *option) /* I - Option to delete */
1075 {
1076 ipp_t *request; /* IPP request */
1077 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1078
1079
1080 /*
1081 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
1082 * requires the following attributes:
1083 *
1084 * attributes-charset
1085 * attributes-natural-language
1086 * printer-uri
1087 * requesting-user-name
1088 * option with deleteAttr tag
1089 */
1090
1091 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1092 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1093 else
1094 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1095
1096 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1097 "printer-uri", NULL, uri);
1098 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1099 "requesting-user-name", NULL, cupsUser());
1100 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);
1101
1102 /*
1103 * Do the request and get back a response...
1104 */
1105
1106 ippDelete(cupsDoRequest(http, request, "/admin/"));
1107
1108 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1109 {
1110 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1111
1112 return (1);
1113 }
1114 else
1115 return (0);
1116 }
1117
1118
1119 /*
1120 * 'enable_printer()' - Enable a printer...
1121 */
1122
1123 static int /* O - 0 on success, 1 on fail */
1124 enable_printer(http_t *http, /* I - Server connection */
1125 char *printer) /* I - Printer to enable */
1126 {
1127 ipp_t *request; /* IPP Request */
1128 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1129
1130
1131 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1132
1133 /*
1134 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
1135 * require the following attributes:
1136 *
1137 * attributes-charset
1138 * attributes-natural-language
1139 * printer-uri
1140 * requesting-user-name
1141 * printer-state
1142 * printer-is-accepting-jobs
1143 */
1144
1145 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1146 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1147 else
1148 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1149
1150 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1151 "printer-uri", NULL, uri);
1152 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1153 "requesting-user-name", NULL, cupsUser());
1154 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1155 IPP_PSTATE_IDLE);
1156 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1157
1158 /*
1159 * Do the request and get back a response...
1160 */
1161
1162 ippDelete(cupsDoRequest(http, request, "/admin/"));
1163
1164 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1165 {
1166 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1167
1168 return (1);
1169 }
1170 else
1171 return (0);
1172 }
1173
1174
1175 /*
1176 * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
1177 */
1178
1179 static char * /* O - Filename or NULL */
1180 get_printer_ppd(const char *uri, /* I - Printer URI */
1181 char *buffer, /* I - Filename buffer */
1182 size_t bufsize) /* I - Size of filename buffer */
1183 {
1184 http_t *http; /* Connection to printer */
1185 ipp_t *request, /* Get-Printer-Attributes request */
1186 *response; /* Get-Printer-Attributes response */
1187 char resolved[1024], /* Resolved URI */
1188 scheme[32], /* URI scheme */
1189 userpass[256], /* Username:password */
1190 host[256], /* Hostname */
1191 resource[256]; /* Resource path */
1192 int port; /* Port number */
1193
1194
1195 /*
1196 * Connect to the printer...
1197 */
1198
1199 if (strstr(uri, "._tcp"))
1200 {
1201 /*
1202 * Resolve URI...
1203 */
1204
1205 if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
1206 {
1207 _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri);
1208 return (NULL);
1209 }
1210
1211 uri = resolved;
1212 }
1213
1214 if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
1215 {
1216 _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri);
1217 return (NULL);
1218 }
1219
1220 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
1221 if (!http)
1222 {
1223 _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString());
1224 return (NULL);
1225 }
1226
1227 /*
1228 * Send a Get-Printer-Attributes request...
1229 */
1230
1231 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1232 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1233 response = cupsDoRequest(http, request, resource);
1234
1235 if (!_ppdCreateFromIPP(buffer, bufsize, response))
1236 _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno));
1237
1238 ippDelete(response);
1239 httpClose(http);
1240
1241 if (buffer[0])
1242 return (buffer);
1243 else
1244 return (NULL);
1245 }
1246
1247
1248 /*
1249 * 'get_printer_type()' - Determine the printer type and URI.
1250 */
1251
1252 static cups_ptype_t /* O - printer-type value */
1253 get_printer_type(http_t *http, /* I - Server connection */
1254 char *printer, /* I - Printer name */
1255 char *uri, /* I - URI buffer */
1256 size_t urisize) /* I - Size of URI buffer */
1257 {
1258 ipp_t *request, /* IPP request */
1259 *response; /* IPP response */
1260 ipp_attribute_t *attr; /* printer-type attribute */
1261 cups_ptype_t type; /* printer-type value */
1262
1263
1264 /*
1265 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1266 * attributes:
1267 *
1268 * attributes-charset
1269 * attributes-natural-language
1270 * printer-uri
1271 * requested-attributes
1272 * requesting-user-name
1273 */
1274
1275 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
1276
1277 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1278 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1279 "printer-uri", NULL, uri);
1280 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1281 "requested-attributes", NULL, "printer-type");
1282 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1283 "requesting-user-name", NULL, cupsUser());
1284
1285 /*
1286 * Do the request...
1287 */
1288
1289 response = cupsDoRequest(http, request, "/");
1290 if ((attr = ippFindAttribute(response, "printer-type",
1291 IPP_TAG_ENUM)) != NULL)
1292 {
1293 type = (cups_ptype_t)attr->values[0].integer;
1294
1295 if (type & CUPS_PRINTER_CLASS)
1296 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer);
1297 }
1298 else
1299 type = CUPS_PRINTER_LOCAL;
1300
1301 ippDelete(response);
1302
1303 return (type);
1304 }
1305
1306
1307 /*
1308 * 'set_printer_options()' - Set the printer options.
1309 */
1310
1311 static int /* O - 0 on success, 1 on fail */
1312 set_printer_options(
1313 http_t *http, /* I - Server connection */
1314 char *printer, /* I - Printer */
1315 int num_options, /* I - Number of options */
1316 cups_option_t *options, /* I - Options */
1317 char *file) /* I - PPD file/interface script */
1318 {
1319 ipp_t *request; /* IPP Request */
1320 const char *ppdfile; /* PPD filename */
1321 int ppdchanged = 0; /* PPD changed? */
1322 ppd_file_t *ppd; /* PPD file */
1323 ppd_choice_t *choice; /* Marked choice */
1324 char uri[HTTP_MAX_URI], /* URI for printer/class */
1325 line[1024], /* Line from PPD file */
1326 keyword[1024], /* Keyword from Default line */
1327 *keyptr, /* Pointer into keyword... */
1328 tempfile[1024]; /* Temporary filename */
1329 cups_file_t *in, /* PPD file */
1330 *out; /* Temporary file */
1331 const char *ppdname, /* ppd-name value */
1332 *protocol, /* Old protocol option */
1333 *customval, /* Custom option value */
1334 *boolval; /* Boolean value */
1335 int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */
1336 wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */
1337 copied_options = 0; /* Copied options? */
1338
1339
1340 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1341 "options=%p, file=\"%s\")\n", http, printer, num_options,
1342 options, file));
1343
1344 /*
1345 * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request,
1346 * which requires the following attributes:
1347 *
1348 * attributes-charset
1349 * attributes-natural-language
1350 * printer-uri
1351 * requesting-user-name
1352 * other options
1353 */
1354
1355 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1356 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1357 else
1358 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1359
1360 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1361 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
1362
1363 /*
1364 * Add the options...
1365 */
1366
1367 if (file)
1368 ppdfile = file;
1369 else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "raw") && num_options > 1)
1370 {
1371 if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL)
1372 {
1373 /*
1374 * Copy options array and remove ppd-name from it...
1375 */
1376
1377 cups_option_t *temp = NULL, *optr;
1378 int i, num_temp = 0;
1379 for (i = num_options, optr = options; i > 0; i --, optr ++)
1380 if (strcmp(optr->name, "ppd-name"))
1381 num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp);
1382
1383 copied_options = 1;
1384 ppdchanged = 1;
1385 num_options = num_temp;
1386 options = temp;
1387 }
1388 }
1389 else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER)
1390 ppdfile = cupsGetPPD(printer);
1391 else
1392 ppdfile = NULL;
1393
1394 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
1395 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1396
1397 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1398 {
1399 if (!_cups_strcasecmp(protocol, "bcp"))
1400 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1401 NULL, "bcp");
1402 else if (!_cups_strcasecmp(protocol, "tbcp"))
1403 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1404 NULL, "tbcp");
1405 }
1406
1407 if (ppdfile)
1408 {
1409 /*
1410 * Set default options in the PPD file...
1411 */
1412
1413 if ((ppd = ppdOpenFile(ppdfile)) == NULL)
1414 {
1415 int linenum; /* Line number of error */
1416 ppd_status_t status = ppdLastError(&linenum);
1417 /* Status code */
1418
1419 _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum);
1420 }
1421
1422 ppdMarkDefaults(ppd);
1423 cupsMarkOptions(ppd, num_options, options);
1424
1425 if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
1426 {
1427 _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
1428 ippDelete(request);
1429 if (ppdfile != file)
1430 unlink(ppdfile);
1431 if (copied_options)
1432 cupsFreeOptions(num_options, options);
1433 return (1);
1434 }
1435
1436 if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
1437 {
1438 _cupsLangPrintf(stderr,
1439 _("lpadmin: Unable to open PPD file \"%s\" - %s"),
1440 ppdfile, strerror(errno));
1441 ippDelete(request);
1442 if (ppdfile != file)
1443 unlink(ppdfile);
1444 if (copied_options)
1445 cupsFreeOptions(num_options, options);
1446 cupsFileClose(out);
1447 unlink(tempfile);
1448 return (1);
1449 }
1450
1451 while (cupsFileGets(in, line, sizeof(line)))
1452 {
1453 if (!strncmp(line, "*cupsIPPSupplies:", 17) &&
1454 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1455 options)) != NULL)
1456 {
1457 wrote_ipp_supplies = 1;
1458 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1459 (!_cups_strcasecmp(boolval, "true") ||
1460 !_cups_strcasecmp(boolval, "yes") ||
1461 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1462 }
1463 else if (!strncmp(line, "*cupsSNMPSupplies:", 18) &&
1464 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1465 options)) != NULL)
1466 {
1467 wrote_snmp_supplies = 1;
1468 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1469 (!_cups_strcasecmp(boolval, "true") ||
1470 !_cups_strcasecmp(boolval, "yes") ||
1471 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1472 }
1473 else if (strncmp(line, "*Default", 8))
1474 cupsFilePrintf(out, "%s\n", line);
1475 else
1476 {
1477 /*
1478 * Get default option name...
1479 */
1480
1481 strlcpy(keyword, line + 8, sizeof(keyword));
1482
1483 for (keyptr = keyword; *keyptr; keyptr ++)
1484 if (*keyptr == ':' || isspace(*keyptr & 255))
1485 break;
1486
1487 *keyptr++ = '\0';
1488 while (isspace(*keyptr & 255))
1489 keyptr ++;
1490
1491 if (!strcmp(keyword, "PageRegion") ||
1492 !strcmp(keyword, "PageSize") ||
1493 !strcmp(keyword, "PaperDimension") ||
1494 !strcmp(keyword, "ImageableArea"))
1495 {
1496 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1497 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1498 }
1499 else
1500 choice = ppdFindMarkedChoice(ppd, keyword);
1501
1502 if (choice && strcmp(choice->choice, keyptr))
1503 {
1504 if (strcmp(choice->choice, "Custom"))
1505 {
1506 cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
1507 ppdchanged = 1;
1508 }
1509 else if ((customval = cupsGetOption(keyword, num_options,
1510 options)) != NULL)
1511 {
1512 cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
1513 ppdchanged = 1;
1514 }
1515 else
1516 cupsFilePrintf(out, "%s\n", line);
1517 }
1518 else
1519 cupsFilePrintf(out, "%s\n", line);
1520 }
1521 }
1522
1523 if (!wrote_ipp_supplies &&
1524 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1525 options)) != NULL)
1526 {
1527 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1528 (!_cups_strcasecmp(boolval, "true") ||
1529 !_cups_strcasecmp(boolval, "yes") ||
1530 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1531 }
1532
1533 if (!wrote_snmp_supplies &&
1534 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1535 options)) != NULL)
1536 {
1537 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1538 (!_cups_strcasecmp(boolval, "true") ||
1539 !_cups_strcasecmp(boolval, "yes") ||
1540 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1541 }
1542
1543 cupsFileClose(in);
1544 cupsFileClose(out);
1545 ppdClose(ppd);
1546
1547 /*
1548 * Do the request...
1549 */
1550
1551 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1552 ppdchanged ? tempfile : file));
1553
1554 /*
1555 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1556 * lpadmin)
1557 */
1558
1559 if (ppdfile != file)
1560 unlink(ppdfile);
1561 unlink(tempfile);
1562 }
1563 else
1564 {
1565 /*
1566 * No PPD file - just set the options...
1567 */
1568
1569 ippDelete(cupsDoRequest(http, request, "/admin/"));
1570 }
1571
1572 if (copied_options)
1573 cupsFreeOptions(num_options, options);
1574
1575 /*
1576 * Check the response...
1577 */
1578
1579 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1580 {
1581 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1582
1583 return (1);
1584 }
1585 else
1586 return (0);
1587 }
1588
1589
1590 /*
1591 * 'validate_name()' - Make sure the printer name only contains valid chars.
1592 */
1593
1594 static int /* O - 0 if name is no good, 1 if name is good */
1595 validate_name(const char *name) /* I - Name to check */
1596 {
1597 const char *ptr; /* Pointer into name */
1598
1599
1600 /*
1601 * Scan the whole name...
1602 */
1603
1604 for (ptr = name; *ptr; ptr ++)
1605 if (*ptr == '@')
1606 break;
1607 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1608 *ptr == '#')
1609 return (0);
1610
1611 /*
1612 * All the characters are good; validate the length, too...
1613 */
1614
1615 return ((ptr - name) < 128);
1616 }
1617
1618
1619 /*
1620 * End of "$Id$".
1621 */