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