]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpadmin.c
Merge pull request #5155 from DavieV/check-printer-first
[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 * 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 (printer == NULL)
605 {
606 _cupsLangPuts(stderr,
607 _("lpadmin: Unable to set the printer options:\n"
608 " You must specify a printer name first."));
609 return (1);
610 }
611
612 if (!http)
613 {
614 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
615 cupsEncryption(), 1, 30000, NULL);
616
617 if (http == NULL) {
618 _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"),
619 strerror(errno));
620 return (1);
621 }
622 }
623
624 if (set_printer_options(http, printer, num_options, options, file))
625 return (1);
626 }
627
628 if (evefile[0])
629 unlink(evefile);
630
631 if (printer == NULL)
632 {
633 _cupsLangPuts(stdout,
634 _("Usage:\n"
635 "\n"
636 " lpadmin [-h server] -d destination\n"
637 " lpadmin [-h server] -x destination\n"
638 " lpadmin [-h server] -p printer [-c add-class] "
639 "[-i interface] [-m model]\n"
640 " [-r remove-class] [-v device] "
641 "[-D description]\n"
642 " [-P ppd-file] [-o name=value]\n"
643 " [-u allow:user,user] "
644 "[-u deny:user,user]"));
645 }
646
647 if (http)
648 httpClose(http);
649
650 return (0);
651 }
652
653
654 /*
655 * 'add_printer_to_class()' - Add a printer to a class.
656 */
657
658 static int /* O - 0 on success, 1 on fail */
659 add_printer_to_class(http_t *http, /* I - Server connection */
660 char *printer, /* I - Printer to add */
661 char *pclass) /* I - Class to add to */
662 {
663 int i; /* Looping var */
664 ipp_t *request, /* IPP Request */
665 *response; /* IPP Response */
666 ipp_attribute_t *attr, /* Current attribute */
667 *members; /* Members in class */
668 char uri[HTTP_MAX_URI]; /* URI for printer/class */
669
670
671 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
672 printer, pclass));
673
674 /*
675 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
676 * attributes:
677 *
678 * attributes-charset
679 * attributes-natural-language
680 * printer-uri
681 * requesting-user-name
682 */
683
684 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
685
686 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
687 "localhost", 0, "/classes/%s", pclass);
688 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
689 "printer-uri", NULL, uri);
690 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
691 NULL, cupsUser());
692
693 /*
694 * Do the request and get back a response...
695 */
696
697 response = cupsDoRequest(http, request, "/");
698
699 /*
700 * Build a CUPS-Add-Modify-Class request, which requires the following
701 * attributes:
702 *
703 * attributes-charset
704 * attributes-natural-language
705 * printer-uri
706 * requesting-user-name
707 * member-uris
708 */
709
710 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
711
712 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
713 "printer-uri", NULL, uri);
714 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
715 NULL, cupsUser());
716
717 /*
718 * See if the printer is already in the class...
719 */
720
721 if (response != NULL &&
722 (members = ippFindAttribute(response, "member-names",
723 IPP_TAG_NAME)) != NULL)
724 for (i = 0; i < members->num_values; i ++)
725 if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
726 {
727 _cupsLangPrintf(stderr,
728 _("lpadmin: Printer %s is already a member of class "
729 "%s."), printer, pclass);
730 ippDelete(request);
731 ippDelete(response);
732 return (0);
733 }
734
735 /*
736 * OK, the printer isn't part of the class, so add it...
737 */
738
739 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
740 "localhost", 0, "/printers/%s", printer);
741
742 if (response != NULL &&
743 (members = ippFindAttribute(response, "member-uris",
744 IPP_TAG_URI)) != NULL)
745 {
746 /*
747 * Add the printer to the existing list...
748 */
749
750 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
751 "member-uris", members->num_values + 1, NULL, NULL);
752 for (i = 0; i < members->num_values; i ++)
753 attr->values[i].string.text =
754 _cupsStrAlloc(members->values[i].string.text);
755
756 attr->values[i].string.text = _cupsStrAlloc(uri);
757 }
758 else
759 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
760 uri);
761
762 /*
763 * Then send the request...
764 */
765
766 ippDelete(response);
767
768 ippDelete(cupsDoRequest(http, request, "/admin/"));
769 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
770 {
771 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
772
773 return (1);
774 }
775 else
776 return (0);
777 }
778
779
780 /*
781 * 'default_printer()' - Set the default printing destination.
782 */
783
784 static int /* O - 0 on success, 1 on fail */
785 default_printer(http_t *http, /* I - Server connection */
786 char *printer) /* I - Printer name */
787 {
788 ipp_t *request; /* IPP Request */
789 char uri[HTTP_MAX_URI]; /* URI for printer/class */
790
791
792 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
793
794 /*
795 * Build a CUPS-Set-Default request, which requires the following
796 * attributes:
797 *
798 * attributes-charset
799 * attributes-natural-language
800 * printer-uri
801 * requesting-user-name
802 */
803
804 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
805 "localhost", 0, "/printers/%s", printer);
806
807 request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
808
809 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
810 "printer-uri", NULL, uri);
811 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
812 NULL, cupsUser());
813
814 /*
815 * Do the request and get back a response...
816 */
817
818 ippDelete(cupsDoRequest(http, request, "/admin/"));
819
820 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
821 {
822 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
823
824 return (1);
825 }
826 else
827 return (0);
828 }
829
830
831 /*
832 * 'delete_printer()' - Delete a printer from the system...
833 */
834
835 static int /* O - 0 on success, 1 on fail */
836 delete_printer(http_t *http, /* I - Server connection */
837 char *printer) /* I - Printer to delete */
838 {
839 ipp_t *request; /* IPP Request */
840 char uri[HTTP_MAX_URI]; /* URI for printer/class */
841
842
843 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
844
845 /*
846 * Build a CUPS-Delete-Printer request, which requires the following
847 * attributes:
848 *
849 * attributes-charset
850 * attributes-natural-language
851 * printer-uri
852 * requesting-user-name
853 */
854
855 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
856
857 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
858 "localhost", 0, "/printers/%s", printer);
859 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
860 "printer-uri", NULL, uri);
861 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
862 NULL, cupsUser());
863
864 /*
865 * Do the request and get back a response...
866 */
867
868 ippDelete(cupsDoRequest(http, request, "/admin/"));
869
870 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
871 {
872 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
873
874 return (1);
875 }
876 else
877 return (0);
878 }
879
880
881 /*
882 * 'delete_printer_from_class()' - Delete a printer from a class.
883 */
884
885 static int /* O - 0 on success, 1 on fail */
886 delete_printer_from_class(
887 http_t *http, /* I - Server connection */
888 char *printer, /* I - Printer to remove */
889 char *pclass) /* I - Class to remove from */
890 {
891 int i, j, k; /* Looping vars */
892 ipp_t *request, /* IPP Request */
893 *response; /* IPP Response */
894 ipp_attribute_t *attr, /* Current attribute */
895 *members; /* Members in class */
896 char uri[HTTP_MAX_URI]; /* URI for printer/class */
897
898
899 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
900 printer, pclass));
901
902 /*
903 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
904 * attributes:
905 *
906 * attributes-charset
907 * attributes-natural-language
908 * printer-uri
909 * requesting-user-name
910 */
911
912 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
913
914 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
915 "localhost", 0, "/classes/%s", pclass);
916 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
917 "printer-uri", NULL, uri);
918 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
919 NULL, cupsUser());
920
921 /*
922 * Do the request and get back a response...
923 */
924
925 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
926 response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND)
927 {
928 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
929
930 ippDelete(response);
931
932 return (1);
933 }
934
935 /*
936 * See if the printer is already in the class...
937 */
938
939 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
940 {
941 _cupsLangPuts(stderr, _("lpadmin: No member names were seen."));
942
943 ippDelete(response);
944
945 return (1);
946 }
947
948 for (i = 0; i < members->num_values; i ++)
949 if (!_cups_strcasecmp(printer, members->values[i].string.text))
950 break;
951
952 if (i >= members->num_values)
953 {
954 _cupsLangPrintf(stderr,
955 _("lpadmin: Printer %s is not a member of class %s."),
956 printer, pclass);
957
958 ippDelete(response);
959
960 return (1);
961 }
962
963 if (members->num_values == 1)
964 {
965 /*
966 * Build a CUPS-Delete-Class request, which requires the following
967 * attributes:
968 *
969 * attributes-charset
970 * attributes-natural-language
971 * printer-uri
972 * requesting-user-name
973 */
974
975 request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS);
976
977 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
978 "printer-uri", NULL, uri);
979 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
980 "requesting-user-name", NULL, cupsUser());
981 }
982 else
983 {
984 /*
985 * Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following
986 * attributes:
987 *
988 * attributes-charset
989 * attributes-natural-language
990 * printer-uri
991 * requesting-user-name
992 * member-uris
993 */
994
995 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
996
997 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
998 "printer-uri", NULL, uri);
999 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1000 "requesting-user-name", NULL, cupsUser());
1001
1002 /*
1003 * Delete the printer from the class...
1004 */
1005
1006 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1007 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1008 "member-uris", members->num_values - 1, NULL, NULL);
1009
1010 for (j = 0, k = 0; j < members->num_values; j ++)
1011 if (j != i)
1012 attr->values[k ++].string.text =
1013 _cupsStrAlloc(members->values[j].string.text);
1014 }
1015
1016 /*
1017 * Then send the request...
1018 */
1019
1020 ippDelete(response);
1021
1022 ippDelete(cupsDoRequest(http, request, "/admin/"));
1023
1024 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1025 {
1026 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1027
1028 return (1);
1029 }
1030 else
1031 return (0);
1032 }
1033
1034
1035 /*
1036 * 'delete_printer_option()' - Delete a printer option.
1037 */
1038
1039 static int /* O - 0 on success, 1 on fail */
1040 delete_printer_option(http_t *http, /* I - Server connection */
1041 char *printer, /* I - Printer */
1042 char *option) /* I - Option to delete */
1043 {
1044 ipp_t *request; /* IPP request */
1045 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1046
1047
1048 /*
1049 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
1050 * requires the following attributes:
1051 *
1052 * attributes-charset
1053 * attributes-natural-language
1054 * printer-uri
1055 * requesting-user-name
1056 * option with deleteAttr tag
1057 */
1058
1059 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1060 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1061 else
1062 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1063
1064 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1065 "printer-uri", NULL, uri);
1066 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1067 "requesting-user-name", NULL, cupsUser());
1068 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);
1069
1070 /*
1071 * Do the request and get back a response...
1072 */
1073
1074 ippDelete(cupsDoRequest(http, request, "/admin/"));
1075
1076 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1077 {
1078 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1079
1080 return (1);
1081 }
1082 else
1083 return (0);
1084 }
1085
1086
1087 /*
1088 * 'enable_printer()' - Enable a printer...
1089 */
1090
1091 static int /* O - 0 on success, 1 on fail */
1092 enable_printer(http_t *http, /* I - Server connection */
1093 char *printer) /* I - Printer to enable */
1094 {
1095 ipp_t *request; /* IPP Request */
1096 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1097
1098
1099 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1100
1101 /*
1102 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
1103 * require the following attributes:
1104 *
1105 * attributes-charset
1106 * attributes-natural-language
1107 * printer-uri
1108 * requesting-user-name
1109 * printer-state
1110 * printer-is-accepting-jobs
1111 */
1112
1113 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1114 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1115 else
1116 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1117
1118 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1119 "printer-uri", NULL, uri);
1120 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1121 "requesting-user-name", NULL, cupsUser());
1122 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1123 IPP_PSTATE_IDLE);
1124 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1125
1126 /*
1127 * Do the request and get back a response...
1128 */
1129
1130 ippDelete(cupsDoRequest(http, request, "/admin/"));
1131
1132 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1133 {
1134 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1135
1136 return (1);
1137 }
1138 else
1139 return (0);
1140 }
1141
1142
1143 /*
1144 * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
1145 */
1146
1147 static char * /* O - Filename or NULL */
1148 get_printer_ppd(const char *uri, /* I - Printer URI */
1149 char *buffer, /* I - Filename buffer */
1150 size_t bufsize) /* I - Size of filename buffer */
1151 {
1152 http_t *http; /* Connection to printer */
1153 ipp_t *request, /* Get-Printer-Attributes request */
1154 *response; /* Get-Printer-Attributes response */
1155 char resolved[1024], /* Resolved URI */
1156 scheme[32], /* URI scheme */
1157 userpass[256], /* Username:password */
1158 host[256], /* Hostname */
1159 resource[256]; /* Resource path */
1160 int port; /* Port number */
1161
1162
1163 /*
1164 * Connect to the printer...
1165 */
1166
1167 if (strstr(uri, "._tcp"))
1168 {
1169 /*
1170 * Resolve URI...
1171 */
1172
1173 if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
1174 {
1175 _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri);
1176 return (NULL);
1177 }
1178
1179 uri = resolved;
1180 }
1181
1182 if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
1183 {
1184 _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri);
1185 return (NULL);
1186 }
1187
1188 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
1189 if (!http)
1190 {
1191 _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString());
1192 return (NULL);
1193 }
1194
1195 /*
1196 * Send a Get-Printer-Attributes request...
1197 */
1198
1199 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1200 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1201 response = cupsDoRequest(http, request, resource);
1202
1203 if (!_ppdCreateFromIPP(buffer, bufsize, response))
1204 _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno));
1205
1206 ippDelete(response);
1207 httpClose(http);
1208
1209 if (buffer[0])
1210 return (buffer);
1211 else
1212 return (NULL);
1213 }
1214
1215
1216 /*
1217 * 'get_printer_type()' - Determine the printer type and URI.
1218 */
1219
1220 static cups_ptype_t /* O - printer-type value */
1221 get_printer_type(http_t *http, /* I - Server connection */
1222 char *printer, /* I - Printer name */
1223 char *uri, /* I - URI buffer */
1224 size_t urisize) /* I - Size of URI buffer */
1225 {
1226 ipp_t *request, /* IPP request */
1227 *response; /* IPP response */
1228 ipp_attribute_t *attr; /* printer-type attribute */
1229 cups_ptype_t type; /* printer-type value */
1230
1231
1232 /*
1233 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1234 * attributes:
1235 *
1236 * attributes-charset
1237 * attributes-natural-language
1238 * printer-uri
1239 * requested-attributes
1240 * requesting-user-name
1241 */
1242
1243 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
1244
1245 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1246 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1247 "printer-uri", NULL, uri);
1248 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1249 "requested-attributes", NULL, "printer-type");
1250 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1251 "requesting-user-name", NULL, cupsUser());
1252
1253 /*
1254 * Do the request...
1255 */
1256
1257 response = cupsDoRequest(http, request, "/");
1258 if ((attr = ippFindAttribute(response, "printer-type",
1259 IPP_TAG_ENUM)) != NULL)
1260 {
1261 type = (cups_ptype_t)attr->values[0].integer;
1262
1263 if (type & CUPS_PRINTER_CLASS)
1264 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer);
1265 }
1266 else
1267 type = CUPS_PRINTER_LOCAL;
1268
1269 ippDelete(response);
1270
1271 return (type);
1272 }
1273
1274
1275 /*
1276 * 'set_printer_options()' - Set the printer options.
1277 */
1278
1279 static int /* O - 0 on success, 1 on fail */
1280 set_printer_options(
1281 http_t *http, /* I - Server connection */
1282 char *printer, /* I - Printer */
1283 int num_options, /* I - Number of options */
1284 cups_option_t *options, /* I - Options */
1285 char *file) /* I - PPD file/interface script */
1286 {
1287 ipp_t *request; /* IPP Request */
1288 const char *ppdfile; /* PPD filename */
1289 int ppdchanged = 0; /* PPD changed? */
1290 ppd_file_t *ppd; /* PPD file */
1291 ppd_choice_t *choice; /* Marked choice */
1292 char uri[HTTP_MAX_URI], /* URI for printer/class */
1293 line[1024], /* Line from PPD file */
1294 keyword[1024], /* Keyword from Default line */
1295 *keyptr, /* Pointer into keyword... */
1296 tempfile[1024]; /* Temporary filename */
1297 cups_file_t *in, /* PPD file */
1298 *out; /* Temporary file */
1299 const char *ppdname, /* ppd-name value */
1300 *protocol, /* Old protocol option */
1301 *customval, /* Custom option value */
1302 *boolval; /* Boolean value */
1303 int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */
1304 wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */
1305 copied_options = 0; /* Copied options? */
1306
1307
1308 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1309 "options=%p, file=\"%s\")\n", http, printer, num_options,
1310 options, file));
1311
1312 /*
1313 * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request,
1314 * which requires the following attributes:
1315 *
1316 * attributes-charset
1317 * attributes-natural-language
1318 * printer-uri
1319 * requesting-user-name
1320 * other options
1321 */
1322
1323 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1324 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1325 else
1326 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1327
1328 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1329 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
1330
1331 /*
1332 * Add the options...
1333 */
1334
1335 if (file)
1336 ppdfile = file;
1337 else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "raw") && num_options > 1)
1338 {
1339 if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL)
1340 {
1341 /*
1342 * Copy options array and remove ppd-name from it...
1343 */
1344
1345 cups_option_t *temp = NULL, *optr;
1346 int i, num_temp = 0;
1347 for (i = num_options, optr = options; i > 0; i --, optr ++)
1348 if (strcmp(optr->name, "ppd-name"))
1349 num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp);
1350
1351 copied_options = 1;
1352 ppdchanged = 1;
1353 num_options = num_temp;
1354 options = temp;
1355 }
1356 }
1357 else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER)
1358 ppdfile = cupsGetPPD(printer);
1359 else
1360 ppdfile = NULL;
1361
1362 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
1363 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1364
1365 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1366 {
1367 if (!_cups_strcasecmp(protocol, "bcp"))
1368 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1369 NULL, "bcp");
1370 else if (!_cups_strcasecmp(protocol, "tbcp"))
1371 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1372 NULL, "tbcp");
1373 }
1374
1375 if (ppdfile)
1376 {
1377 /*
1378 * Set default options in the PPD file...
1379 */
1380
1381 if ((ppd = ppdOpenFile(ppdfile)) == NULL)
1382 {
1383 int linenum; /* Line number of error */
1384 ppd_status_t status = ppdLastError(&linenum);
1385 /* Status code */
1386
1387 _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum);
1388 }
1389
1390 ppdMarkDefaults(ppd);
1391 cupsMarkOptions(ppd, num_options, options);
1392
1393 if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
1394 {
1395 _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
1396 ippDelete(request);
1397 if (ppdfile != file)
1398 unlink(ppdfile);
1399 if (copied_options)
1400 cupsFreeOptions(num_options, options);
1401 return (1);
1402 }
1403
1404 if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
1405 {
1406 _cupsLangPrintf(stderr,
1407 _("lpadmin: Unable to open PPD file \"%s\" - %s"),
1408 ppdfile, strerror(errno));
1409 ippDelete(request);
1410 if (ppdfile != file)
1411 unlink(ppdfile);
1412 if (copied_options)
1413 cupsFreeOptions(num_options, options);
1414 cupsFileClose(out);
1415 unlink(tempfile);
1416 return (1);
1417 }
1418
1419 while (cupsFileGets(in, line, sizeof(line)))
1420 {
1421 if (!strncmp(line, "*cupsIPPSupplies:", 17) &&
1422 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1423 options)) != NULL)
1424 {
1425 wrote_ipp_supplies = 1;
1426 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1427 (!_cups_strcasecmp(boolval, "true") ||
1428 !_cups_strcasecmp(boolval, "yes") ||
1429 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1430 }
1431 else if (!strncmp(line, "*cupsSNMPSupplies:", 18) &&
1432 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1433 options)) != NULL)
1434 {
1435 wrote_snmp_supplies = 1;
1436 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1437 (!_cups_strcasecmp(boolval, "true") ||
1438 !_cups_strcasecmp(boolval, "yes") ||
1439 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1440 }
1441 else if (strncmp(line, "*Default", 8))
1442 cupsFilePrintf(out, "%s\n", line);
1443 else
1444 {
1445 /*
1446 * Get default option name...
1447 */
1448
1449 strlcpy(keyword, line + 8, sizeof(keyword));
1450
1451 for (keyptr = keyword; *keyptr; keyptr ++)
1452 if (*keyptr == ':' || isspace(*keyptr & 255))
1453 break;
1454
1455 *keyptr++ = '\0';
1456 while (isspace(*keyptr & 255))
1457 keyptr ++;
1458
1459 if (!strcmp(keyword, "PageRegion") ||
1460 !strcmp(keyword, "PageSize") ||
1461 !strcmp(keyword, "PaperDimension") ||
1462 !strcmp(keyword, "ImageableArea"))
1463 {
1464 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1465 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1466 }
1467 else
1468 choice = ppdFindMarkedChoice(ppd, keyword);
1469
1470 if (choice && strcmp(choice->choice, keyptr))
1471 {
1472 if (strcmp(choice->choice, "Custom"))
1473 {
1474 cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
1475 ppdchanged = 1;
1476 }
1477 else if ((customval = cupsGetOption(keyword, num_options,
1478 options)) != NULL)
1479 {
1480 cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
1481 ppdchanged = 1;
1482 }
1483 else
1484 cupsFilePrintf(out, "%s\n", line);
1485 }
1486 else
1487 cupsFilePrintf(out, "%s\n", line);
1488 }
1489 }
1490
1491 if (!wrote_ipp_supplies &&
1492 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1493 options)) != NULL)
1494 {
1495 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1496 (!_cups_strcasecmp(boolval, "true") ||
1497 !_cups_strcasecmp(boolval, "yes") ||
1498 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1499 }
1500
1501 if (!wrote_snmp_supplies &&
1502 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1503 options)) != NULL)
1504 {
1505 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1506 (!_cups_strcasecmp(boolval, "true") ||
1507 !_cups_strcasecmp(boolval, "yes") ||
1508 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1509 }
1510
1511 cupsFileClose(in);
1512 cupsFileClose(out);
1513 ppdClose(ppd);
1514
1515 /*
1516 * Do the request...
1517 */
1518
1519 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1520 ppdchanged ? tempfile : file));
1521
1522 /*
1523 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1524 * lpadmin)
1525 */
1526
1527 if (ppdfile != file)
1528 unlink(ppdfile);
1529 unlink(tempfile);
1530 }
1531 else
1532 {
1533 /*
1534 * No PPD file - just set the options...
1535 */
1536
1537 ippDelete(cupsDoRequest(http, request, "/admin/"));
1538 }
1539
1540 if (copied_options)
1541 cupsFreeOptions(num_options, options);
1542
1543 /*
1544 * Check the response...
1545 */
1546
1547 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1548 {
1549 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1550
1551 return (1);
1552 }
1553 else
1554 return (0);
1555 }
1556
1557
1558 /*
1559 * 'validate_name()' - Make sure the printer name only contains valid chars.
1560 */
1561
1562 static int /* O - 0 if name is no good, 1 if name is good */
1563 validate_name(const char *name) /* I - Name to check */
1564 {
1565 const char *ptr; /* Pointer into name */
1566
1567
1568 /*
1569 * Scan the whole name...
1570 */
1571
1572 for (ptr = name; *ptr; ptr ++)
1573 if (*ptr == '@')
1574 break;
1575 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1576 *ptr == '#')
1577 return (0);
1578
1579 /*
1580 * All the characters are good; validate the length, too...
1581 */
1582
1583 return ((ptr - name) < 128);
1584 }