]>
Commit | Line | Data |
---|---|---|
104fd4ae | 1 | /* |
104fd4ae MS |
2 | * CUPS destination API test program for CUPS. |
3 | * | |
e22f464e | 4 | * Copyright © 2012-2018 by Apple Inc. |
104fd4ae | 5 | * |
e3101897 | 6 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
104fd4ae MS |
7 | */ |
8 | ||
9 | /* | |
10 | * Include necessary headers... | |
11 | */ | |
12 | ||
13 | #include <stdio.h> | |
c585706d | 14 | #include <errno.h> |
104fd4ae MS |
15 | #include "cups.h" |
16 | ||
17 | ||
18 | /* | |
19 | * Local functions... | |
20 | */ | |
21 | ||
46385a1a | 22 | static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest); |
104fd4ae MS |
23 | static void localize(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value); |
24 | static void print_file(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *filename, int num_options, cups_option_t *options); | |
25 | static void show_conflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, int num_options, cups_option_t *options); | |
26 | static void show_default(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option); | |
27 | static void show_media(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, unsigned flags, const char *name); | |
28 | static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value); | |
29 | static void usage(const char *arg) __attribute__((noreturn)); | |
30 | ||
31 | ||
32 | /* | |
33 | * 'main()' - Main entry. | |
34 | */ | |
35 | ||
36 | int /* O - Exit status */ | |
37 | main(int argc, /* I - Number of command-line arguments */ | |
38 | char *argv[]) /* I - Command-line arguments */ | |
39 | { | |
b969d5af | 40 | int i; /* Looping var */ |
104fd4ae MS |
41 | http_t *http; /* Connection to destination */ |
42 | cups_dest_t *dest = NULL; /* Destination */ | |
43 | cups_dinfo_t *dinfo; /* Destination info */ | |
b969d5af MS |
44 | unsigned dflags = CUPS_DEST_FLAGS_NONE; |
45 | /* Destination flags */ | |
104fd4ae MS |
46 | |
47 | ||
48 | if (argc < 2) | |
e22f464e | 49 | return (0); |
104fd4ae | 50 | |
c5f5c5a7 MS |
51 | if (!strcmp(argv[1], "--get")) |
52 | { | |
c5f5c5a7 MS |
53 | cups_dest_t *dests; /* Destinations */ |
54 | int num_dests = cupsGetDests2(CUPS_HTTP_DEFAULT, &dests); | |
55 | /* Number of destinations */ | |
56 | ||
57 | for (i = 0; i < num_dests; i ++) | |
58 | enum_cb(NULL, 0, dests + i); | |
59 | ||
60 | cupsFreeDests(num_dests, dests); | |
61 | return (0); | |
62 | } | |
63 | else if (!strcmp(argv[1], "--enum")) | |
104fd4ae | 64 | { |
46385a1a MS |
65 | cups_ptype_t type = 0, /* Printer type filter */ |
66 | mask = 0; /* Printer type mask */ | |
67 | ||
68 | ||
69 | for (i = 2; i < argc; i ++) | |
70 | { | |
71 | if (!strcmp(argv[i], "grayscale")) | |
72 | { | |
73 | type |= CUPS_PRINTER_BW; | |
74 | mask |= CUPS_PRINTER_BW; | |
75 | } | |
76 | else if (!strcmp(argv[i], "color")) | |
77 | { | |
78 | type |= CUPS_PRINTER_COLOR; | |
79 | mask |= CUPS_PRINTER_COLOR; | |
80 | } | |
81 | else if (!strcmp(argv[i], "duplex")) | |
82 | { | |
83 | type |= CUPS_PRINTER_DUPLEX; | |
84 | mask |= CUPS_PRINTER_DUPLEX; | |
85 | } | |
86 | else if (!strcmp(argv[i], "staple")) | |
87 | { | |
88 | type |= CUPS_PRINTER_STAPLE; | |
89 | mask |= CUPS_PRINTER_STAPLE; | |
90 | } | |
91 | else if (!strcmp(argv[i], "small")) | |
92 | { | |
93 | type |= CUPS_PRINTER_SMALL; | |
94 | mask |= CUPS_PRINTER_SMALL; | |
95 | } | |
96 | else if (!strcmp(argv[i], "medium")) | |
97 | { | |
98 | type |= CUPS_PRINTER_MEDIUM; | |
99 | mask |= CUPS_PRINTER_MEDIUM; | |
100 | } | |
101 | else if (!strcmp(argv[i], "large")) | |
102 | { | |
103 | type |= CUPS_PRINTER_LARGE; | |
104 | mask |= CUPS_PRINTER_LARGE; | |
105 | } | |
106 | else | |
107 | usage(argv[i]); | |
108 | } | |
109 | ||
110 | cupsEnumDests(CUPS_DEST_FLAGS_NONE, 5000, NULL, type, mask, enum_cb, NULL); | |
111 | ||
104fd4ae MS |
112 | return (0); |
113 | } | |
b969d5af MS |
114 | |
115 | i = 1; | |
116 | if (!strcmp(argv[i], "--device")) | |
117 | { | |
118 | dflags = CUPS_DEST_FLAGS_DEVICE; | |
119 | i ++; | |
120 | } | |
121 | ||
122 | if (!strncmp(argv[i], "ipp://", 6) || !strncmp(argv[i], "ipps://", 7)) | |
123 | dest = cupsGetDestWithURI(NULL, argv[i]); | |
124 | else if (!strcmp(argv[i], "default")) | |
c536b6c5 MS |
125 | { |
126 | dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL); | |
127 | if (dest && dest->instance) | |
128 | printf("default is \"%s/%s\".\n", dest->name, dest->instance); | |
e22f464e | 129 | else if (dest) |
c536b6c5 | 130 | printf("default is \"%s\".\n", dest->name); |
e22f464e MS |
131 | else |
132 | puts("no default destination."); | |
c536b6c5 | 133 | } |
104fd4ae | 134 | else |
b969d5af | 135 | dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[i], NULL); |
104fd4ae MS |
136 | |
137 | if (!dest) | |
138 | { | |
b969d5af | 139 | printf("testdest: Unable to get destination \"%s\": %s\n", argv[i], cupsLastErrorString()); |
104fd4ae MS |
140 | return (1); |
141 | } | |
142 | ||
b969d5af MS |
143 | i ++; |
144 | ||
145 | if ((http = cupsConnectDest(dest, dflags, 30000, NULL, NULL, 0, NULL, NULL)) == NULL) | |
104fd4ae | 146 | { |
b969d5af | 147 | printf("testdest: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString()); |
104fd4ae MS |
148 | return (1); |
149 | } | |
150 | ||
151 | if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL) | |
152 | { | |
b969d5af | 153 | printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString()); |
104fd4ae MS |
154 | return (1); |
155 | } | |
156 | ||
b969d5af | 157 | if (i == argc || !strcmp(argv[i], "supported")) |
104fd4ae | 158 | { |
b969d5af MS |
159 | i ++; |
160 | ||
161 | if ((i + 1) < argc) | |
162 | show_supported(http, dest, dinfo, argv[i], argv[i + 1]); | |
104fd4ae | 163 | else if (argc > 2) |
b969d5af | 164 | show_supported(http, dest, dinfo, argv[i], NULL); |
104fd4ae MS |
165 | else |
166 | show_supported(http, dest, dinfo, NULL, NULL); | |
167 | } | |
b969d5af | 168 | else if (!strcmp(argv[i], "conflicts") && (i + 1) < argc) |
104fd4ae | 169 | { |
b969d5af | 170 | int num_options = 0;/* Number of options */ |
104fd4ae MS |
171 | cups_option_t *options = NULL;/* Options */ |
172 | ||
b969d5af | 173 | for (i ++; i < argc; i ++) |
104fd4ae MS |
174 | num_options = cupsParseOptions(argv[i], num_options, &options); |
175 | ||
176 | show_conflicts(http, dest, dinfo, num_options, options); | |
177 | } | |
b969d5af | 178 | else if (!strcmp(argv[i], "default") && (i + 1) < argc) |
104fd4ae | 179 | { |
b969d5af | 180 | show_default(http, dest, dinfo, argv[i + 1]); |
104fd4ae | 181 | } |
b969d5af | 182 | else if (!strcmp(argv[i], "localize")) |
104fd4ae | 183 | { |
b969d5af MS |
184 | i ++; |
185 | if ((i + 1) < argc) | |
186 | localize(http, dest, dinfo, argv[i], argv[i + 1]); | |
c585706d | 187 | else if (argc > 2) |
b969d5af | 188 | localize(http, dest, dinfo, argv[i], NULL); |
c585706d MS |
189 | else |
190 | localize(http, dest, dinfo, NULL, NULL); | |
104fd4ae | 191 | } |
b969d5af | 192 | else if (!strcmp(argv[i], "media")) |
104fd4ae | 193 | { |
104fd4ae MS |
194 | const char *name = NULL; /* Media name, if any */ |
195 | unsigned flags = CUPS_MEDIA_FLAGS_DEFAULT; | |
196 | /* Media selection flags */ | |
197 | ||
b969d5af | 198 | for (i ++; i < argc; i ++) |
104fd4ae MS |
199 | { |
200 | if (!strcmp(argv[i], "borderless")) | |
201 | flags = CUPS_MEDIA_FLAGS_BORDERLESS; | |
202 | else if (!strcmp(argv[i], "duplex")) | |
203 | flags = CUPS_MEDIA_FLAGS_DUPLEX; | |
204 | else if (!strcmp(argv[i], "exact")) | |
205 | flags = CUPS_MEDIA_FLAGS_EXACT; | |
206 | else if (!strcmp(argv[i], "ready")) | |
207 | flags = CUPS_MEDIA_FLAGS_READY; | |
208 | else if (name) | |
209 | usage(argv[i]); | |
210 | else | |
211 | name = argv[i]; | |
212 | } | |
213 | ||
214 | show_media(http, dest, dinfo, flags, name); | |
215 | } | |
b969d5af | 216 | else if (!strcmp(argv[i], "print") && (i + 1) < argc) |
104fd4ae | 217 | { |
b969d5af | 218 | int num_options = 0;/* Number of options */ |
104fd4ae | 219 | cups_option_t *options = NULL;/* Options */ |
b969d5af | 220 | const char *filename = argv[i + 1]; |
104fd4ae | 221 | |
b969d5af | 222 | for (i += 2; i < argc; i ++) |
104fd4ae MS |
223 | num_options = cupsParseOptions(argv[i], num_options, &options); |
224 | ||
b969d5af | 225 | print_file(http, dest, dinfo, filename, num_options, options); |
104fd4ae MS |
226 | } |
227 | else | |
b969d5af | 228 | usage(argv[i]); |
104fd4ae MS |
229 | |
230 | return (0); | |
231 | } | |
232 | ||
233 | ||
46385a1a MS |
234 | /* |
235 | * 'enum_cb()' - Print the results from the enumeration of destinations. | |
236 | */ | |
237 | ||
238 | static int /* O - 1 to continue */ | |
239 | enum_cb(void *user_data, /* I - User data (unused) */ | |
240 | unsigned flags, /* I - Flags */ | |
241 | cups_dest_t *dest) /* I - Destination */ | |
242 | { | |
243 | int i; /* Looping var */ | |
244 | ||
245 | ||
246 | (void)user_data; | |
247 | (void)flags; | |
248 | ||
249 | if (dest->instance) | |
c5f5c5a7 | 250 | printf("%s%s/%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->instance, dest->is_default ? " (Default)" : ""); |
46385a1a | 251 | else |
c5f5c5a7 | 252 | printf("%s%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->is_default ? " (Default)" : ""); |
46385a1a MS |
253 | |
254 | for (i = 0; i < dest->num_options; i ++) | |
255 | printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value); | |
256 | ||
c5f5c5a7 MS |
257 | puts(""); |
258 | ||
46385a1a MS |
259 | return (1); |
260 | } | |
261 | ||
262 | ||
104fd4ae MS |
263 | /* |
264 | * 'localize()' - Localize an option and value. | |
265 | */ | |
266 | ||
267 | static void | |
268 | localize(http_t *http, /* I - Connection to destination */ | |
269 | cups_dest_t *dest, /* I - Destination */ | |
270 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
271 | const char *option, /* I - Option */ | |
272 | const char *value) /* I - Value, if any */ | |
273 | { | |
c585706d MS |
274 | ipp_attribute_t *attr; /* Attribute */ |
275 | int i, /* Looping var */ | |
276 | count; /* Number of values */ | |
277 | ||
278 | ||
279 | if (!option) | |
280 | { | |
281 | attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes"); | |
282 | if (attr) | |
283 | { | |
284 | count = ippGetCount(attr); | |
285 | for (i = 0; i < count; i ++) | |
286 | localize(http, dest, dinfo, ippGetString(attr, i, NULL), NULL); | |
287 | } | |
288 | else | |
289 | { | |
290 | static const char * const options[] = | |
291 | { /* List of standard options */ | |
292 | CUPS_COPIES, | |
293 | CUPS_FINISHINGS, | |
294 | CUPS_MEDIA, | |
295 | CUPS_NUMBER_UP, | |
296 | CUPS_ORIENTATION, | |
297 | CUPS_PRINT_COLOR_MODE, | |
298 | CUPS_PRINT_QUALITY, | |
299 | CUPS_SIDES | |
300 | }; | |
301 | ||
302 | puts("No job-creation-attributes-supported attribute, probing instead."); | |
303 | ||
304 | for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++) | |
305 | if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL)) | |
306 | localize(http, dest, dinfo, options[i], NULL); | |
307 | } | |
308 | } | |
309 | else if (!value) | |
310 | { | |
311 | printf("%s (%s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option)); | |
312 | ||
313 | if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL) | |
314 | { | |
315 | count = ippGetCount(attr); | |
316 | ||
317 | switch (ippGetValueTag(attr)) | |
318 | { | |
319 | case IPP_TAG_INTEGER : | |
320 | for (i = 0; i < count; i ++) | |
321 | printf(" %d\n", ippGetInteger(attr, i)); | |
322 | break; | |
323 | ||
324 | case IPP_TAG_ENUM : | |
325 | for (i = 0; i < count; i ++) | |
326 | printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i))); | |
327 | break; | |
328 | ||
329 | case IPP_TAG_RANGE : | |
330 | for (i = 0; i < count; i ++) | |
331 | { | |
332 | int upper, lower = ippGetRange(attr, i, &upper); | |
333 | ||
334 | printf(" %d-%d\n", lower, upper); | |
335 | } | |
336 | break; | |
337 | ||
338 | case IPP_TAG_RESOLUTION : | |
339 | for (i = 0; i < count; i ++) | |
340 | { | |
341 | int xres, yres; | |
342 | ipp_res_t units; | |
343 | xres = ippGetResolution(attr, i, &yres, &units); | |
344 | ||
345 | if (xres == yres) | |
346 | printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
347 | else | |
348 | printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
349 | } | |
350 | break; | |
351 | ||
352 | case IPP_TAG_TEXTLANG : | |
353 | case IPP_TAG_NAMELANG : | |
354 | case IPP_TAG_TEXT : | |
355 | case IPP_TAG_NAME : | |
356 | case IPP_TAG_KEYWORD : | |
357 | case IPP_TAG_URI : | |
358 | case IPP_TAG_URISCHEME : | |
359 | case IPP_TAG_CHARSET : | |
360 | case IPP_TAG_LANGUAGE : | |
361 | case IPP_TAG_MIMETYPE : | |
362 | for (i = 0; i < count; i ++) | |
363 | printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL))); | |
364 | break; | |
365 | ||
366 | case IPP_TAG_STRING : | |
367 | for (i = 0; i < count; i ++) | |
368 | { | |
369 | int j, len; | |
370 | unsigned char *data = ippGetOctetString(attr, i, &len); | |
371 | ||
372 | fputs(" ", stdout); | |
373 | for (j = 0; j < len; j ++) | |
374 | { | |
375 | if (data[j] < ' ' || data[j] >= 0x7f) | |
376 | printf("<%02X>", data[j]); | |
377 | else | |
378 | putchar(data[j]); | |
379 | } | |
380 | putchar('\n'); | |
381 | } | |
382 | break; | |
383 | ||
384 | case IPP_TAG_BOOLEAN : | |
385 | break; | |
386 | ||
387 | default : | |
388 | printf(" %s\n", ippTagString(ippGetValueTag(attr))); | |
389 | break; | |
390 | } | |
391 | } | |
503b54c9 | 392 | |
c585706d MS |
393 | } |
394 | else | |
395 | puts(cupsLocalizeDestValue(http, dest, dinfo, option, value)); | |
104fd4ae MS |
396 | } |
397 | ||
398 | ||
399 | /* | |
400 | * 'print_file()' - Print a file. | |
401 | */ | |
402 | ||
403 | static void | |
404 | print_file(http_t *http, /* I - Connection to destination */ | |
405 | cups_dest_t *dest, /* I - Destination */ | |
406 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
407 | const char *filename, /* I - File to print */ | |
408 | int num_options, /* I - Number of options */ | |
409 | cups_option_t *options) /* I - Options */ | |
410 | { | |
c585706d MS |
411 | cups_file_t *fp; /* File to print */ |
412 | int job_id; /* Job ID */ | |
413 | ipp_status_t status; /* Submission status */ | |
414 | const char *title; /* Title of job */ | |
415 | char buffer[32768]; /* File buffer */ | |
416 | ssize_t bytes; /* Bytes read/to write */ | |
417 | ||
418 | ||
419 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
420 | { | |
421 | printf("Unable to open \"%s\": %s\n", filename, strerror(errno)); | |
422 | return; | |
423 | } | |
424 | ||
425 | if ((title = strrchr(filename, '/')) != NULL) | |
426 | title ++; | |
427 | else | |
428 | title = filename; | |
429 | ||
430 | if ((status = cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) | |
431 | { | |
432 | printf("Unable to create job: %s\n", cupsLastErrorString()); | |
433 | cupsFileClose(fp); | |
434 | return; | |
435 | } | |
436 | ||
437 | printf("Created job ID: %d\n", job_id); | |
438 | ||
439 | if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE) | |
440 | { | |
441 | printf("Unable to send document: %s\n", cupsLastErrorString()); | |
442 | cupsFileClose(fp); | |
443 | return; | |
444 | } | |
445 | ||
446 | while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) | |
447 | { | |
448 | if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE) | |
449 | { | |
450 | printf("Unable to write document data: %s\n", cupsLastErrorString()); | |
451 | break; | |
452 | } | |
453 | } | |
454 | ||
455 | cupsFileClose(fp); | |
456 | ||
457 | if ((status = cupsFinishDestDocument(http, dest, dinfo)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) | |
458 | { | |
459 | printf("Unable to send document: %s\n", cupsLastErrorString()); | |
460 | return; | |
461 | } | |
462 | ||
463 | puts("Job queued."); | |
104fd4ae MS |
464 | } |
465 | ||
466 | ||
467 | /* | |
468 | * 'show_conflicts()' - Show conflicts for selected options. | |
469 | */ | |
470 | ||
471 | static void | |
472 | show_conflicts( | |
473 | http_t *http, /* I - Connection to destination */ | |
474 | cups_dest_t *dest, /* I - Destination */ | |
475 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
476 | int num_options, /* I - Number of options */ | |
477 | cups_option_t *options) /* I - Options */ | |
478 | { | |
479 | (void)http; | |
480 | (void)dest; | |
481 | (void)dinfo; | |
482 | (void)num_options; | |
483 | (void)options; | |
484 | } | |
485 | ||
486 | ||
487 | /* | |
488 | * 'show_default()' - Show default value for option. | |
489 | */ | |
490 | ||
491 | static void | |
492 | show_default(http_t *http, /* I - Connection to destination */ | |
493 | cups_dest_t *dest, /* I - Destination */ | |
494 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
495 | const char *option) /* I - Option */ | |
496 | { | |
534dfe8e MS |
497 | if (!strcmp(option, "media")) |
498 | { | |
499 | /* | |
500 | * Show default media option... | |
501 | */ | |
502 | ||
503 | cups_size_t size; /* Media size information */ | |
504 | ||
505 | if (cupsGetDestMediaDefault(http, dest, dinfo, CUPS_MEDIA_FLAGS_DEFAULT, &size)) | |
506 | printf("%s (%.2fx%.2fmm, margins=[%.2f %.2f %.2f %.2f])\n", size.media, size.width * 0.01, size.length * 0.01, size.left * 0.01, size.bottom * 0.01, size.right * 0.01, size.top * 0.01); | |
507 | else | |
508 | puts("FAILED"); | |
509 | } | |
510 | else | |
511 | { | |
512 | /* | |
513 | * Show default other option... | |
514 | */ | |
515 | ||
516 | ipp_attribute_t *defattr; /* Default attribute */ | |
517 | ||
518 | if ((defattr = cupsFindDestDefault(http, dest, dinfo, option)) != NULL) | |
519 | { | |
520 | char value[1024]; /* Value of default attribute */ | |
521 | ||
522 | ippAttributeString(defattr, value, sizeof(value)); | |
523 | puts(value); | |
524 | } | |
525 | else | |
526 | puts("FAILED"); | |
527 | } | |
104fd4ae MS |
528 | } |
529 | ||
530 | ||
531 | /* | |
532 | * 'show_media()' - Show available media. | |
533 | */ | |
534 | ||
535 | static void | |
536 | show_media(http_t *http, /* I - Connection to destination */ | |
537 | cups_dest_t *dest, /* I - Destination */ | |
538 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
539 | unsigned flags, /* I - Media flags */ | |
540 | const char *name) /* I - Size name */ | |
541 | { | |
542 | int i, /* Looping var */ | |
543 | count; /* Number of sizes */ | |
544 | cups_size_t size; /* Media size info */ | |
545 | ||
546 | ||
547 | if (name) | |
548 | { | |
549 | double dw, dl; /* Width and length from name */ | |
550 | char units[32]; /* Units */ | |
551 | int width, /* Width in 100ths of millimeters */ | |
552 | length; /* Length in 100ths of millimeters */ | |
553 | ||
554 | ||
555 | if (sscanf(name, "%lfx%lf%31s", &dw, &dl, units) == 3) | |
556 | { | |
557 | if (!strcmp(units, "in")) | |
558 | { | |
559 | width = (int)(dw * 2540.0); | |
560 | length = (int)(dl * 2540.0); | |
561 | } | |
562 | else if (!strcmp(units, "mm")) | |
563 | { | |
564 | width = (int)(dw * 100.0); | |
565 | length = (int)(dl * 100.0); | |
566 | } | |
567 | else | |
568 | { | |
569 | puts(" bad units in size"); | |
570 | return; | |
571 | } | |
572 | ||
573 | if (cupsGetDestMediaBySize(http, dest, dinfo, width, length, flags, &size)) | |
574 | { | |
575 | printf(" %s (%s) %dx%d B%d L%d R%d T%d\n", size.media, cupsLocalizeDestMedia(http, dest, dinfo, flags, &size), size.width, size.length, size.bottom, size.left, size.right, size.top); | |
576 | } | |
577 | else | |
578 | { | |
579 | puts(" not supported"); | |
580 | } | |
581 | } | |
582 | else if (cupsGetDestMediaByName(http, dest, dinfo, name, flags, &size)) | |
583 | { | |
584 | printf(" %s (%s) %dx%d B%d L%d R%d T%d\n", size.media, cupsLocalizeDestMedia(http, dest, dinfo, flags, &size), size.width, size.length, size.bottom, size.left, size.right, size.top); | |
585 | } | |
586 | else | |
587 | { | |
588 | puts(" not supported"); | |
589 | } | |
590 | } | |
591 | else | |
592 | { | |
593 | count = cupsGetDestMediaCount(http, dest, dinfo, flags); | |
594 | printf("%d size%s:\n", count, count == 1 ? "" : "s"); | |
595 | ||
596 | for (i = 0; i < count; i ++) | |
597 | { | |
598 | if (cupsGetDestMediaByIndex(http, dest, dinfo, i, flags, &size)) | |
599 | printf(" %s (%s) %dx%d B%d L%d R%d T%d\n", size.media, cupsLocalizeDestMedia(http, dest, dinfo, flags, &size), size.width, size.length, size.bottom, size.left, size.right, size.top); | |
600 | else | |
601 | puts(" error"); | |
602 | } | |
603 | } | |
604 | } | |
605 | ||
606 | ||
607 | /* | |
608 | * 'show_supported()' - Show supported options, values, etc. | |
609 | */ | |
610 | ||
611 | static void | |
612 | show_supported(http_t *http, /* I - Connection to destination */ | |
613 | cups_dest_t *dest, /* I - Destination */ | |
614 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
615 | const char *option, /* I - Option, if any */ | |
616 | const char *value) /* I - Value, if any */ | |
617 | { | |
618 | ipp_attribute_t *attr; /* Attribute */ | |
619 | int i, /* Looping var */ | |
620 | count; /* Number of values */ | |
621 | ||
622 | ||
623 | if (!option) | |
624 | { | |
625 | attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes"); | |
626 | if (attr) | |
627 | { | |
628 | count = ippGetCount(attr); | |
629 | for (i = 0; i < count; i ++) | |
630 | show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL); | |
631 | } | |
632 | else | |
633 | { | |
634 | static const char * const options[] = | |
635 | { /* List of standard options */ | |
636 | CUPS_COPIES, | |
637 | CUPS_FINISHINGS, | |
638 | CUPS_MEDIA, | |
639 | CUPS_NUMBER_UP, | |
640 | CUPS_ORIENTATION, | |
641 | CUPS_PRINT_COLOR_MODE, | |
642 | CUPS_PRINT_QUALITY, | |
643 | CUPS_SIDES | |
644 | }; | |
645 | ||
646 | puts("No job-creation-attributes-supported attribute, probing instead."); | |
647 | ||
648 | for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++) | |
649 | if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL)) | |
650 | show_supported(http, dest, dinfo, options[i], NULL); | |
651 | } | |
652 | } | |
653 | else if (!value) | |
654 | { | |
a9357c9d | 655 | printf("%s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported"); |
ca9e55c9 | 656 | |
104fd4ae MS |
657 | if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL) |
658 | { | |
659 | count = ippGetCount(attr); | |
660 | ||
661 | switch (ippGetValueTag(attr)) | |
662 | { | |
663 | case IPP_TAG_INTEGER : | |
664 | for (i = 0; i < count; i ++) | |
665 | printf(" %d\n", ippGetInteger(attr, i)); | |
666 | break; | |
667 | ||
668 | case IPP_TAG_ENUM : | |
669 | for (i = 0; i < count; i ++) | |
a9357c9d MS |
670 | { |
671 | int val = ippGetInteger(attr, i); | |
672 | char valstr[256]; | |
673 | ||
674 | snprintf(valstr, sizeof(valstr), "%d", val); | |
675 | printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr)); | |
676 | } | |
104fd4ae MS |
677 | break; |
678 | ||
679 | case IPP_TAG_RANGE : | |
680 | for (i = 0; i < count; i ++) | |
681 | { | |
682 | int upper, lower = ippGetRange(attr, i, &upper); | |
683 | ||
684 | printf(" %d-%d\n", lower, upper); | |
685 | } | |
686 | break; | |
687 | ||
4db7fcee MS |
688 | case IPP_TAG_RESOLUTION : |
689 | for (i = 0; i < count; i ++) | |
690 | { | |
691 | int xres, yres; | |
692 | ipp_res_t units; | |
693 | xres = ippGetResolution(attr, i, &yres, &units); | |
694 | ||
695 | if (xres == yres) | |
696 | printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
697 | else | |
698 | printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
699 | } | |
700 | break; | |
701 | ||
a9357c9d MS |
702 | case IPP_TAG_KEYWORD : |
703 | for (i = 0; i < count; i ++) | |
704 | printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL))); | |
705 | break; | |
706 | ||
104fd4ae MS |
707 | case IPP_TAG_TEXTLANG : |
708 | case IPP_TAG_NAMELANG : | |
709 | case IPP_TAG_TEXT : | |
710 | case IPP_TAG_NAME : | |
104fd4ae MS |
711 | case IPP_TAG_URI : |
712 | case IPP_TAG_URISCHEME : | |
713 | case IPP_TAG_CHARSET : | |
714 | case IPP_TAG_LANGUAGE : | |
715 | case IPP_TAG_MIMETYPE : | |
716 | for (i = 0; i < count; i ++) | |
717 | printf(" %s\n", ippGetString(attr, i, NULL)); | |
718 | break; | |
719 | ||
720 | case IPP_TAG_STRING : | |
721 | for (i = 0; i < count; i ++) | |
722 | { | |
723 | int j, len; | |
724 | unsigned char *data = ippGetOctetString(attr, i, &len); | |
725 | ||
726 | fputs(" ", stdout); | |
727 | for (j = 0; j < len; j ++) | |
728 | { | |
729 | if (data[j] < ' ' || data[j] >= 0x7f) | |
730 | printf("<%02X>", data[j]); | |
731 | else | |
732 | putchar(data[j]); | |
733 | } | |
734 | putchar('\n'); | |
735 | } | |
736 | break; | |
737 | ||
738 | case IPP_TAG_BOOLEAN : | |
739 | break; | |
740 | ||
741 | default : | |
742 | printf(" %s\n", ippTagString(ippGetValueTag(attr))); | |
743 | break; | |
744 | } | |
745 | } | |
503b54c9 | 746 | |
104fd4ae MS |
747 | } |
748 | else if (cupsCheckDestSupported(http, dest, dinfo, option, value)) | |
749 | puts("YES"); | |
750 | else | |
751 | puts("NO"); | |
104fd4ae MS |
752 | } |
753 | ||
754 | ||
755 | /* | |
756 | * 'usage()' - Show program usage. | |
757 | */ | |
758 | ||
759 | static void | |
760 | usage(const char *arg) /* I - Argument for usage message */ | |
761 | { | |
762 | if (arg) | |
763 | printf("testdest: Unknown option \"%s\".\n", arg); | |
764 | ||
765 | puts("Usage:"); | |
b969d5af MS |
766 | puts(" ./testdest [--device] name [operation ...]"); |
767 | puts(" ./testdest [--device] ipp://... [operation ...]"); | |
768 | puts(" ./testdest [--device] ipps://... [operation ...]"); | |
8d59b9f7 | 769 | puts(" ./testdest --get"); |
104fd4ae MS |
770 | puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n" |
771 | " [medium] [large]"); | |
772 | puts(""); | |
773 | puts("Operations:"); | |
774 | puts(" conflicts options"); | |
775 | puts(" default option"); | |
776 | puts(" localize option [value]"); | |
777 | puts(" media [borderless] [duplex] [exact] [ready] [name or size]"); | |
778 | puts(" print filename [options]"); | |
779 | puts(" supported [option [value]]"); | |
780 | ||
781 | exit(arg != NULL); | |
782 | } |