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