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
) __attribute__((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]]");