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