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