]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpadmin.c
Merge changes from 1.4svn-r7067.
[thirdparty/cups.git] / systemv / lpadmin.c
CommitLineData
ef416fc2 1/*
bc44d920 2 * "$Id: lpadmin.c 6649 2007-07-11 21:46:42Z mike $"
ef416fc2 3 *
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
ef416fc2 7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 14 *
15 * Contents:
16 *
17 * main() - Parse options and configure the scheduler.
18 * add_printer_to_class() - Add a printer to a class.
19 * default_printer() - Set the default printing destination.
20 * delete_printer() - Delete a printer from the system...
21 * delete_printer_from_class() - Delete a printer from a class.
22 * enable_printer() - Enable a printer...
23 * set_printer_device() - Set the device-uri attribute.
24 * set_printer_file() - Set the interface script or PPD file.
25 * set_printer_info() - Set the printer description string.
26 * set_printer_location() - Set the printer location string.
27 * set_printer_model() - Set the driver model file.
28 * set_printer_options() - Set the printer options.
29 * validate_name() - Make sure the printer name only contains
30 * valid chars...
31 */
32
33/*
34 * Include necessary headers...
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <ctype.h>
40#include <errno.h>
41#include <cups/string.h>
42#include <cups/cups.h>
43#include <cups/i18n.h>
44#include <cups/debug.h>
45#ifdef HAVE_LIBZ
46# include <zlib.h>
47#endif /* HAVE_LIBZ */
48
49
50/*
51 * Local functions...
52 */
53
54static int add_printer_to_class(http_t *, char *, char *);
55static int default_printer(http_t *, char *);
56static int delete_printer(http_t *, char *);
57static int delete_printer_from_class(http_t *, char *, char *);
58static int enable_printer(http_t *, char *);
59static char *get_line(char *, int, FILE *fp);
60static int set_printer_device(http_t *, char *, char *);
61static int set_printer_file(http_t *, char *, char *);
62static int set_printer_info(http_t *, char *, char *);
63static int set_printer_location(http_t *, char *, char *);
64static int set_printer_model(http_t *, char *, char *);
65static int set_printer_options(http_t *, char *, int, cups_option_t *);
66static int validate_name(const char *);
67
68
69/*
70 * 'main()' - Parse options and configure the scheduler.
71 */
72
73int
74main(int argc, /* I - Number of command-line arguments */
75 char *argv[]) /* I - Command-line arguments */
76{
77 int i; /* Looping var */
78 http_t *http; /* Connection to server */
79 char *printer, /* Destination printer */
80 *pclass, /* Printer class name */
81 *val; /* Pointer to allow/deny value */
82 int num_options; /* Number of options */
83 cups_option_t *options; /* Options */
84
85
07725fee 86 _cupsSetLocale(argv);
d09495fa 87
ef416fc2 88 http = NULL;
89 printer = NULL;
90 num_options = 0;
91 options = NULL;
92
93 for (i = 1; i < argc; i ++)
94 if (argv[i][0] == '-')
95 switch (argv[i][1])
96 {
97 case 'c' : /* Add printer to class */
98 if (!http)
99 {
100 http = httpConnectEncrypt(cupsServer(), ippPort(),
101 cupsEncryption());
102
103 if (http == NULL)
104 {
fa73b229 105 _cupsLangPrintf(stderr,
ef416fc2 106 _("lpadmin: Unable to connect to server: %s\n"),
107 strerror(errno));
108 return (1);
109 }
110 }
111
112 if (printer == NULL)
113 {
fa73b229 114 _cupsLangPuts(stderr,
ef416fc2 115 _("lpadmin: Unable to add a printer to the class:\n"
116 " You must specify a printer name "
117 "first!\n"));
118 return (1);
119 }
120
121 if (argv[i][2])
122 pclass = argv[i] + 2;
123 else
124 {
125 i ++;
126
127 if (i >= argc)
128 {
fa73b229 129 _cupsLangPuts(stderr,
ef416fc2 130 _("lpadmin: Expected class name after \'-c\' "
131 "option!\n"));
132 return (1);
133 }
134
135 pclass = argv[i];
136 }
137
138 if (!validate_name(pclass))
139 {
fa73b229 140 _cupsLangPuts(stderr,
ef416fc2 141 _("lpadmin: Class name can only contain printable "
142 "characters!\n"));
143 return (1);
144 }
145
146 if (add_printer_to_class(http, printer, pclass))
147 return (1);
148 break;
149
150 case 'd' : /* Set as default destination */
151 if (!http)
152 {
153 http = httpConnectEncrypt(cupsServer(), ippPort(),
154 cupsEncryption());
155
156 if (http == NULL)
157 {
fa73b229 158 _cupsLangPrintf(stderr,
ef416fc2 159 _("lpadmin: Unable to connect to server: %s\n"),
160 strerror(errno));
161 return (1);
162 }
163 }
164
165 if (argv[i][2])
166 printer = argv[i] + 2;
167 else
168 {
169 i ++;
170
171 if (i >= argc)
172 {
fa73b229 173 _cupsLangPuts(stderr,
ef416fc2 174 _("lpadmin: Expected printer name after \'-d\' "
175 "option!\n"));
176 return (1);
177 }
178
179 printer = argv[i];
180 }
181
182 if (!validate_name(printer))
183 {
fa73b229 184 _cupsLangPuts(stderr,
ef416fc2 185 _("lpadmin: Printer name can only contain "
186 "printable characters!\n"));
187 return (1);
188 }
189
190 if (default_printer(http, printer))
191 return (1);
192
193 i = argc;
194 break;
195
196 case 'h' : /* Connect to host */
197 if (http)
198 {
199 httpClose(http);
200 http = NULL;
201 }
202
203 if (argv[i][2] != '\0')
204 cupsSetServer(argv[i] + 2);
205 else
206 {
207 i ++;
208
209 if (i >= argc)
210 {
fa73b229 211 _cupsLangPuts(stderr,
ef416fc2 212 _("lpadmin: Expected hostname after \'-h\' "
213 "option!\n"));
214 return (1);
215 }
216
217 cupsSetServer(argv[i]);
218 }
219 break;
220
221 case 'i' : /* Use the specified interface script */
222 if (!http)
223 {
224 http = httpConnectEncrypt(cupsServer(), ippPort(),
225 cupsEncryption());
226
227 if (http == NULL)
228 {
fa73b229 229 _cupsLangPrintf(stderr,
ef416fc2 230 _("lpadmin: Unable to connect to server: %s\n"),
231 strerror(errno));
232 return (1);
233 }
234 }
235
236 if (printer == NULL)
237 {
fa73b229 238 _cupsLangPuts(stderr,
ef416fc2 239 _("lpadmin: Unable to set the interface script:\n"
240 " You must specify a printer name "
241 "first!\n"));
242 return (1);
243 }
244
245 if (argv[i][2])
246 {
247 if (set_printer_file(http, printer, argv[i] + 2))
248 return (1);
249 }
250 else
251 {
252 i ++;
253
254 if (i >= argc)
255 {
fa73b229 256 _cupsLangPuts(stderr,
ef416fc2 257 _("lpadmin: Expected interface after \'-i\' "
258 "option!\n"));
259 return (1);
260 }
261
262 if (set_printer_file(http, printer, argv[i]))
263 return (1);
264 }
265 break;
266
267 case 'E' : /* Enable the printer */
268 if (printer == NULL)
269 {
270#ifdef HAVE_SSL
271 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
272
273 if (http)
274 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
275#else
fa73b229 276 _cupsLangPrintf(stderr,
ef416fc2 277 _("%s: Sorry, no encryption support compiled in!\n"),
278 argv[0]);
279#endif /* HAVE_SSL */
280 break;
281 }
282
283 if (!http)
284 {
285 http = httpConnectEncrypt(cupsServer(), ippPort(),
286 cupsEncryption());
287
288 if (http == NULL)
289 {
fa73b229 290 _cupsLangPrintf(stderr,
ef416fc2 291 _("lpadmin: Unable to connect to server: %s\n"),
292 strerror(errno));
293 return (1);
294 }
295 }
296
297 if (enable_printer(http, printer))
298 return (1);
299 break;
300
301 case 'm' : /* Use the specified standard script/PPD file */
302 if (!http)
303 {
304 http = httpConnectEncrypt(cupsServer(), ippPort(),
305 cupsEncryption());
306
307 if (http == NULL)
308 {
fa73b229 309 _cupsLangPrintf(stderr,
ef416fc2 310 _("lpadmin: Unable to connect to server: %s\n"),
311 strerror(errno));
312 return (1);
313 }
314 }
315
316 if (printer == NULL)
317 {
fa73b229 318 _cupsLangPuts(stderr,
ef416fc2 319 _("lpadmin: Unable to set the interface script or "
320 "PPD file:\n"
321 " You must specify a printer name "
322 "first!\n"));
323 return (1);
324 }
325
326 if (argv[i][2])
327 {
328 if (set_printer_model(http, printer, argv[i] + 2))
329 return (1);
330 }
331 else
332 {
333 i ++;
334
335 if (i >= argc)
336 {
fa73b229 337 _cupsLangPuts(stderr,
ef416fc2 338 _("lpadmin: Expected model after \'-m\' "
339 "option!\n"));
340 return (1);
341 }
342
343 if (set_printer_model(http, printer, argv[i]))
344 return (1);
345 }
346 break;
347
348 case 'o' : /* Set option */
349 if (argv[i][2])
350 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
351 else
352 {
353 i ++;
354
355 if (i >= argc)
356 {
fa73b229 357 _cupsLangPuts(stderr,
ef416fc2 358 _("lpadmin: Expected name=value after \'-o\' "
359 "option!\n"));
360 return (1);
361 }
362
363 num_options = cupsParseOptions(argv[i], num_options, &options);
364 }
365 break;
366
367 case 'p' : /* Add/modify a printer */
368 if (!http)
369 {
370 http = httpConnectEncrypt(cupsServer(), ippPort(),
371 cupsEncryption());
372
373 if (http == NULL)
374 {
fa73b229 375 _cupsLangPrintf(stderr,
ef416fc2 376 _("lpadmin: Unable to connect to server: %s\n"),
377 strerror(errno));
378 return (1);
379 }
380 }
381
382 if (argv[i][2])
383 printer = argv[i] + 2;
384 else
385 {
386 i ++;
387
388 if (i >= argc)
389 {
fa73b229 390 _cupsLangPuts(stderr,
ef416fc2 391 _("lpadmin: Expected printer after \'-p\' "
392 "option!\n"));
393 return (1);
394 }
395
396 printer = argv[i];
397 }
398
399 if (!validate_name(printer))
400 {
fa73b229 401 _cupsLangPuts(stderr,
ef416fc2 402 _("lpadmin: Printer name can only contain "
403 "printable characters!\n"));
404 return (1);
405 }
406 break;
407
408 case 'r' : /* Remove printer from class */
409 if (!http)
410 {
411 http = httpConnectEncrypt(cupsServer(), ippPort(),
412 cupsEncryption());
413
414 if (http == NULL)
415 {
fa73b229 416 _cupsLangPrintf(stderr,
ef416fc2 417 _("lpadmin: Unable to connect to server: %s\n"),
418 strerror(errno));
419 return (1);
420 }
421 }
422
423 if (printer == NULL)
424 {
fa73b229 425 _cupsLangPuts(stderr,
ef416fc2 426 _("lpadmin: Unable to remove a printer from the "
427 "class:\n"
428 " You must specify a printer name "
429 "first!\n"));
430 return (1);
431 }
432
433 if (argv[i][2])
434 pclass = argv[i] + 2;
435 else
436 {
437 i ++;
438
439 if (i >= argc)
440 {
fa73b229 441 _cupsLangPuts(stderr,
ef416fc2 442 _("lpadmin: Expected class after \'-r\' "
443 "option!\n"));
444 return (1);
445 }
446
447 pclass = argv[i];
448 }
449
450 if (!validate_name(pclass))
451 {
fa73b229 452 _cupsLangPuts(stderr,
ef416fc2 453 _("lpadmin: Class name can only contain printable "
454 "characters!\n"));
455 return (1);
456 }
457
458 if (delete_printer_from_class(http, printer, pclass))
459 return (1);
460 break;
461
f301802f 462 case 'U' : /* Username */
463 if (argv[i][2] != '\0')
464 cupsSetUser(argv[i] + 2);
465 else
466 {
467 i ++;
468 if (i >= argc)
469 {
470 _cupsLangPrintf(stderr,
471 _("%s: Error - expected username after "
472 "\'-U\' option!\n"),
473 argv[0]);
474 return (1);
475 }
476
477 cupsSetUser(argv[i]);
478 }
479 break;
480
ef416fc2 481 case 'u' : /* Allow/deny users */
482 if (argv[i][2])
483 val = argv[i] + 2;
484 else
485 {
486 i ++;
487
488 if (i >= argc)
489 {
fa73b229 490 _cupsLangPuts(stderr,
ef416fc2 491 _("lpadmin: Expected allow/deny:userlist after "
492 "\'-u\' option!\n"));
493 return (1);
494 }
495
496 val = argv[i];
497 }
498
499 if (!strncasecmp(val, "allow:", 6))
500 num_options = cupsAddOption("requesting-user-name-allowed",
501 val + 6, num_options, &options);
502 else if (!strncasecmp(val, "deny:", 5))
503 num_options = cupsAddOption("requesting-user-name-denied",
504 val + 5, num_options, &options);
505 else
506 {
fa73b229 507 _cupsLangPrintf(stderr,
ef416fc2 508 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
509 val);
510 return (1);
511 }
512 break;
513
514 case 'v' : /* Set the device-uri attribute */
515 if (!http)
516 {
517 http = httpConnectEncrypt(cupsServer(), ippPort(),
518 cupsEncryption());
519
520 if (http == NULL)
521 {
fa73b229 522 _cupsLangPrintf(stderr,
ef416fc2 523 _("lpadmin: Unable to connect to server: %s\n"),
524 strerror(errno));
525 return (1);
526 }
527 }
528
529 if (printer == NULL)
530 {
fa73b229 531 _cupsLangPuts(stderr,
ef416fc2 532 _("lpadmin: Unable to set the device URI:\n"
533 " You must specify a printer name "
534 "first!\n"));
535 return (1);
536 }
537
538 if (argv[i][2])
539 {
540 if (set_printer_device(http, printer, argv[i] + 2))
541 return (1);
542 }
543 else
544 {
545 i ++;
546
547 if (i >= argc)
548 {
fa73b229 549 _cupsLangPuts(stderr,
ef416fc2 550 _("lpadmin: Expected device URI after \'-v\' "
551 "option!\n"));
552 return (1);
553 }
554
555 if (set_printer_device(http, printer, argv[i]))
556 return (1);
557 }
558 break;
559
560 case 'x' : /* Delete a printer */
561 if (!http)
562 {
563 http = httpConnectEncrypt(cupsServer(), ippPort(),
564 cupsEncryption());
565
566 if (http == NULL)
567 {
fa73b229 568 _cupsLangPrintf(stderr,
ef416fc2 569 _("lpadmin: Unable to connect to server: %s\n"),
570 strerror(errno));
571 return (1);
572 }
573 }
574
575 if (argv[i][2])
576 printer = argv[i] + 2;
577 else
578 {
579 i ++;
580
581 if (i >= argc)
582 {
fa73b229 583 _cupsLangPuts(stderr,
ef416fc2 584 _("lpadmin: Expected printer or class after "
585 "\'-x\' option!\n"));
586 return (1);
587 }
588
589 printer = argv[i];
590 }
591
592 if (!validate_name(printer))
593 {
fa73b229 594 _cupsLangPuts(stderr,
ef416fc2 595 _("lpadmin: Printer name can only contain "
596 "printable characters!\n"));
597 return (1);
598 }
599
600 if (delete_printer(http, printer))
601 return (1);
602
603 i = argc;
604 break;
605
606 case 'D' : /* Set the printer-info attribute */
607 if (!http)
608 {
609 http = httpConnectEncrypt(cupsServer(), ippPort(),
610 cupsEncryption());
611
612 if (http == NULL)
613 {
fa73b229 614 _cupsLangPrintf(stderr,
ef416fc2 615 _("lpadmin: Unable to connect to server: %s\n"),
616 strerror(errno));
617 return (1);
618 }
619 }
620
621 if (printer == NULL)
622 {
fa73b229 623 _cupsLangPuts(stderr,
ef416fc2 624 _("lpadmin: Unable to set the printer "
625 "description:\n"
626 " You must specify a printer name "
627 "first!\n"));
628 return (1);
629 }
630
631 if (argv[i][2])
632 {
633 if (set_printer_info(http, printer, argv[i] + 2))
634 return (1);
635 }
636 else
637 {
638 i ++;
639
640 if (i >= argc)
641 {
fa73b229 642 _cupsLangPuts(stderr,
ef416fc2 643 _("lpadmin: Expected description after "
644 "\'-D\' option!\n"));
645 return (1);
646 }
647
648 if (set_printer_info(http, printer, argv[i]))
649 return (1);
650 }
651 break;
652
653 case 'I' : /* Set the supported file types (ignored) */
654 i ++;
655
656 if (i >= argc)
657 {
fa73b229 658 _cupsLangPuts(stderr,
ef416fc2 659 _("lpadmin: Expected file type(s) after \'-I\' "
660 "option!\n"));
661 return (1);
662 }
663
fa73b229 664 _cupsLangPuts(stderr,
ef416fc2 665 _("lpadmin: Warning - content type list ignored!\n"));
666 break;
667
668 case 'L' : /* Set the printer-location attribute */
669 if (!http)
670 {
671 http = httpConnectEncrypt(cupsServer(), ippPort(),
672 cupsEncryption());
673
674 if (http == NULL)
675 {
fa73b229 676 _cupsLangPrintf(stderr,
ef416fc2 677 _("lpadmin: Unable to connect to server: %s\n"),
678 strerror(errno));
679 return (1);
680 }
681 }
682
683 if (printer == NULL)
684 {
fa73b229 685 _cupsLangPuts(stderr,
ef416fc2 686 _("lpadmin: Unable to set the printer location:\n"
687 " You must specify a printer name "
688 "first!\n"));
689 return (1);
690 }
691
692 if (argv[i][2])
693 {
694 if (set_printer_location(http, printer, argv[i] + 2))
695 return (1);
696 }
697 else
698 {
699 i ++;
700
701 if (i >= argc)
702 {
fa73b229 703 _cupsLangPuts(stderr,
ef416fc2 704 _("lpadmin: Expected location after \'-L\' "
705 "option!\n"));
706 return (1);
707 }
708
709 if (set_printer_location(http, printer, argv[i]))
710 return (1);
711 }
712 break;
713
714 case 'P' : /* Use the specified PPD file */
715 if (!http)
716 {
717 http = httpConnectEncrypt(cupsServer(), ippPort(),
718 cupsEncryption());
719
720 if (http == NULL)
721 {
fa73b229 722 _cupsLangPrintf(stderr,
ef416fc2 723 _("lpadmin: Unable to connect to server: %s\n"),
724 strerror(errno));
725 return (1);
726 }
727 }
728
729 if (printer == NULL)
730 {
fa73b229 731 _cupsLangPuts(stderr,
ef416fc2 732 _("lpadmin: Unable to set the PPD file:\n"
733 " You must specify a printer name "
734 "first!\n"));
735 return (1);
736 }
737
738 if (argv[i][2])
739 {
740 if (set_printer_file(http, printer, argv[i] + 2))
741 return (1);
742 }
743 else
744 {
745 i ++;
746
747 if (i >= argc)
748 {
fa73b229 749 _cupsLangPuts(stderr,
ef416fc2 750 _("lpadmin: Expected PPD after \'-P\' option!\n"));
751 return (1);
752 }
753
754 if (set_printer_file(http, printer, argv[i]))
755 return (1);
756 }
757 break;
758
759 default :
fa73b229 760 _cupsLangPrintf(stderr,
ef416fc2 761 _("lpadmin: Unknown option \'%c\'!\n"), argv[i][1]);
762 return (1);
763 }
764 else
765 {
fa73b229 766 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \'%s\'!\n"),
ef416fc2 767 argv[i]);
768 return (1);
769 }
770
771 /*
772 * Set options as needed...
773 */
774
775 if (num_options)
776 {
777 if (!http)
778 {
779 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
780
781 if (http == NULL)
782 {
fa73b229 783 _cupsLangPrintf(stderr,
ef416fc2 784 _("lpadmin: Unable to connect to server: %s\n"),
785 strerror(errno));
786 return (1);
787 }
788 }
789
790 if (printer == NULL)
791 {
fa73b229 792 _cupsLangPuts(stderr,
ef416fc2 793 _("lpadmin: Unable to set the printer options:\n"
794 " You must specify a printer name first!\n"));
795 return (1);
796 }
797
798 if (set_printer_options(http, printer, num_options, options))
799 return (1);
800 }
801
802 if (printer == NULL)
803 {
fa73b229 804 _cupsLangPuts(stdout,
ef416fc2 805 _("Usage:\n"
806 "\n"
807 " lpadmin [-h server] -d destination\n"
808 " lpadmin [-h server] -x destination\n"
809 " lpadmin [-h server] -p printer [-c add-class] "
810 "[-i interface] [-m model]\n"
811 " [-r remove-class] [-v device] "
812 "[-D description]\n"
813 " [-P ppd-file] [-o name=value]\n"
814 " [-u allow:user,user] "
815 "[-u deny:user,user]\n"
816 "\n"));
817 }
818
819 if (http)
820 httpClose(http);
821
822 return (0);
823}
824
825
826/*
827 * 'add_printer_to_class()' - Add a printer to a class.
828 */
829
830static int /* O - 0 on success, 1 on fail */
831add_printer_to_class(http_t *http, /* I - Server connection */
832 char *printer, /* I - Printer to add */
833 char *pclass) /* I - Class to add to */
834{
835 int i; /* Looping var */
836 ipp_t *request, /* IPP Request */
837 *response; /* IPP Response */
838 ipp_attribute_t *attr, /* Current attribute */
839 *members; /* Members in class */
ef416fc2 840 char uri[HTTP_MAX_URI]; /* URI for printer/class */
841
842
843 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
844 printer, pclass));
845
846 /*
847 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
848 * attributes:
849 *
850 * attributes-charset
851 * attributes-natural-language
852 * printer-uri
853 */
854
fa73b229 855 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
856
a4d04587 857 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
858 "localhost", 0, "/classes/%s", pclass);
ef416fc2 859 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
860 "printer-uri", NULL, uri);
861
862 /*
863 * Do the request and get back a response...
864 */
865
866 response = cupsDoRequest(http, request, "/");
867
868 /*
869 * Build a CUPS_ADD_CLASS request, which requires the following
870 * attributes:
871 *
872 * attributes-charset
873 * attributes-natural-language
874 * printer-uri
875 * member-uris
876 */
877
fa73b229 878 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 879
880 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
881 "printer-uri", NULL, uri);
882
883 /*
884 * See if the printer is already in the class...
885 */
886
887 if (response != NULL &&
888 (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
889 for (i = 0; i < members->num_values; i ++)
890 if (strcasecmp(printer, members->values[i].string.text) == 0)
891 {
fa73b229 892 _cupsLangPrintf(stderr,
893 _("lpadmin: Printer %s is already a member of class %s.\n"),
894 printer, pclass);
ef416fc2 895 ippDelete(request);
896 ippDelete(response);
897 return (0);
898 }
899
900 /*
901 * OK, the printer isn't part of the class, so add it...
902 */
903
a4d04587 904 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
905 "localhost", 0, "/printers/%s", printer);
ef416fc2 906
907 if (response != NULL &&
908 (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
909 {
910 /*
911 * Add the printer to the existing list...
912 */
913
914 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
915 "member-uris", members->num_values + 1, NULL, NULL);
916 for (i = 0; i < members->num_values; i ++)
917 attr->values[i].string.text = strdup(members->values[i].string.text);
918
919 attr->values[i].string.text = strdup(uri);
920 }
921 else
922 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL, uri);
923
924 /*
925 * Then send the request...
926 */
927
928 ippDelete(response);
929
930 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
931 {
fa73b229 932 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 933
934 return (1);
935 }
936 else if (response->request.status.status_code > IPP_OK_CONFLICT)
937 {
fa73b229 938 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 939
940 ippDelete(response);
941
942 return (1);
943 }
944 else
945 {
946 ippDelete(response);
947
948 return (0);
949 }
950}
951
952
953/*
954 * 'default_printer()' - Set the default printing destination.
955 */
956
957static int /* O - 0 on success, 1 on fail */
958default_printer(http_t *http, /* I - Server connection */
959 char *printer) /* I - Printer name */
960{
961 ipp_t *request, /* IPP Request */
962 *response; /* IPP Response */
ef416fc2 963 char uri[HTTP_MAX_URI]; /* URI for printer/class */
964
965
966 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
967
968 /*
969 * Build a CUPS_SET_DEFAULT request, which requires the following
970 * attributes:
971 *
972 * attributes-charset
973 * attributes-natural-language
974 * printer-uri
975 */
976
a4d04587 977 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
978 "localhost", 0, "/printers/%s", printer);
ef416fc2 979
fa73b229 980 request = ippNewRequest(CUPS_SET_DEFAULT);
ef416fc2 981
982 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
983 "printer-uri", NULL, uri);
984
985 /*
986 * Do the request and get back a response...
987 */
988
989 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
990 {
fa73b229 991 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 992
993 return (1);
994 }
995 else if (response->request.status.status_code > IPP_OK_CONFLICT)
996 {
fa73b229 997 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 998
999 ippDelete(response);
1000
1001 return (1);
1002 }
1003 else
1004 {
1005 ippDelete(response);
1006
1007 return (0);
1008 }
1009}
1010
1011
1012/*
1013 * 'delete_printer()' - Delete a printer from the system...
1014 */
1015
1016static int /* O - 0 on success, 1 on fail */
1017delete_printer(http_t *http, /* I - Server connection */
1018 char *printer) /* I - Printer to delete */
1019{
1020 ipp_t *request, /* IPP Request */
1021 *response; /* IPP Response */
ef416fc2 1022 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1023
1024
1025 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
1026
1027 /*
1028 * Build a CUPS_DELETE_PRINTER request, which requires the following
1029 * attributes:
1030 *
1031 * attributes-charset
1032 * attributes-natural-language
1033 * printer-uri
1034 */
1035
fa73b229 1036 request = ippNewRequest(CUPS_DELETE_PRINTER);
1037
a4d04587 1038 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1039 "localhost", 0, "/printers/%s", printer);
ef416fc2 1040 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1041 "printer-uri", NULL, uri);
1042
1043 /*
1044 * Do the request and get back a response...
1045 */
1046
1047 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1048 {
fa73b229 1049 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1050
1051 return (1);
1052 }
1053 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1054 {
fa73b229 1055 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1056
1057 ippDelete(response);
1058
1059 return (1);
1060 }
1061 else
1062 {
1063 ippDelete(response);
1064
1065 return (0);
1066 }
1067}
1068
1069
1070/*
1071 * 'delete_printer_from_class()' - Delete a printer from a class.
1072 */
1073
1074static int /* O - 0 on success, 1 on fail */
fa73b229 1075delete_printer_from_class(
1076 http_t *http, /* I - Server connection */
1077 char *printer, /* I - Printer to remove */
1078 char *pclass) /* I - Class to remove from */
ef416fc2 1079{
1080 int i, j, k; /* Looping vars */
1081 ipp_t *request, /* IPP Request */
1082 *response; /* IPP Response */
1083 ipp_attribute_t *attr, /* Current attribute */
1084 *members; /* Members in class */
ef416fc2 1085 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1086
1087
1088 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
1089 printer, pclass));
1090
1091 /*
1092 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1093 * attributes:
1094 *
1095 * attributes-charset
1096 * attributes-natural-language
1097 * printer-uri
1098 */
1099
fa73b229 1100 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
1101
a4d04587 1102 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1103 "localhost", 0, "/classes/%s", pclass);
ef416fc2 1104 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1105 "printer-uri", NULL, uri);
1106
1107 /*
1108 * Do the request and get back a response...
1109 */
1110
1111 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
1112 response->request.status.status_code == IPP_NOT_FOUND)
1113 {
fa73b229 1114 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1115
ef416fc2 1116 ippDelete(response);
fa73b229 1117
ef416fc2 1118 return (1);
1119 }
1120
1121 /*
1122 * See if the printer is already in the class...
1123 */
1124
1125 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
1126 {
fa73b229 1127 _cupsLangPuts(stderr, _("lpadmin: No member names were seen!\n"));
1128
ef416fc2 1129 ippDelete(response);
fa73b229 1130
ef416fc2 1131 return (1);
1132 }
1133
1134 for (i = 0; i < members->num_values; i ++)
fa73b229 1135 if (!strcasecmp(printer, members->values[i].string.text))
ef416fc2 1136 break;
1137
1138 if (i >= members->num_values)
1139 {
fa73b229 1140 _cupsLangPrintf(stderr,
1141 _("lpadmin: Printer %s is not a member of class %s.\n"),
1142 printer, pclass);
1143
ef416fc2 1144 ippDelete(response);
fa73b229 1145
ef416fc2 1146 return (1);
1147 }
1148
1149 if (members->num_values == 1)
1150 {
1151 /*
1152 * Build a CUPS_DELETE_CLASS request, which requires the following
1153 * attributes:
1154 *
1155 * attributes-charset
1156 * attributes-natural-language
1157 * printer-uri
1158 */
1159
fa73b229 1160 request = ippNewRequest(CUPS_DELETE_CLASS);
ef416fc2 1161
1162 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1163 "printer-uri", NULL, uri);
1164 }
1165 else
1166 {
1167 /*
1168 * Build a CUPS_ADD_CLASS request, which requires the following
1169 * attributes:
1170 *
1171 * attributes-charset
1172 * attributes-natural-language
1173 * printer-uri
1174 * member-uris
1175 */
1176
fa73b229 1177 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 1178
1179 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1180 "printer-uri", NULL, uri);
1181
1182 /*
1183 * Delete the printer from the class...
1184 */
1185
1186 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1187 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1188 "member-uris", members->num_values - 1, NULL, NULL);
1189
1190 for (j = 0, k = 0; j < members->num_values; j ++)
1191 if (j != i)
1192 attr->values[k ++].string.text = strdup(members->values[j].string.text);
1193 }
1194
1195 /*
1196 * Then send the request...
1197 */
1198
1199 ippDelete(response);
1200
1201 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1202 {
fa73b229 1203 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1204
ef416fc2 1205 return (1);
1206 }
1207 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1208 {
fa73b229 1209 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1210
1211 ippDelete(response);
1212
1213 return (1);
1214 }
1215 else
1216 {
1217 ippDelete(response);
1218
1219 return (0);
1220 }
1221}
1222
1223
1224/*
1225 * 'enable_printer()' - Enable a printer...
1226 */
1227
1228static int /* O - 0 on success, 1 on fail */
1229enable_printer(http_t *http, /* I - Server connection */
1230 char *printer) /* I - Printer to enable */
1231{
1232 ipp_t *request, /* IPP Request */
1233 *response; /* IPP Response */
ef416fc2 1234 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1235
1236
1237 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1238
1239 /*
1240 * Build a CUPS_ADD_PRINTER request, which requires the following
1241 * attributes:
1242 *
1243 * attributes-charset
1244 * attributes-natural-language
1245 * printer-uri
1246 * printer-state
1247 * printer-is-accepting-jobs
1248 */
1249
fa73b229 1250 request = ippNewRequest(CUPS_ADD_PRINTER);
1251
a4d04587 1252 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1253 "localhost", 0, "/printers/%s", printer);
ef416fc2 1254 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1255 "printer-uri", NULL, uri);
1256
1257 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1258 IPP_PRINTER_IDLE);
1259
1260 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1261
1262 /*
1263 * Do the request and get back a response...
1264 */
1265
1266 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1267 {
fa73b229 1268 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1269
ef416fc2 1270 return (1);
1271 }
1272 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1273 {
fa73b229 1274 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1275
1276 ippDelete(response);
1277
1278 return (1);
1279 }
1280 else
1281 {
1282 ippDelete(response);
1283
1284 return (0);
1285 }
1286}
1287
1288
1289/*
1290 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1291 */
1292
1293static char * /* O - Pointer to buf or NULL on EOF */
1294get_line(char *buf, /* I - Line buffer */
1295 int length, /* I - Length of buffer */
1296 FILE *fp) /* I - File to read from */
1297{
1298 char *bufptr; /* Pointer into buffer */
1299 int ch; /* Character from file */
1300
1301
1302 length --;
1303 bufptr = buf;
1304
1305 while ((ch = getc(fp)) != EOF)
1306 {
1307 if (ch == '\n')
1308 break;
1309 else if (ch == '\r')
1310 {
1311 /*
1312 * Look for LF...
1313 */
1314
1315 ch = getc(fp);
1316 if (ch != '\n' && ch != EOF)
1317 ungetc(ch, fp);
1318
1319 break;
1320 }
1321
1322 *bufptr++ = ch;
1323 length --;
1324 if (length == 0)
1325 break;
1326 }
1327
1328 *bufptr = '\0';
1329
1330 if (ch == EOF)
1331 return (NULL);
1332 else
1333 return (buf);
1334}
1335
1336
1337/*
1338 * 'set_printer_device()' - Set the device-uri attribute.
1339 */
1340
1341static int /* O - 0 on success, 1 on fail */
1342set_printer_device(http_t *http, /* I - Server connection */
1343 char *printer, /* I - Printer */
1344 char *device) /* I - New device URI */
1345{
1346 ipp_t *request, /* IPP Request */
1347 *response; /* IPP Response */
ef416fc2 1348 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1349
1350
1351 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http, printer,
1352 device));
1353
1354 /*
1355 * Build a CUPS_ADD_PRINTER request, which requires the following
1356 * attributes:
1357 *
1358 * attributes-charset
1359 * attributes-natural-language
1360 * printer-uri
1361 */
1362
fa73b229 1363 request = ippNewRequest(CUPS_ADD_PRINTER);
1364
a4d04587 1365 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1366 "localhost", 0, "/printers/%s", printer);
ef416fc2 1367 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1368 "printer-uri", NULL, uri);
1369
1370 /*
1371 * Add the device URI...
1372 */
1373
1374 if (device[0] == '/')
1375 {
1376 /*
1377 * Convert filename to URI...
1378 */
1379
fa73b229 1380 snprintf(uri, sizeof(uri), "file://%s", device);
ef416fc2 1381 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1382 uri);
1383 }
1384 else
1385 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1386 device);
1387
1388 /*
1389 * Do the request and get back a response...
1390 */
1391
1392 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1393 {
fa73b229 1394 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1395
ef416fc2 1396 return (1);
1397 }
1398 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1399 {
fa73b229 1400 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1401
1402 ippDelete(response);
1403
1404 return (1);
1405 }
1406 else
1407 {
1408 ippDelete(response);
1409
1410 return (0);
1411 }
1412}
1413
1414
1415/*
1416 * 'set_printer_file()' - Set the interface script or PPD file.
1417 */
1418
1419static int /* O - 0 on success, 1 on fail */
1420set_printer_file(http_t *http, /* I - Server connection */
1421 char *printer, /* I - Printer */
1422 char *file) /* I - PPD file or interface script */
1423{
ef416fc2 1424 ipp_t *request, /* IPP Request */
1425 *response; /* IPP Response */
ef416fc2 1426 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1427#ifdef HAVE_LIBZ
1428 char tempfile[1024]; /* Temporary filename */
1429 int fd; /* Temporary file */
1430 gzFile *gz; /* GZIP'd file */
1431 char buffer[8192]; /* Copy buffer */
1432 int bytes; /* Bytes in buffer */
1433
1434
1435 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http, printer,
1436 file));
1437
1438 /*
1439 * See if the file is gzip'd; if so, unzip it to a temporary file and
1440 * send the uncompressed file.
1441 */
1442
1443 if (!strcmp(file + strlen(file) - 3, ".gz"))
1444 {
1445 /*
1446 * Yes, the file is compressed; uncompress to a temp file...
1447 */
1448
1449 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1450 {
fa73b229 1451 _cupsLangPrintf(stderr,
ef416fc2 1452 _("lpadmin: Unable to create temporary file: %s\n"),
1453 strerror(errno));
1454 return (1);
1455 }
1456
1457 if ((gz = gzopen(file, "rb")) == NULL)
1458 {
fa73b229 1459 _cupsLangPrintf(stderr,
ef416fc2 1460 _("lpadmin: Unable to open file \"%s\": %s\n"),
1461 file, strerror(errno));
1462 close(fd);
1463 unlink(tempfile);
1464 return (1);
1465 }
1466
1467 while ((bytes = gzread(gz, buffer, sizeof(buffer))) > 0)
1468 write(fd, buffer, bytes);
1469
1470 close(fd);
1471 gzclose(gz);
1472
1473 file = tempfile;
1474 }
1475#endif /* HAVE_LIBZ */
1476
1477 /*
1478 * Build a CUPS_ADD_PRINTER request, which requires the following
1479 * attributes:
1480 *
1481 * attributes-charset
1482 * attributes-natural-language
1483 * printer-uri
1484 */
1485
fa73b229 1486 request = ippNewRequest(CUPS_ADD_PRINTER);
1487
a4d04587 1488 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1489 "localhost", 0, "/printers/%s", printer);
ef416fc2 1490 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1491 "printer-uri", NULL, uri);
1492
1493 /*
1494 * Do the request and get back a response...
1495 */
1496
fa73b229 1497 response = cupsDoFileRequest(http, request, "/admin/", file);
1498 ippDelete(response);
ef416fc2 1499
1500#ifdef HAVE_LIBZ
1501 /*
1502 * Remove the temporary file as needed...
1503 */
1504
1505 if (file == tempfile)
1506 unlink(tempfile);
1507#endif /* HAVE_LIBZ */
1508
fa73b229 1509 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1510 {
fa73b229 1511 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1512
1513 return (1);
1514 }
1515 else
1516 return (0);
1517}
1518
1519
1520/*
1521 * 'set_printer_info()' - Set the printer description string.
1522 */
1523
1524static int /* O - 0 on success, 1 on fail */
1525set_printer_info(http_t *http, /* I - Server connection */
1526 char *printer, /* I - Printer */
1527 char *info) /* I - New description string */
1528{
1529 ipp_t *request, /* IPP Request */
1530 *response; /* IPP Response */
ef416fc2 1531 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1532
1533
1534 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http, printer,
1535 info));
1536
1537 /*
1538 * Build a CUPS_ADD_PRINTER request, which requires the following
1539 * attributes:
1540 *
1541 * attributes-charset
1542 * attributes-natural-language
1543 * printer-uri
1544 */
1545
fa73b229 1546 request = ippNewRequest(CUPS_ADD_PRINTER);
1547
a4d04587 1548 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1549 "localhost", 0, "/printers/%s", printer);
ef416fc2 1550 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1551 "printer-uri", NULL, uri);
1552
1553 /*
1554 * Add the info string...
1555 */
1556
1557 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL,
1558 info);
1559
1560 /*
1561 * Do the request and get back a response...
1562 */
1563
1564 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1565 {
fa73b229 1566 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1567 return (1);
1568 }
1569 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1570 {
fa73b229 1571 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1572
1573 ippDelete(response);
1574
1575 return (1);
1576 }
1577 else
1578 {
1579 ippDelete(response);
1580
1581 return (0);
1582 }
1583}
1584
1585
1586/*
1587 * 'set_printer_location()' - Set the printer location string.
1588 */
1589
1590static int /* O - 0 on success, 1 on fail */
1591set_printer_location(http_t *http, /* I - Server connection */
1592 char *printer, /* I - Printer */
1593 char *location) /* I - New location string */
1594{
1595 ipp_t *request, /* IPP Request */
1596 *response; /* IPP Response */
ef416fc2 1597 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1598
1599
1600 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http, printer,
1601 location));
1602
1603 /*
1604 * Build a CUPS_ADD_PRINTER request, which requires the following
1605 * attributes:
1606 *
1607 * attributes-charset
1608 * attributes-natural-language
1609 * printer-uri
1610 */
1611
fa73b229 1612 request = ippNewRequest(CUPS_ADD_PRINTER);
1613
a4d04587 1614 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1615 "localhost", 0, "/printers/%s", printer);
ef416fc2 1616 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1617 "printer-uri", NULL, uri);
1618
1619 /*
1620 * Add the location string...
1621 */
1622
1623 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL,
1624 location);
1625
1626 /*
1627 * Do the request and get back a response...
1628 */
1629
1630 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1631 {
fa73b229 1632 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1633
1634 return (1);
1635 }
1636 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1637 {
fa73b229 1638 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1639
1640 ippDelete(response);
1641
1642 return (1);
1643 }
1644 else
1645 {
1646 ippDelete(response);
1647
1648 return (0);
1649 }
1650}
1651
1652
1653/*
1654 * 'set_printer_model()' - Set the driver model file.
1655 */
1656
1657static int /* O - 0 on success, 1 on fail */
1658set_printer_model(http_t *http, /* I - Server connection */
1659 char *printer, /* I - Printer */
1660 char *model) /* I - Driver model file */
1661{
1662 ipp_t *request, /* IPP Request */
1663 *response; /* IPP Response */
ef416fc2 1664 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1665
1666
1667 /*
1668 * Build a CUPS_ADD_PRINTER request, which requires the following
1669 * attributes:
1670 *
1671 * attributes-charset
1672 * attributes-natural-language
1673 * printer-uri
1674 * ppd-name
1675 */
1676
fa73b229 1677 request = ippNewRequest(CUPS_ADD_PRINTER);
1678
a4d04587 1679 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1680 "localhost", 0, "/printers/%s", printer);
ef416fc2 1681 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1682 "printer-uri", NULL, uri);
1683
1684 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1685 "ppd-name", NULL, model);
1686
1687 /*
1688 * Do the request and get back a response...
1689 */
1690
1691 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1692 {
fa73b229 1693 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1694
1695 return (1);
1696 }
1697 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1698 {
fa73b229 1699 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1700
1701 ippDelete(response);
1702
1703 return (1);
1704 }
1705 else
1706 {
1707 ippDelete(response);
1708
1709 return (0);
1710 }
1711}
1712
1713
1714/*
1715 * 'set_printer_options()' - Set the printer options.
1716 */
1717
1718static int /* O - 0 on success, 1 on fail */
fa73b229 1719set_printer_options(
1720 http_t *http, /* I - Server connection */
1721 char *printer, /* I - Printer */
1722 int num_options, /* I - Number of options */
1723 cups_option_t *options) /* I - Options */
ef416fc2 1724{
1725 ipp_t *request, /* IPP Request */
1726 *response; /* IPP Response */
1727 ipp_attribute_t *attr; /* IPP attribute */
ef416fc2 1728 ipp_op_t op; /* Operation to perform */
b423cd4c 1729 const char *ppdfile; /* PPD filename */
1730 int ppdchanged; /* PPD changed? */
1731 ppd_file_t *ppd; /* PPD file */
1732 ppd_choice_t *choice; /* Marked choice */
ef416fc2 1733 char uri[HTTP_MAX_URI], /* URI for printer/class */
1734 line[1024], /* Line from PPD file */
1735 keyword[1024], /* Keyword from Default line */
1736 *keyptr, /* Pointer into keyword... */
1737 tempfile[1024]; /* Temporary filename */
1738 FILE *in, /* PPD file */
1739 *out; /* Temporary file */
1740 int outfd; /* Temporary file descriptor */
b423cd4c 1741 const char *protocol; /* Old protocol option */
ef416fc2 1742
1743
1744 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http, printer,
1745 num_options, options));
1746
a4d04587 1747 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1748 "localhost", 0, "/printers/%s", printer);
ef416fc2 1749
1750 /*
1751 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1752 * attributes:
1753 *
1754 * attributes-charset
1755 * attributes-natural-language
1756 * printer-uri
1757 * requested-attributes
1758 */
1759
fa73b229 1760 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 1761
1762 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1763 "printer-uri", NULL, uri);
1764
1765 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1766 "requested-attributes", NULL, "printer-type");
1767
1768 /*
1769 * Do the request...
1770 */
1771
1772 op = CUPS_ADD_PRINTER;
1773
1774 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1775 {
1776 /*
1777 * See what kind of printer or class it is...
1778 */
1779
b423cd4c 1780 if ((attr = ippFindAttribute(response, "printer-type",
1781 IPP_TAG_ENUM)) != NULL)
ef416fc2 1782 {
1783 if (attr->values[0].integer & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
1784 {
1785 op = CUPS_ADD_CLASS;
a4d04587 1786 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1787 "localhost", 0, "/classes/%s", printer);
ef416fc2 1788 }
1789 }
1790
1791 ippDelete(response);
1792 }
1793
1794 /*
1795 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1796 * the following attributes:
1797 *
1798 * attributes-charset
1799 * attributes-natural-language
1800 * printer-uri
1801 * other options
1802 */
1803
fa73b229 1804 request = ippNewRequest(op);
ef416fc2 1805
1806 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1807 "printer-uri", NULL, uri);
1808
1809 /*
1810 * Add the options...
1811 */
1812
b423cd4c 1813 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1814
1815 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1816 {
1817 if (!strcasecmp(protocol, "bcp"))
a41f09e2 1818 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
b423cd4c 1819 NULL, "bcp");
1820 else if (!strcasecmp(protocol, "tbcp"))
a41f09e2 1821 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
b423cd4c 1822 NULL, "tbcp");
1823 }
ef416fc2 1824
1825 if (op == CUPS_ADD_PRINTER)
1826 ppdfile = cupsGetPPD(printer);
1827 else
1828 ppdfile = NULL;
1829
1830 if (ppdfile != NULL)
1831 {
1832 /*
1833 * Set default options in the PPD file...
1834 */
1835
b423cd4c 1836 ppd = ppdOpenFile(ppdfile);
1837 ppdMarkDefaults(ppd);
1838 cupsMarkOptions(ppd, num_options, options);
1839
ef416fc2 1840 if ((outfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1841 {
fa73b229 1842 _cupsLangPrintf(stderr,
ef416fc2 1843 _("lpadmin: Unable to create temporary file - %s\n"),
1844 strerror(errno));
1845 ippDelete(request);
1846 unlink(ppdfile);
1847 return (1);
1848 }
1849
1850 if ((in = fopen(ppdfile, "rb")) == NULL)
1851 {
fa73b229 1852 _cupsLangPrintf(stderr,
ef416fc2 1853 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1854 ppdfile, strerror(errno));
1855 ippDelete(request);
1856 unlink(ppdfile);
1857 close(outfd);
1858 unlink(tempfile);
1859 return (1);
1860 }
1861
b423cd4c 1862 out = fdopen(outfd, "wb");
1863 ppdchanged = 0;
ef416fc2 1864
1865 while (get_line(line, sizeof(line), in) != NULL)
1866 {
b423cd4c 1867 if (strncmp(line, "*Default", 8))
ef416fc2 1868 fprintf(out, "%s\n", line);
1869 else
1870 {
1871 /*
1872 * Get default option name...
1873 */
1874
1875 strlcpy(keyword, line + 8, sizeof(keyword));
1876
1877 for (keyptr = keyword; *keyptr; keyptr ++)
1878 if (*keyptr == ':' || isspace(*keyptr & 255))
1879 break;
1880
b423cd4c 1881 *keyptr++ = '\0';
1882 while (isspace(*keyptr & 255))
1883 keyptr ++;
1884
1885 if (!strcmp(keyword, "PageRegion") ||
1886 !strcmp(keyword, "PageSize") ||
1887 !strcmp(keyword, "PaperDimension") ||
1888 !strcmp(keyword, "ImageableArea"))
1889 {
1890 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1891 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1892 }
ef416fc2 1893 else
b423cd4c 1894 choice = ppdFindMarkedChoice(ppd, keyword);
ef416fc2 1895
b423cd4c 1896 if (choice && strcmp(choice->choice, keyptr))
1897 {
1898 fprintf(out, "*Default%s: %s\n", keyword, choice->choice);
1899 ppdchanged = 1;
1900 }
ef416fc2 1901 else
1902 fprintf(out, "%s\n", line);
1903 }
1904 }
1905
ef416fc2 1906 fclose(in);
1907 fclose(out);
1908 close(outfd);
b423cd4c 1909 ppdClose(ppd);
ef416fc2 1910
1911 /*
1912 * Do the request...
1913 */
1914
b423cd4c 1915 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1916 ppdchanged ? tempfile : NULL));
ef416fc2 1917
1918 /*
1919 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1920 * lpadmin)
1921 */
1922
1923 unlink(ppdfile);
1924 unlink(tempfile);
1925 }
1926 else
1927 {
1928 /*
1929 * No PPD file - just set the options...
1930 */
1931
b423cd4c 1932 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1933 }
1934
1935 /*
1936 * Check the response...
1937 */
1938
fa73b229 1939 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1940 {
fa73b229 1941 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1942
1943 return (1);
1944 }
1945 else
ef416fc2 1946 return (0);
ef416fc2 1947}
1948
1949
1950/*
1951 * 'validate_name()' - Make sure the printer name only contains valid chars.
1952 */
1953
fa73b229 1954static int /* O - 0 if name is no good, 1 if name is good */
1955validate_name(const char *name) /* I - Name to check */
ef416fc2 1956{
fa73b229 1957 const char *ptr; /* Pointer into name */
ef416fc2 1958
1959
1960 /*
1961 * Scan the whole name...
1962 */
1963
1964 for (ptr = name; *ptr; ptr ++)
1965 if (*ptr == '@')
1966 break;
1967 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1968 *ptr == '#')
1969 return (0);
1970
1971 /*
1972 * All the characters are good; validate the length, too...
1973 */
1974
1975 return ((ptr - name) < 128);
1976}
1977
1978
1979/*
bc44d920 1980 * End of "$Id: lpadmin.c 6649 2007-07-11 21:46:42Z mike $".
ef416fc2 1981 */