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