]>
Commit | Line | Data |
---|---|---|
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> |
ef416fc2 | 23 | |
24 | ||
25 | /* | |
26 | * Local functions... | |
27 | */ | |
28 | ||
eac3a0a0 MS |
29 | static int add_printer_to_class(http_t *http, char *printer, char *pclass); |
30 | static int default_printer(http_t *http, char *printer); | |
31 | static int delete_printer(http_t *http, char *printer); | |
32 | static int delete_printer_from_class(http_t *http, char *printer, | |
33 | char *pclass); | |
34 | static int delete_printer_option(http_t *http, char *printer, | |
35 | char *option); | |
36 | static int enable_printer(http_t *http, char *printer); | |
fffed089 | 37 | static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize); |
eac3a0a0 MS |
38 | static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri, |
39 | size_t urisize); | |
40 | static int set_printer_options(http_t *http, char *printer, | |
41 | int num_options, cups_option_t *options, | |
42 | char *file); | |
43 | static int validate_name(const char *name); | |
ef416fc2 | 44 | |
45 | ||
46 | /* | |
47 | * 'main()' - Parse options and configure the scheduler. | |
48 | */ | |
49 | ||
50 | int | |
51 | main(int argc, /* I - Number of command-line arguments */ | |
52 | char *argv[]) /* I - Command-line arguments */ | |
53 | { | |
54 | int i; /* Looping var */ | |
55 | http_t *http; /* Connection to server */ | |
56 | char *printer, /* Destination printer */ | |
57 | *pclass, /* Printer class name */ | |
58 | *val; /* Pointer to allow/deny value */ | |
59 | int num_options; /* Number of options */ | |
60 | cups_option_t *options; /* Options */ | |
fffed089 MS |
61 | char *file, /* New PPD file/interface script */ |
62 | evefile[1024] = ""; | |
63 | /* IPP Everywhere PPD */ | |
64 | const char *ppd_name, /* ppd-name value */ | |
65 | *device_uri; /* device-uri value */ | |
ef416fc2 | 66 | |
67 | ||
07725fee | 68 | _cupsSetLocale(argv); |
d09495fa | 69 | |
ef416fc2 | 70 | http = NULL; |
71 | printer = NULL; | |
72 | num_options = 0; | |
73 | options = NULL; | |
7cf5915e | 74 | file = NULL; |
ef416fc2 | 75 | |
76 | for (i = 1; i < argc; i ++) | |
77 | if (argv[i][0] == '-') | |
78 | switch (argv[i][1]) | |
79 | { | |
80 | case 'c' : /* Add printer to class */ | |
81 | if (!http) | |
82 | { | |
fffed089 | 83 | http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL); |
ef416fc2 | 84 | |
85 | if (http == NULL) | |
86 | { | |
fa73b229 | 87 | _cupsLangPrintf(stderr, |
0837b7e8 | 88 | _("lpadmin: Unable to connect to server: %s"), |
ef416fc2 | 89 | strerror(errno)); |
90 | return (1); | |
91 | } | |
92 | } | |
93 | ||
94 | if (printer == NULL) | |
95 | { | |
fa73b229 | 96 | _cupsLangPuts(stderr, |
ef416fc2 | 97 | _("lpadmin: Unable to add a printer to the class:\n" |
98 | " You must specify a printer name " | |
0837b7e8 | 99 | "first.")); |
ef416fc2 | 100 | return (1); |
101 | } | |
102 | ||
103 | if (argv[i][2]) | |
104 | pclass = argv[i] + 2; | |
105 | else | |
106 | { | |
107 | i ++; | |
108 | ||
109 | if (i >= argc) | |
110 | { | |
fa73b229 | 111 | _cupsLangPuts(stderr, |
0837b7e8 MS |
112 | _("lpadmin: Expected class name after \"-c\" " |
113 | "option.")); | |
ef416fc2 | 114 | return (1); |
115 | } | |
116 | ||
117 | pclass = argv[i]; | |
118 | } | |
119 | ||
120 | if (!validate_name(pclass)) | |
121 | { | |
fa73b229 | 122 | _cupsLangPuts(stderr, |
ef416fc2 | 123 | _("lpadmin: Class name can only contain printable " |
0837b7e8 | 124 | "characters.")); |
ef416fc2 | 125 | return (1); |
126 | } | |
127 | ||
128 | if (add_printer_to_class(http, printer, pclass)) | |
129 | return (1); | |
130 | break; | |
131 | ||
132 | case 'd' : /* Set as default destination */ | |
133 | if (!http) | |
134 | { | |
fffed089 | 135 | http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL); |
ef416fc2 | 136 | |
137 | if (http == NULL) | |
138 | { | |
fa73b229 | 139 | _cupsLangPrintf(stderr, |
0837b7e8 | 140 | _("lpadmin: Unable to connect to server: %s"), |
ef416fc2 | 141 | strerror(errno)); |
142 | return (1); | |
143 | } | |
144 | } | |
145 | ||
146 | if (argv[i][2]) | |
147 | printer = argv[i] + 2; | |
148 | else | |
149 | { | |
150 | i ++; | |
151 | ||
152 | if (i >= argc) | |
153 | { | |
fa73b229 | 154 | _cupsLangPuts(stderr, |
0837b7e8 MS |
155 | _("lpadmin: Expected printer name after \"-d\" " |
156 | "option.")); | |
ef416fc2 | 157 | return (1); |
158 | } | |
159 | ||
160 | printer = argv[i]; | |
161 | } | |
162 | ||
163 | if (!validate_name(printer)) | |
164 | { | |
fa73b229 | 165 | _cupsLangPuts(stderr, |
ef416fc2 | 166 | _("lpadmin: Printer name can only contain " |
0837b7e8 | 167 | "printable characters.")); |
ef416fc2 | 168 | return (1); |
169 | } | |
170 | ||
171 | if (default_printer(http, printer)) | |
172 | return (1); | |
173 | ||
174 | i = argc; | |
175 | break; | |
176 | ||
177 | case 'h' : /* Connect to host */ | |
178 | if (http) | |
179 | { | |
180 | httpClose(http); | |
181 | http = NULL; | |
182 | } | |
183 | ||
184 | if (argv[i][2] != '\0') | |
185 | cupsSetServer(argv[i] + 2); | |
186 | else | |
187 | { | |
188 | i ++; | |
189 | ||
190 | if (i >= argc) | |
191 | { | |
fa73b229 | 192 | _cupsLangPuts(stderr, |
0837b7e8 MS |
193 | _("lpadmin: Expected hostname after \"-h\" " |
194 | "option.")); | |
ef416fc2 | 195 | return (1); |
196 | } | |
197 | ||
198 | cupsSetServer(argv[i]); | |
199 | } | |
200 | break; | |
201 | ||
202 | case 'i' : /* Use the specified interface script */ | |
ef416fc2 | 203 | if (argv[i][2]) |
7cf5915e | 204 | file = argv[i] + 2; |
ef416fc2 | 205 | else |
206 | { | |
207 | i ++; | |
208 | ||
209 | if (i >= argc) | |
210 | { | |
fa73b229 | 211 | _cupsLangPuts(stderr, |
0837b7e8 MS |
212 | _("lpadmin: Expected interface after \"-i\" " |
213 | "option.")); | |
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 | ||
591 | case 'P' : /* Use the specified PPD file */ | |
ef416fc2 | 592 | if (argv[i][2]) |
7cf5915e | 593 | file = argv[i] + 2; |
ef416fc2 | 594 | else |
595 | { | |
596 | i ++; | |
597 | ||
598 | if (i >= argc) | |
599 | { | |
fa73b229 | 600 | _cupsLangPuts(stderr, |
0837b7e8 | 601 | _("lpadmin: Expected PPD after \"-P\" option.")); |
ef416fc2 | 602 | return (1); |
603 | } | |
604 | ||
7cf5915e | 605 | file = argv[i]; |
ef416fc2 | 606 | } |
607 | break; | |
608 | ||
609 | default : | |
fa73b229 | 610 | _cupsLangPrintf(stderr, |
0837b7e8 | 611 | _("lpadmin: Unknown option \"%c\"."), argv[i][1]); |
ef416fc2 | 612 | return (1); |
613 | } | |
614 | else | |
615 | { | |
0837b7e8 | 616 | _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), |
ef416fc2 | 617 | argv[i]); |
618 | return (1); | |
619 | } | |
620 | ||
621 | /* | |
622 | * Set options as needed... | |
623 | */ | |
624 | ||
fffed089 MS |
625 | if ((ppd_name = cupsGetOption("ppd-name", num_options, options)) != NULL && !strcmp(ppd_name, "everywhere") && (device_uri = cupsGetOption("device-uri", num_options, options)) != NULL) |
626 | { | |
627 | if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile))) == NULL) | |
628 | return (1); | |
629 | ||
630 | num_options = cupsRemoveOption("ppd-name", num_options, &options); | |
631 | } | |
632 | ||
7cf5915e | 633 | if (num_options || file) |
ef416fc2 | 634 | { |
635 | if (!http) | |
636 | { | |
fffed089 | 637 | http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL); |
ef416fc2 | 638 | |
639 | if (http == NULL) | |
640 | { | |
fa73b229 | 641 | _cupsLangPrintf(stderr, |
0837b7e8 | 642 | _("lpadmin: Unable to connect to server: %s"), |
ef416fc2 | 643 | strerror(errno)); |
644 | return (1); | |
645 | } | |
646 | } | |
647 | ||
648 | if (printer == NULL) | |
649 | { | |
fa73b229 | 650 | _cupsLangPuts(stderr, |
ef416fc2 | 651 | _("lpadmin: Unable to set the printer options:\n" |
0837b7e8 | 652 | " You must specify a printer name first.")); |
ef416fc2 | 653 | return (1); |
654 | } | |
655 | ||
7cf5915e | 656 | if (set_printer_options(http, printer, num_options, options, file)) |
ef416fc2 | 657 | return (1); |
658 | } | |
659 | ||
fffed089 MS |
660 | if (evefile[0]) |
661 | unlink(evefile); | |
662 | ||
ef416fc2 | 663 | if (printer == NULL) |
664 | { | |
fa73b229 | 665 | _cupsLangPuts(stdout, |
ef416fc2 | 666 | _("Usage:\n" |
667 | "\n" | |
668 | " lpadmin [-h server] -d destination\n" | |
669 | " lpadmin [-h server] -x destination\n" | |
670 | " lpadmin [-h server] -p printer [-c add-class] " | |
671 | "[-i interface] [-m model]\n" | |
672 | " [-r remove-class] [-v device] " | |
673 | "[-D description]\n" | |
674 | " [-P ppd-file] [-o name=value]\n" | |
675 | " [-u allow:user,user] " | |
0837b7e8 | 676 | "[-u deny:user,user]")); |
ef416fc2 | 677 | } |
678 | ||
679 | if (http) | |
680 | httpClose(http); | |
681 | ||
682 | return (0); | |
683 | } | |
684 | ||
685 | ||
686 | /* | |
687 | * 'add_printer_to_class()' - Add a printer to a class. | |
688 | */ | |
689 | ||
690 | static int /* O - 0 on success, 1 on fail */ | |
691 | add_printer_to_class(http_t *http, /* I - Server connection */ | |
692 | char *printer, /* I - Printer to add */ | |
693 | char *pclass) /* I - Class to add to */ | |
694 | { | |
695 | int i; /* Looping var */ | |
696 | ipp_t *request, /* IPP Request */ | |
697 | *response; /* IPP Response */ | |
698 | ipp_attribute_t *attr, /* Current attribute */ | |
699 | *members; /* Members in class */ | |
ef416fc2 | 700 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ |
701 | ||
702 | ||
703 | DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http, | |
704 | printer, pclass)); | |
705 | ||
706 | /* | |
fffed089 | 707 | * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following |
ef416fc2 | 708 | * attributes: |
709 | * | |
710 | * attributes-charset | |
711 | * attributes-natural-language | |
712 | * printer-uri | |
eac3a0a0 | 713 | * requesting-user-name |
ef416fc2 | 714 | */ |
715 | ||
fffed089 | 716 | request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); |
fa73b229 | 717 | |
a4d04587 | 718 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
719 | "localhost", 0, "/classes/%s", pclass); | |
ef416fc2 | 720 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
721 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
722 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
723 | NULL, cupsUser()); | |
ef416fc2 | 724 | |
725 | /* | |
726 | * Do the request and get back a response... | |
727 | */ | |
728 | ||
729 | response = cupsDoRequest(http, request, "/"); | |
730 | ||
731 | /* | |
fffed089 | 732 | * Build a CUPS-Add-Modify-Class request, which requires the following |
ef416fc2 | 733 | * attributes: |
734 | * | |
735 | * attributes-charset | |
736 | * attributes-natural-language | |
737 | * printer-uri | |
eac3a0a0 | 738 | * requesting-user-name |
ef416fc2 | 739 | * member-uris |
740 | */ | |
741 | ||
fffed089 | 742 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); |
ef416fc2 | 743 | |
744 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
745 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
746 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
747 | NULL, cupsUser()); | |
ef416fc2 | 748 | |
749 | /* | |
750 | * See if the printer is already in the class... | |
751 | */ | |
752 | ||
753 | if (response != NULL && | |
eac3a0a0 MS |
754 | (members = ippFindAttribute(response, "member-names", |
755 | IPP_TAG_NAME)) != NULL) | |
ef416fc2 | 756 | for (i = 0; i < members->num_values; i ++) |
88f9aafc | 757 | if (_cups_strcasecmp(printer, members->values[i].string.text) == 0) |
ef416fc2 | 758 | { |
fa73b229 | 759 | _cupsLangPrintf(stderr, |
0837b7e8 MS |
760 | _("lpadmin: Printer %s is already a member of class " |
761 | "%s."), printer, pclass); | |
ef416fc2 | 762 | ippDelete(request); |
763 | ippDelete(response); | |
764 | return (0); | |
765 | } | |
766 | ||
767 | /* | |
768 | * OK, the printer isn't part of the class, so add it... | |
769 | */ | |
770 | ||
a4d04587 | 771 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
772 | "localhost", 0, "/printers/%s", printer); | |
ef416fc2 | 773 | |
774 | if (response != NULL && | |
eac3a0a0 MS |
775 | (members = ippFindAttribute(response, "member-uris", |
776 | IPP_TAG_URI)) != NULL) | |
ef416fc2 | 777 | { |
778 | /* | |
779 | * Add the printer to the existing list... | |
780 | */ | |
781 | ||
782 | attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, | |
783 | "member-uris", members->num_values + 1, NULL, NULL); | |
784 | for (i = 0; i < members->num_values; i ++) | |
eac3a0a0 MS |
785 | attr->values[i].string.text = |
786 | _cupsStrAlloc(members->values[i].string.text); | |
ef416fc2 | 787 | |
1f0275e3 | 788 | attr->values[i].string.text = _cupsStrAlloc(uri); |
ef416fc2 | 789 | } |
790 | else | |
1f0275e3 MS |
791 | ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL, |
792 | uri); | |
ef416fc2 | 793 | |
794 | /* | |
795 | * Then send the request... | |
796 | */ | |
797 | ||
798 | ippDelete(response); | |
799 | ||
eac3a0a0 | 800 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
fffed089 | 801 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 802 | { |
eac3a0a0 | 803 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 804 | |
805 | return (1); | |
806 | } | |
807 | else | |
ef416fc2 | 808 | return (0); |
ef416fc2 | 809 | } |
810 | ||
811 | ||
812 | /* | |
813 | * 'default_printer()' - Set the default printing destination. | |
814 | */ | |
815 | ||
816 | static int /* O - 0 on success, 1 on fail */ | |
817 | default_printer(http_t *http, /* I - Server connection */ | |
818 | char *printer) /* I - Printer name */ | |
819 | { | |
eac3a0a0 | 820 | ipp_t *request; /* IPP Request */ |
ef416fc2 | 821 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ |
822 | ||
823 | ||
824 | DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer)); | |
825 | ||
826 | /* | |
fffed089 | 827 | * Build a CUPS-Set-Default request, which requires the following |
ef416fc2 | 828 | * attributes: |
829 | * | |
830 | * attributes-charset | |
831 | * attributes-natural-language | |
832 | * printer-uri | |
eac3a0a0 | 833 | * requesting-user-name |
ef416fc2 | 834 | */ |
835 | ||
a4d04587 | 836 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
837 | "localhost", 0, "/printers/%s", printer); | |
ef416fc2 | 838 | |
fffed089 | 839 | request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT); |
ef416fc2 | 840 | |
841 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
842 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
843 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
844 | NULL, cupsUser()); | |
ef416fc2 | 845 | |
846 | /* | |
847 | * Do the request and get back a response... | |
848 | */ | |
849 | ||
eac3a0a0 | 850 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
ef416fc2 | 851 | |
fffed089 | 852 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 853 | { |
eac3a0a0 | 854 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 855 | |
856 | return (1); | |
857 | } | |
858 | else | |
ef416fc2 | 859 | return (0); |
ef416fc2 | 860 | } |
861 | ||
862 | ||
863 | /* | |
864 | * 'delete_printer()' - Delete a printer from the system... | |
865 | */ | |
866 | ||
867 | static int /* O - 0 on success, 1 on fail */ | |
868 | delete_printer(http_t *http, /* I - Server connection */ | |
869 | char *printer) /* I - Printer to delete */ | |
870 | { | |
eac3a0a0 | 871 | ipp_t *request; /* IPP Request */ |
ef416fc2 | 872 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ |
873 | ||
874 | ||
875 | DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer)); | |
876 | ||
877 | /* | |
fffed089 | 878 | * Build a CUPS-Delete-Printer request, which requires the following |
ef416fc2 | 879 | * attributes: |
880 | * | |
881 | * attributes-charset | |
882 | * attributes-natural-language | |
883 | * printer-uri | |
eac3a0a0 | 884 | * requesting-user-name |
ef416fc2 | 885 | */ |
886 | ||
fffed089 | 887 | request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER); |
fa73b229 | 888 | |
a4d04587 | 889 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
890 | "localhost", 0, "/printers/%s", printer); | |
ef416fc2 | 891 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
892 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
893 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
894 | NULL, cupsUser()); | |
ef416fc2 | 895 | |
896 | /* | |
897 | * Do the request and get back a response... | |
898 | */ | |
899 | ||
eac3a0a0 | 900 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
ef416fc2 | 901 | |
fffed089 | 902 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 903 | { |
eac3a0a0 | 904 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 905 | |
906 | return (1); | |
907 | } | |
908 | else | |
ef416fc2 | 909 | return (0); |
ef416fc2 | 910 | } |
911 | ||
912 | ||
913 | /* | |
914 | * 'delete_printer_from_class()' - Delete a printer from a class. | |
915 | */ | |
916 | ||
917 | static int /* O - 0 on success, 1 on fail */ | |
fa73b229 | 918 | delete_printer_from_class( |
919 | http_t *http, /* I - Server connection */ | |
920 | char *printer, /* I - Printer to remove */ | |
921 | char *pclass) /* I - Class to remove from */ | |
ef416fc2 | 922 | { |
923 | int i, j, k; /* Looping vars */ | |
924 | ipp_t *request, /* IPP Request */ | |
925 | *response; /* IPP Response */ | |
926 | ipp_attribute_t *attr, /* Current attribute */ | |
927 | *members; /* Members in class */ | |
ef416fc2 | 928 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ |
929 | ||
930 | ||
931 | DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http, | |
932 | printer, pclass)); | |
933 | ||
934 | /* | |
fffed089 | 935 | * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following |
ef416fc2 | 936 | * attributes: |
937 | * | |
938 | * attributes-charset | |
939 | * attributes-natural-language | |
940 | * printer-uri | |
eac3a0a0 | 941 | * requesting-user-name |
ef416fc2 | 942 | */ |
943 | ||
fffed089 | 944 | request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); |
fa73b229 | 945 | |
a4d04587 | 946 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
947 | "localhost", 0, "/classes/%s", pclass); | |
ef416fc2 | 948 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
949 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
950 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
951 | NULL, cupsUser()); | |
ef416fc2 | 952 | |
953 | /* | |
954 | * Do the request and get back a response... | |
955 | */ | |
956 | ||
957 | if ((response = cupsDoRequest(http, request, "/classes/")) == NULL || | |
fffed089 | 958 | response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND) |
ef416fc2 | 959 | { |
eac3a0a0 | 960 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
fa73b229 | 961 | |
ef416fc2 | 962 | ippDelete(response); |
fa73b229 | 963 | |
ef416fc2 | 964 | return (1); |
965 | } | |
966 | ||
967 | /* | |
968 | * See if the printer is already in the class... | |
969 | */ | |
970 | ||
971 | if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL) | |
972 | { | |
0837b7e8 | 973 | _cupsLangPuts(stderr, _("lpadmin: No member names were seen.")); |
fa73b229 | 974 | |
ef416fc2 | 975 | ippDelete(response); |
fa73b229 | 976 | |
ef416fc2 | 977 | return (1); |
978 | } | |
979 | ||
980 | for (i = 0; i < members->num_values; i ++) | |
88f9aafc | 981 | if (!_cups_strcasecmp(printer, members->values[i].string.text)) |
ef416fc2 | 982 | break; |
983 | ||
984 | if (i >= members->num_values) | |
985 | { | |
fa73b229 | 986 | _cupsLangPrintf(stderr, |
0837b7e8 | 987 | _("lpadmin: Printer %s is not a member of class %s."), |
fa73b229 | 988 | printer, pclass); |
989 | ||
ef416fc2 | 990 | ippDelete(response); |
fa73b229 | 991 | |
ef416fc2 | 992 | return (1); |
993 | } | |
994 | ||
995 | if (members->num_values == 1) | |
996 | { | |
997 | /* | |
fffed089 | 998 | * Build a CUPS-Delete-Class request, which requires the following |
ef416fc2 | 999 | * attributes: |
1000 | * | |
1001 | * attributes-charset | |
1002 | * attributes-natural-language | |
1003 | * printer-uri | |
eac3a0a0 | 1004 | * requesting-user-name |
ef416fc2 | 1005 | */ |
1006 | ||
fffed089 | 1007 | request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS); |
ef416fc2 | 1008 | |
1009 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
1010 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
1011 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, |
1012 | "requesting-user-name", NULL, cupsUser()); | |
ef416fc2 | 1013 | } |
1014 | else | |
1015 | { | |
1016 | /* | |
fffed089 | 1017 | * Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following |
ef416fc2 | 1018 | * attributes: |
1019 | * | |
1020 | * attributes-charset | |
1021 | * attributes-natural-language | |
1022 | * printer-uri | |
eac3a0a0 | 1023 | * requesting-user-name |
ef416fc2 | 1024 | * member-uris |
1025 | */ | |
1026 | ||
fffed089 | 1027 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); |
ef416fc2 | 1028 | |
1029 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
1030 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
1031 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, |
1032 | "requesting-user-name", NULL, cupsUser()); | |
ef416fc2 | 1033 | |
1034 | /* | |
1035 | * Delete the printer from the class... | |
1036 | */ | |
1037 | ||
1038 | members = ippFindAttribute(response, "member-uris", IPP_TAG_URI); | |
1039 | attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, | |
1040 | "member-uris", members->num_values - 1, NULL, NULL); | |
1041 | ||
1042 | for (j = 0, k = 0; j < members->num_values; j ++) | |
1043 | if (j != i) | |
1f0275e3 MS |
1044 | attr->values[k ++].string.text = |
1045 | _cupsStrAlloc(members->values[j].string.text); | |
ef416fc2 | 1046 | } |
1047 | ||
1048 | /* | |
1049 | * Then send the request... | |
1050 | */ | |
1051 | ||
1052 | ippDelete(response); | |
1053 | ||
eac3a0a0 MS |
1054 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
1055 | ||
fffed089 | 1056 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 1057 | { |
eac3a0a0 | 1058 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
fa73b229 | 1059 | |
ef416fc2 | 1060 | return (1); |
1061 | } | |
eac3a0a0 MS |
1062 | else |
1063 | return (0); | |
1064 | } | |
ef416fc2 | 1065 | |
ef416fc2 | 1066 | |
eac3a0a0 MS |
1067 | /* |
1068 | * 'delete_printer_option()' - Delete a printer option. | |
1069 | */ | |
1070 | ||
1071 | static int /* O - 0 on success, 1 on fail */ | |
1072 | delete_printer_option(http_t *http, /* I - Server connection */ | |
1073 | char *printer, /* I - Printer */ | |
1074 | char *option) /* I - Option to delete */ | |
1075 | { | |
1076 | ipp_t *request; /* IPP request */ | |
1077 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ | |
1078 | ||
1079 | ||
1080 | /* | |
fffed089 | 1081 | * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which |
eac3a0a0 MS |
1082 | * requires the following attributes: |
1083 | * | |
1084 | * attributes-charset | |
1085 | * attributes-natural-language | |
1086 | * printer-uri | |
1087 | * requesting-user-name | |
1088 | * option with deleteAttr tag | |
1089 | */ | |
1090 | ||
a2326b5b | 1091 | if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) |
fffed089 | 1092 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); |
ef416fc2 | 1093 | else |
fffed089 | 1094 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER); |
eac3a0a0 MS |
1095 | |
1096 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
1097 | "printer-uri", NULL, uri); | |
1098 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
1099 | "requesting-user-name", NULL, cupsUser()); | |
1100 | ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0); | |
1101 | ||
1102 | /* | |
1103 | * Do the request and get back a response... | |
1104 | */ | |
1105 | ||
1106 | ippDelete(cupsDoRequest(http, request, "/admin/")); | |
1107 | ||
fffed089 | 1108 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 1109 | { |
eac3a0a0 | 1110 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 1111 | |
eac3a0a0 | 1112 | return (1); |
ef416fc2 | 1113 | } |
eac3a0a0 MS |
1114 | else |
1115 | return (0); | |
ef416fc2 | 1116 | } |
1117 | ||
1118 | ||
1119 | /* | |
1120 | * 'enable_printer()' - Enable a printer... | |
1121 | */ | |
1122 | ||
1123 | static int /* O - 0 on success, 1 on fail */ | |
1124 | enable_printer(http_t *http, /* I - Server connection */ | |
1125 | char *printer) /* I - Printer to enable */ | |
1126 | { | |
eac3a0a0 | 1127 | ipp_t *request; /* IPP Request */ |
ef416fc2 | 1128 | char uri[HTTP_MAX_URI]; /* URI for printer/class */ |
1129 | ||
1130 | ||
1131 | DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer)); | |
1132 | ||
1133 | /* | |
fffed089 | 1134 | * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which |
eac3a0a0 | 1135 | * require the following attributes: |
ef416fc2 | 1136 | * |
1137 | * attributes-charset | |
1138 | * attributes-natural-language | |
1139 | * printer-uri | |
eac3a0a0 | 1140 | * requesting-user-name |
ef416fc2 | 1141 | * printer-state |
1142 | * printer-is-accepting-jobs | |
1143 | */ | |
1144 | ||
a2326b5b | 1145 | if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) |
fffed089 | 1146 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); |
eac3a0a0 | 1147 | else |
fffed089 | 1148 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER); |
fa73b229 | 1149 | |
ef416fc2 | 1150 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
1151 | "printer-uri", NULL, uri); | |
eac3a0a0 MS |
1152 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, |
1153 | "requesting-user-name", NULL, cupsUser()); | |
ef416fc2 | 1154 | ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", |
fffed089 | 1155 | IPP_PSTATE_IDLE); |
ef416fc2 | 1156 | ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); |
1157 | ||
1158 | /* | |
1159 | * Do the request and get back a response... | |
1160 | */ | |
1161 | ||
eac3a0a0 | 1162 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
fa73b229 | 1163 | |
fffed089 | 1164 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 1165 | { |
eac3a0a0 | 1166 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 1167 | |
1168 | return (1); | |
1169 | } | |
1170 | else | |
eac3a0a0 MS |
1171 | return (0); |
1172 | } | |
1173 | ||
1174 | ||
fffed089 MS |
1175 | /* |
1176 | * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI. | |
1177 | */ | |
1178 | ||
1179 | static char * /* O - Filename or NULL */ | |
1180 | get_printer_ppd(const char *uri, /* I - Printer URI */ | |
1181 | char *buffer, /* I - Filename buffer */ | |
1182 | size_t bufsize) /* I - Size of filename buffer */ | |
1183 | { | |
1184 | http_t *http; /* Connection to printer */ | |
1185 | ipp_t *request, /* Get-Printer-Attributes request */ | |
1186 | *response; /* Get-Printer-Attributes response */ | |
fb2d5470 MS |
1187 | char resolved[1024], /* Resolved URI */ |
1188 | scheme[32], /* URI scheme */ | |
fffed089 MS |
1189 | userpass[256], /* Username:password */ |
1190 | host[256], /* Hostname */ | |
1191 | resource[256]; /* Resource path */ | |
1192 | int port; /* Port number */ | |
1193 | ||
1194 | ||
1195 | /* | |
1196 | * Connect to the printer... | |
1197 | */ | |
1198 | ||
fb2d5470 MS |
1199 | if (strstr(uri, "._tcp")) |
1200 | { | |
1201 | /* | |
1202 | * Resolve URI... | |
1203 | */ | |
1204 | ||
1205 | if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) | |
1206 | { | |
1207 | _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri); | |
1208 | return (NULL); | |
1209 | } | |
1210 | ||
1211 | uri = resolved; | |
1212 | } | |
1213 | ||
fffed089 MS |
1214 | if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) |
1215 | { | |
1216 | _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri); | |
1217 | return (NULL); | |
1218 | } | |
1219 | ||
1220 | http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); | |
1221 | if (!http) | |
1222 | { | |
1223 | _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString()); | |
1224 | return (NULL); | |
1225 | } | |
1226 | ||
1227 | /* | |
1228 | * Send a Get-Printer-Attributes request... | |
1229 | */ | |
1230 | ||
1231 | request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); | |
1232 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); | |
1233 | response = cupsDoRequest(http, request, resource); | |
1234 | ||
1235 | if (!_ppdCreateFromIPP(buffer, bufsize, response)) | |
1236 | _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno)); | |
1237 | ||
1238 | ippDelete(response); | |
1239 | httpClose(http); | |
1240 | ||
1241 | if (buffer[0]) | |
1242 | return (buffer); | |
1243 | else | |
1244 | return (NULL); | |
1245 | } | |
1246 | ||
1247 | ||
eac3a0a0 MS |
1248 | /* |
1249 | * 'get_printer_type()' - Determine the printer type and URI. | |
1250 | */ | |
1251 | ||
1252 | static cups_ptype_t /* O - printer-type value */ | |
1253 | get_printer_type(http_t *http, /* I - Server connection */ | |
1254 | char *printer, /* I - Printer name */ | |
1255 | char *uri, /* I - URI buffer */ | |
1256 | size_t urisize) /* I - Size of URI buffer */ | |
1257 | { | |
1258 | ipp_t *request, /* IPP request */ | |
1259 | *response; /* IPP response */ | |
1260 | ipp_attribute_t *attr; /* printer-type attribute */ | |
1261 | cups_ptype_t type; /* printer-type value */ | |
1262 | ||
1263 | ||
1264 | /* | |
1265 | * Build a GET_PRINTER_ATTRIBUTES request, which requires the following | |
1266 | * attributes: | |
1267 | * | |
1268 | * attributes-charset | |
1269 | * attributes-natural-language | |
1270 | * printer-uri | |
1271 | * requested-attributes | |
1272 | * requesting-user-name | |
1273 | */ | |
1274 | ||
7e86f2f6 | 1275 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer); |
eac3a0a0 | 1276 | |
fffed089 | 1277 | request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); |
eac3a0a0 MS |
1278 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
1279 | "printer-uri", NULL, uri); | |
1280 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
1281 | "requested-attributes", NULL, "printer-type"); | |
1282 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
1283 | "requesting-user-name", NULL, cupsUser()); | |
1284 | ||
1285 | /* | |
1286 | * Do the request... | |
1287 | */ | |
1288 | ||
1289 | response = cupsDoRequest(http, request, "/"); | |
1290 | if ((attr = ippFindAttribute(response, "printer-type", | |
1291 | IPP_TAG_ENUM)) != NULL) | |
ef416fc2 | 1292 | { |
eac3a0a0 | 1293 | type = (cups_ptype_t)attr->values[0].integer; |
ef416fc2 | 1294 | |
a2326b5b | 1295 | if (type & CUPS_PRINTER_CLASS) |
7e86f2f6 | 1296 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer); |
ef416fc2 | 1297 | } |
eac3a0a0 MS |
1298 | else |
1299 | type = CUPS_PRINTER_LOCAL; | |
1300 | ||
1301 | ippDelete(response); | |
1302 | ||
1303 | return (type); | |
ef416fc2 | 1304 | } |
1305 | ||
1306 | ||
ef416fc2 | 1307 | /* |
1308 | * 'set_printer_options()' - Set the printer options. | |
1309 | */ | |
1310 | ||
1311 | static int /* O - 0 on success, 1 on fail */ | |
fa73b229 | 1312 | set_printer_options( |
1313 | http_t *http, /* I - Server connection */ | |
1314 | char *printer, /* I - Printer */ | |
1315 | int num_options, /* I - Number of options */ | |
7cf5915e MS |
1316 | cups_option_t *options, /* I - Options */ |
1317 | char *file) /* I - PPD file/interface script */ | |
ef416fc2 | 1318 | { |
eac3a0a0 | 1319 | ipp_t *request; /* IPP Request */ |
b423cd4c | 1320 | const char *ppdfile; /* PPD filename */ |
1321 | int ppdchanged; /* PPD changed? */ | |
1322 | ppd_file_t *ppd; /* PPD file */ | |
1323 | ppd_choice_t *choice; /* Marked choice */ | |
ef416fc2 | 1324 | char uri[HTTP_MAX_URI], /* URI for printer/class */ |
1325 | line[1024], /* Line from PPD file */ | |
1326 | keyword[1024], /* Keyword from Default line */ | |
1327 | *keyptr, /* Pointer into keyword... */ | |
1328 | tempfile[1024]; /* Temporary filename */ | |
7cf5915e | 1329 | cups_file_t *in, /* PPD file */ |
ef416fc2 | 1330 | *out; /* Temporary file */ |
7cf5915e | 1331 | const char *protocol, /* Old protocol option */ |
eac3a0a0 MS |
1332 | *customval, /* Custom option value */ |
1333 | *boolval; /* Boolean value */ | |
1334 | int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */ | |
1335 | wrote_snmp_supplies = 0;/* Wrote cupsSNMPSupplies keyword? */ | |
ef416fc2 | 1336 | |
1337 | ||
7cf5915e MS |
1338 | DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, " |
1339 | "options=%p, file=\"%s\")\n", http, printer, num_options, | |
1340 | options, file)); | |
ef416fc2 | 1341 | |
ef416fc2 | 1342 | /* |
fffed089 MS |
1343 | * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request, |
1344 | * which requires the following attributes: | |
ef416fc2 | 1345 | * |
1346 | * attributes-charset | |
1347 | * attributes-natural-language | |
1348 | * printer-uri | |
eac3a0a0 | 1349 | * requesting-user-name |
ef416fc2 | 1350 | * other options |
1351 | */ | |
1352 | ||
a2326b5b | 1353 | if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) |
fffed089 | 1354 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); |
eac3a0a0 | 1355 | else |
fffed089 | 1356 | request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER); |
ef416fc2 | 1357 | |
fffed089 MS |
1358 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); |
1359 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); | |
ef416fc2 | 1360 | |
1361 | /* | |
1362 | * Add the options... | |
1363 | */ | |
1364 | ||
fffed089 MS |
1365 | if (file) |
1366 | ppdfile = file; | |
1367 | else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER) | |
1368 | ppdfile = cupsGetPPD(printer); | |
1369 | else | |
1370 | ppdfile = NULL; | |
1371 | ||
b0f26938 | 1372 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); |
b423cd4c | 1373 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER); |
1374 | ||
1375 | if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL) | |
1376 | { | |
88f9aafc | 1377 | if (!_cups_strcasecmp(protocol, "bcp")) |
a41f09e2 | 1378 | ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor", |
b423cd4c | 1379 | NULL, "bcp"); |
88f9aafc | 1380 | else if (!_cups_strcasecmp(protocol, "tbcp")) |
a41f09e2 | 1381 | ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor", |
b423cd4c | 1382 | NULL, "tbcp"); |
1383 | } | |
ef416fc2 | 1384 | |
fffed089 | 1385 | if (ppdfile) |
ef416fc2 | 1386 | { |
1387 | /* | |
1388 | * Set default options in the PPD file... | |
1389 | */ | |
1390 | ||
b423cd4c | 1391 | ppd = ppdOpenFile(ppdfile); |
1392 | ppdMarkDefaults(ppd); | |
1393 | cupsMarkOptions(ppd, num_options, options); | |
1394 | ||
0268488e | 1395 | if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) |
ef416fc2 | 1396 | { |
0837b7e8 | 1397 | _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file")); |
ef416fc2 | 1398 | ippDelete(request); |
7cf5915e MS |
1399 | if (ppdfile != file) |
1400 | unlink(ppdfile); | |
ef416fc2 | 1401 | return (1); |
1402 | } | |
1403 | ||
7cf5915e | 1404 | if ((in = cupsFileOpen(ppdfile, "r")) == NULL) |
ef416fc2 | 1405 | { |
fa73b229 | 1406 | _cupsLangPrintf(stderr, |
0837b7e8 | 1407 | _("lpadmin: Unable to open PPD file \"%s\" - %s"), |
ef416fc2 | 1408 | ppdfile, strerror(errno)); |
1409 | ippDelete(request); | |
7cf5915e MS |
1410 | if (ppdfile != file) |
1411 | unlink(ppdfile); | |
1412 | cupsFileClose(out); | |
ef416fc2 | 1413 | unlink(tempfile); |
1414 | return (1); | |
1415 | } | |
1416 | ||
b423cd4c | 1417 | ppdchanged = 0; |
ef416fc2 | 1418 | |
7cf5915e | 1419 | while (cupsFileGets(in, line, sizeof(line))) |
ef416fc2 | 1420 | { |
eac3a0a0 MS |
1421 | if (!strncmp(line, "*cupsIPPSupplies:", 17) && |
1422 | (boolval = cupsGetOption("cupsIPPSupplies", num_options, | |
1423 | options)) != NULL) | |
1424 | { | |
1425 | wrote_ipp_supplies = 1; | |
1426 | cupsFilePrintf(out, "*cupsIPPSupplies: %s\n", | |
88f9aafc MS |
1427 | (!_cups_strcasecmp(boolval, "true") || |
1428 | !_cups_strcasecmp(boolval, "yes") || | |
1429 | !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); | |
eac3a0a0 MS |
1430 | } |
1431 | else if (!strncmp(line, "*cupsSNMPSupplies:", 18) && | |
1432 | (boolval = cupsGetOption("cupsSNMPSupplies", num_options, | |
1433 | options)) != NULL) | |
1434 | { | |
1435 | wrote_snmp_supplies = 1; | |
1436 | cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n", | |
88f9aafc MS |
1437 | (!_cups_strcasecmp(boolval, "true") || |
1438 | !_cups_strcasecmp(boolval, "yes") || | |
1439 | !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); | |
eac3a0a0 MS |
1440 | } |
1441 | else if (strncmp(line, "*Default", 8)) | |
7cf5915e | 1442 | cupsFilePrintf(out, "%s\n", line); |
ef416fc2 | 1443 | else |
1444 | { | |
1445 | /* | |
1446 | * Get default option name... | |
1447 | */ | |
1448 | ||
1449 | strlcpy(keyword, line + 8, sizeof(keyword)); | |
1450 | ||
1451 | for (keyptr = keyword; *keyptr; keyptr ++) | |
1452 | if (*keyptr == ':' || isspace(*keyptr & 255)) | |
1453 | break; | |
1454 | ||
b423cd4c | 1455 | *keyptr++ = '\0'; |
1456 | while (isspace(*keyptr & 255)) | |
1457 | keyptr ++; | |
1458 | ||
1459 | if (!strcmp(keyword, "PageRegion") || | |
1460 | !strcmp(keyword, "PageSize") || | |
1461 | !strcmp(keyword, "PaperDimension") || | |
1462 | !strcmp(keyword, "ImageableArea")) | |
1463 | { | |
1464 | if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL) | |
1465 | choice = ppdFindMarkedChoice(ppd, "PageRegion"); | |
1466 | } | |
ef416fc2 | 1467 | else |
b423cd4c | 1468 | choice = ppdFindMarkedChoice(ppd, keyword); |
ef416fc2 | 1469 | |
b423cd4c | 1470 | if (choice && strcmp(choice->choice, keyptr)) |
1471 | { | |
7cf5915e MS |
1472 | if (strcmp(choice->choice, "Custom")) |
1473 | { | |
1474 | cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice); | |
1475 | ppdchanged = 1; | |
1476 | } | |
1477 | else if ((customval = cupsGetOption(keyword, num_options, | |
1478 | options)) != NULL) | |
1479 | { | |
1480 | cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval); | |
1481 | ppdchanged = 1; | |
1482 | } | |
1483 | else | |
1484 | cupsFilePrintf(out, "%s\n", line); | |
b423cd4c | 1485 | } |
ef416fc2 | 1486 | else |
7cf5915e | 1487 | cupsFilePrintf(out, "%s\n", line); |
ef416fc2 | 1488 | } |
1489 | } | |
1490 | ||
eac3a0a0 MS |
1491 | if (!wrote_ipp_supplies && |
1492 | (boolval = cupsGetOption("cupsIPPSupplies", num_options, | |
1493 | options)) != NULL) | |
1494 | { | |
1495 | cupsFilePrintf(out, "*cupsIPPSupplies: %s\n", | |
88f9aafc MS |
1496 | (!_cups_strcasecmp(boolval, "true") || |
1497 | !_cups_strcasecmp(boolval, "yes") || | |
1498 | !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); | |
eac3a0a0 MS |
1499 | } |
1500 | ||
1501 | if (!wrote_snmp_supplies && | |
1502 | (boolval = cupsGetOption("cupsSNMPSupplies", num_options, | |
1503 | options)) != NULL) | |
1504 | { | |
1505 | cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n", | |
88f9aafc MS |
1506 | (!_cups_strcasecmp(boolval, "true") || |
1507 | !_cups_strcasecmp(boolval, "yes") || | |
1508 | !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); | |
eac3a0a0 MS |
1509 | } |
1510 | ||
7cf5915e MS |
1511 | cupsFileClose(in); |
1512 | cupsFileClose(out); | |
b423cd4c | 1513 | ppdClose(ppd); |
ef416fc2 | 1514 | |
1515 | /* | |
1516 | * Do the request... | |
1517 | */ | |
1518 | ||
b423cd4c | 1519 | ippDelete(cupsDoFileRequest(http, request, "/admin/", |
7cf5915e | 1520 | ppdchanged ? tempfile : file)); |
ef416fc2 | 1521 | |
1522 | /* | |
1523 | * Clean up temp files... (TODO: catch signals in case we CTRL-C during | |
1524 | * lpadmin) | |
1525 | */ | |
1526 | ||
7cf5915e MS |
1527 | if (ppdfile != file) |
1528 | unlink(ppdfile); | |
ef416fc2 | 1529 | unlink(tempfile); |
1530 | } | |
1531 | else | |
1532 | { | |
1533 | /* | |
1534 | * No PPD file - just set the options... | |
1535 | */ | |
1536 | ||
b423cd4c | 1537 | ippDelete(cupsDoRequest(http, request, "/admin/")); |
ef416fc2 | 1538 | } |
1539 | ||
1540 | /* | |
1541 | * Check the response... | |
1542 | */ | |
1543 | ||
fffed089 | 1544 | if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) |
ef416fc2 | 1545 | { |
eac3a0a0 | 1546 | _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); |
ef416fc2 | 1547 | |
1548 | return (1); | |
1549 | } | |
1550 | else | |
ef416fc2 | 1551 | return (0); |
ef416fc2 | 1552 | } |
1553 | ||
1554 | ||
1555 | /* | |
1556 | * 'validate_name()' - Make sure the printer name only contains valid chars. | |
1557 | */ | |
1558 | ||
fa73b229 | 1559 | static int /* O - 0 if name is no good, 1 if name is good */ |
1560 | validate_name(const char *name) /* I - Name to check */ | |
ef416fc2 | 1561 | { |
fa73b229 | 1562 | const char *ptr; /* Pointer into name */ |
ef416fc2 | 1563 | |
1564 | ||
1565 | /* | |
1566 | * Scan the whole name... | |
1567 | */ | |
1568 | ||
1569 | for (ptr = name; *ptr; ptr ++) | |
1570 | if (*ptr == '@') | |
1571 | break; | |
1572 | else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || | |
1573 | *ptr == '#') | |
1574 | return (0); | |
1575 | ||
1576 | /* | |
1577 | * All the characters are good; validate the length, too... | |
1578 | */ | |
1579 | ||
1580 | return ((ptr - name) < 128); | |
1581 | } | |
1582 | ||
1583 | ||
1584 | /* | |
f2d18633 | 1585 | * End of "$Id$". |
ef416fc2 | 1586 | */ |