]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpadmin.c
More bundle localization changes:
[thirdparty/cups.git] / systemv / lpadmin.c
CommitLineData
3270670b 1/*
c9d3f842 2 * "$Id$"
3270670b 3 *
3d94661a 4 * "lpadmin" command for CUPS.
3270670b 5 *
3d94661a 6 * Copyright 2007-2010 by Apple Inc.
0e66904d 7 * Copyright 1997-2006 by Easy Software Products.
3270670b 8 *
9 * These coded instructions, statements, and computer programs are the
4e8d321f 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/".
3270670b 14 *
15 * Contents:
16 *
17 * main() - Parse options and configure the scheduler.
18 * add_printer_to_class() - Add a printer to a class.
19 * default_printer() - Set the default printing destination.
6bff400e 20 * delete_printer() - Delete a printer from the system.
3270670b 21 * delete_printer_from_class() - Delete a printer from a class.
6bff400e 22 * enable_printer() - Enable a printer.
23 * set_printer_options() - Set the printer options and/or file.
9c817392 24 * validate_name() - Make sure the printer name only contains
6bff400e 25 * valid chars.
3270670b 26 */
27
28/*
29 * Include necessary headers...
30 */
31
3d94661a 32#include <cups/cups-private.h>
3270670b 33
34
35/*
36 * Local functions...
37 */
38
6bff400e 39static int add_printer_to_class(http_t *http, char *printer, char *pclass);
40static int default_printer(http_t *http, char *printer);
41static int delete_printer(http_t *http, char *printer);
42static int delete_printer_from_class(http_t *http, char *printer,
43 char *pclass);
44static int enable_printer(http_t *http, char *printer);
45static int set_printer_options(http_t *http, char *printer,
46 int num_options, cups_option_t *options,
47 char *file);
48static int validate_name(const char *name);
3270670b 49
50
51/*
52 * 'main()' - Parse options and configure the scheduler.
53 */
54
55int
01a426e9 56main(int argc, /* I - Number of command-line arguments */
57 char *argv[]) /* I - Command-line arguments */
3270670b 58{
fb10bf13 59 int i; /* Looping var */
9c817392 60 http_t *http; /* Connection to server */
fb10bf13 61 char *printer, /* Destination printer */
9c817392 62 *pclass, /* Printer class name */
b070f93d 63 *val; /* Pointer to allow/deny value */
01a426e9 64 int num_options; /* Number of options */
65 cups_option_t *options; /* Options */
6bff400e 66 char *file; /* New PPD file/interface script */
3270670b 67
68
156dd8aa 69 _cupsSetLocale(argv);
ebad28ad 70
01a426e9 71 http = NULL;
72 printer = NULL;
73 num_options = 0;
74 options = NULL;
6bff400e 75 file = NULL;
3270670b 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 */
96ecd6f0 82 if (!http)
83 {
192a8a08 84 http = httpConnectEncrypt(cupsServer(), ippPort(),
85 cupsEncryption());
96ecd6f0 86
87 if (http == NULL)
88 {
89fd567e 89 _cupsLangPrintf(stderr,
b7382443 90 _("lpadmin: Unable to connect to server: %s\n"),
91 strerror(errno));
96ecd6f0 92 return (1);
93 }
94 }
95
3270670b 96 if (printer == NULL)
97 {
89fd567e 98 _cupsLangPuts(stderr,
b7382443 99 _("lpadmin: Unable to add a printer to the class:\n"
100 " You must specify a printer name "
157fcea9 101 "first\n"));
3270670b 102 return (1);
103 }
104
105 if (argv[i][2])
9c817392 106 pclass = argv[i] + 2;
3270670b 107 else
108 {
109 i ++;
9c817392 110
111 if (i >= argc)
112 {
89fd567e 113 _cupsLangPuts(stderr,
b7382443 114 _("lpadmin: Expected class name after \'-c\' "
157fcea9 115 "option\n"));
9c817392 116 return (1);
117 }
118
119 pclass = argv[i];
120 }
121
122 if (!validate_name(pclass))
123 {
89fd567e 124 _cupsLangPuts(stderr,
b7382443 125 _("lpadmin: Class name can only contain printable "
157fcea9 126 "characters\n"));
9c817392 127 return (1);
3270670b 128 }
0bd85f71 129
3b8ff70f 130 if (add_printer_to_class(http, printer, pclass))
131 return (1);
3270670b 132 break;
133
134 case 'd' : /* Set as default destination */
96ecd6f0 135 if (!http)
136 {
192a8a08 137 http = httpConnectEncrypt(cupsServer(), ippPort(),
138 cupsEncryption());
96ecd6f0 139
140 if (http == NULL)
141 {
89fd567e 142 _cupsLangPrintf(stderr,
b7382443 143 _("lpadmin: Unable to connect to server: %s\n"),
144 strerror(errno));
96ecd6f0 145 return (1);
146 }
147 }
148
3270670b 149 if (argv[i][2])
150 printer = argv[i] + 2;
151 else
152 {
153 i ++;
9c817392 154
155 if (i >= argc)
156 {
89fd567e 157 _cupsLangPuts(stderr,
b7382443 158 _("lpadmin: Expected printer name after \'-d\' "
157fcea9 159 "option\n"));
9c817392 160 return (1);
161 }
162
3270670b 163 printer = argv[i];
164 }
165
9c817392 166 if (!validate_name(printer))
167 {
89fd567e 168 _cupsLangPuts(stderr,
b7382443 169 _("lpadmin: Printer name can only contain "
157fcea9 170 "printable characters\n"));
9c817392 171 return (1);
172 }
173
3b8ff70f 174 if (default_printer(http, printer))
175 return (1);
176
3270670b 177 i = argc;
178 break;
179
808dd474 180 case 'h' : /* Connect to host */
96ecd6f0 181 if (http)
192a8a08 182 {
96ecd6f0 183 httpClose(http);
192a8a08 184 http = NULL;
185 }
808dd474 186
187 if (argv[i][2] != '\0')
192a8a08 188 cupsSetServer(argv[i] + 2);
808dd474 189 else
190 {
191 i ++;
8a4fe7c7 192
193 if (i >= argc)
194 {
89fd567e 195 _cupsLangPuts(stderr,
b7382443 196 _("lpadmin: Expected hostname after \'-h\' "
157fcea9 197 "option\n"));
8a4fe7c7 198 return (1);
199 }
808dd474 200
192a8a08 201 cupsSetServer(argv[i]);
808dd474 202 }
203 break;
204
3270670b 205 case 'i' : /* Use the specified interface script */
3270670b 206 if (argv[i][2])
6bff400e 207 file = argv[i] + 2;
3270670b 208 else
209 {
210 i ++;
9c817392 211
212 if (i >= argc)
213 {
89fd567e 214 _cupsLangPuts(stderr,
b7382443 215 _("lpadmin: Expected interface after \'-i\' "
157fcea9 216 "option\n"));
9c817392 217 return (1);
218 }
219
6bff400e 220 file = argv[i];
3270670b 221 }
222 break;
223
65a75084 224 case 'E' : /* Enable the printer */
1c9e0181 225 if (printer == NULL)
226 {
bcf61448 227#ifdef HAVE_SSL
192a8a08 228 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
1c9e0181 229
230 if (http)
192a8a08 231 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
1c9e0181 232#else
89fd567e 233 _cupsLangPrintf(stderr,
157fcea9 234 _("%s: Sorry, no encryption support compiled in\n"),
b7382443 235 argv[0]);
bcf61448 236#endif /* HAVE_SSL */
1c9e0181 237 break;
238 }
239
96ecd6f0 240 if (!http)
241 {
192a8a08 242 http = httpConnectEncrypt(cupsServer(), ippPort(),
243 cupsEncryption());
96ecd6f0 244
245 if (http == NULL)
246 {
89fd567e 247 _cupsLangPrintf(stderr,
b7382443 248 _("lpadmin: Unable to connect to server: %s\n"),
249 strerror(errno));
96ecd6f0 250 return (1);
251 }
1c9e0181 252 }
65a75084 253
3b8ff70f 254 if (enable_printer(http, printer))
255 return (1);
65a75084 256 break;
257
3270670b 258 case 'm' : /* Use the specified standard script/PPD file */
3270670b 259 if (argv[i][2])
6bff400e 260 num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options,
261 &options);
3270670b 262 else
263 {
264 i ++;
9c817392 265
266 if (i >= argc)
267 {
89fd567e 268 _cupsLangPuts(stderr,
b7382443 269 _("lpadmin: Expected model after \'-m\' "
157fcea9 270 "option\n"));
9c817392 271 return (1);
272 }
273
6bff400e 274 num_options = cupsAddOption("ppd-name", argv[i], num_options,
275 &options);
3270670b 276 }
3270670b 277 break;
278
01a426e9 279 case 'o' : /* Set option */
280 if (argv[i][2])
281 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
282 else
283 {
284 i ++;
285
286 if (i >= argc)
287 {
89fd567e 288 _cupsLangPuts(stderr,
b7382443 289 _("lpadmin: Expected name=value after \'-o\' "
157fcea9 290 "option\n"));
01a426e9 291 return (1);
292 }
293
294 num_options = cupsParseOptions(argv[i], num_options, &options);
295 }
296 break;
297
3270670b 298 case 'p' : /* Add/modify a printer */
299 if (argv[i][2])
300 printer = argv[i] + 2;
301 else
302 {
303 i ++;
9c817392 304
305 if (i >= argc)
306 {
89fd567e 307 _cupsLangPuts(stderr,
b7382443 308 _("lpadmin: Expected printer after \'-p\' "
157fcea9 309 "option\n"));
9c817392 310 return (1);
311 }
312
3270670b 313 printer = argv[i];
314 }
808dd474 315
9c817392 316 if (!validate_name(printer))
317 {
89fd567e 318 _cupsLangPuts(stderr,
b7382443 319 _("lpadmin: Printer name can only contain "
157fcea9 320 "printable characters\n"));
9c817392 321 return (1);
322 }
3270670b 323 break;
324
325 case 'r' : /* Remove printer from class */
96ecd6f0 326 if (!http)
327 {
192a8a08 328 http = httpConnectEncrypt(cupsServer(), ippPort(),
329 cupsEncryption());
96ecd6f0 330
331 if (http == NULL)
332 {
89fd567e 333 _cupsLangPrintf(stderr,
b7382443 334 _("lpadmin: Unable to connect to server: %s\n"),
335 strerror(errno));
96ecd6f0 336 return (1);
337 }
338 }
339
3270670b 340 if (printer == NULL)
341 {
89fd567e 342 _cupsLangPuts(stderr,
b7382443 343 _("lpadmin: Unable to remove a printer from the "
344 "class:\n"
345 " You must specify a printer name "
157fcea9 346 "first\n"));
3270670b 347 return (1);
348 }
349
350 if (argv[i][2])
9c817392 351 pclass = argv[i] + 2;
3270670b 352 else
353 {
354 i ++;
9c817392 355
356 if (i >= argc)
357 {
89fd567e 358 _cupsLangPuts(stderr,
b7382443 359 _("lpadmin: Expected class after \'-r\' "
157fcea9 360 "option\n"));
9c817392 361 return (1);
362 }
363
364 pclass = argv[i];
3270670b 365 }
9c817392 366
367 if (!validate_name(pclass))
368 {
89fd567e 369 _cupsLangPuts(stderr,
b7382443 370 _("lpadmin: Class name can only contain printable "
157fcea9 371 "characters\n"));
9c817392 372 return (1);
373 }
374
3b8ff70f 375 if (delete_printer_from_class(http, printer, pclass))
376 return (1);
3270670b 377 break;
378
5bce1394 379 case 'U' : /* Username */
380 if (argv[i][2] != '\0')
381 cupsSetUser(argv[i] + 2);
382 else
383 {
384 i ++;
385 if (i >= argc)
386 {
387 _cupsLangPrintf(stderr,
388 _("%s: Error - expected username after "
157fcea9 389 "\'-U\' option\n"),
5bce1394 390 argv[0]);
391 return (1);
392 }
393
394 cupsSetUser(argv[i]);
395 }
396 break;
397
01a426e9 398 case 'u' : /* Allow/deny users */
399 if (argv[i][2])
400 val = argv[i] + 2;
401 else
402 {
403 i ++;
404
405 if (i >= argc)
406 {
89fd567e 407 _cupsLangPuts(stderr,
b7382443 408 _("lpadmin: Expected allow/deny:userlist after "
157fcea9 409 "\'-u\' option\n"));
01a426e9 410 return (1);
411 }
412
413 val = argv[i];
414 }
415
b7382443 416 if (!strncasecmp(val, "allow:", 6))
01a426e9 417 num_options = cupsAddOption("requesting-user-name-allowed",
418 val + 6, num_options, &options);
b7382443 419 else if (!strncasecmp(val, "deny:", 5))
01a426e9 420 num_options = cupsAddOption("requesting-user-name-denied",
421 val + 5, num_options, &options);
422 else
423 {
89fd567e 424 _cupsLangPrintf(stderr,
157fcea9 425 _("lpadmin: Unknown allow/deny option \"%s\"\n"),
b7382443 426 val);
01a426e9 427 return (1);
428 }
429 break;
430
3270670b 431 case 'v' : /* Set the device-uri attribute */
3270670b 432 if (argv[i][2])
6bff400e 433 num_options = cupsAddOption("device-uri", argv[i] + 2,
434 num_options, &options);
3270670b 435 else
436 {
437 i ++;
9c817392 438
439 if (i >= argc)
440 {
89fd567e 441 _cupsLangPuts(stderr,
b7382443 442 _("lpadmin: Expected device URI after \'-v\' "
157fcea9 443 "option\n"));
9c817392 444 return (1);
445 }
446
6bff400e 447 num_options = cupsAddOption("device-uri", argv[i],
448 num_options, &options);
3270670b 449 }
450 break;
451
452 case 'x' : /* Delete a printer */
96ecd6f0 453 if (!http)
454 {
192a8a08 455 http = httpConnectEncrypt(cupsServer(), ippPort(),
456 cupsEncryption());
96ecd6f0 457
458 if (http == NULL)
459 {
89fd567e 460 _cupsLangPrintf(stderr,
b7382443 461 _("lpadmin: Unable to connect to server: %s\n"),
462 strerror(errno));
96ecd6f0 463 return (1);
464 }
465 }
466
3270670b 467 if (argv[i][2])
468 printer = argv[i] + 2;
469 else
470 {
471 i ++;
9c817392 472
473 if (i >= argc)
474 {
89fd567e 475 _cupsLangPuts(stderr,
b7382443 476 _("lpadmin: Expected printer or class after "
157fcea9 477 "\'-x\' option\n"));
9c817392 478 return (1);
479 }
480
3270670b 481 printer = argv[i];
482 }
483
9c817392 484 if (!validate_name(printer))
485 {
89fd567e 486 _cupsLangPuts(stderr,
b7382443 487 _("lpadmin: Printer name can only contain "
157fcea9 488 "printable characters\n"));
9c817392 489 return (1);
490 }
491
3b8ff70f 492 if (delete_printer(http, printer))
493 return (1);
494
3270670b 495 i = argc;
496 break;
497
498 case 'D' : /* Set the printer-info attribute */
3270670b 499 if (argv[i][2])
6bff400e 500 num_options = cupsAddOption("printer-info", argv[i] + 2,
501 num_options, &options);
3270670b 502 else
503 {
504 i ++;
9c817392 505
506 if (i >= argc)
507 {
89fd567e 508 _cupsLangPuts(stderr,
b7382443 509 _("lpadmin: Expected description after "
157fcea9 510 "\'-D\' option\n"));
9c817392 511 return (1);
512 }
513
6bff400e 514 num_options = cupsAddOption("printer-info", argv[i],
515 num_options, &options);
3270670b 516 }
517 break;
518
f8f971b2 519 case 'I' : /* Set the supported file types (ignored) */
520 i ++;
521
522 if (i >= argc)
523 {
89fd567e 524 _cupsLangPuts(stderr,
b7382443 525 _("lpadmin: Expected file type(s) after \'-I\' "
157fcea9 526 "option\n"));
f8f971b2 527 return (1);
528 }
529
89fd567e 530 _cupsLangPuts(stderr,
157fcea9 531 _("lpadmin: Warning - content type list ignored\n"));
f8f971b2 532 break;
533
6c7527d1 534 case 'L' : /* Set the printer-location attribute */
6c7527d1 535 if (argv[i][2])
6bff400e 536 num_options = cupsAddOption("printer-location", argv[i] + 2,
537 num_options, &options);
6c7527d1 538 else
539 {
540 i ++;
9c817392 541
542 if (i >= argc)
543 {
89fd567e 544 _cupsLangPuts(stderr,
b7382443 545 _("lpadmin: Expected location after \'-L\' "
157fcea9 546 "option\n"));
9c817392 547 return (1);
548 }
549
6bff400e 550 num_options = cupsAddOption("printer-location", argv[i],
551 num_options, &options);
6c7527d1 552 }
553 break;
554
3270670b 555 case 'P' : /* Use the specified PPD file */
3270670b 556 if (argv[i][2])
6bff400e 557 file = argv[i] + 2;
3270670b 558 else
559 {
560 i ++;
9c817392 561
562 if (i >= argc)
563 {
89fd567e 564 _cupsLangPuts(stderr,
157fcea9 565 _("lpadmin: Expected PPD after \'-P\' option\n"));
9c817392 566 return (1);
567 }
568
6bff400e 569 file = argv[i];
3270670b 570 }
571 break;
572
573 default :
89fd567e 574 _cupsLangPrintf(stderr,
157fcea9 575 _("lpadmin: Unknown option \'%c\'\n"), argv[i][1]);
3270670b 576 return (1);
577 }
578 else
579 {
157fcea9 580 _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \'%s\'\n"),
b7382443 581 argv[i]);
3270670b 582 return (1);
583 }
584
01a426e9 585 /*
586 * Set options as needed...
587 */
588
6bff400e 589 if (num_options || file)
01a426e9 590 {
591 if (!http)
592 {
192a8a08 593 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
01a426e9 594
595 if (http == NULL)
596 {
89fd567e 597 _cupsLangPrintf(stderr,
b7382443 598 _("lpadmin: Unable to connect to server: %s\n"),
599 strerror(errno));
01a426e9 600 return (1);
601 }
602 }
603
604 if (printer == NULL)
605 {
89fd567e 606 _cupsLangPuts(stderr,
b7382443 607 _("lpadmin: Unable to set the printer options:\n"
157fcea9 608 " You must specify a printer name first\n"));
01a426e9 609 return (1);
610 }
611
6bff400e 612 if (set_printer_options(http, printer, num_options, options, file))
3b8ff70f 613 return (1);
01a426e9 614 }
615
3270670b 616 if (printer == NULL)
617 {
89fd567e 618 _cupsLangPuts(stdout,
b7382443 619 _("Usage:\n"
620 "\n"
621 " lpadmin [-h server] -d destination\n"
622 " lpadmin [-h server] -x destination\n"
623 " lpadmin [-h server] -p printer [-c add-class] "
624 "[-i interface] [-m model]\n"
625 " [-r remove-class] [-v device] "
626 "[-D description]\n"
627 " [-P ppd-file] [-o name=value]\n"
628 " [-u allow:user,user] "
629 "[-u deny:user,user]\n"
630 "\n"));
3270670b 631 }
632
96ecd6f0 633 if (http)
634 httpClose(http);
3270670b 635
636 return (0);
637}
638
639
640/*
641 * 'add_printer_to_class()' - Add a printer to a class.
642 */
643
3b8ff70f 644static int /* O - 0 on success, 1 on fail */
3270670b 645add_printer_to_class(http_t *http, /* I - Server connection */
646 char *printer, /* I - Printer to add */
647 char *pclass) /* I - Class to add to */
648{
649 int i; /* Looping var */
650 ipp_t *request, /* IPP Request */
651 *response; /* IPP Response */
652 ipp_attribute_t *attr, /* Current attribute */
653 *members; /* Members in class */
3270670b 654 char uri[HTTP_MAX_URI]; /* URI for printer/class */
655
656
01a426e9 657 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
65a75084 658 printer, pclass));
659
3270670b 660 /*
661 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
662 * attributes:
663 *
664 * attributes-charset
665 * attributes-natural-language
666 * printer-uri
667 */
668
00f3aaf5 669 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
670
00a1fad8 671 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
672 "localhost", 0, "/classes/%s", pclass);
3270670b 673 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
674 "printer-uri", NULL, uri);
675
676 /*
677 * Do the request and get back a response...
678 */
679
96ecd6f0 680 response = cupsDoRequest(http, request, "/");
3270670b 681
682 /*
683 * Build a CUPS_ADD_CLASS request, which requires the following
684 * attributes:
685 *
686 * attributes-charset
687 * attributes-natural-language
688 * printer-uri
689 * member-uris
690 */
691
00f3aaf5 692 request = ippNewRequest(CUPS_ADD_CLASS);
3270670b 693
694 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
695 "printer-uri", NULL, uri);
696
697 /*
698 * See if the printer is already in the class...
699 */
700
701 if (response != NULL &&
702 (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
703 for (i = 0; i < members->num_values; i ++)
704 if (strcasecmp(printer, members->values[i].string.text) == 0)
705 {
00f3aaf5 706 _cupsLangPrintf(stderr,
707 _("lpadmin: Printer %s is already a member of class %s.\n"),
708 printer, pclass);
3270670b 709 ippDelete(request);
710 ippDelete(response);
3b8ff70f 711 return (0);
3270670b 712 }
713
714 /*
715 * OK, the printer isn't part of the class, so add it...
716 */
717
00a1fad8 718 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
719 "localhost", 0, "/printers/%s", printer);
3270670b 720
721 if (response != NULL &&
722 (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
723 {
724 /*
725 * Add the printer to the existing list...
726 */
727
728 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
729 "member-uris", members->num_values + 1, NULL, NULL);
730 for (i = 0; i < members->num_values; i ++)
c97b7208 731 attr->values[i].string.text = _cupsStrAlloc(members->values[i].string.text);
3270670b 732
c97b7208 733 attr->values[i].string.text = _cupsStrAlloc(uri);
3270670b 734 }
735 else
c97b7208 736 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
737 uri);
3270670b 738
739 /*
740 * Then send the request...
741 */
742
743 ippDelete(response);
744
745 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
3b8ff70f 746 {
00f3aaf5 747 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3b8ff70f 748
749 return (1);
750 }
7b2e6b69 751 else if (response->request.status.status_code > IPP_OK_CONFLICT)
96ecd6f0 752 {
00f3aaf5 753 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
96ecd6f0 754
3270670b 755 ippDelete(response);
3b8ff70f 756
757 return (1);
96ecd6f0 758 }
7b2e6b69 759 else
760 {
761 ippDelete(response);
3b8ff70f 762
7b2e6b69 763 return (0);
764 }
3270670b 765}
766
767
768/*
769 * 'default_printer()' - Set the default printing destination.
770 */
771
3b8ff70f 772static int /* O - 0 on success, 1 on fail */
3270670b 773default_printer(http_t *http, /* I - Server connection */
774 char *printer) /* I - Printer name */
775{
776 ipp_t *request, /* IPP Request */
777 *response; /* IPP Response */
3270670b 778 char uri[HTTP_MAX_URI]; /* URI for printer/class */
779
780
01a426e9 781 DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
65a75084 782
3270670b 783 /*
784 * Build a CUPS_SET_DEFAULT request, which requires the following
785 * attributes:
786 *
787 * attributes-charset
788 * attributes-natural-language
789 * printer-uri
790 */
791
00a1fad8 792 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
793 "localhost", 0, "/printers/%s", printer);
3270670b 794
00f3aaf5 795 request = ippNewRequest(CUPS_SET_DEFAULT);
3270670b 796
797 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
798 "printer-uri", NULL, uri);
799
800 /*
801 * Do the request and get back a response...
802 */
803
804 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
3b8ff70f 805 {
00f3aaf5 806 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3b8ff70f 807
808 return (1);
809 }
810 else if (response->request.status.status_code > IPP_OK_CONFLICT)
3270670b 811 {
00f3aaf5 812 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3270670b 813
814 ippDelete(response);
3b8ff70f 815
816 return (1);
817 }
818 else
819 {
820 ippDelete(response);
821
822 return (0);
3270670b 823 }
824}
825
826
827/*
828 * 'delete_printer()' - Delete a printer from the system...
829 */
830
3b8ff70f 831static int /* O - 0 on success, 1 on fail */
3270670b 832delete_printer(http_t *http, /* I - Server connection */
833 char *printer) /* I - Printer to delete */
834{
835 ipp_t *request, /* IPP Request */
836 *response; /* IPP Response */
3270670b 837 char uri[HTTP_MAX_URI]; /* URI for printer/class */
838
839
01a426e9 840 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
65a75084 841
3270670b 842 /*
843 * Build a CUPS_DELETE_PRINTER request, which requires the following
844 * attributes:
845 *
846 * attributes-charset
847 * attributes-natural-language
848 * printer-uri
849 */
850
00f3aaf5 851 request = ippNewRequest(CUPS_DELETE_PRINTER);
852
00a1fad8 853 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
854 "localhost", 0, "/printers/%s", printer);
3270670b 855 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
856 "printer-uri", NULL, uri);
857
858 /*
859 * Do the request and get back a response...
860 */
861
862 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
3b8ff70f 863 {
00f3aaf5 864 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3b8ff70f 865
866 return (1);
867 }
868 else if (response->request.status.status_code > IPP_OK_CONFLICT)
3270670b 869 {
00f3aaf5 870 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3270670b 871
872 ippDelete(response);
3b8ff70f 873
874 return (1);
875 }
876 else
877 {
878 ippDelete(response);
879
880 return (0);
3270670b 881 }
882}
883
884
885/*
886 * 'delete_printer_from_class()' - Delete a printer from a class.
887 */
888
3b8ff70f 889static int /* O - 0 on success, 1 on fail */
00f3aaf5 890delete_printer_from_class(
891 http_t *http, /* I - Server connection */
892 char *printer, /* I - Printer to remove */
893 char *pclass) /* I - Class to remove from */
3270670b 894{
895 int i, j, k; /* Looping vars */
896 ipp_t *request, /* IPP Request */
897 *response; /* IPP Response */
898 ipp_attribute_t *attr, /* Current attribute */
899 *members; /* Members in class */
3270670b 900 char uri[HTTP_MAX_URI]; /* URI for printer/class */
901
902
01a426e9 903 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
65a75084 904 printer, pclass));
905
3270670b 906 /*
907 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
908 * attributes:
909 *
910 * attributes-charset
911 * attributes-natural-language
912 * printer-uri
913 */
914
00f3aaf5 915 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
916
00a1fad8 917 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
918 "localhost", 0, "/classes/%s", pclass);
3270670b 919 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
920 "printer-uri", NULL, uri);
921
922 /*
923 * Do the request and get back a response...
924 */
925
926 if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
0a3ac972 927 response->request.status.status_code == IPP_NOT_FOUND)
3270670b 928 {
00f3aaf5 929 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
930
3270670b 931 ippDelete(response);
00f3aaf5 932
3b8ff70f 933 return (1);
3270670b 934 }
935
936 /*
937 * See if the printer is already in the class...
938 */
939
940 if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
941 {
157fcea9 942 _cupsLangPuts(stderr, _("lpadmin: No member names were seen\n"));
00f3aaf5 943
3270670b 944 ippDelete(response);
00f3aaf5 945
3b8ff70f 946 return (1);
3270670b 947 }
948
949 for (i = 0; i < members->num_values; i ++)
00f3aaf5 950 if (!strcasecmp(printer, members->values[i].string.text))
3270670b 951 break;
952
953 if (i >= members->num_values)
954 {
00f3aaf5 955 _cupsLangPrintf(stderr,
956 _("lpadmin: Printer %s is not a member of class %s.\n"),
957 printer, pclass);
958
3270670b 959 ippDelete(response);
00f3aaf5 960
3b8ff70f 961 return (1);
3270670b 962 }
963
964 if (members->num_values == 1)
965 {
966 /*
967 * Build a CUPS_DELETE_CLASS request, which requires the following
968 * attributes:
969 *
970 * attributes-charset
971 * attributes-natural-language
972 * printer-uri
973 */
974
00f3aaf5 975 request = ippNewRequest(CUPS_DELETE_CLASS);
3270670b 976
977 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
978 "printer-uri", NULL, uri);
979 }
980 else
981 {
982 /*
983 * Build a CUPS_ADD_CLASS request, which requires the following
984 * attributes:
985 *
986 * attributes-charset
987 * attributes-natural-language
988 * printer-uri
989 * member-uris
990 */
991
00f3aaf5 992 request = ippNewRequest(CUPS_ADD_CLASS);
3270670b 993
994 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
995 "printer-uri", NULL, uri);
996
997 /*
998 * Delete the printer from the class...
999 */
1000
1001 members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1002 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1003 "member-uris", members->num_values - 1, NULL, NULL);
1004
1005 for (j = 0, k = 0; j < members->num_values; j ++)
1006 if (j != i)
c97b7208 1007 attr->values[k ++].string.text =
1008 _cupsStrAlloc(members->values[j].string.text);
3270670b 1009 }
1010
1011 /*
1012 * Then send the request...
1013 */
1014
1015 ippDelete(response);
1016
1017 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
3b8ff70f 1018 {
00f3aaf5 1019 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1020
3b8ff70f 1021 return (1);
1022 }
1023 else if (response->request.status.status_code > IPP_OK_CONFLICT)
96ecd6f0 1024 {
00f3aaf5 1025 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
96ecd6f0 1026
3270670b 1027 ippDelete(response);
3b8ff70f 1028
1029 return (1);
1030 }
1031 else
1032 {
1033 ippDelete(response);
1034
1035 return (0);
96ecd6f0 1036 }
3270670b 1037}
1038
1039
65a75084 1040/*
1041 * 'enable_printer()' - Enable a printer...
1042 */
1043
3b8ff70f 1044static int /* O - 0 on success, 1 on fail */
65a75084 1045enable_printer(http_t *http, /* I - Server connection */
1046 char *printer) /* I - Printer to enable */
1047{
1048 ipp_t *request, /* IPP Request */
1049 *response; /* IPP Response */
65a75084 1050 char uri[HTTP_MAX_URI]; /* URI for printer/class */
1051
1052
01a426e9 1053 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
65a75084 1054
1055 /*
1056 * Build a CUPS_ADD_PRINTER request, which requires the following
1057 * attributes:
1058 *
1059 * attributes-charset
1060 * attributes-natural-language
1061 * printer-uri
1062 * printer-state
1063 * printer-is-accepting-jobs
1064 */
1065
00f3aaf5 1066 request = ippNewRequest(CUPS_ADD_PRINTER);
1067
00a1fad8 1068 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1069 "localhost", 0, "/printers/%s", printer);
65a75084 1070 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1071 "printer-uri", NULL, uri);
1072
1073 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1074 IPP_PRINTER_IDLE);
1075
1076 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1077
1078 /*
1079 * Do the request and get back a response...
1080 */
1081
1082 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
3b8ff70f 1083 {
00f3aaf5 1084 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
1085
3b8ff70f 1086 return (1);
1087 }
1088 else if (response->request.status.status_code > IPP_OK_CONFLICT)
65a75084 1089 {
00f3aaf5 1090 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
65a75084 1091
1092 ippDelete(response);
3b8ff70f 1093
1094 return (1);
1095 }
1096 else
1097 {
1098 ippDelete(response);
1099
1100 return (0);
65a75084 1101 }
1102}
1103
1104
01a426e9 1105/*
1106 * 'set_printer_options()' - Set the printer options.
1107 */
1108
3b8ff70f 1109static int /* O - 0 on success, 1 on fail */
00f3aaf5 1110set_printer_options(
1111 http_t *http, /* I - Server connection */
1112 char *printer, /* I - Printer */
1113 int num_options, /* I - Number of options */
6bff400e 1114 cups_option_t *options, /* I - Options */
1115 char *file) /* I - PPD file/interface script */
01a426e9 1116{
1117 ipp_t *request, /* IPP Request */
1118 *response; /* IPP Response */
5a3ef28d 1119 ipp_attribute_t *attr; /* IPP attribute */
5a3ef28d 1120 ipp_op_t op; /* Operation to perform */
a309520e 1121 const char *ppdfile; /* PPD filename */
1122 int ppdchanged; /* PPD changed? */
1123 ppd_file_t *ppd; /* PPD file */
1124 ppd_choice_t *choice; /* Marked choice */
01a426e9 1125 char uri[HTTP_MAX_URI], /* URI for printer/class */
1126 line[1024], /* Line from PPD file */
1127 keyword[1024], /* Keyword from Default line */
1128 *keyptr, /* Pointer into keyword... */
1129 tempfile[1024]; /* Temporary filename */
6bff400e 1130 cups_file_t *in, /* PPD file */
01a426e9 1131 *out; /* Temporary file */
0050629b 1132 const char *protocol, /* Old protocol option */
1133 *customval; /* Custom option value */
01a426e9 1134
1135
6bff400e 1136 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1137 "options=%p, file=\"%s\")\n", http, printer, num_options,
1138 options, file));
01a426e9 1139
00a1fad8 1140 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1141 "localhost", 0, "/printers/%s", printer);
5a3ef28d 1142
01a426e9 1143 /*
5a3ef28d 1144 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
01a426e9 1145 * attributes:
1146 *
1147 * attributes-charset
1148 * attributes-natural-language
1149 * printer-uri
5a3ef28d 1150 * requested-attributes
01a426e9 1151 */
1152
00f3aaf5 1153 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
5a3ef28d 1154
1155 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1156 "printer-uri", NULL, uri);
5a3ef28d 1157 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1158 "requested-attributes", NULL, "printer-type");
1159
1160 /*
1161 * Do the request...
1162 */
1163
6bff400e 1164 op = CUPS_ADD_MODIFY_PRINTER;
5a3ef28d 1165
1166 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1167 {
1168 /*
1169 * See what kind of printer or class it is...
1170 */
1171
a309520e 1172 if ((attr = ippFindAttribute(response, "printer-type",
1173 IPP_TAG_ENUM)) != NULL)
5a3ef28d 1174 {
1175 if (attr->values[0].integer & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
1176 {
6bff400e 1177 op = CUPS_ADD_MODIFY_CLASS;
00a1fad8 1178 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1179 "localhost", 0, "/classes/%s", printer);
5a3ef28d 1180 }
1181 }
1182
1183 ippDelete(response);
1184 }
1185
1186 /*
6bff400e 1187 * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
1188 * requires the following attributes:
5a3ef28d 1189 *
1190 * attributes-charset
1191 * attributes-natural-language
1192 * printer-uri
1193 * other options
1194 */
1195
00f3aaf5 1196 request = ippNewRequest(op);
01a426e9 1197
1198 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1199 "printer-uri", NULL, uri);
6bff400e 1200 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1201 "requesting-user-name", NULL, cupsUser());
01a426e9 1202
1203 /*
1204 * Add the options...
1205 */
1206
a309520e 1207 cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1208
1209 if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1210 {
1211 if (!strcasecmp(protocol, "bcp"))
a88691d5 1212 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
a309520e 1213 NULL, "bcp");
1214 else if (!strcasecmp(protocol, "tbcp"))
a88691d5 1215 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
a309520e 1216 NULL, "tbcp");
1217 }
01a426e9 1218
6bff400e 1219 if (file)
1220 ppdfile = file;
1221 else if (op == CUPS_ADD_MODIFY_PRINTER)
5a3ef28d 1222 ppdfile = cupsGetPPD(printer);
1223 else
1224 ppdfile = NULL;
1225
1226 if (ppdfile != NULL)
01a426e9 1227 {
1228 /*
1229 * Set default options in the PPD file...
1230 */
1231
a309520e 1232 ppd = ppdOpenFile(ppdfile);
1233 ppdMarkDefaults(ppd);
1234 cupsMarkOptions(ppd, num_options, options);
1235
6bff400e 1236 if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) < 0)
b2d75006 1237 {
bd2147fb 1238 _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
b2d75006 1239 ippDelete(request);
6bff400e 1240 if (ppdfile != file)
1241 unlink(ppdfile);
b2d75006 1242 return (1);
1243 }
1244
6bff400e 1245 if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
b2d75006 1246 {
89fd567e 1247 _cupsLangPrintf(stderr,
b7382443 1248 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1249 ppdfile, strerror(errno));
b2d75006 1250 ippDelete(request);
6bff400e 1251 if (ppdfile != file)
1252 unlink(ppdfile);
1253 cupsFileClose(out);
b2d75006 1254 unlink(tempfile);
1255 return (1);
1256 }
01a426e9 1257
a309520e 1258 ppdchanged = 0;
01a426e9 1259
6bff400e 1260 while (cupsFileGets(in, line, sizeof(line)))
01a426e9 1261 {
a309520e 1262 if (strncmp(line, "*Default", 8))
6bff400e 1263 cupsFilePrintf(out, "%s\n", line);
01a426e9 1264 else
1265 {
1266 /*
1267 * Get default option name...
1268 */
1269
def978d5 1270 strlcpy(keyword, line + 8, sizeof(keyword));
01a426e9 1271
1272 for (keyptr = keyword; *keyptr; keyptr ++)
64bbab09 1273 if (*keyptr == ':' || isspace(*keyptr & 255))
01a426e9 1274 break;
1275
a309520e 1276 *keyptr++ = '\0';
1277 while (isspace(*keyptr & 255))
1278 keyptr ++;
01a426e9 1279
42d6b787 1280 if (!strcmp(keyword, "PageRegion") ||
1281 !strcmp(keyword, "PageSize") ||
1282 !strcmp(keyword, "PaperDimension") ||
1283 !strcmp(keyword, "ImageableArea"))
1284 {
1285 if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1286 choice = ppdFindMarkedChoice(ppd, "PageRegion");
1287 }
01a426e9 1288 else
a309520e 1289 choice = ppdFindMarkedChoice(ppd, keyword);
01a426e9 1290
a309520e 1291 if (choice && strcmp(choice->choice, keyptr))
1292 {
0050629b 1293 if (strcmp(choice->choice, "Custom"))
1294 {
1295 cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
1296 ppdchanged = 1;
1297 }
1298 else if ((customval = cupsGetOption(keyword, num_options,
1299 options)) != NULL)
1300 {
1301 cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
1302 ppdchanged = 1;
1303 }
1304 else
1305 cupsFilePrintf(out, "%s\n", line);
a309520e 1306 }
01a426e9 1307 else
6bff400e 1308 cupsFilePrintf(out, "%s\n", line);
01a426e9 1309 }
1310 }
1311
6bff400e 1312 cupsFileClose(in);
1313 cupsFileClose(out);
a309520e 1314 ppdClose(ppd);
01a426e9 1315
1316 /*
1317 * Do the request...
1318 */
1319
a309520e 1320 ippDelete(cupsDoFileRequest(http, request, "/admin/",
6bff400e 1321 ppdchanged ? tempfile : file));
01a426e9 1322
1323 /*
1324 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1325 * lpadmin)
1326 */
1327
6bff400e 1328 if (ppdfile != file)
1329 unlink(ppdfile);
01a426e9 1330 unlink(tempfile);
1331 }
1332 else
1333 {
1334 /*
1335 * No PPD file - just set the options...
1336 */
1337
a309520e 1338 ippDelete(cupsDoRequest(http, request, "/admin/"));
01a426e9 1339 }
1340
1341 /*
5a3ef28d 1342 * Check the response...
01a426e9 1343 */
1344
00f3aaf5 1345 if (cupsLastError() > IPP_OK_CONFLICT)
01a426e9 1346 {
00f3aaf5 1347 _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
3b8ff70f 1348
1349 return (1);
1350 }
1351 else
3b8ff70f 1352 return (0);
01a426e9 1353}
1354
1355
6c7527d1 1356/*
aa37e40e 1357 * 'validate_name()' - Make sure the printer name only contains valid chars.
9c817392 1358 */
1359
00f3aaf5 1360static int /* O - 0 if name is no good, 1 if name is good */
1361validate_name(const char *name) /* I - Name to check */
9c817392 1362{
00f3aaf5 1363 const char *ptr; /* Pointer into name */
095bb32d 1364
1365
74bb2a4e 1366 /*
1367 * Scan the whole name...
1368 */
1369
095bb32d 1370 for (ptr = name; *ptr; ptr ++)
1371 if (*ptr == '@')
1372 break;
a3901bc4 1373 else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
1374 *ptr == '#')
9c817392 1375 return (0);
9c817392 1376
095bb32d 1377 /*
1378 * All the characters are good; validate the length, too...
1379 */
1380
1381 return ((ptr - name) < 128);
9c817392 1382}
1383
1384
1385/*
c9d3f842 1386 * End of "$Id$".
3270670b 1387 */