]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpadmin.c
Do some code reorganization so that all of the PPD code is separate from the rest.
[thirdparty/cups.git] / systemv / lpadmin.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
7e86f2f6 4 * "lpadmin" command for CUPS.
ef416fc2 5 *
fffed089 6 * Copyright 2007-2015 by Apple Inc.
7e86f2f6 7 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 8 *
7e86f2f6
MS
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 */
15
16/*
17 * Include necessary headers...
18 */
19
fffed089
MS
20#define _CUPS_NO_DEPRECATED
21#define _PPD_DEPRECATED
71e16022 22#include <cups/cups-private.h>
f787e1e3 23#include <cups/ppd-private.h>
ef416fc2 24
25
26/*
27 * Local functions...
28 */
29
eac3a0a0
MS
30static int add_printer_to_class(http_t *http, char *printer, char *pclass);
31static int default_printer(http_t *http, char *printer);
32static int delete_printer(http_t *http, char *printer);
33static int delete_printer_from_class(http_t *http, char *printer,
34 char *pclass);
35static int delete_printer_option(http_t *http, char *printer,
36 char *option);
37static int enable_printer(http_t *http, char *printer);
fffed089 38static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize);
eac3a0a0
MS
39static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri,
40 size_t urisize);
41static int set_printer_options(http_t *http, char *printer,
42 int num_options, cups_option_t *options,
43 char *file);
44static int validate_name(const char *name);
ef416fc2 45
46
47/*
48 * 'main()' - Parse options and configure the scheduler.
49 */
50
51int
52main(int argc, /* I - Number of command-line arguments */
53 char *argv[]) /* I - Command-line arguments */
54{
55 int i; /* Looping var */
56 http_t *http; /* Connection to server */
57 char *printer, /* Destination printer */
58 *pclass, /* Printer class name */
59 *val; /* Pointer to allow/deny value */
60 int num_options; /* Number of options */
61 cups_option_t *options; /* Options */
e67e2f9e 62 char *file, /* New PPD file */
fffed089
MS
63 evefile[1024] = "";
64 /* IPP Everywhere PPD */
65 const char *ppd_name, /* ppd-name value */
66 *device_uri; /* device-uri value */
ef416fc2 67
68
07725fee 69 _cupsSetLocale(argv);
d09495fa 70
ef416fc2 71 http = NULL;
72 printer = NULL;
73 num_options = 0;
74 options = NULL;
7cf5915e 75 file = NULL;
ef416fc2 76
77 for (i = 1; i < argc; i ++)
78 if (argv[i][0] == '-')
79 switch (argv[i][1])
80 {
81 case 'c' : /* Add printer to class */
82 if (!http)
83 {
fffed089 84 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 85
86 if (http == NULL)
87 {
fa73b229 88 _cupsLangPrintf(stderr,
0837b7e8 89 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 90 strerror(errno));
91 return (1);
92 }
93 }
94
95 if (printer == NULL)
96 {
fa73b229 97 _cupsLangPuts(stderr,
ef416fc2 98 _("lpadmin: Unable to add a printer to the class:\n"
99 " You must specify a printer name "
0837b7e8 100 "first."));
ef416fc2 101 return (1);
102 }
103
104 if (argv[i][2])
105 pclass = argv[i] + 2;
106 else
107 {
108 i ++;
109
110 if (i >= argc)
111 {
fa73b229 112 _cupsLangPuts(stderr,
0837b7e8
MS
113 _("lpadmin: Expected class name after \"-c\" "
114 "option."));
ef416fc2 115 return (1);
116 }
117
118 pclass = argv[i];
119 }
120
121 if (!validate_name(pclass))
122 {
fa73b229 123 _cupsLangPuts(stderr,
ef416fc2 124 _("lpadmin: Class name can only contain printable "
0837b7e8 125 "characters."));
ef416fc2 126 return (1);
127 }
128
129 if (add_printer_to_class(http, printer, pclass))
130 return (1);
131 break;
132
133 case 'd' : /* Set as default destination */
134 if (!http)
135 {
fffed089 136 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 137
138 if (http == NULL)
139 {
fa73b229 140 _cupsLangPrintf(stderr,
0837b7e8 141 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 142 strerror(errno));
143 return (1);
144 }
145 }
146
147 if (argv[i][2])
148 printer = argv[i] + 2;
149 else
150 {
151 i ++;
152
153 if (i >= argc)
154 {
fa73b229 155 _cupsLangPuts(stderr,
0837b7e8
MS
156 _("lpadmin: Expected printer name after \"-d\" "
157 "option."));
ef416fc2 158 return (1);
159 }
160
161 printer = argv[i];
162 }
163
164 if (!validate_name(printer))
165 {
fa73b229 166 _cupsLangPuts(stderr,
ef416fc2 167 _("lpadmin: Printer name can only contain "
0837b7e8 168 "printable characters."));
ef416fc2 169 return (1);
170 }
171
172 if (default_printer(http, printer))
173 return (1);
174
175 i = argc;
176 break;
177
178 case 'h' : /* Connect to host */
179 if (http)
180 {
181 httpClose(http);
182 http = NULL;
183 }
184
185 if (argv[i][2] != '\0')
186 cupsSetServer(argv[i] + 2);
187 else
188 {
189 i ++;
190
191 if (i >= argc)
192 {
fa73b229 193 _cupsLangPuts(stderr,
0837b7e8
MS
194 _("lpadmin: Expected hostname after \"-h\" "
195 "option."));
ef416fc2 196 return (1);
197 }
198
199 cupsSetServer(argv[i]);
200 }
201 break;
202
e67e2f9e
MS
203 case 'P' : /* Use the specified PPD file */
204 case 'i' : /* Use the specified PPD file */
ef416fc2 205 if (argv[i][2])
7cf5915e 206 file = argv[i] + 2;
ef416fc2 207 else
208 {
209 i ++;
210
211 if (i >= argc)
212 {
e67e2f9e 213 _cupsLangPrintf(stderr, _("lpadmin: Expected PPD after \"-%c\" option."), argv[i - 1][1]);
ef416fc2 214 return (1);
215 }
216
7cf5915e 217 file = argv[i];
ef416fc2 218 }
219 break;
220
221 case 'E' : /* Enable the printer */
222 if (printer == NULL)
223 {
224#ifdef HAVE_SSL
fffed089 225 cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
ef416fc2 226
227 if (http)
fffed089 228 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 229#else
0837b7e8 230 _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
ef416fc2 231 argv[0]);
232#endif /* HAVE_SSL */
233 break;
234 }
235
236 if (!http)
237 {
fffed089 238 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 239
240 if (http == NULL)
241 {
fa73b229 242 _cupsLangPrintf(stderr,
0837b7e8 243 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 244 strerror(errno));
245 return (1);
246 }
247 }
248
249 if (enable_printer(http, printer))
250 return (1);
251 break;
252
253 case 'm' : /* Use the specified standard script/PPD file */
ef416fc2 254 if (argv[i][2])
7cf5915e
MS
255 num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options,
256 &options);
ef416fc2 257 else
258 {
259 i ++;
260
261 if (i >= argc)
262 {
fa73b229 263 _cupsLangPuts(stderr,
0837b7e8
MS
264 _("lpadmin: Expected model after \"-m\" "
265 "option."));
ef416fc2 266 return (1);
267 }
268
7cf5915e
MS
269 num_options = cupsAddOption("ppd-name", argv[i], num_options,
270 &options);
ef416fc2 271 }
272 break;
273
274 case 'o' : /* Set option */
275 if (argv[i][2])
276 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
277 else
278 {
279 i ++;
280
281 if (i >= argc)
282 {
fa73b229 283 _cupsLangPuts(stderr,
0837b7e8
MS
284 _("lpadmin: Expected name=value after \"-o\" "
285 "option."));
ef416fc2 286 return (1);
287 }
288
289 num_options = cupsParseOptions(argv[i], num_options, &options);
290 }
291 break;
292
293 case 'p' : /* Add/modify a printer */
ef416fc2 294 if (argv[i][2])
295 printer = argv[i] + 2;
296 else
297 {
298 i ++;
299
300 if (i >= argc)
301 {
fa73b229 302 _cupsLangPuts(stderr,
0837b7e8
MS
303 _("lpadmin: Expected printer after \"-p\" "
304 "option."));
ef416fc2 305 return (1);
306 }
307
308 printer = argv[i];
309 }
310
311 if (!validate_name(printer))
312 {
fa73b229 313 _cupsLangPuts(stderr,
ef416fc2 314 _("lpadmin: Printer name can only contain "
0837b7e8 315 "printable characters."));
ef416fc2 316 return (1);
317 }
318 break;
319
320 case 'r' : /* Remove printer from class */
321 if (!http)
322 {
fffed089 323 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 324
325 if (http == NULL)
326 {
fa73b229 327 _cupsLangPrintf(stderr,
0837b7e8 328 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 329 strerror(errno));
330 return (1);
331 }
332 }
333
334 if (printer == NULL)
335 {
fa73b229 336 _cupsLangPuts(stderr,
ef416fc2 337 _("lpadmin: Unable to remove a printer from the "
338 "class:\n"
339 " You must specify a printer name "
0837b7e8 340 "first."));
ef416fc2 341 return (1);
342 }
343
344 if (argv[i][2])
345 pclass = argv[i] + 2;
346 else
347 {
348 i ++;
349
350 if (i >= argc)
351 {
fa73b229 352 _cupsLangPuts(stderr,
0837b7e8
MS
353 _("lpadmin: Expected class after \"-r\" "
354 "option."));
ef416fc2 355 return (1);
356 }
357
358 pclass = argv[i];
359 }
360
361 if (!validate_name(pclass))
362 {
fa73b229 363 _cupsLangPuts(stderr,
ef416fc2 364 _("lpadmin: Class name can only contain printable "
0837b7e8 365 "characters."));
ef416fc2 366 return (1);
367 }
368
369 if (delete_printer_from_class(http, printer, pclass))
370 return (1);
371 break;
372
eac3a0a0
MS
373 case 'R' : /* Remove option */
374 if (!http)
375 {
fffed089 376 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
eac3a0a0
MS
377
378 if (http == NULL)
379 {
380 _cupsLangPrintf(stderr,
381 _("lpadmin: Unable to connect to server: %s"),
382 strerror(errno));
383 return (1);
384 }
385 }
386
387 if (printer == NULL)
388 {
389 _cupsLangPuts(stderr,
390 _("lpadmin: Unable to delete option:\n"
391 " You must specify a printer name "
392 "first."));
393 return (1);
394 }
395
396 if (argv[i][2])
397 val = argv[i] + 2;
398 else
399 {
400 i ++;
401
402 if (i >= argc)
403 {
404 _cupsLangPuts(stderr,
405 _("lpadmin: Expected name after \"-R\" "
406 "option."));
407 return (1);
408 }
409
410 val = argv[i];
411 }
412
413 if (delete_printer_option(http, printer, val))
414 return (1);
415 break;
416
f301802f 417 case 'U' : /* Username */
418 if (argv[i][2] != '\0')
419 cupsSetUser(argv[i] + 2);
420 else
421 {
422 i ++;
423 if (i >= argc)
424 {
425 _cupsLangPrintf(stderr,
426 _("%s: Error - expected username after "
0837b7e8 427 "\"-U\" option."), argv[0]);
f301802f 428 return (1);
429 }
430
431 cupsSetUser(argv[i]);
432 }
433 break;
88f9aafc 434
ef416fc2 435 case 'u' : /* Allow/deny users */
436 if (argv[i][2])
437 val = argv[i] + 2;
438 else
439 {
440 i ++;
441
442 if (i >= argc)
443 {
fa73b229 444 _cupsLangPuts(stderr,
ef416fc2 445 _("lpadmin: Expected allow/deny:userlist after "
0837b7e8 446 "\"-u\" option."));
ef416fc2 447 return (1);
448 }
449
450 val = argv[i];
451 }
452
88f9aafc 453 if (!_cups_strncasecmp(val, "allow:", 6))
ef416fc2 454 num_options = cupsAddOption("requesting-user-name-allowed",
455 val + 6, num_options, &options);
88f9aafc 456 else if (!_cups_strncasecmp(val, "deny:", 5))
ef416fc2 457 num_options = cupsAddOption("requesting-user-name-denied",
458 val + 5, num_options, &options);
459 else
460 {
fa73b229 461 _cupsLangPrintf(stderr,
0837b7e8 462 _("lpadmin: Unknown allow/deny option \"%s\"."),
ef416fc2 463 val);
464 return (1);
465 }
466 break;
467
468 case 'v' : /* Set the device-uri attribute */
ef416fc2 469 if (argv[i][2])
7cf5915e
MS
470 num_options = cupsAddOption("device-uri", argv[i] + 2,
471 num_options, &options);
ef416fc2 472 else
473 {
474 i ++;
475
476 if (i >= argc)
477 {
fa73b229 478 _cupsLangPuts(stderr,
0837b7e8
MS
479 _("lpadmin: Expected device URI after \"-v\" "
480 "option."));
ef416fc2 481 return (1);
482 }
483
7cf5915e
MS
484 num_options = cupsAddOption("device-uri", argv[i],
485 num_options, &options);
ef416fc2 486 }
487 break;
488
489 case 'x' : /* Delete a printer */
490 if (!http)
491 {
fffed089 492 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 493
494 if (http == NULL)
495 {
fa73b229 496 _cupsLangPrintf(stderr,
0837b7e8 497 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 498 strerror(errno));
499 return (1);
500 }
501 }
502
503 if (argv[i][2])
504 printer = argv[i] + 2;
505 else
506 {
507 i ++;
508
509 if (i >= argc)
510 {
fa73b229 511 _cupsLangPuts(stderr,
ef416fc2 512 _("lpadmin: Expected printer or class after "
0837b7e8 513 "\"-x\" option."));
ef416fc2 514 return (1);
515 }
516
517 printer = argv[i];
518 }
519
520 if (!validate_name(printer))
521 {
fa73b229 522 _cupsLangPuts(stderr,
ef416fc2 523 _("lpadmin: Printer name can only contain "
0837b7e8 524 "printable characters."));
ef416fc2 525 return (1);
526 }
527
528 if (delete_printer(http, printer))
529 return (1);
530
531 i = argc;
532 break;
533
534 case 'D' : /* Set the printer-info attribute */
ef416fc2 535 if (argv[i][2])
7cf5915e
MS
536 num_options = cupsAddOption("printer-info", argv[i] + 2,
537 num_options, &options);
ef416fc2 538 else
539 {
540 i ++;
541
542 if (i >= argc)
543 {
fa73b229 544 _cupsLangPuts(stderr,
ef416fc2 545 _("lpadmin: Expected description after "
0837b7e8 546 "\"-D\" option."));
ef416fc2 547 return (1);
548 }
549
7cf5915e
MS
550 num_options = cupsAddOption("printer-info", argv[i],
551 num_options, &options);
ef416fc2 552 }
553 break;
554
555 case 'I' : /* Set the supported file types (ignored) */
556 i ++;
557
558 if (i >= argc)
559 {
fa73b229 560 _cupsLangPuts(stderr,
0837b7e8
MS
561 _("lpadmin: Expected file type(s) after \"-I\" "
562 "option."));
ef416fc2 563 return (1);
564 }
565
fa73b229 566 _cupsLangPuts(stderr,
0837b7e8 567 _("lpadmin: Warning - content type list ignored."));
ef416fc2 568 break;
88f9aafc 569
ef416fc2 570 case 'L' : /* Set the printer-location attribute */
ef416fc2 571 if (argv[i][2])
7cf5915e
MS
572 num_options = cupsAddOption("printer-location", argv[i] + 2,
573 num_options, &options);
ef416fc2 574 else
575 {
576 i ++;
577
578 if (i >= argc)
579 {
fa73b229 580 _cupsLangPuts(stderr,
0837b7e8
MS
581 _("lpadmin: Expected location after \"-L\" "
582 "option."));
ef416fc2 583 return (1);
584 }
585
7cf5915e
MS
586 num_options = cupsAddOption("printer-location", argv[i],
587 num_options, &options);
ef416fc2 588 }
589 break;
590
ef416fc2 591 default :
fa73b229 592 _cupsLangPrintf(stderr,
0837b7e8 593 _("lpadmin: Unknown option \"%c\"."), argv[i][1]);
ef416fc2 594 return (1);
595 }
596 else
597 {
0837b7e8 598 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."),
ef416fc2 599 argv[i]);
600 return (1);
601 }
602
603 /*
604 * Set options as needed...
605 */
606
fffed089
MS
607 if ((ppd_name = cupsGetOption("ppd-name", num_options, options)) != NULL && !strcmp(ppd_name, "everywhere") && (device_uri = cupsGetOption("device-uri", num_options, options)) != NULL)
608 {
609 if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile))) == NULL)
610 return (1);
611
612 num_options = cupsRemoveOption("ppd-name", num_options, &options);
613 }
614
7cf5915e 615 if (num_options || file)
ef416fc2 616 {
617 if (!http)
618 {
fffed089 619 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
ef416fc2 620
621 if (http == NULL)
622 {
fa73b229 623 _cupsLangPrintf(stderr,
0837b7e8 624 _("lpadmin: Unable to connect to server: %s"),
ef416fc2 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 options:\n"
0837b7e8 634 " You must specify a printer name first."));
ef416fc2 635 return (1);
636 }
637
7cf5915e 638 if (set_printer_options(http, printer, num_options, options, file))
ef416fc2 639 return (1);
640 }
641
fffed089
MS
642 if (evefile[0])
643 unlink(evefile);
644
ef416fc2 645 if (printer == NULL)
646 {
fa73b229 647 _cupsLangPuts(stdout,
ef416fc2 648 _("Usage:\n"
649 "\n"
650 " lpadmin [-h server] -d destination\n"
651 " lpadmin [-h server] -x destination\n"
652 " lpadmin [-h server] -p printer [-c add-class] "
653 "[-i interface] [-m model]\n"
654 " [-r remove-class] [-v device] "
655 "[-D description]\n"
656 " [-P ppd-file] [-o name=value]\n"
657 " [-u allow:user,user] "
0837b7e8 658 "[-u deny:user,user]"));
ef416fc2 659 }
660
661 if (http)
662 httpClose(http);
663
664 return (0);
665}
666
667
668/*
669 * 'add_printer_to_class()' - Add a printer to a class.
670 */
671
672static int /* O - 0 on success, 1 on fail */
673add_printer_to_class(http_t *http, /* I - Server connection */
674 char *printer, /* I - Printer to add */
675 char *pclass) /* I - Class to add to */
676{
677 int i; /* Looping var */
678 ipp_t *request, /* IPP Request */
679 *response; /* IPP Response */
680 ipp_attribute_t *attr, /* Current attribute */
681 *members; /* Members in class */
ef416fc2 682 char uri[HTTP_MAX_URI]; /* URI for printer/class */
683
684
685 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
686 printer, pclass));
687
688 /*
fffed089 689 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
ef416fc2 690 * attributes:
691 *
692 * attributes-charset
693 * attributes-natural-language
694 * printer-uri
eac3a0a0 695 * requesting-user-name
ef416fc2 696 */
697
fffed089 698 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
fa73b229 699
a4d04587 700 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
701 "localhost", 0, "/classes/%s", pclass);
ef416fc2 702 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
703 "printer-uri", NULL, uri);
eac3a0a0
MS
704 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
705 NULL, cupsUser());
ef416fc2 706
707 /*
708 * Do the request and get back a response...
709 */
710
711 response = cupsDoRequest(http, request, "/");
712
713 /*
fffed089 714 * Build a CUPS-Add-Modify-Class request, which requires the following
ef416fc2 715 * attributes:
716 *
717 * attributes-charset
718 * attributes-natural-language
719 * printer-uri
eac3a0a0 720 * requesting-user-name
ef416fc2 721 * member-uris
722 */
723
fffed089 724 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
ef416fc2 725
726 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
727 "printer-uri", NULL, uri);
eac3a0a0
MS
728 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
729 NULL, cupsUser());
ef416fc2 730
731 /*
732 * See if the printer is already in the class...
733 */
734
735 if (response != NULL &&
eac3a0a0
MS
736 (members = ippFindAttribute(response, "member-names",
737 IPP_TAG_NAME)) != NULL)
ef416fc2 738 for (i = 0; i < members->num_values; i ++)
88f9aafc 739 if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
ef416fc2 740 {
fa73b229 741 _cupsLangPrintf(stderr,
0837b7e8
MS
742 _("lpadmin: Printer %s is already a member of class "
743 "%s."), printer, pclass);
ef416fc2 744 ippDelete(request);
745 ippDelete(response);
746 return (0);
747 }
748
749 /*
750 * OK, the printer isn't part of the class, so add it...
751 */
752
a4d04587 753 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
754 "localhost", 0, "/printers/%s", printer);
ef416fc2 755
756 if (response != NULL &&
eac3a0a0
MS
757 (members = ippFindAttribute(response, "member-uris",
758 IPP_TAG_URI)) != NULL)
ef416fc2 759 {
760 /*
761 * Add the printer to the existing list...
762 */
763
764 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
765 "member-uris", members->num_values + 1, NULL, NULL);
766 for (i = 0; i < members->num_values; i ++)
eac3a0a0
MS
767 attr->values[i].string.text =
768 _cupsStrAlloc(members->values[i].string.text);
ef416fc2 769
1f0275e3 770 attr->values[i].string.text = _cupsStrAlloc(uri);
ef416fc2 771 }
772 else
1f0275e3
MS
773 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
774 uri);
ef416fc2 775
776 /*
777 * Then send the request...
778 */
779
780 ippDelete(response);
781
eac3a0a0 782 ippDelete(cupsDoRequest(http, request, "/admin/"));
fffed089 783 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 784 {
eac3a0a0 785 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 786
787 return (1);
788 }
789 else
ef416fc2 790 return (0);
ef416fc2 791}
792
793
794/*
795 * 'default_printer()' - Set the default printing destination.
796 */
797
798static int /* O - 0 on success, 1 on fail */
799default_printer(http_t *http, /* I - Server connection */
800 char *printer) /* I - Printer name */
801{
eac3a0a0 802 ipp_t *request; /* IPP Request */
ef416fc2 803 char uri[HTTP_MAX_URI]; /* URI for printer/class */
804
805
806 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
807
808 /*
fffed089 809 * Build a CUPS-Set-Default request, which requires the following
ef416fc2 810 * attributes:
811 *
812 * attributes-charset
813 * attributes-natural-language
814 * printer-uri
eac3a0a0 815 * requesting-user-name
ef416fc2 816 */
817
a4d04587 818 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
819 "localhost", 0, "/printers/%s", printer);
ef416fc2 820
fffed089 821 request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
ef416fc2 822
823 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
824 "printer-uri", NULL, uri);
eac3a0a0
MS
825 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
826 NULL, cupsUser());
ef416fc2 827
828 /*
829 * Do the request and get back a response...
830 */
831
eac3a0a0 832 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 833
fffed089 834 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 835 {
eac3a0a0 836 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 837
838 return (1);
839 }
840 else
ef416fc2 841 return (0);
ef416fc2 842}
843
844
845/*
846 * 'delete_printer()' - Delete a printer from the system...
847 */
848
849static int /* O - 0 on success, 1 on fail */
850delete_printer(http_t *http, /* I - Server connection */
851 char *printer) /* I - Printer to delete */
852{
eac3a0a0 853 ipp_t *request; /* IPP Request */
ef416fc2 854 char uri[HTTP_MAX_URI]; /* URI for printer/class */
855
856
857 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
858
859 /*
fffed089 860 * Build a CUPS-Delete-Printer request, which requires the following
ef416fc2 861 * attributes:
862 *
863 * attributes-charset
864 * attributes-natural-language
865 * printer-uri
eac3a0a0 866 * requesting-user-name
ef416fc2 867 */
868
fffed089 869 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
fa73b229 870
a4d04587 871 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
872 "localhost", 0, "/printers/%s", printer);
ef416fc2 873 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
874 "printer-uri", NULL, uri);
eac3a0a0
MS
875 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
876 NULL, cupsUser());
ef416fc2 877
878 /*
879 * Do the request and get back a response...
880 */
881
eac3a0a0 882 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 883
fffed089 884 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 885 {
eac3a0a0 886 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 887
888 return (1);
889 }
890 else
ef416fc2 891 return (0);
ef416fc2 892}
893
894
895/*
896 * 'delete_printer_from_class()' - Delete a printer from a class.
897 */
898
899static int /* O - 0 on success, 1 on fail */
fa73b229 900delete_printer_from_class(
901 http_t *http, /* I - Server connection */
902 char *printer, /* I - Printer to remove */
903 char *pclass) /* I - Class to remove from */
ef416fc2 904{
905 int i, j, k; /* Looping vars */
906 ipp_t *request, /* IPP Request */
907 *response; /* IPP Response */
908 ipp_attribute_t *attr, /* Current attribute */
909 *members; /* Members in class */
ef416fc2 910 char uri[HTTP_MAX_URI]; /* URI for printer/class */
911
912
913 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
914 printer, pclass));
915
916 /*
fffed089 917 * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
ef416fc2 918 * attributes:
919 *
920 * attributes-charset
921 * attributes-natural-language
922 * printer-uri
eac3a0a0 923 * requesting-user-name
ef416fc2 924 */
925
fffed089 926 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
fa73b229 927
a4d04587 928 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
929 "localhost", 0, "/classes/%s", pclass);
ef416fc2 930 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
931 "printer-uri", NULL, uri);
eac3a0a0
MS
932 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
933 NULL, cupsUser());
ef416fc2 934
935 /*
936 * Do the request and get back a response...
937 */
938
939 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
fffed089 940 response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND)
ef416fc2 941 {
eac3a0a0 942 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
fa73b229 943
ef416fc2 944 ippDelete(response);
fa73b229 945
ef416fc2 946 return (1);
947 }
948
949 /*
950 * See if the printer is already in the class...
951 */
952
953 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
954 {
0837b7e8 955 _cupsLangPuts(stderr, _("lpadmin: No member names were seen."));
fa73b229 956
ef416fc2 957 ippDelete(response);
fa73b229 958
ef416fc2 959 return (1);
960 }
961
962 for (i = 0; i < members->num_values; i ++)
88f9aafc 963 if (!_cups_strcasecmp(printer, members->values[i].string.text))
ef416fc2 964 break;
965
966 if (i >= members->num_values)
967 {
fa73b229 968 _cupsLangPrintf(stderr,
0837b7e8 969 _("lpadmin: Printer %s is not a member of class %s."),
fa73b229 970 printer, pclass);
971
ef416fc2 972 ippDelete(response);
fa73b229 973
ef416fc2 974 return (1);
975 }
976
977 if (members->num_values == 1)
978 {
979 /*
fffed089 980 * Build a CUPS-Delete-Class request, which requires the following
ef416fc2 981 * attributes:
982 *
983 * attributes-charset
984 * attributes-natural-language
985 * printer-uri
eac3a0a0 986 * requesting-user-name
ef416fc2 987 */
988
fffed089 989 request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS);
ef416fc2 990
991 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
992 "printer-uri", NULL, uri);
eac3a0a0
MS
993 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
994 "requesting-user-name", NULL, cupsUser());
ef416fc2 995 }
996 else
997 {
998 /*
fffed089 999 * Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following
ef416fc2 1000 * attributes:
1001 *
1002 * attributes-charset
1003 * attributes-natural-language
1004 * printer-uri
eac3a0a0 1005 * requesting-user-name
ef416fc2 1006 * member-uris
1007 */
1008
fffed089 1009 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
ef416fc2 1010
1011 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1012 "printer-uri", NULL, uri);
eac3a0a0
MS
1013 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1014 "requesting-user-name", NULL, cupsUser());
ef416fc2 1015
1016 /*
1017 * Delete the printer from the class...
1018 */
1019
1020 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1021 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1022 "member-uris", members->num_values - 1, NULL, NULL);
1023
1024 for (j = 0, k = 0; j < members->num_values; j ++)
1025 if (j != i)
1f0275e3
MS
1026 attr->values[k ++].string.text =
1027 _cupsStrAlloc(members->values[j].string.text);
ef416fc2 1028 }
1029
1030 /*
1031 * Then send the request...
1032 */
1033
1034 ippDelete(response);
1035
eac3a0a0
MS
1036 ippDelete(cupsDoRequest(http, request, "/admin/"));
1037
fffed089 1038 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 1039 {
eac3a0a0 1040 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
fa73b229 1041
ef416fc2 1042 return (1);
1043 }
eac3a0a0
MS
1044 else
1045 return (0);
1046}
ef416fc2 1047
ef416fc2 1048
eac3a0a0
MS
1049/*
1050 * 'delete_printer_option()' - Delete a printer option.
1051 */
1052
1053static int /* O - 0 on success, 1 on fail */
1054delete_printer_option(http_t *http, /* I - Server connection */
1055 char *printer, /* I - Printer */
1056 char *option) /* I - Option to delete */
1057{
1058 ipp_t *request; /* IPP request */
1059 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1060
1061
1062 /*
fffed089 1063 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
eac3a0a0
MS
1064 * requires the following attributes:
1065 *
1066 * attributes-charset
1067 * attributes-natural-language
1068 * printer-uri
1069 * requesting-user-name
1070 * option with deleteAttr tag
1071 */
1072
a2326b5b 1073 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
fffed089 1074 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
ef416fc2 1075 else
fffed089 1076 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
eac3a0a0
MS
1077
1078 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1079 "printer-uri", NULL, uri);
1080 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1081 "requesting-user-name", NULL, cupsUser());
1082 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);
1083
1084 /*
1085 * Do the request and get back a response...
1086 */
1087
1088 ippDelete(cupsDoRequest(http, request, "/admin/"));
1089
fffed089 1090 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 1091 {
eac3a0a0 1092 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 1093
eac3a0a0 1094 return (1);
ef416fc2 1095 }
eac3a0a0
MS
1096 else
1097 return (0);
ef416fc2 1098}
1099
1100
1101/*
1102 * 'enable_printer()' - Enable a printer...
1103 */
1104
1105static int /* O - 0 on success, 1 on fail */
1106enable_printer(http_t *http, /* I - Server connection */
1107 char *printer) /* I - Printer to enable */
1108{
eac3a0a0 1109 ipp_t *request; /* IPP Request */
ef416fc2 1110 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1111
1112
1113 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
1114
1115 /*
fffed089 1116 * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
eac3a0a0 1117 * require the following attributes:
ef416fc2 1118 *
1119 * attributes-charset
1120 * attributes-natural-language
1121 * printer-uri
eac3a0a0 1122 * requesting-user-name
ef416fc2 1123 * printer-state
1124 * printer-is-accepting-jobs
1125 */
1126
a2326b5b 1127 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
fffed089 1128 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
eac3a0a0 1129 else
fffed089 1130 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
fa73b229 1131
ef416fc2 1132 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1133 "printer-uri", NULL, uri);
eac3a0a0
MS
1134 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1135 "requesting-user-name", NULL, cupsUser());
ef416fc2 1136 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
fffed089 1137 IPP_PSTATE_IDLE);
ef416fc2 1138 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1139
1140 /*
1141 * Do the request and get back a response...
1142 */
1143
eac3a0a0 1144 ippDelete(cupsDoRequest(http, request, "/admin/"));
fa73b229 1145
fffed089 1146 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 1147 {
eac3a0a0 1148 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 1149
1150 return (1);
1151 }
1152 else
eac3a0a0
MS
1153 return (0);
1154}
1155
1156
fffed089
MS
1157/*
1158 * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
1159 */
1160
1161static char * /* O - Filename or NULL */
1162get_printer_ppd(const char *uri, /* I - Printer URI */
1163 char *buffer, /* I - Filename buffer */
1164 size_t bufsize) /* I - Size of filename buffer */
1165{
1166 http_t *http; /* Connection to printer */
1167 ipp_t *request, /* Get-Printer-Attributes request */
1168 *response; /* Get-Printer-Attributes response */
fb2d5470
MS
1169 char resolved[1024], /* Resolved URI */
1170 scheme[32], /* URI scheme */
fffed089
MS
1171 userpass[256], /* Username:password */
1172 host[256], /* Hostname */
1173 resource[256]; /* Resource path */
1174 int port; /* Port number */
1175
1176
1177 /*
1178 * Connect to the printer...
1179 */
1180
fb2d5470
MS
1181 if (strstr(uri, "._tcp"))
1182 {
1183 /*
1184 * Resolve URI...
1185 */
1186
1187 if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
1188 {
1189 _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri);
1190 return (NULL);
1191 }
1192
1193 uri = resolved;
1194 }
1195
fffed089
MS
1196 if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
1197 {
1198 _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri);
1199 return (NULL);
1200 }
1201
1202 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
1203 if (!http)
1204 {
1205 _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString());
1206 return (NULL);
1207 }
1208
1209 /*
1210 * Send a Get-Printer-Attributes request...
1211 */
1212
1213 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1214 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1215 response = cupsDoRequest(http, request, resource);
1216
1217 if (!_ppdCreateFromIPP(buffer, bufsize, response))
1218 _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno));
1219
1220 ippDelete(response);
1221 httpClose(http);
1222
1223 if (buffer[0])
1224 return (buffer);
1225 else
1226 return (NULL);
1227}
1228
1229
eac3a0a0
MS
1230/*
1231 * 'get_printer_type()' - Determine the printer type and URI.
1232 */
1233
1234static cups_ptype_t /* O - printer-type value */
1235get_printer_type(http_t *http, /* I - Server connection */
1236 char *printer, /* I - Printer name */
1237 char *uri, /* I - URI buffer */
1238 size_t urisize) /* I - Size of URI buffer */
1239{
1240 ipp_t *request, /* IPP request */
1241 *response; /* IPP response */
1242 ipp_attribute_t *attr; /* printer-type attribute */
1243 cups_ptype_t type; /* printer-type value */
1244
1245
1246 /*
1247 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1248 * attributes:
1249 *
1250 * attributes-charset
1251 * attributes-natural-language
1252 * printer-uri
1253 * requested-attributes
1254 * requesting-user-name
1255 */
1256
7e86f2f6 1257 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
eac3a0a0 1258
fffed089 1259 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
eac3a0a0
MS
1260 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1261 "printer-uri", NULL, uri);
1262 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1263 "requested-attributes", NULL, "printer-type");
1264 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1265 "requesting-user-name", NULL, cupsUser());
1266
1267 /*
1268 * Do the request...
1269 */
1270
1271 response = cupsDoRequest(http, request, "/");
1272 if ((attr = ippFindAttribute(response, "printer-type",
1273 IPP_TAG_ENUM)) != NULL)
ef416fc2 1274 {
eac3a0a0 1275 type = (cups_ptype_t)attr->values[0].integer;
ef416fc2 1276
a2326b5b 1277 if (type & CUPS_PRINTER_CLASS)
7e86f2f6 1278 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer);
ef416fc2 1279 }
eac3a0a0
MS
1280 else
1281 type = CUPS_PRINTER_LOCAL;
1282
1283 ippDelete(response);
1284
1285 return (type);
ef416fc2 1286}
1287
1288
ef416fc2 1289/*
1290 * 'set_printer_options()' - Set the printer options.
1291 */
1292
1293static int /* O - 0 on success, 1 on fail */
fa73b229 1294set_printer_options(
1295 http_t *http, /* I - Server connection */
1296 char *printer, /* I - Printer */
1297 int num_options, /* I - Number of options */
7cf5915e
MS
1298 cups_option_t *options, /* I - Options */
1299 char *file) /* I - PPD file/interface script */
ef416fc2 1300{
eac3a0a0 1301 ipp_t *request; /* IPP Request */
b423cd4c 1302 const char *ppdfile; /* PPD filename */
61c9d9f8 1303 int ppdchanged = 0; /* PPD changed? */
b423cd4c 1304 ppd_file_t *ppd; /* PPD file */
1305 ppd_choice_t *choice; /* Marked choice */
ef416fc2 1306 char uri[HTTP_MAX_URI], /* URI for printer/class */
1307 line[1024], /* Line from PPD file */
1308 keyword[1024], /* Keyword from Default line */
1309 *keyptr, /* Pointer into keyword... */
1310 tempfile[1024]; /* Temporary filename */
7cf5915e 1311 cups_file_t *in, /* PPD file */
ef416fc2 1312 *out; /* Temporary file */
61c9d9f8
MS
1313 const char *ppdname, /* ppd-name value */
1314 *protocol, /* Old protocol option */
eac3a0a0
MS
1315 *customval, /* Custom option value */
1316 *boolval; /* Boolean value */
1317 int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */
61c9d9f8
MS
1318 wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */
1319 copied_options = 0; /* Copied options? */
ef416fc2 1320
1321
7cf5915e
MS
1322 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1323 "options=%p, file=\"%s\")\n", http, printer, num_options,
1324 options, file));
ef416fc2 1325
ef416fc2 1326 /*
fffed089
MS
1327 * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request,
1328 * which requires the following attributes:
ef416fc2 1329 *
1330 * attributes-charset
1331 * attributes-natural-language
1332 * printer-uri
eac3a0a0 1333 * requesting-user-name
ef416fc2 1334 * other options
1335 */
1336
a2326b5b 1337 if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
fffed089 1338 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
eac3a0a0 1339 else
fffed089 1340 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
ef416fc2 1341
fffed089
MS
1342 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1343 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
ef416fc2 1344
1345 /*
1346 * Add the options...
1347 */
1348
fffed089
MS
1349 if (file)
1350 ppdfile = file;
61c9d9f8
MS
1351 else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "raw") && num_options > 1)
1352 {
1353 if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL)
1354 {
1355 /*
1356 * Copy options array and remove ppd-name from it...
1357 */
1358
1359 cups_option_t *temp = NULL, *optr;
1360 int i, num_temp = 0;
1361 for (i = num_options, optr = options; i > 0; i --, optr ++)
1362 if (strcmp(optr->name, "ppd-name"))
1363 num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp);
1364
1365 copied_options = 1;
1366 ppdchanged = 1;
1367 num_options = num_temp;
1368 options = temp;
1369 }
1370 }
fffed089
MS
1371 else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER)
1372 ppdfile = cupsGetPPD(printer);
1373 else
1374 ppdfile = NULL;
1375
b0f26938 1376 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
b423cd4c 1377 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1378
1379 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1380 {
88f9aafc 1381 if (!_cups_strcasecmp(protocol, "bcp"))
a41f09e2 1382 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
b423cd4c 1383 NULL, "bcp");
88f9aafc 1384 else if (!_cups_strcasecmp(protocol, "tbcp"))
a41f09e2 1385 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
b423cd4c 1386 NULL, "tbcp");
1387 }
ef416fc2 1388
fffed089 1389 if (ppdfile)
ef416fc2 1390 {
1391 /*
1392 * Set default options in the PPD file...
1393 */
1394
61c9d9f8
MS
1395 if ((ppd = ppdOpenFile(ppdfile)) == NULL)
1396 {
1397 int linenum; /* Line number of error */
1398 ppd_status_t status = ppdLastError(&linenum);
1399 /* Status code */
1400
1401 _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum);
1402 }
1403
b423cd4c 1404 ppdMarkDefaults(ppd);
1405 cupsMarkOptions(ppd, num_options, options);
1406
0268488e 1407 if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
ef416fc2 1408 {
0837b7e8 1409 _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
ef416fc2 1410 ippDelete(request);
7cf5915e
MS
1411 if (ppdfile != file)
1412 unlink(ppdfile);
61c9d9f8
MS
1413 if (copied_options)
1414 cupsFreeOptions(num_options, options);
ef416fc2 1415 return (1);
1416 }
1417
7cf5915e 1418 if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
ef416fc2 1419 {
fa73b229 1420 _cupsLangPrintf(stderr,
0837b7e8 1421 _("lpadmin: Unable to open PPD file \"%s\" - %s"),
ef416fc2 1422 ppdfile, strerror(errno));
1423 ippDelete(request);
7cf5915e
MS
1424 if (ppdfile != file)
1425 unlink(ppdfile);
61c9d9f8
MS
1426 if (copied_options)
1427 cupsFreeOptions(num_options, options);
7cf5915e 1428 cupsFileClose(out);
ef416fc2 1429 unlink(tempfile);
1430 return (1);
1431 }
1432
7cf5915e 1433 while (cupsFileGets(in, line, sizeof(line)))
ef416fc2 1434 {
eac3a0a0
MS
1435 if (!strncmp(line, "*cupsIPPSupplies:", 17) &&
1436 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1437 options)) != NULL)
1438 {
1439 wrote_ipp_supplies = 1;
1440 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
88f9aafc
MS
1441 (!_cups_strcasecmp(boolval, "true") ||
1442 !_cups_strcasecmp(boolval, "yes") ||
1443 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
eac3a0a0
MS
1444 }
1445 else if (!strncmp(line, "*cupsSNMPSupplies:", 18) &&
1446 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1447 options)) != NULL)
1448 {
1449 wrote_snmp_supplies = 1;
1450 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
88f9aafc
MS
1451 (!_cups_strcasecmp(boolval, "true") ||
1452 !_cups_strcasecmp(boolval, "yes") ||
1453 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
eac3a0a0
MS
1454 }
1455 else if (strncmp(line, "*Default", 8))
7cf5915e 1456 cupsFilePrintf(out, "%s\n", line);
ef416fc2 1457 else
1458 {
1459 /*
1460 * Get default option name...
1461 */
1462
1463 strlcpy(keyword, line + 8, sizeof(keyword));
1464
1465 for (keyptr = keyword; *keyptr; keyptr ++)
1466 if (*keyptr == ':' || isspace(*keyptr & 255))
1467 break;
1468
b423cd4c 1469 *keyptr++ = '\0';
1470 while (isspace(*keyptr & 255))
1471 keyptr ++;
1472
1473 if (!strcmp(keyword, "PageRegion") ||
1474 !strcmp(keyword, "PageSize") ||
1475 !strcmp(keyword, "PaperDimension") ||
1476 !strcmp(keyword, "ImageableArea"))
1477 {
1478 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1479 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1480 }
ef416fc2 1481 else
b423cd4c 1482 choice = ppdFindMarkedChoice(ppd, keyword);
ef416fc2 1483
b423cd4c 1484 if (choice && strcmp(choice->choice, keyptr))
1485 {
7cf5915e
MS
1486 if (strcmp(choice->choice, "Custom"))
1487 {
1488 cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
1489 ppdchanged = 1;
1490 }
1491 else if ((customval = cupsGetOption(keyword, num_options,
1492 options)) != NULL)
1493 {
1494 cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
1495 ppdchanged = 1;
1496 }
1497 else
1498 cupsFilePrintf(out, "%s\n", line);
b423cd4c 1499 }
ef416fc2 1500 else
7cf5915e 1501 cupsFilePrintf(out, "%s\n", line);
ef416fc2 1502 }
1503 }
1504
eac3a0a0
MS
1505 if (!wrote_ipp_supplies &&
1506 (boolval = cupsGetOption("cupsIPPSupplies", num_options,
1507 options)) != NULL)
1508 {
1509 cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
88f9aafc
MS
1510 (!_cups_strcasecmp(boolval, "true") ||
1511 !_cups_strcasecmp(boolval, "yes") ||
1512 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
eac3a0a0
MS
1513 }
1514
1515 if (!wrote_snmp_supplies &&
1516 (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1517 options)) != NULL)
1518 {
1519 cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
88f9aafc
MS
1520 (!_cups_strcasecmp(boolval, "true") ||
1521 !_cups_strcasecmp(boolval, "yes") ||
1522 !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
eac3a0a0
MS
1523 }
1524
7cf5915e
MS
1525 cupsFileClose(in);
1526 cupsFileClose(out);
b423cd4c 1527 ppdClose(ppd);
ef416fc2 1528
1529 /*
1530 * Do the request...
1531 */
1532
b423cd4c 1533 ippDelete(cupsDoFileRequest(http, request, "/admin/",
7cf5915e 1534 ppdchanged ? tempfile : file));
ef416fc2 1535
1536 /*
1537 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1538 * lpadmin)
1539 */
1540
7cf5915e
MS
1541 if (ppdfile != file)
1542 unlink(ppdfile);
ef416fc2 1543 unlink(tempfile);
1544 }
1545 else
1546 {
1547 /*
1548 * No PPD file - just set the options...
1549 */
1550
b423cd4c 1551 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1552 }
1553
61c9d9f8
MS
1554 if (copied_options)
1555 cupsFreeOptions(num_options, options);
1556
ef416fc2 1557 /*
1558 * Check the response...
1559 */
1560
fffed089 1561 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
ef416fc2 1562 {
eac3a0a0 1563 _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
ef416fc2 1564
1565 return (1);
1566 }
1567 else
ef416fc2 1568 return (0);
ef416fc2 1569}
1570
1571
1572/*
1573 * 'validate_name()' - Make sure the printer name only contains valid chars.
1574 */
1575
fa73b229 1576static int /* O - 0 if name is no good, 1 if name is good */
1577validate_name(const char *name) /* I - Name to check */
ef416fc2 1578{
fa73b229 1579 const char *ptr; /* Pointer into name */
ef416fc2 1580
1581
1582 /*
1583 * Scan the whole name...
1584 */
1585
1586 for (ptr = name; *ptr; ptr ++)
1587 if (*ptr == '@')
1588 break;
1589 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1590 *ptr == '#')
1591 return (0);
1592
1593 /*
1594 * All the characters are good; validate the length, too...
1595 */
1596
1597 return ((ptr - name) < 128);
1598}
1599
1600
1601/*
f2d18633 1602 * End of "$Id$".
ef416fc2 1603 */