2 * CUPS destination API test program for CUPS.
4 * Copyright © 2012-2018 by Apple Inc.
6 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
10 * Include necessary headers...
22 static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest);
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) _CUPS_NORETURN;
33 * 'main()' - Main entry.
36 int /* O - Exit status */
37 main(int argc, /* I - Number of command-line arguments */
38 char *argv[]) /* I - Command-line arguments */
40 int i; /* Looping var */
41 http_t *http; /* Connection to destination */
42 cups_dest_t *dest = NULL; /* Destination */
43 cups_dinfo_t *dinfo; /* Destination info */
44 unsigned dflags = CUPS_DEST_FLAGS_NONE;
45 /* Destination flags */
51 if (!strcmp(argv[1], "--get"))
53 cups_dest_t *dests; /* Destinations */
54 int num_dests = cupsGetDests2(CUPS_HTTP_DEFAULT, &dests);
55 /* Number of destinations */
57 for (i = 0; i < num_dests; i ++)
58 enum_cb(NULL, 0, dests + i);
60 cupsFreeDests(num_dests, dests);
63 else if (!strcmp(argv[1], "--enum"))
65 cups_ptype_t type = 0, /* Printer type filter */
66 mask = 0; /* Printer type mask */
69 for (i = 2; i < argc; i ++)
71 if (!strcmp(argv[i], "grayscale"))
73 type |= CUPS_PRINTER_BW;
74 mask |= CUPS_PRINTER_BW;
76 else if (!strcmp(argv[i], "color"))
78 type |= CUPS_PRINTER_COLOR;
79 mask |= CUPS_PRINTER_COLOR;
81 else if (!strcmp(argv[i], "duplex"))
83 type |= CUPS_PRINTER_DUPLEX;
84 mask |= CUPS_PRINTER_DUPLEX;
86 else if (!strcmp(argv[i], "staple"))
88 type |= CUPS_PRINTER_STAPLE;
89 mask |= CUPS_PRINTER_STAPLE;
91 else if (!strcmp(argv[i], "small"))
93 type |= CUPS_PRINTER_SMALL;
94 mask |= CUPS_PRINTER_SMALL;
96 else if (!strcmp(argv[i], "medium"))
98 type |= CUPS_PRINTER_MEDIUM;
99 mask |= CUPS_PRINTER_MEDIUM;
101 else if (!strcmp(argv[i], "large"))
103 type |= CUPS_PRINTER_LARGE;
104 mask |= CUPS_PRINTER_LARGE;
110 cupsEnumDests(CUPS_DEST_FLAGS_NONE, 5000, NULL, type, mask, enum_cb, NULL);
116 if (!strcmp(argv[i], "--device"))
118 dflags = CUPS_DEST_FLAGS_DEVICE;
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"))
126 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
127 if (dest && dest->instance)
128 printf("default is \"%s/%s\".\n", dest->name, dest->instance);
130 printf("default is \"%s\".\n", dest->name);
132 puts("no default destination.");
135 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[i], NULL);
139 printf("testdest: Unable to get destination \"%s\": %s\n", argv[i], cupsLastErrorString());
145 if ((http = cupsConnectDest(dest, dflags, 30000, NULL, NULL, 0, NULL, NULL)) == NULL)
147 printf("testdest: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString());
151 if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL)
153 printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString());
157 if (i == argc || !strcmp(argv[i], "supported"))
162 show_supported(http, dest, dinfo, argv[i], argv[i + 1]);
164 show_supported(http, dest, dinfo, argv[i], NULL);
166 show_supported(http, dest, dinfo, NULL, NULL);
168 else if (!strcmp(argv[i], "conflicts") && (i + 1) < argc)
170 int num_options = 0;/* Number of options */
171 cups_option_t *options = NULL;/* Options */
173 for (i ++; i < argc; i ++)
174 num_options = cupsParseOptions(argv[i], num_options, &options);
176 show_conflicts(http, dest, dinfo, num_options, options);
178 else if (!strcmp(argv[i], "default") && (i + 1) < argc)
180 show_default(http, dest, dinfo, argv[i + 1]);
182 else if (!strcmp(argv[i], "localize"))
186 localize(http, dest, dinfo, argv[i], argv[i + 1]);
188 localize(http, dest, dinfo, argv[i], NULL);
190 localize(http, dest, dinfo, NULL, NULL);
192 else if (!strcmp(argv[i], "media"))
194 const char *name = NULL; /* Media name, if any */
195 unsigned flags = CUPS_MEDIA_FLAGS_DEFAULT;
196 /* Media selection flags */
198 for (i ++; i < argc; i ++)
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;
214 show_media(http, dest, dinfo, flags, name);
216 else if (!strcmp(argv[i], "print") && (i + 1) < argc)
218 int num_options = 0;/* Number of options */
219 cups_option_t *options = NULL;/* Options */
220 const char *filename = argv[i + 1];
222 for (i += 2; i < argc; i ++)
223 num_options = cupsParseOptions(argv[i], num_options, &options);
225 print_file(http, dest, dinfo, filename, num_options, options);
235 * 'enum_cb()' - Print the results from the enumeration of destinations.
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 */
243 int i; /* Looping var */
250 printf("%s%s/%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->instance, dest->is_default ? " (Default)" : "");
252 printf("%s%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->is_default ? " (Default)" : "");
254 for (i = 0; i < dest->num_options; i ++)
255 printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value);
264 * 'localize()' - Localize an option and value.
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 */
274 ipp_attribute_t *attr; /* Attribute */
275 int i, /* Looping var */
276 count; /* Number of values */
281 attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
284 count = ippGetCount(attr);
285 for (i = 0; i < count; i ++)
286 localize(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
290 static const char * const options[] =
291 { /* List of standard options */
297 CUPS_PRINT_COLOR_MODE,
302 puts("No job-creation-attributes-supported attribute, probing instead.");
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);
311 printf("%s (%s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option));
313 if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
315 count = ippGetCount(attr);
317 switch (ippGetValueTag(attr))
319 case IPP_TAG_INTEGER :
320 for (i = 0; i < count; i ++)
321 printf(" %d\n", ippGetInteger(attr, i));
325 for (i = 0; i < count; i ++)
326 printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i)));
330 for (i = 0; i < count; i ++)
332 int upper, lower = ippGetRange(attr, i, &upper);
334 printf(" %d-%d\n", lower, upper);
338 case IPP_TAG_RESOLUTION :
339 for (i = 0; i < count; i ++)
343 xres = ippGetResolution(attr, i, &yres, &units);
346 printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
348 printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
352 case IPP_TAG_TEXTLANG :
353 case IPP_TAG_NAMELANG :
356 case IPP_TAG_KEYWORD :
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)));
366 case IPP_TAG_STRING :
367 for (i = 0; i < count; i ++)
370 unsigned char *data = ippGetOctetString(attr, i, &len);
373 for (j = 0; j < len; j ++)
375 if (data[j] < ' ' || data[j] >= 0x7f)
376 printf("<%02X>", data[j]);
384 case IPP_TAG_BOOLEAN :
388 printf(" %s\n", ippTagString(ippGetValueTag(attr)));
395 puts(cupsLocalizeDestValue(http, dest, dinfo, option, value));
400 * 'print_file()' - Print a file.
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 */
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 */
419 if ((fp = cupsFileOpen(filename, "r")) == NULL)
421 printf("Unable to open \"%s\": %s\n", filename, strerror(errno));
425 if ((title = strrchr(filename, '/')) != NULL)
430 if ((status = cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
432 printf("Unable to create job: %s\n", cupsLastErrorString());
437 printf("Created job ID: %d\n", job_id);
439 if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE)
441 printf("Unable to send document: %s\n", cupsLastErrorString());
446 while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
448 if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE)
450 printf("Unable to write document data: %s\n", cupsLastErrorString());
457 if ((status = cupsFinishDestDocument(http, dest, dinfo)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
459 printf("Unable to send document: %s\n", cupsLastErrorString());
468 * 'show_conflicts()' - Show conflicts for selected options.
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 */
488 * 'show_default()' - Show default value for option.
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 */
497 if (!strcmp(option, "media"))
500 * Show default media option...
503 cups_size_t size; /* Media size information */
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);
513 * Show default other option...
516 ipp_attribute_t *defattr; /* Default attribute */
518 if ((defattr = cupsFindDestDefault(http, dest, dinfo, option)) != NULL)
520 char value[1024]; /* Value of default attribute */
522 ippAttributeString(defattr, value, sizeof(value));
532 * 'show_media()' - Show available media.
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 */
542 int i, /* Looping var */
543 count; /* Number of sizes */
544 cups_size_t size; /* Media size info */
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 */
555 if (sscanf(name, "%lfx%lf%31s", &dw, &dl, units) == 3)
557 if (!strcmp(units, "in"))
559 width = (int)(dw * 2540.0);
560 length = (int)(dl * 2540.0);
562 else if (!strcmp(units, "mm"))
564 width = (int)(dw * 100.0);
565 length = (int)(dl * 100.0);
569 puts(" bad units in size");
573 if (cupsGetDestMediaBySize(http, dest, dinfo, width, length, flags, &size))
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);
579 puts(" not supported");
582 else if (cupsGetDestMediaByName(http, dest, dinfo, name, flags, &size))
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);
588 puts(" not supported");
593 count = cupsGetDestMediaCount(http, dest, dinfo, flags);
594 printf("%d size%s:\n", count, count == 1 ? "" : "s");
596 for (i = 0; i < count; i ++)
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);
608 * 'show_supported()' - Show supported options, values, etc.
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 */
618 ipp_attribute_t *attr; /* Attribute */
619 int i, /* Looping var */
620 count; /* Number of values */
625 attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
628 count = ippGetCount(attr);
629 for (i = 0; i < count; i ++)
630 show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
634 static const char * const options[] =
635 { /* List of standard options */
641 CUPS_PRINT_COLOR_MODE,
646 puts("No job-creation-attributes-supported attribute, probing instead.");
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);
655 printf("%s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported");
657 if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
659 count = ippGetCount(attr);
661 switch (ippGetValueTag(attr))
663 case IPP_TAG_INTEGER :
664 for (i = 0; i < count; i ++)
665 printf(" %d\n", ippGetInteger(attr, i));
669 for (i = 0; i < count; i ++)
671 int val = ippGetInteger(attr, i);
674 snprintf(valstr, sizeof(valstr), "%d", val);
675 printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr));
680 for (i = 0; i < count; i ++)
682 int upper, lower = ippGetRange(attr, i, &upper);
684 printf(" %d-%d\n", lower, upper);
688 case IPP_TAG_RESOLUTION :
689 for (i = 0; i < count; i ++)
693 xres = ippGetResolution(attr, i, &yres, &units);
696 printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
698 printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
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)));
707 case IPP_TAG_TEXTLANG :
708 case IPP_TAG_NAMELANG :
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));
720 case IPP_TAG_STRING :
721 for (i = 0; i < count; i ++)
724 unsigned char *data = ippGetOctetString(attr, i, &len);
727 for (j = 0; j < len; j ++)
729 if (data[j] < ' ' || data[j] >= 0x7f)
730 printf("<%02X>", data[j]);
738 case IPP_TAG_BOOLEAN :
742 printf(" %s\n", ippTagString(ippGetValueTag(attr)));
748 else if (cupsCheckDestSupported(http, dest, dinfo, option, value))
756 * 'usage()' - Show program usage.
760 usage(const char *arg) /* I - Argument for usage message */
763 printf("testdest: Unknown option \"%s\".\n", arg);
766 puts(" ./testdest [--device] name [operation ...]");
767 puts(" ./testdest [--device] ipp://... [operation ...]");
768 puts(" ./testdest [--device] ipps://... [operation ...]");
769 puts(" ./testdest --get");
770 puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n"
771 " [medium] [large]");
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]]");