]>
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); | |
a32af27c | 29 | static void usage(const char *arg) _CUPS_NORETURN; |
104fd4ae MS |
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 */ | |
c585706d MS |
413 | const char *title; /* Title of job */ |
414 | char buffer[32768]; /* File buffer */ | |
415 | ssize_t bytes; /* Bytes read/to write */ | |
416 | ||
417 | ||
418 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
419 | { | |
420 | printf("Unable to open \"%s\": %s\n", filename, strerror(errno)); | |
421 | return; | |
422 | } | |
423 | ||
424 | if ((title = strrchr(filename, '/')) != NULL) | |
425 | title ++; | |
426 | else | |
427 | title = filename; | |
428 | ||
064e50fb | 429 | if (cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) |
c585706d MS |
430 | { |
431 | printf("Unable to create job: %s\n", cupsLastErrorString()); | |
432 | cupsFileClose(fp); | |
433 | return; | |
434 | } | |
435 | ||
436 | printf("Created job ID: %d\n", job_id); | |
437 | ||
438 | if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE) | |
439 | { | |
440 | printf("Unable to send document: %s\n", cupsLastErrorString()); | |
441 | cupsFileClose(fp); | |
442 | return; | |
443 | } | |
444 | ||
445 | while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) | |
446 | { | |
447 | if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE) | |
448 | { | |
449 | printf("Unable to write document data: %s\n", cupsLastErrorString()); | |
450 | break; | |
451 | } | |
452 | } | |
453 | ||
454 | cupsFileClose(fp); | |
455 | ||
064e50fb | 456 | if (cupsFinishDestDocument(http, dest, dinfo) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) |
c585706d MS |
457 | { |
458 | printf("Unable to send document: %s\n", cupsLastErrorString()); | |
459 | return; | |
460 | } | |
461 | ||
462 | puts("Job queued."); | |
104fd4ae MS |
463 | } |
464 | ||
465 | ||
466 | /* | |
467 | * 'show_conflicts()' - Show conflicts for selected options. | |
468 | */ | |
469 | ||
470 | static void | |
471 | show_conflicts( | |
472 | http_t *http, /* I - Connection to destination */ | |
473 | cups_dest_t *dest, /* I - Destination */ | |
474 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
475 | int num_options, /* I - Number of options */ | |
476 | cups_option_t *options) /* I - Options */ | |
477 | { | |
478 | (void)http; | |
479 | (void)dest; | |
480 | (void)dinfo; | |
481 | (void)num_options; | |
482 | (void)options; | |
483 | } | |
484 | ||
485 | ||
486 | /* | |
487 | * 'show_default()' - Show default value for option. | |
488 | */ | |
489 | ||
490 | static void | |
491 | show_default(http_t *http, /* I - Connection to destination */ | |
492 | cups_dest_t *dest, /* I - Destination */ | |
493 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
494 | const char *option) /* I - Option */ | |
495 | { | |
534dfe8e MS |
496 | if (!strcmp(option, "media")) |
497 | { | |
498 | /* | |
499 | * Show default media option... | |
500 | */ | |
501 | ||
502 | cups_size_t size; /* Media size information */ | |
503 | ||
504 | if (cupsGetDestMediaDefault(http, dest, dinfo, CUPS_MEDIA_FLAGS_DEFAULT, &size)) | |
505 | 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); | |
506 | else | |
507 | puts("FAILED"); | |
508 | } | |
509 | else | |
510 | { | |
511 | /* | |
512 | * Show default other option... | |
513 | */ | |
514 | ||
515 | ipp_attribute_t *defattr; /* Default attribute */ | |
516 | ||
517 | if ((defattr = cupsFindDestDefault(http, dest, dinfo, option)) != NULL) | |
518 | { | |
519 | char value[1024]; /* Value of default attribute */ | |
520 | ||
521 | ippAttributeString(defattr, value, sizeof(value)); | |
522 | puts(value); | |
523 | } | |
524 | else | |
525 | puts("FAILED"); | |
526 | } | |
104fd4ae MS |
527 | } |
528 | ||
529 | ||
530 | /* | |
531 | * 'show_media()' - Show available media. | |
532 | */ | |
533 | ||
534 | static void | |
535 | show_media(http_t *http, /* I - Connection to destination */ | |
536 | cups_dest_t *dest, /* I - Destination */ | |
537 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
538 | unsigned flags, /* I - Media flags */ | |
539 | const char *name) /* I - Size name */ | |
540 | { | |
541 | int i, /* Looping var */ | |
542 | count; /* Number of sizes */ | |
543 | cups_size_t size; /* Media size info */ | |
544 | ||
545 | ||
546 | if (name) | |
547 | { | |
548 | double dw, dl; /* Width and length from name */ | |
549 | char units[32]; /* Units */ | |
550 | int width, /* Width in 100ths of millimeters */ | |
551 | length; /* Length in 100ths of millimeters */ | |
552 | ||
553 | ||
554 | if (sscanf(name, "%lfx%lf%31s", &dw, &dl, units) == 3) | |
555 | { | |
556 | if (!strcmp(units, "in")) | |
557 | { | |
558 | width = (int)(dw * 2540.0); | |
559 | length = (int)(dl * 2540.0); | |
560 | } | |
561 | else if (!strcmp(units, "mm")) | |
562 | { | |
563 | width = (int)(dw * 100.0); | |
564 | length = (int)(dl * 100.0); | |
565 | } | |
566 | else | |
567 | { | |
568 | puts(" bad units in size"); | |
569 | return; | |
570 | } | |
571 | ||
572 | if (cupsGetDestMediaBySize(http, dest, dinfo, width, length, flags, &size)) | |
573 | { | |
574 | 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); | |
575 | } | |
576 | else | |
577 | { | |
578 | puts(" not supported"); | |
579 | } | |
580 | } | |
581 | else if (cupsGetDestMediaByName(http, dest, dinfo, name, flags, &size)) | |
582 | { | |
583 | 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); | |
584 | } | |
585 | else | |
586 | { | |
587 | puts(" not supported"); | |
588 | } | |
589 | } | |
590 | else | |
591 | { | |
592 | count = cupsGetDestMediaCount(http, dest, dinfo, flags); | |
593 | printf("%d size%s:\n", count, count == 1 ? "" : "s"); | |
594 | ||
595 | for (i = 0; i < count; i ++) | |
596 | { | |
597 | if (cupsGetDestMediaByIndex(http, dest, dinfo, i, flags, &size)) | |
598 | 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); | |
599 | else | |
600 | puts(" error"); | |
601 | } | |
602 | } | |
603 | } | |
604 | ||
605 | ||
606 | /* | |
607 | * 'show_supported()' - Show supported options, values, etc. | |
608 | */ | |
609 | ||
610 | static void | |
611 | show_supported(http_t *http, /* I - Connection to destination */ | |
612 | cups_dest_t *dest, /* I - Destination */ | |
613 | cups_dinfo_t *dinfo, /* I - Destination information */ | |
614 | const char *option, /* I - Option, if any */ | |
615 | const char *value) /* I - Value, if any */ | |
616 | { | |
617 | ipp_attribute_t *attr; /* Attribute */ | |
618 | int i, /* Looping var */ | |
619 | count; /* Number of values */ | |
620 | ||
621 | ||
622 | if (!option) | |
623 | { | |
624 | attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes"); | |
625 | if (attr) | |
626 | { | |
627 | count = ippGetCount(attr); | |
628 | for (i = 0; i < count; i ++) | |
629 | show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL); | |
630 | } | |
631 | else | |
632 | { | |
633 | static const char * const options[] = | |
634 | { /* List of standard options */ | |
635 | CUPS_COPIES, | |
636 | CUPS_FINISHINGS, | |
637 | CUPS_MEDIA, | |
638 | CUPS_NUMBER_UP, | |
639 | CUPS_ORIENTATION, | |
640 | CUPS_PRINT_COLOR_MODE, | |
641 | CUPS_PRINT_QUALITY, | |
642 | CUPS_SIDES | |
643 | }; | |
644 | ||
645 | puts("No job-creation-attributes-supported attribute, probing instead."); | |
646 | ||
647 | for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++) | |
648 | if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL)) | |
649 | show_supported(http, dest, dinfo, options[i], NULL); | |
650 | } | |
651 | } | |
652 | else if (!value) | |
653 | { | |
a9357c9d | 654 | printf("%s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported"); |
ca9e55c9 | 655 | |
104fd4ae MS |
656 | if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL) |
657 | { | |
658 | count = ippGetCount(attr); | |
659 | ||
660 | switch (ippGetValueTag(attr)) | |
661 | { | |
662 | case IPP_TAG_INTEGER : | |
663 | for (i = 0; i < count; i ++) | |
664 | printf(" %d\n", ippGetInteger(attr, i)); | |
665 | break; | |
666 | ||
667 | case IPP_TAG_ENUM : | |
668 | for (i = 0; i < count; i ++) | |
a9357c9d MS |
669 | { |
670 | int val = ippGetInteger(attr, i); | |
671 | char valstr[256]; | |
672 | ||
673 | snprintf(valstr, sizeof(valstr), "%d", val); | |
674 | printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr)); | |
675 | } | |
104fd4ae MS |
676 | break; |
677 | ||
678 | case IPP_TAG_RANGE : | |
679 | for (i = 0; i < count; i ++) | |
680 | { | |
681 | int upper, lower = ippGetRange(attr, i, &upper); | |
682 | ||
683 | printf(" %d-%d\n", lower, upper); | |
684 | } | |
685 | break; | |
686 | ||
4db7fcee MS |
687 | case IPP_TAG_RESOLUTION : |
688 | for (i = 0; i < count; i ++) | |
689 | { | |
690 | int xres, yres; | |
691 | ipp_res_t units; | |
692 | xres = ippGetResolution(attr, i, &yres, &units); | |
693 | ||
694 | if (xres == yres) | |
695 | printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
696 | else | |
697 | printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); | |
698 | } | |
699 | break; | |
700 | ||
a9357c9d MS |
701 | case IPP_TAG_KEYWORD : |
702 | for (i = 0; i < count; i ++) | |
703 | printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL))); | |
704 | break; | |
705 | ||
104fd4ae MS |
706 | case IPP_TAG_TEXTLANG : |
707 | case IPP_TAG_NAMELANG : | |
708 | case IPP_TAG_TEXT : | |
709 | case IPP_TAG_NAME : | |
104fd4ae MS |
710 | case IPP_TAG_URI : |
711 | case IPP_TAG_URISCHEME : | |
712 | case IPP_TAG_CHARSET : | |
713 | case IPP_TAG_LANGUAGE : | |
714 | case IPP_TAG_MIMETYPE : | |
715 | for (i = 0; i < count; i ++) | |
716 | printf(" %s\n", ippGetString(attr, i, NULL)); | |
717 | break; | |
718 | ||
719 | case IPP_TAG_STRING : | |
720 | for (i = 0; i < count; i ++) | |
721 | { | |
722 | int j, len; | |
723 | unsigned char *data = ippGetOctetString(attr, i, &len); | |
724 | ||
725 | fputs(" ", stdout); | |
726 | for (j = 0; j < len; j ++) | |
727 | { | |
728 | if (data[j] < ' ' || data[j] >= 0x7f) | |
729 | printf("<%02X>", data[j]); | |
730 | else | |
731 | putchar(data[j]); | |
732 | } | |
733 | putchar('\n'); | |
734 | } | |
735 | break; | |
736 | ||
737 | case IPP_TAG_BOOLEAN : | |
738 | break; | |
739 | ||
740 | default : | |
741 | printf(" %s\n", ippTagString(ippGetValueTag(attr))); | |
742 | break; | |
743 | } | |
744 | } | |
503b54c9 | 745 | |
104fd4ae MS |
746 | } |
747 | else if (cupsCheckDestSupported(http, dest, dinfo, option, value)) | |
748 | puts("YES"); | |
749 | else | |
750 | puts("NO"); | |
104fd4ae MS |
751 | } |
752 | ||
753 | ||
754 | /* | |
755 | * 'usage()' - Show program usage. | |
756 | */ | |
757 | ||
758 | static void | |
759 | usage(const char *arg) /* I - Argument for usage message */ | |
760 | { | |
761 | if (arg) | |
762 | printf("testdest: Unknown option \"%s\".\n", arg); | |
763 | ||
764 | puts("Usage:"); | |
b969d5af MS |
765 | puts(" ./testdest [--device] name [operation ...]"); |
766 | puts(" ./testdest [--device] ipp://... [operation ...]"); | |
767 | puts(" ./testdest [--device] ipps://... [operation ...]"); | |
8d59b9f7 | 768 | puts(" ./testdest --get"); |
104fd4ae MS |
769 | puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n" |
770 | " [medium] [large]"); | |
771 | puts(""); | |
772 | puts("Operations:"); | |
773 | puts(" conflicts options"); | |
774 | puts(" default option"); | |
775 | puts(" localize option [value]"); | |
776 | puts(" media [borderless] [duplex] [exact] [ready] [name or size]"); | |
777 | puts(" print filename [options]"); | |
778 | puts(" supported [option [value]]"); | |
779 | ||
780 | exit(arg != NULL); | |
781 | } |