]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpadmin.c
Merge changes from CUPS 1.5svn-r8849.
[thirdparty/cups.git] / systemv / lpadmin.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $"
ef416fc2 3 *
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
5 *
f0ab5bff 6 * Copyright 2007-2009 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 "
4d301e69 117 "first\n"));
ef416fc2 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\' "
4d301e69 131 "option\n"));
ef416fc2 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 "
4d301e69 142 "characters\n"));
ef416fc2 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\' "
4d301e69 175 "option\n"));
ef416fc2 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 "
4d301e69 186 "printable characters\n"));
ef416fc2 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\' "
4d301e69 213 "option\n"));
ef416fc2 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 "
4d301e69 241 "first\n"));
ef416fc2 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\' "
4d301e69 258 "option\n"));
ef416fc2 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,
4d301e69 277 _("%s: Sorry, no encryption support compiled in\n"),
ef416fc2 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 "
4d301e69 322 "first\n"));
ef416fc2 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\' "
4d301e69 339 "option\n"));
ef416fc2 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\' "
4d301e69 359 "option\n"));
ef416fc2 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\' "
4d301e69 392 "option\n"));
ef416fc2 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 "
4d301e69 403 "printable characters\n"));
ef416fc2 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 "
4d301e69 429 "first\n"));
ef416fc2 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\' "
4d301e69 443 "option\n"));
ef416fc2 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 "
4d301e69 454 "characters\n"));
ef416fc2 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 "
4d301e69 472 "\'-U\' option\n"),
f301802f 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 "
4d301e69 492 "\'-u\' option\n"));
ef416fc2 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,
4d301e69 508 _("lpadmin: Unknown allow/deny option \"%s\"\n"),
ef416fc2 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 "
4d301e69 534 "first\n"));
ef416fc2 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\' "
4d301e69 551 "option\n"));
ef416fc2 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 "
4d301e69 585 "\'-x\' option\n"));
ef416fc2 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 "
4d301e69 596 "printable characters\n"));
ef416fc2 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 "
4d301e69 627 "first\n"));
ef416fc2 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 "
4d301e69 644 "\'-D\' option\n"));
ef416fc2 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\' "
4d301e69 660 "option\n"));
ef416fc2 661 return (1);
662 }
663
fa73b229 664 _cupsLangPuts(stderr,
4d301e69 665 _("lpadmin: Warning - content type list ignored\n"));
ef416fc2 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 "
4d301e69 688 "first\n"));
ef416fc2 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\' "
4d301e69 705 "option\n"));
ef416fc2 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 "
4d301e69 734 "first\n"));
ef416fc2 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,
4d301e69 750 _("lpadmin: Expected PPD after \'-P\' option\n"));
ef416fc2 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,
4d301e69 761 _("lpadmin: Unknown option \'%c\'\n"), argv[i][1]);
ef416fc2 762 return (1);
763 }
764 else
765 {
4d301e69 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"
4d301e69 794 " You must specify a printer name first\n"));
ef416fc2 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 ++)
1f0275e3 917 attr->values[i].string.text = _cupsStrAlloc(members->values[i].string.text);
ef416fc2 918
1f0275e3 919 attr->values[i].string.text = _cupsStrAlloc(uri);
ef416fc2 920 }
921 else
1f0275e3
MS
922 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
923 uri);
ef416fc2 924
925 /*
926 * Then send the request...
927 */
928
929 ippDelete(response);
930
931 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
932 {
fa73b229 933 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 934
935 return (1);
936 }
937 else if (response->request.status.status_code > IPP_OK_CONFLICT)
938 {
fa73b229 939 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 940
941 ippDelete(response);
942
943 return (1);
944 }
945 else
946 {
947 ippDelete(response);
948
949 return (0);
950 }
951}
952
953
954/*
955 * 'default_printer()' - Set the default printing destination.
956 */
957
958static int /* O - 0 on success, 1 on fail */
959default_printer(http_t *http, /* I - Server connection */
960 char *printer) /* I - Printer name */
961{
962 ipp_t *request, /* IPP Request */
963 *response; /* IPP Response */
ef416fc2 964 char uri[HTTP_MAX_URI]; /* URI for printer/class */
965
966
967 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
968
969 /*
970 * Build a CUPS_SET_DEFAULT request, which requires the following
971 * attributes:
972 *
973 * attributes-charset
974 * attributes-natural-language
975 * printer-uri
976 */
977
a4d04587 978 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
979 "localhost", 0, "/printers/%s", printer);
ef416fc2 980
fa73b229 981 request = ippNewRequest(CUPS_SET_DEFAULT);
ef416fc2 982
983 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
984 "printer-uri", NULL, uri);
985
986 /*
987 * Do the request and get back a response...
988 */
989
990 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
991 {
fa73b229 992 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 993
994 return (1);
995 }
996 else if (response->request.status.status_code > IPP_OK_CONFLICT)
997 {
fa73b229 998 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 999
1000 ippDelete(response);
1001
1002 return (1);
1003 }
1004 else
1005 {
1006 ippDelete(response);
1007
1008 return (0);
1009 }
1010}
1011
1012
1013/*
1014 * 'delete_printer()' - Delete a printer from the system...
1015 */
1016
1017static int /* O - 0 on success, 1 on fail */
1018delete_printer(http_t *http, /* I - Server connection */
1019 char *printer) /* I - Printer to delete */
1020{
1021 ipp_t *request, /* IPP Request */
1022 *response; /* IPP Response */
ef416fc2 1023 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1024
1025
1026 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
1027
1028 /*
1029 * Build a CUPS_DELETE_PRINTER request, which requires the following
1030 * attributes:
1031 *
1032 * attributes-charset
1033 * attributes-natural-language
1034 * printer-uri
1035 */
1036
fa73b229 1037 request = ippNewRequest(CUPS_DELETE_PRINTER);
1038
a4d04587 1039 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1040 "localhost", 0, "/printers/%s", printer);
ef416fc2 1041 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1042 "printer-uri", NULL, uri);
1043
1044 /*
1045 * Do the request and get back a response...
1046 */
1047
1048 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1049 {
fa73b229 1050 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1051
1052 return (1);
1053 }
1054 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1055 {
fa73b229 1056 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1057
1058 ippDelete(response);
1059
1060 return (1);
1061 }
1062 else
1063 {
1064 ippDelete(response);
1065
1066 return (0);
1067 }
1068}
1069
1070
1071/*
1072 * 'delete_printer_from_class()' - Delete a printer from a class.
1073 */
1074
1075static int /* O - 0 on success, 1 on fail */
fa73b229 1076delete_printer_from_class(
1077 http_t *http, /* I - Server connection */
1078 char *printer, /* I - Printer to remove */
1079 char *pclass) /* I - Class to remove from */
ef416fc2 1080{
1081 int i, j, k; /* Looping vars */
1082 ipp_t *request, /* IPP Request */
1083 *response; /* IPP Response */
1084 ipp_attribute_t *attr, /* Current attribute */
1085 *members; /* Members in class */
ef416fc2 1086 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1087
1088
1089 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
1090 printer, pclass));
1091
1092 /*
1093 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1094 * attributes:
1095 *
1096 * attributes-charset
1097 * attributes-natural-language
1098 * printer-uri
1099 */
1100
fa73b229 1101 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
1102
a4d04587 1103 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1104 "localhost", 0, "/classes/%s", pclass);
ef416fc2 1105 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1106 "printer-uri", NULL, uri);
1107
1108 /*
1109 * Do the request and get back a response...
1110 */
1111
1112 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
1113 response->request.status.status_code == IPP_NOT_FOUND)
1114 {
fa73b229 1115 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1116
ef416fc2 1117 ippDelete(response);
fa73b229 1118
ef416fc2 1119 return (1);
1120 }
1121
1122 /*
1123 * See if the printer is already in the class...
1124 */
1125
1126 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
1127 {
4d301e69 1128 _cupsLangPuts(stderr, _("lpadmin: No member names were seen\n"));
fa73b229 1129
ef416fc2 1130 ippDelete(response);
fa73b229 1131
ef416fc2 1132 return (1);
1133 }
1134
1135 for (i = 0; i < members->num_values; i ++)
fa73b229 1136 if (!strcasecmp(printer, members->values[i].string.text))
ef416fc2 1137 break;
1138
1139 if (i >= members->num_values)
1140 {
fa73b229 1141 _cupsLangPrintf(stderr,
1142 _("lpadmin: Printer %s is not a member of class %s.\n"),
1143 printer, pclass);
1144
ef416fc2 1145 ippDelete(response);
fa73b229 1146
ef416fc2 1147 return (1);
1148 }
1149
1150 if (members->num_values == 1)
1151 {
1152 /*
1153 * Build a CUPS_DELETE_CLASS request, which requires the following
1154 * attributes:
1155 *
1156 * attributes-charset
1157 * attributes-natural-language
1158 * printer-uri
1159 */
1160
fa73b229 1161 request = ippNewRequest(CUPS_DELETE_CLASS);
ef416fc2 1162
1163 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1164 "printer-uri", NULL, uri);
1165 }
1166 else
1167 {
1168 /*
1169 * Build a CUPS_ADD_CLASS request, which requires the following
1170 * attributes:
1171 *
1172 * attributes-charset
1173 * attributes-natural-language
1174 * printer-uri
1175 * member-uris
1176 */
1177
fa73b229 1178 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 1179
1180 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1181 "printer-uri", NULL, uri);
1182
1183 /*
1184 * Delete the printer from the class...
1185 */
1186
1187 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1188 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1189 "member-uris", members->num_values - 1, NULL, NULL);
1190
1191 for (j = 0, k = 0; j < members->num_values; j ++)
1192 if (j != i)
1f0275e3
MS
1193 attr->values[k ++].string.text =
1194 _cupsStrAlloc(members->values[j].string.text);
ef416fc2 1195 }
1196
1197 /*
1198 * Then send the request...
1199 */
1200
1201 ippDelete(response);
1202
1203 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1204 {
fa73b229 1205 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1206
ef416fc2 1207 return (1);
1208 }
1209 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1210 {
fa73b229 1211 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1212
1213 ippDelete(response);
1214
1215 return (1);
1216 }
1217 else
1218 {
1219 ippDelete(response);
1220
1221 return (0);
1222 }
1223}
1224
1225
1226/*
1227 * 'enable_printer()' - Enable a printer...
1228 */
1229
1230static int /* O - 0 on success, 1 on fail */
1231enable_printer(http_t *http, /* I - Server connection */
1232 char *printer) /* I - Printer to enable */
1233{
1234 ipp_t *request, /* IPP Request */
1235 *response; /* IPP Response */
ef416fc2 1236 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1237
1238
1239 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1240
1241 /*
1242 * Build a CUPS_ADD_PRINTER request, which requires the following
1243 * attributes:
1244 *
1245 * attributes-charset
1246 * attributes-natural-language
1247 * printer-uri
1248 * printer-state
1249 * printer-is-accepting-jobs
1250 */
1251
fa73b229 1252 request = ippNewRequest(CUPS_ADD_PRINTER);
1253
a4d04587 1254 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1255 "localhost", 0, "/printers/%s", printer);
ef416fc2 1256 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1257 "printer-uri", NULL, uri);
1258
1259 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1260 IPP_PRINTER_IDLE);
1261
1262 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1263
1264 /*
1265 * Do the request and get back a response...
1266 */
1267
1268 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1269 {
fa73b229 1270 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1271
ef416fc2 1272 return (1);
1273 }
1274 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1275 {
fa73b229 1276 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1277
1278 ippDelete(response);
1279
1280 return (1);
1281 }
1282 else
1283 {
1284 ippDelete(response);
1285
1286 return (0);
1287 }
1288}
1289
1290
1291/*
1292 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1293 */
1294
1295static char * /* O - Pointer to buf or NULL on EOF */
1296get_line(char *buf, /* I - Line buffer */
1297 int length, /* I - Length of buffer */
1298 FILE *fp) /* I - File to read from */
1299{
1300 char *bufptr; /* Pointer into buffer */
1301 int ch; /* Character from file */
1302
1303
1304 length --;
1305 bufptr = buf;
1306
1307 while ((ch = getc(fp)) != EOF)
1308 {
1309 if (ch == '\n')
1310 break;
1311 else if (ch == '\r')
1312 {
1313 /*
1314 * Look for LF...
1315 */
1316
1317 ch = getc(fp);
1318 if (ch != '\n' && ch != EOF)
1319 ungetc(ch, fp);
1320
1321 break;
1322 }
1323
1324 *bufptr++ = ch;
1325 length --;
1326 if (length == 0)
1327 break;
1328 }
1329
1330 *bufptr = '\0';
1331
1332 if (ch == EOF)
1333 return (NULL);
1334 else
1335 return (buf);
1336}
1337
1338
1339/*
1340 * 'set_printer_device()' - Set the device-uri attribute.
1341 */
1342
1343static int /* O - 0 on success, 1 on fail */
1344set_printer_device(http_t *http, /* I - Server connection */
1345 char *printer, /* I - Printer */
1346 char *device) /* I - New device URI */
1347{
1348 ipp_t *request, /* IPP Request */
1349 *response; /* IPP Response */
ef416fc2 1350 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1351
1352
1353 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http, printer,
1354 device));
1355
1356 /*
1357 * Build a CUPS_ADD_PRINTER request, which requires the following
1358 * attributes:
1359 *
1360 * attributes-charset
1361 * attributes-natural-language
1362 * printer-uri
1363 */
1364
fa73b229 1365 request = ippNewRequest(CUPS_ADD_PRINTER);
1366
a4d04587 1367 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1368 "localhost", 0, "/printers/%s", printer);
ef416fc2 1369 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1370 "printer-uri", NULL, uri);
1371
1372 /*
1373 * Add the device URI...
1374 */
1375
1376 if (device[0] == '/')
1377 {
1378 /*
1379 * Convert filename to URI...
1380 */
1381
fa73b229 1382 snprintf(uri, sizeof(uri), "file://%s", device);
ef416fc2 1383 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1384 uri);
1385 }
1386 else
1387 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1388 device);
1389
1390 /*
1391 * Do the request and get back a response...
1392 */
1393
1394 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
1395 {
fa73b229 1396 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1397
ef416fc2 1398 return (1);
1399 }
1400 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1401 {
fa73b229 1402 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1403
1404 ippDelete(response);
1405
1406 return (1);
1407 }
1408 else
1409 {
1410 ippDelete(response);
1411
1412 return (0);
1413 }
1414}
1415
1416
1417/*
1418 * 'set_printer_file()' - Set the interface script or PPD file.
1419 */
1420
1421static int /* O - 0 on success, 1 on fail */
1422set_printer_file(http_t *http, /* I - Server connection */
1423 char *printer, /* I - Printer */
1424 char *file) /* I - PPD file or interface script */
1425{
ef416fc2 1426 ipp_t *request, /* IPP Request */
1427 *response; /* IPP Response */
ef416fc2 1428 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1429#ifdef HAVE_LIBZ
1430 char tempfile[1024]; /* Temporary filename */
1431 int fd; /* Temporary file */
1432 gzFile *gz; /* GZIP'd file */
1433 char buffer[8192]; /* Copy buffer */
1434 int bytes; /* Bytes in buffer */
1435
1436
1437 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http, printer,
1438 file));
1439
1440 /*
1441 * See if the file is gzip'd; if so, unzip it to a temporary file and
1442 * send the uncompressed file.
1443 */
1444
1445 if (!strcmp(file + strlen(file) - 3, ".gz"))
1446 {
1447 /*
1448 * Yes, the file is compressed; uncompress to a temp file...
1449 */
1450
1451 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1452 {
f0ab5bff 1453 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
ef416fc2 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 {
f0ab5bff 1842 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
ef416fc2 1843 ippDelete(request);
1844 unlink(ppdfile);
1845 return (1);
1846 }
1847
1848 if ((in = fopen(ppdfile, "rb")) == NULL)
1849 {
fa73b229 1850 _cupsLangPrintf(stderr,
ef416fc2 1851 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1852 ppdfile, strerror(errno));
1853 ippDelete(request);
1854 unlink(ppdfile);
1855 close(outfd);
1856 unlink(tempfile);
1857 return (1);
1858 }
1859
b423cd4c 1860 out = fdopen(outfd, "wb");
1861 ppdchanged = 0;
ef416fc2 1862
1863 while (get_line(line, sizeof(line), in) != NULL)
1864 {
b423cd4c 1865 if (strncmp(line, "*Default", 8))
ef416fc2 1866 fprintf(out, "%s\n", line);
1867 else
1868 {
1869 /*
1870 * Get default option name...
1871 */
1872
1873 strlcpy(keyword, line + 8, sizeof(keyword));
1874
1875 for (keyptr = keyword; *keyptr; keyptr ++)
1876 if (*keyptr == ':' || isspace(*keyptr & 255))
1877 break;
1878
b423cd4c 1879 *keyptr++ = '\0';
1880 while (isspace(*keyptr & 255))
1881 keyptr ++;
1882
1883 if (!strcmp(keyword, "PageRegion") ||
1884 !strcmp(keyword, "PageSize") ||
1885 !strcmp(keyword, "PaperDimension") ||
1886 !strcmp(keyword, "ImageableArea"))
1887 {
1888 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1889 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1890 }
ef416fc2 1891 else
b423cd4c 1892 choice = ppdFindMarkedChoice(ppd, keyword);
ef416fc2 1893
b423cd4c 1894 if (choice && strcmp(choice->choice, keyptr))
1895 {
1896 fprintf(out, "*Default%s: %s\n", keyword, choice->choice);
1897 ppdchanged = 1;
1898 }
ef416fc2 1899 else
1900 fprintf(out, "%s\n", line);
1901 }
1902 }
1903
ef416fc2 1904 fclose(in);
1905 fclose(out);
1906 close(outfd);
b423cd4c 1907 ppdClose(ppd);
ef416fc2 1908
1909 /*
1910 * Do the request...
1911 */
1912
b423cd4c 1913 ippDelete(cupsDoFileRequest(http, request, "/admin/",
1914 ppdchanged ? tempfile : NULL));
ef416fc2 1915
1916 /*
1917 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1918 * lpadmin)
1919 */
1920
1921 unlink(ppdfile);
1922 unlink(tempfile);
1923 }
1924 else
1925 {
1926 /*
1927 * No PPD file - just set the options...
1928 */
1929
b423cd4c 1930 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1931 }
1932
1933 /*
1934 * Check the response...
1935 */
1936
fa73b229 1937 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1938 {
fa73b229 1939 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
ef416fc2 1940
1941 return (1);
1942 }
1943 else
ef416fc2 1944 return (0);
ef416fc2 1945}
1946
1947
1948/*
1949 * 'validate_name()' - Make sure the printer name only contains valid chars.
1950 */
1951
fa73b229 1952static int /* O - 0 if name is no good, 1 if name is good */
1953validate_name(const char *name) /* I - Name to check */
ef416fc2 1954{
fa73b229 1955 const char *ptr; /* Pointer into name */
ef416fc2 1956
1957
1958 /*
1959 * Scan the whole name...
1960 */
1961
1962 for (ptr = name; *ptr; ptr ++)
1963 if (*ptr == '@')
1964 break;
1965 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1966 *ptr == '#')
1967 return (0);
1968
1969 /*
1970 * All the characters are good; validate the length, too...
1971 */
1972
1973 return ((ptr - name) < 128);
1974}
1975
1976
1977/*
b19ccc9e 1978 * End of "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $".
ef416fc2 1979 */