2 * CUPS destination API test program for CUPS.
4 * Copyright 2012-2016 by Apple Inc.
6 * These coded instructions, statements, and computer programs are the
7 * property of Apple Inc. and are protected by Federal copyright
8 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
9 * which should have been included with this file. If this file is
10 * file is missing or damaged, see the license at "http://www.cups.org/".
12 * This file is subject to the Apple OS-Developed Software exception.
16 * Include necessary headers...
28 static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest);
29 static void localize(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value);
30 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);
31 static void show_conflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, int num_options, cups_option_t *options);
32 static void show_default(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option);
33 static void show_media(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, unsigned flags, const char *name);
34 static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value);
35 static void usage(const char *arg) __attribute__((noreturn));
39 * 'main()' - Main entry.
42 int /* O - Exit status */
43 main(int argc, /* I - Number of command-line arguments */
44 char *argv[]) /* I - Command-line arguments */
46 http_t *http; /* Connection to destination */
47 cups_dest_t *dest = NULL; /* Destination */
48 cups_dinfo_t *dinfo; /* Destination info */
54 if (!strcmp(argv[1], "--enum"))
56 int i; /* Looping var */
57 cups_ptype_t type = 0, /* Printer type filter */
58 mask = 0; /* Printer type mask */
61 for (i = 2; i < argc; i ++)
63 if (!strcmp(argv[i], "grayscale"))
65 type |= CUPS_PRINTER_BW;
66 mask |= CUPS_PRINTER_BW;
68 else if (!strcmp(argv[i], "color"))
70 type |= CUPS_PRINTER_COLOR;
71 mask |= CUPS_PRINTER_COLOR;
73 else if (!strcmp(argv[i], "duplex"))
75 type |= CUPS_PRINTER_DUPLEX;
76 mask |= CUPS_PRINTER_DUPLEX;
78 else if (!strcmp(argv[i], "staple"))
80 type |= CUPS_PRINTER_STAPLE;
81 mask |= CUPS_PRINTER_STAPLE;
83 else if (!strcmp(argv[i], "small"))
85 type |= CUPS_PRINTER_SMALL;
86 mask |= CUPS_PRINTER_SMALL;
88 else if (!strcmp(argv[i], "medium"))
90 type |= CUPS_PRINTER_MEDIUM;
91 mask |= CUPS_PRINTER_MEDIUM;
93 else if (!strcmp(argv[i], "large"))
95 type |= CUPS_PRINTER_LARGE;
96 mask |= CUPS_PRINTER_LARGE;
102 cupsEnumDests(CUPS_DEST_FLAGS_NONE, 5000, NULL, type, mask, enum_cb, NULL);
106 else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7))
107 dest = cupsGetDestWithURI(NULL, argv[1]);
109 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[1], NULL);
113 printf("testdest: Unable to get destination \"%s\": %s\n", argv[1], cupsLastErrorString());
117 if ((http = cupsConnectDest(dest, CUPS_DEST_FLAGS_NONE, 30000, NULL, NULL, 0, NULL, NULL)) == NULL)
119 printf("testdest: Unable to connect to destination \"%s\": %s\n", argv[1], cupsLastErrorString());
123 if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL)
125 printf("testdest: Unable to get information for destination \"%s\": %s\n", argv[1], cupsLastErrorString());
129 if (argc == 2 || (!strcmp(argv[2], "supported") && argc < 6))
132 show_supported(http, dest, dinfo, argv[3], argv[4]);
134 show_supported(http, dest, dinfo, argv[3], NULL);
136 show_supported(http, dest, dinfo, NULL, NULL);
138 else if (!strcmp(argv[2], "conflicts") && argc > 3)
140 int i, /* Looping var */
141 num_options = 0;/* Number of options */
142 cups_option_t *options = NULL;/* Options */
144 for (i = 3; i < argc; i ++)
145 num_options = cupsParseOptions(argv[i], num_options, &options);
147 show_conflicts(http, dest, dinfo, num_options, options);
149 else if (!strcmp(argv[2], "default") && argc == 4)
151 show_default(http, dest, dinfo, argv[3]);
153 else if (!strcmp(argv[2], "localize") && argc < 6)
156 localize(http, dest, dinfo, argv[3], argv[4]);
158 localize(http, dest, dinfo, argv[3], NULL);
160 localize(http, dest, dinfo, NULL, NULL);
162 else if (!strcmp(argv[2], "media"))
164 int i; /* Looping var */
165 const char *name = NULL; /* Media name, if any */
166 unsigned flags = CUPS_MEDIA_FLAGS_DEFAULT;
167 /* Media selection flags */
169 for (i = 3; i < argc; i ++)
171 if (!strcmp(argv[i], "borderless"))
172 flags = CUPS_MEDIA_FLAGS_BORDERLESS;
173 else if (!strcmp(argv[i], "duplex"))
174 flags = CUPS_MEDIA_FLAGS_DUPLEX;
175 else if (!strcmp(argv[i], "exact"))
176 flags = CUPS_MEDIA_FLAGS_EXACT;
177 else if (!strcmp(argv[i], "ready"))
178 flags = CUPS_MEDIA_FLAGS_READY;
185 show_media(http, dest, dinfo, flags, name);
187 else if (!strcmp(argv[2], "print") && argc > 3)
189 int i, /* Looping var */
190 num_options = 0;/* Number of options */
191 cups_option_t *options = NULL;/* Options */
193 for (i = 4; i < argc; i ++)
194 num_options = cupsParseOptions(argv[i], num_options, &options);
196 print_file(http, dest, dinfo, argv[3], num_options, options);
206 * 'enum_cb()' - Print the results from the enumeration of destinations.
209 static int /* O - 1 to continue */
210 enum_cb(void *user_data, /* I - User data (unused) */
211 unsigned flags, /* I - Flags */
212 cups_dest_t *dest) /* I - Destination */
214 int i; /* Looping var */
221 printf("%s/%s:\n", dest->name, dest->instance);
223 printf("%s:\n", dest->name);
225 for (i = 0; i < dest->num_options; i ++)
226 printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value);
233 * 'localize()' - Localize an option and value.
237 localize(http_t *http, /* I - Connection to destination */
238 cups_dest_t *dest, /* I - Destination */
239 cups_dinfo_t *dinfo, /* I - Destination information */
240 const char *option, /* I - Option */
241 const char *value) /* I - Value, if any */
243 ipp_attribute_t *attr; /* Attribute */
244 int i, /* Looping var */
245 count; /* Number of values */
250 attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
253 count = ippGetCount(attr);
254 for (i = 0; i < count; i ++)
255 localize(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
259 static const char * const options[] =
260 { /* List of standard options */
266 CUPS_PRINT_COLOR_MODE,
271 puts("No job-creation-attributes-supported attribute, probing instead.");
273 for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++)
274 if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL))
275 localize(http, dest, dinfo, options[i], NULL);
280 printf("%s (%s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option));
282 if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
284 count = ippGetCount(attr);
286 switch (ippGetValueTag(attr))
288 case IPP_TAG_INTEGER :
289 for (i = 0; i < count; i ++)
290 printf(" %d\n", ippGetInteger(attr, i));
294 for (i = 0; i < count; i ++)
295 printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i)));
299 for (i = 0; i < count; i ++)
301 int upper, lower = ippGetRange(attr, i, &upper);
303 printf(" %d-%d\n", lower, upper);
307 case IPP_TAG_RESOLUTION :
308 for (i = 0; i < count; i ++)
312 xres = ippGetResolution(attr, i, &yres, &units);
315 printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
317 printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
321 case IPP_TAG_TEXTLANG :
322 case IPP_TAG_NAMELANG :
325 case IPP_TAG_KEYWORD :
327 case IPP_TAG_URISCHEME :
328 case IPP_TAG_CHARSET :
329 case IPP_TAG_LANGUAGE :
330 case IPP_TAG_MIMETYPE :
331 for (i = 0; i < count; i ++)
332 printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL)));
335 case IPP_TAG_STRING :
336 for (i = 0; i < count; i ++)
339 unsigned char *data = ippGetOctetString(attr, i, &len);
342 for (j = 0; j < len; j ++)
344 if (data[j] < ' ' || data[j] >= 0x7f)
345 printf("<%02X>", data[j]);
353 case IPP_TAG_BOOLEAN :
357 printf(" %s\n", ippTagString(ippGetValueTag(attr)));
364 puts(cupsLocalizeDestValue(http, dest, dinfo, option, value));
369 * 'print_file()' - Print a file.
373 print_file(http_t *http, /* I - Connection to destination */
374 cups_dest_t *dest, /* I - Destination */
375 cups_dinfo_t *dinfo, /* I - Destination information */
376 const char *filename, /* I - File to print */
377 int num_options, /* I - Number of options */
378 cups_option_t *options) /* I - Options */
380 cups_file_t *fp; /* File to print */
381 int job_id; /* Job ID */
382 ipp_status_t status; /* Submission status */
383 const char *title; /* Title of job */
384 char buffer[32768]; /* File buffer */
385 ssize_t bytes; /* Bytes read/to write */
388 if ((fp = cupsFileOpen(filename, "r")) == NULL)
390 printf("Unable to open \"%s\": %s\n", filename, strerror(errno));
394 if ((title = strrchr(filename, '/')) != NULL)
399 if ((status = cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
401 printf("Unable to create job: %s\n", cupsLastErrorString());
406 printf("Created job ID: %d\n", job_id);
408 if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE)
410 printf("Unable to send document: %s\n", cupsLastErrorString());
415 while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
417 if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE)
419 printf("Unable to write document data: %s\n", cupsLastErrorString());
426 if ((status = cupsFinishDestDocument(http, dest, dinfo)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
428 printf("Unable to send document: %s\n", cupsLastErrorString());
437 * 'show_conflicts()' - Show conflicts for selected options.
442 http_t *http, /* I - Connection to destination */
443 cups_dest_t *dest, /* I - Destination */
444 cups_dinfo_t *dinfo, /* I - Destination information */
445 int num_options, /* I - Number of options */
446 cups_option_t *options) /* I - Options */
457 * 'show_default()' - Show default value for option.
461 show_default(http_t *http, /* I - Connection to destination */
462 cups_dest_t *dest, /* I - Destination */
463 cups_dinfo_t *dinfo, /* I - Destination information */
464 const char *option) /* I - Option */
474 * 'show_media()' - Show available media.
478 show_media(http_t *http, /* I - Connection to destination */
479 cups_dest_t *dest, /* I - Destination */
480 cups_dinfo_t *dinfo, /* I - Destination information */
481 unsigned flags, /* I - Media flags */
482 const char *name) /* I - Size name */
484 int i, /* Looping var */
485 count; /* Number of sizes */
486 cups_size_t size; /* Media size info */
491 double dw, dl; /* Width and length from name */
492 char units[32]; /* Units */
493 int width, /* Width in 100ths of millimeters */
494 length; /* Length in 100ths of millimeters */
497 if (sscanf(name, "%lfx%lf%31s", &dw, &dl, units) == 3)
499 if (!strcmp(units, "in"))
501 width = (int)(dw * 2540.0);
502 length = (int)(dl * 2540.0);
504 else if (!strcmp(units, "mm"))
506 width = (int)(dw * 100.0);
507 length = (int)(dl * 100.0);
511 puts(" bad units in size");
515 if (cupsGetDestMediaBySize(http, dest, dinfo, width, length, flags, &size))
517 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);
521 puts(" not supported");
524 else if (cupsGetDestMediaByName(http, dest, dinfo, name, flags, &size))
526 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);
530 puts(" not supported");
535 count = cupsGetDestMediaCount(http, dest, dinfo, flags);
536 printf("%d size%s:\n", count, count == 1 ? "" : "s");
538 for (i = 0; i < count; i ++)
540 if (cupsGetDestMediaByIndex(http, dest, dinfo, i, flags, &size))
541 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);
550 * 'show_supported()' - Show supported options, values, etc.
554 show_supported(http_t *http, /* I - Connection to destination */
555 cups_dest_t *dest, /* I - Destination */
556 cups_dinfo_t *dinfo, /* I - Destination information */
557 const char *option, /* I - Option, if any */
558 const char *value) /* I - Value, if any */
560 ipp_attribute_t *attr; /* Attribute */
561 int i, /* Looping var */
562 count; /* Number of values */
567 attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
570 count = ippGetCount(attr);
571 for (i = 0; i < count; i ++)
572 show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
576 static const char * const options[] =
577 { /* List of standard options */
583 CUPS_PRINT_COLOR_MODE,
588 puts("No job-creation-attributes-supported attribute, probing instead.");
590 for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++)
591 if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL))
592 show_supported(http, dest, dinfo, options[i], NULL);
598 if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
600 count = ippGetCount(attr);
602 switch (ippGetValueTag(attr))
604 case IPP_TAG_INTEGER :
605 for (i = 0; i < count; i ++)
606 printf(" %d\n", ippGetInteger(attr, i));
610 for (i = 0; i < count; i ++)
611 printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i)));
615 for (i = 0; i < count; i ++)
617 int upper, lower = ippGetRange(attr, i, &upper);
619 printf(" %d-%d\n", lower, upper);
623 case IPP_TAG_RESOLUTION :
624 for (i = 0; i < count; i ++)
628 xres = ippGetResolution(attr, i, &yres, &units);
631 printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
633 printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
637 case IPP_TAG_TEXTLANG :
638 case IPP_TAG_NAMELANG :
641 case IPP_TAG_KEYWORD :
643 case IPP_TAG_URISCHEME :
644 case IPP_TAG_CHARSET :
645 case IPP_TAG_LANGUAGE :
646 case IPP_TAG_MIMETYPE :
647 for (i = 0; i < count; i ++)
648 printf(" %s\n", ippGetString(attr, i, NULL));
651 case IPP_TAG_STRING :
652 for (i = 0; i < count; i ++)
655 unsigned char *data = ippGetOctetString(attr, i, &len);
658 for (j = 0; j < len; j ++)
660 if (data[j] < ' ' || data[j] >= 0x7f)
661 printf("<%02X>", data[j]);
669 case IPP_TAG_BOOLEAN :
673 printf(" %s\n", ippTagString(ippGetValueTag(attr)));
679 else if (cupsCheckDestSupported(http, dest, dinfo, option, value))
687 * 'usage()' - Show program usage.
691 usage(const char *arg) /* I - Argument for usage message */
694 printf("testdest: Unknown option \"%s\".\n", arg);
697 puts(" ./testdest name [operation ...]");
698 puts(" ./testdest ipp://... [operation ...]");
699 puts(" ./testdest ipps://... [operation ...]");
700 puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n"
701 " [medium] [large]");
704 puts(" conflicts options");
705 puts(" default option");
706 puts(" localize option [value]");
707 puts(" media [borderless] [duplex] [exact] [ready] [name or size]");
708 puts(" print filename [options]");
709 puts(" supported [option [value]]");