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