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