2 * CUPS destination API test program for CUPS.
4 * Copyright 2012-2017 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 * 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]);
108 else if (!strcmp(argv
[1], "default"))
110 dest
= cupsGetNamedDest(CUPS_HTTP_DEFAULT
, NULL
, NULL
);
111 if (dest
&& dest
->instance
)
112 printf("default is \"%s/%s\".\n", dest
->name
, dest
->instance
);
114 printf("default is \"%s\".\n", dest
->name
);
117 dest
= cupsGetNamedDest(CUPS_HTTP_DEFAULT
, argv
[1], NULL
);
121 printf("testdest: Unable to get destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
125 if ((http
= cupsConnectDest(dest
, CUPS_DEST_FLAGS_NONE
, 30000, NULL
, NULL
, 0, NULL
, NULL
)) == NULL
)
127 printf("testdest: Unable to connect to destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
131 if ((dinfo
= cupsCopyDestInfo(http
, dest
)) == NULL
)
133 printf("testdest: Unable to get information for destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
137 if (argc
== 2 || (!strcmp(argv
[2], "supported") && argc
< 6))
140 show_supported(http
, dest
, dinfo
, argv
[3], argv
[4]);
142 show_supported(http
, dest
, dinfo
, argv
[3], NULL
);
144 show_supported(http
, dest
, dinfo
, NULL
, NULL
);
146 else if (!strcmp(argv
[2], "conflicts") && argc
> 3)
148 int i
, /* Looping var */
149 num_options
= 0;/* Number of options */
150 cups_option_t
*options
= NULL
;/* Options */
152 for (i
= 3; i
< argc
; i
++)
153 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
155 show_conflicts(http
, dest
, dinfo
, num_options
, options
);
157 else if (!strcmp(argv
[2], "default") && argc
== 4)
159 show_default(http
, dest
, dinfo
, argv
[3]);
161 else if (!strcmp(argv
[2], "localize") && argc
< 6)
164 localize(http
, dest
, dinfo
, argv
[3], argv
[4]);
166 localize(http
, dest
, dinfo
, argv
[3], NULL
);
168 localize(http
, dest
, dinfo
, NULL
, NULL
);
170 else if (!strcmp(argv
[2], "media"))
172 int i
; /* Looping var */
173 const char *name
= NULL
; /* Media name, if any */
174 unsigned flags
= CUPS_MEDIA_FLAGS_DEFAULT
;
175 /* Media selection flags */
177 for (i
= 3; i
< argc
; i
++)
179 if (!strcmp(argv
[i
], "borderless"))
180 flags
= CUPS_MEDIA_FLAGS_BORDERLESS
;
181 else if (!strcmp(argv
[i
], "duplex"))
182 flags
= CUPS_MEDIA_FLAGS_DUPLEX
;
183 else if (!strcmp(argv
[i
], "exact"))
184 flags
= CUPS_MEDIA_FLAGS_EXACT
;
185 else if (!strcmp(argv
[i
], "ready"))
186 flags
= CUPS_MEDIA_FLAGS_READY
;
193 show_media(http
, dest
, dinfo
, flags
, name
);
195 else if (!strcmp(argv
[2], "print") && argc
> 3)
197 int i
, /* Looping var */
198 num_options
= 0;/* Number of options */
199 cups_option_t
*options
= NULL
;/* Options */
201 for (i
= 4; i
< argc
; i
++)
202 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
204 print_file(http
, dest
, dinfo
, argv
[3], num_options
, options
);
214 * 'enum_cb()' - Print the results from the enumeration of destinations.
217 static int /* O - 1 to continue */
218 enum_cb(void *user_data
, /* I - User data (unused) */
219 unsigned flags
, /* I - Flags */
220 cups_dest_t
*dest
) /* I - Destination */
222 int i
; /* Looping var */
229 printf("%s%s/%s:\n", (flags
& CUPS_DEST_FLAGS_REMOVED
) ? "REMOVE " : "", dest
->name
, dest
->instance
);
231 printf("%s%s:\n", (flags
& CUPS_DEST_FLAGS_REMOVED
) ? "REMOVE " : "", dest
->name
);
233 for (i
= 0; i
< dest
->num_options
; i
++)
234 printf(" %s=\"%s\"\n", dest
->options
[i
].name
, dest
->options
[i
].value
);
241 * 'localize()' - Localize an option and value.
245 localize(http_t
*http
, /* I - Connection to destination */
246 cups_dest_t
*dest
, /* I - Destination */
247 cups_dinfo_t
*dinfo
, /* I - Destination information */
248 const char *option
, /* I - Option */
249 const char *value
) /* I - Value, if any */
251 ipp_attribute_t
*attr
; /* Attribute */
252 int i
, /* Looping var */
253 count
; /* Number of values */
258 attr
= cupsFindDestSupported(http
, dest
, dinfo
, "job-creation-attributes");
261 count
= ippGetCount(attr
);
262 for (i
= 0; i
< count
; i
++)
263 localize(http
, dest
, dinfo
, ippGetString(attr
, i
, NULL
), NULL
);
267 static const char * const options
[] =
268 { /* List of standard options */
274 CUPS_PRINT_COLOR_MODE
,
279 puts("No job-creation-attributes-supported attribute, probing instead.");
281 for (i
= 0; i
< (int)(sizeof(options
) / sizeof(options
[0])); i
++)
282 if (cupsCheckDestSupported(http
, dest
, dinfo
, options
[i
], NULL
))
283 localize(http
, dest
, dinfo
, options
[i
], NULL
);
288 printf("%s (%s)\n", option
, cupsLocalizeDestOption(http
, dest
, dinfo
, option
));
290 if ((attr
= cupsFindDestSupported(http
, dest
, dinfo
, option
)) != NULL
)
292 count
= ippGetCount(attr
);
294 switch (ippGetValueTag(attr
))
296 case IPP_TAG_INTEGER
:
297 for (i
= 0; i
< count
; i
++)
298 printf(" %d\n", ippGetInteger(attr
, i
));
302 for (i
= 0; i
< count
; i
++)
303 printf(" %s\n", ippEnumString(option
, ippGetInteger(attr
, i
)));
307 for (i
= 0; i
< count
; i
++)
309 int upper
, lower
= ippGetRange(attr
, i
, &upper
);
311 printf(" %d-%d\n", lower
, upper
);
315 case IPP_TAG_RESOLUTION
:
316 for (i
= 0; i
< count
; i
++)
320 xres
= ippGetResolution(attr
, i
, &yres
, &units
);
323 printf(" %d%s\n", xres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
325 printf(" %dx%d%s\n", xres
, yres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
329 case IPP_TAG_TEXTLANG
:
330 case IPP_TAG_NAMELANG
:
333 case IPP_TAG_KEYWORD
:
335 case IPP_TAG_URISCHEME
:
336 case IPP_TAG_CHARSET
:
337 case IPP_TAG_LANGUAGE
:
338 case IPP_TAG_MIMETYPE
:
339 for (i
= 0; i
< count
; i
++)
340 printf(" %s (%s)\n", ippGetString(attr
, i
, NULL
), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, ippGetString(attr
, i
, NULL
)));
343 case IPP_TAG_STRING
:
344 for (i
= 0; i
< count
; i
++)
347 unsigned char *data
= ippGetOctetString(attr
, i
, &len
);
350 for (j
= 0; j
< len
; j
++)
352 if (data
[j
] < ' ' || data
[j
] >= 0x7f)
353 printf("<%02X>", data
[j
]);
361 case IPP_TAG_BOOLEAN
:
365 printf(" %s\n", ippTagString(ippGetValueTag(attr
)));
372 puts(cupsLocalizeDestValue(http
, dest
, dinfo
, option
, value
));
377 * 'print_file()' - Print a file.
381 print_file(http_t
*http
, /* I - Connection to destination */
382 cups_dest_t
*dest
, /* I - Destination */
383 cups_dinfo_t
*dinfo
, /* I - Destination information */
384 const char *filename
, /* I - File to print */
385 int num_options
, /* I - Number of options */
386 cups_option_t
*options
) /* I - Options */
388 cups_file_t
*fp
; /* File to print */
389 int job_id
; /* Job ID */
390 ipp_status_t status
; /* Submission status */
391 const char *title
; /* Title of job */
392 char buffer
[32768]; /* File buffer */
393 ssize_t bytes
; /* Bytes read/to write */
396 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
398 printf("Unable to open \"%s\": %s\n", filename
, strerror(errno
));
402 if ((title
= strrchr(filename
, '/')) != NULL
)
407 if ((status
= cupsCreateDestJob(http
, dest
, dinfo
, &job_id
, title
, num_options
, options
)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED
)
409 printf("Unable to create job: %s\n", cupsLastErrorString());
414 printf("Created job ID: %d\n", job_id
);
416 if (cupsStartDestDocument(http
, dest
, dinfo
, job_id
, title
, CUPS_FORMAT_AUTO
, 0, NULL
, 1) != HTTP_STATUS_CONTINUE
)
418 printf("Unable to send document: %s\n", cupsLastErrorString());
423 while ((bytes
= cupsFileRead(fp
, buffer
, sizeof(buffer
))) > 0)
425 if (cupsWriteRequestData(http
, buffer
, (size_t)bytes
) != HTTP_STATUS_CONTINUE
)
427 printf("Unable to write document data: %s\n", cupsLastErrorString());
434 if ((status
= cupsFinishDestDocument(http
, dest
, dinfo
)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED
)
436 printf("Unable to send document: %s\n", cupsLastErrorString());
445 * 'show_conflicts()' - Show conflicts for selected options.
450 http_t
*http
, /* I - Connection to destination */
451 cups_dest_t
*dest
, /* I - Destination */
452 cups_dinfo_t
*dinfo
, /* I - Destination information */
453 int num_options
, /* I - Number of options */
454 cups_option_t
*options
) /* I - Options */
465 * 'show_default()' - Show default value for option.
469 show_default(http_t
*http
, /* I - Connection to destination */
470 cups_dest_t
*dest
, /* I - Destination */
471 cups_dinfo_t
*dinfo
, /* I - Destination information */
472 const char *option
) /* I - Option */
474 if (!strcmp(option
, "media"))
477 * Show default media option...
480 cups_size_t size
; /* Media size information */
482 if (cupsGetDestMediaDefault(http
, dest
, dinfo
, CUPS_MEDIA_FLAGS_DEFAULT
, &size
))
483 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);
490 * Show default other option...
493 ipp_attribute_t
*defattr
; /* Default attribute */
495 if ((defattr
= cupsFindDestDefault(http
, dest
, dinfo
, option
)) != NULL
)
497 char value
[1024]; /* Value of default attribute */
499 ippAttributeString(defattr
, value
, sizeof(value
));
509 * 'show_media()' - Show available media.
513 show_media(http_t
*http
, /* I - Connection to destination */
514 cups_dest_t
*dest
, /* I - Destination */
515 cups_dinfo_t
*dinfo
, /* I - Destination information */
516 unsigned flags
, /* I - Media flags */
517 const char *name
) /* I - Size name */
519 int i
, /* Looping var */
520 count
; /* Number of sizes */
521 cups_size_t size
; /* Media size info */
526 double dw
, dl
; /* Width and length from name */
527 char units
[32]; /* Units */
528 int width
, /* Width in 100ths of millimeters */
529 length
; /* Length in 100ths of millimeters */
532 if (sscanf(name
, "%lfx%lf%31s", &dw
, &dl
, units
) == 3)
534 if (!strcmp(units
, "in"))
536 width
= (int)(dw
* 2540.0);
537 length
= (int)(dl
* 2540.0);
539 else if (!strcmp(units
, "mm"))
541 width
= (int)(dw
* 100.0);
542 length
= (int)(dl
* 100.0);
546 puts(" bad units in size");
550 if (cupsGetDestMediaBySize(http
, dest
, dinfo
, width
, length
, flags
, &size
))
552 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
);
556 puts(" not supported");
559 else if (cupsGetDestMediaByName(http
, dest
, dinfo
, name
, flags
, &size
))
561 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
);
565 puts(" not supported");
570 count
= cupsGetDestMediaCount(http
, dest
, dinfo
, flags
);
571 printf("%d size%s:\n", count
, count
== 1 ? "" : "s");
573 for (i
= 0; i
< count
; i
++)
575 if (cupsGetDestMediaByIndex(http
, dest
, dinfo
, i
, flags
, &size
))
576 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 * 'show_supported()' - Show supported options, values, etc.
589 show_supported(http_t
*http
, /* I - Connection to destination */
590 cups_dest_t
*dest
, /* I - Destination */
591 cups_dinfo_t
*dinfo
, /* I - Destination information */
592 const char *option
, /* I - Option, if any */
593 const char *value
) /* I - Value, if any */
595 ipp_attribute_t
*attr
; /* Attribute */
596 int i
, /* Looping var */
597 count
; /* Number of values */
602 attr
= cupsFindDestSupported(http
, dest
, dinfo
, "job-creation-attributes");
605 count
= ippGetCount(attr
);
606 for (i
= 0; i
< count
; i
++)
607 show_supported(http
, dest
, dinfo
, ippGetString(attr
, i
, NULL
), NULL
);
611 static const char * const options
[] =
612 { /* List of standard options */
618 CUPS_PRINT_COLOR_MODE
,
623 puts("No job-creation-attributes-supported attribute, probing instead.");
625 for (i
= 0; i
< (int)(sizeof(options
) / sizeof(options
[0])); i
++)
626 if (cupsCheckDestSupported(http
, dest
, dinfo
, options
[i
], NULL
))
627 show_supported(http
, dest
, dinfo
, options
[i
], NULL
);
632 printf("%s (%s - %s)\n", option
, cupsLocalizeDestOption(http
, dest
, dinfo
, option
), cupsCheckDestSupported(http
, dest
, dinfo
, option
, NULL
) ? "supported" : "not-supported");
634 if ((attr
= cupsFindDestSupported(http
, dest
, dinfo
, option
)) != NULL
)
636 count
= ippGetCount(attr
);
638 switch (ippGetValueTag(attr
))
640 case IPP_TAG_INTEGER
:
641 for (i
= 0; i
< count
; i
++)
642 printf(" %d\n", ippGetInteger(attr
, i
));
646 for (i
= 0; i
< count
; i
++)
648 int val
= ippGetInteger(attr
, i
);
651 snprintf(valstr
, sizeof(valstr
), "%d", val
);
652 printf(" %s (%s)\n", ippEnumString(option
, ippGetInteger(attr
, i
)), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, valstr
));
657 for (i
= 0; i
< count
; i
++)
659 int upper
, lower
= ippGetRange(attr
, i
, &upper
);
661 printf(" %d-%d\n", lower
, upper
);
665 case IPP_TAG_RESOLUTION
:
666 for (i
= 0; i
< count
; i
++)
670 xres
= ippGetResolution(attr
, i
, &yres
, &units
);
673 printf(" %d%s\n", xres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
675 printf(" %dx%d%s\n", xres
, yres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
679 case IPP_TAG_KEYWORD
:
680 for (i
= 0; i
< count
; i
++)
681 printf(" %s (%s)\n", ippGetString(attr
, i
, NULL
), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, ippGetString(attr
, i
, NULL
)));
684 case IPP_TAG_TEXTLANG
:
685 case IPP_TAG_NAMELANG
:
689 case IPP_TAG_URISCHEME
:
690 case IPP_TAG_CHARSET
:
691 case IPP_TAG_LANGUAGE
:
692 case IPP_TAG_MIMETYPE
:
693 for (i
= 0; i
< count
; i
++)
694 printf(" %s\n", ippGetString(attr
, i
, NULL
));
697 case IPP_TAG_STRING
:
698 for (i
= 0; i
< count
; i
++)
701 unsigned char *data
= ippGetOctetString(attr
, i
, &len
);
704 for (j
= 0; j
< len
; j
++)
706 if (data
[j
] < ' ' || data
[j
] >= 0x7f)
707 printf("<%02X>", data
[j
]);
715 case IPP_TAG_BOOLEAN
:
719 printf(" %s\n", ippTagString(ippGetValueTag(attr
)));
725 else if (cupsCheckDestSupported(http
, dest
, dinfo
, option
, value
))
733 * 'usage()' - Show program usage.
737 usage(const char *arg
) /* I - Argument for usage message */
740 printf("testdest: Unknown option \"%s\".\n", arg
);
743 puts(" ./testdest name [operation ...]");
744 puts(" ./testdest ipp://... [operation ...]");
745 puts(" ./testdest ipps://... [operation ...]");
746 puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n"
747 " [medium] [large]");
750 puts(" conflicts options");
751 puts(" default option");
752 puts(" localize option [value]");
753 puts(" media [borderless] [duplex] [exact] [ready] [name or size]");
754 puts(" print filename [options]");
755 puts(" supported [option [value]]");