2 * CUPS destination API test program for CUPS.
4 * Copyright 2012-2017 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 http_t
*http
; /* Connection to destination */
41 cups_dest_t
*dest
= NULL
; /* Destination */
42 cups_dinfo_t
*dinfo
; /* Destination info */
48 if (!strcmp(argv
[1], "--enum"))
50 int i
; /* Looping var */
51 cups_ptype_t type
= 0, /* Printer type filter */
52 mask
= 0; /* Printer type mask */
55 for (i
= 2; i
< argc
; i
++)
57 if (!strcmp(argv
[i
], "grayscale"))
59 type
|= CUPS_PRINTER_BW
;
60 mask
|= CUPS_PRINTER_BW
;
62 else if (!strcmp(argv
[i
], "color"))
64 type
|= CUPS_PRINTER_COLOR
;
65 mask
|= CUPS_PRINTER_COLOR
;
67 else if (!strcmp(argv
[i
], "duplex"))
69 type
|= CUPS_PRINTER_DUPLEX
;
70 mask
|= CUPS_PRINTER_DUPLEX
;
72 else if (!strcmp(argv
[i
], "staple"))
74 type
|= CUPS_PRINTER_STAPLE
;
75 mask
|= CUPS_PRINTER_STAPLE
;
77 else if (!strcmp(argv
[i
], "small"))
79 type
|= CUPS_PRINTER_SMALL
;
80 mask
|= CUPS_PRINTER_SMALL
;
82 else if (!strcmp(argv
[i
], "medium"))
84 type
|= CUPS_PRINTER_MEDIUM
;
85 mask
|= CUPS_PRINTER_MEDIUM
;
87 else if (!strcmp(argv
[i
], "large"))
89 type
|= CUPS_PRINTER_LARGE
;
90 mask
|= CUPS_PRINTER_LARGE
;
96 cupsEnumDests(CUPS_DEST_FLAGS_NONE
, 5000, NULL
, type
, mask
, enum_cb
, NULL
);
100 else if (!strncmp(argv
[1], "ipp://", 6) || !strncmp(argv
[1], "ipps://", 7))
101 dest
= cupsGetDestWithURI(NULL
, argv
[1]);
102 else if (!strcmp(argv
[1], "default"))
104 dest
= cupsGetNamedDest(CUPS_HTTP_DEFAULT
, NULL
, NULL
);
105 if (dest
&& dest
->instance
)
106 printf("default is \"%s/%s\".\n", dest
->name
, dest
->instance
);
108 printf("default is \"%s\".\n", dest
->name
);
111 dest
= cupsGetNamedDest(CUPS_HTTP_DEFAULT
, argv
[1], NULL
);
115 printf("testdest: Unable to get destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
119 if ((http
= cupsConnectDest(dest
, CUPS_DEST_FLAGS_NONE
, 30000, NULL
, NULL
, 0, NULL
, NULL
)) == NULL
)
121 printf("testdest: Unable to connect to destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
125 if ((dinfo
= cupsCopyDestInfo(http
, dest
)) == NULL
)
127 printf("testdest: Unable to get information for destination \"%s\": %s\n", argv
[1], cupsLastErrorString());
131 if (argc
== 2 || (!strcmp(argv
[2], "supported") && argc
< 6))
134 show_supported(http
, dest
, dinfo
, argv
[3], argv
[4]);
136 show_supported(http
, dest
, dinfo
, argv
[3], NULL
);
138 show_supported(http
, dest
, dinfo
, NULL
, NULL
);
140 else if (!strcmp(argv
[2], "conflicts") && argc
> 3)
142 int i
, /* Looping var */
143 num_options
= 0;/* Number of options */
144 cups_option_t
*options
= NULL
;/* Options */
146 for (i
= 3; i
< argc
; i
++)
147 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
149 show_conflicts(http
, dest
, dinfo
, num_options
, options
);
151 else if (!strcmp(argv
[2], "default") && argc
== 4)
153 show_default(http
, dest
, dinfo
, argv
[3]);
155 else if (!strcmp(argv
[2], "localize") && argc
< 6)
158 localize(http
, dest
, dinfo
, argv
[3], argv
[4]);
160 localize(http
, dest
, dinfo
, argv
[3], NULL
);
162 localize(http
, dest
, dinfo
, NULL
, NULL
);
164 else if (!strcmp(argv
[2], "media"))
166 int i
; /* Looping var */
167 const char *name
= NULL
; /* Media name, if any */
168 unsigned flags
= CUPS_MEDIA_FLAGS_DEFAULT
;
169 /* Media selection flags */
171 for (i
= 3; i
< argc
; i
++)
173 if (!strcmp(argv
[i
], "borderless"))
174 flags
= CUPS_MEDIA_FLAGS_BORDERLESS
;
175 else if (!strcmp(argv
[i
], "duplex"))
176 flags
= CUPS_MEDIA_FLAGS_DUPLEX
;
177 else if (!strcmp(argv
[i
], "exact"))
178 flags
= CUPS_MEDIA_FLAGS_EXACT
;
179 else if (!strcmp(argv
[i
], "ready"))
180 flags
= CUPS_MEDIA_FLAGS_READY
;
187 show_media(http
, dest
, dinfo
, flags
, name
);
189 else if (!strcmp(argv
[2], "print") && argc
> 3)
191 int i
, /* Looping var */
192 num_options
= 0;/* Number of options */
193 cups_option_t
*options
= NULL
;/* Options */
195 for (i
= 4; i
< argc
; i
++)
196 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
198 print_file(http
, dest
, dinfo
, argv
[3], num_options
, options
);
208 * 'enum_cb()' - Print the results from the enumeration of destinations.
211 static int /* O - 1 to continue */
212 enum_cb(void *user_data
, /* I - User data (unused) */
213 unsigned flags
, /* I - Flags */
214 cups_dest_t
*dest
) /* I - Destination */
216 int i
; /* Looping var */
223 printf("%s%s/%s:\n", (flags
& CUPS_DEST_FLAGS_REMOVED
) ? "REMOVE " : "", dest
->name
, dest
->instance
);
225 printf("%s%s:\n", (flags
& CUPS_DEST_FLAGS_REMOVED
) ? "REMOVE " : "", dest
->name
);
227 for (i
= 0; i
< dest
->num_options
; i
++)
228 printf(" %s=\"%s\"\n", dest
->options
[i
].name
, dest
->options
[i
].value
);
235 * 'localize()' - Localize an option and value.
239 localize(http_t
*http
, /* I - Connection to destination */
240 cups_dest_t
*dest
, /* I - Destination */
241 cups_dinfo_t
*dinfo
, /* I - Destination information */
242 const char *option
, /* I - Option */
243 const char *value
) /* I - Value, if any */
245 ipp_attribute_t
*attr
; /* Attribute */
246 int i
, /* Looping var */
247 count
; /* Number of values */
252 attr
= cupsFindDestSupported(http
, dest
, dinfo
, "job-creation-attributes");
255 count
= ippGetCount(attr
);
256 for (i
= 0; i
< count
; i
++)
257 localize(http
, dest
, dinfo
, ippGetString(attr
, i
, NULL
), NULL
);
261 static const char * const options
[] =
262 { /* List of standard options */
268 CUPS_PRINT_COLOR_MODE
,
273 puts("No job-creation-attributes-supported attribute, probing instead.");
275 for (i
= 0; i
< (int)(sizeof(options
) / sizeof(options
[0])); i
++)
276 if (cupsCheckDestSupported(http
, dest
, dinfo
, options
[i
], NULL
))
277 localize(http
, dest
, dinfo
, options
[i
], NULL
);
282 printf("%s (%s)\n", option
, cupsLocalizeDestOption(http
, dest
, dinfo
, option
));
284 if ((attr
= cupsFindDestSupported(http
, dest
, dinfo
, option
)) != NULL
)
286 count
= ippGetCount(attr
);
288 switch (ippGetValueTag(attr
))
290 case IPP_TAG_INTEGER
:
291 for (i
= 0; i
< count
; i
++)
292 printf(" %d\n", ippGetInteger(attr
, i
));
296 for (i
= 0; i
< count
; i
++)
297 printf(" %s\n", ippEnumString(option
, ippGetInteger(attr
, i
)));
301 for (i
= 0; i
< count
; i
++)
303 int upper
, lower
= ippGetRange(attr
, i
, &upper
);
305 printf(" %d-%d\n", lower
, upper
);
309 case IPP_TAG_RESOLUTION
:
310 for (i
= 0; i
< count
; i
++)
314 xres
= ippGetResolution(attr
, i
, &yres
, &units
);
317 printf(" %d%s\n", xres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
319 printf(" %dx%d%s\n", xres
, yres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
323 case IPP_TAG_TEXTLANG
:
324 case IPP_TAG_NAMELANG
:
327 case IPP_TAG_KEYWORD
:
329 case IPP_TAG_URISCHEME
:
330 case IPP_TAG_CHARSET
:
331 case IPP_TAG_LANGUAGE
:
332 case IPP_TAG_MIMETYPE
:
333 for (i
= 0; i
< count
; i
++)
334 printf(" %s (%s)\n", ippGetString(attr
, i
, NULL
), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, ippGetString(attr
, i
, NULL
)));
337 case IPP_TAG_STRING
:
338 for (i
= 0; i
< count
; i
++)
341 unsigned char *data
= ippGetOctetString(attr
, i
, &len
);
344 for (j
= 0; j
< len
; j
++)
346 if (data
[j
] < ' ' || data
[j
] >= 0x7f)
347 printf("<%02X>", data
[j
]);
355 case IPP_TAG_BOOLEAN
:
359 printf(" %s\n", ippTagString(ippGetValueTag(attr
)));
366 puts(cupsLocalizeDestValue(http
, dest
, dinfo
, option
, value
));
371 * 'print_file()' - Print a file.
375 print_file(http_t
*http
, /* I - Connection to destination */
376 cups_dest_t
*dest
, /* I - Destination */
377 cups_dinfo_t
*dinfo
, /* I - Destination information */
378 const char *filename
, /* I - File to print */
379 int num_options
, /* I - Number of options */
380 cups_option_t
*options
) /* I - Options */
382 cups_file_t
*fp
; /* File to print */
383 int job_id
; /* Job ID */
384 ipp_status_t status
; /* Submission status */
385 const char *title
; /* Title of job */
386 char buffer
[32768]; /* File buffer */
387 ssize_t bytes
; /* Bytes read/to write */
390 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
392 printf("Unable to open \"%s\": %s\n", filename
, strerror(errno
));
396 if ((title
= strrchr(filename
, '/')) != NULL
)
401 if ((status
= cupsCreateDestJob(http
, dest
, dinfo
, &job_id
, title
, num_options
, options
)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED
)
403 printf("Unable to create job: %s\n", cupsLastErrorString());
408 printf("Created job ID: %d\n", job_id
);
410 if (cupsStartDestDocument(http
, dest
, dinfo
, job_id
, title
, CUPS_FORMAT_AUTO
, 0, NULL
, 1) != HTTP_STATUS_CONTINUE
)
412 printf("Unable to send document: %s\n", cupsLastErrorString());
417 while ((bytes
= cupsFileRead(fp
, buffer
, sizeof(buffer
))) > 0)
419 if (cupsWriteRequestData(http
, buffer
, (size_t)bytes
) != HTTP_STATUS_CONTINUE
)
421 printf("Unable to write document data: %s\n", cupsLastErrorString());
428 if ((status
= cupsFinishDestDocument(http
, dest
, dinfo
)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED
)
430 printf("Unable to send document: %s\n", cupsLastErrorString());
439 * 'show_conflicts()' - Show conflicts for selected options.
444 http_t
*http
, /* I - Connection to destination */
445 cups_dest_t
*dest
, /* I - Destination */
446 cups_dinfo_t
*dinfo
, /* I - Destination information */
447 int num_options
, /* I - Number of options */
448 cups_option_t
*options
) /* I - Options */
459 * 'show_default()' - Show default value for option.
463 show_default(http_t
*http
, /* I - Connection to destination */
464 cups_dest_t
*dest
, /* I - Destination */
465 cups_dinfo_t
*dinfo
, /* I - Destination information */
466 const char *option
) /* I - Option */
468 if (!strcmp(option
, "media"))
471 * Show default media option...
474 cups_size_t size
; /* Media size information */
476 if (cupsGetDestMediaDefault(http
, dest
, dinfo
, CUPS_MEDIA_FLAGS_DEFAULT
, &size
))
477 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);
484 * Show default other option...
487 ipp_attribute_t
*defattr
; /* Default attribute */
489 if ((defattr
= cupsFindDestDefault(http
, dest
, dinfo
, option
)) != NULL
)
491 char value
[1024]; /* Value of default attribute */
493 ippAttributeString(defattr
, value
, sizeof(value
));
503 * 'show_media()' - Show available media.
507 show_media(http_t
*http
, /* I - Connection to destination */
508 cups_dest_t
*dest
, /* I - Destination */
509 cups_dinfo_t
*dinfo
, /* I - Destination information */
510 unsigned flags
, /* I - Media flags */
511 const char *name
) /* I - Size name */
513 int i
, /* Looping var */
514 count
; /* Number of sizes */
515 cups_size_t size
; /* Media size info */
520 double dw
, dl
; /* Width and length from name */
521 char units
[32]; /* Units */
522 int width
, /* Width in 100ths of millimeters */
523 length
; /* Length in 100ths of millimeters */
526 if (sscanf(name
, "%lfx%lf%31s", &dw
, &dl
, units
) == 3)
528 if (!strcmp(units
, "in"))
530 width
= (int)(dw
* 2540.0);
531 length
= (int)(dl
* 2540.0);
533 else if (!strcmp(units
, "mm"))
535 width
= (int)(dw
* 100.0);
536 length
= (int)(dl
* 100.0);
540 puts(" bad units in size");
544 if (cupsGetDestMediaBySize(http
, dest
, dinfo
, width
, length
, flags
, &size
))
546 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 puts(" not supported");
553 else if (cupsGetDestMediaByName(http
, dest
, dinfo
, name
, flags
, &size
))
555 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
);
559 puts(" not supported");
564 count
= cupsGetDestMediaCount(http
, dest
, dinfo
, flags
);
565 printf("%d size%s:\n", count
, count
== 1 ? "" : "s");
567 for (i
= 0; i
< count
; i
++)
569 if (cupsGetDestMediaByIndex(http
, dest
, dinfo
, i
, flags
, &size
))
570 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 * 'show_supported()' - Show supported options, values, etc.
583 show_supported(http_t
*http
, /* I - Connection to destination */
584 cups_dest_t
*dest
, /* I - Destination */
585 cups_dinfo_t
*dinfo
, /* I - Destination information */
586 const char *option
, /* I - Option, if any */
587 const char *value
) /* I - Value, if any */
589 ipp_attribute_t
*attr
; /* Attribute */
590 int i
, /* Looping var */
591 count
; /* Number of values */
596 attr
= cupsFindDestSupported(http
, dest
, dinfo
, "job-creation-attributes");
599 count
= ippGetCount(attr
);
600 for (i
= 0; i
< count
; i
++)
601 show_supported(http
, dest
, dinfo
, ippGetString(attr
, i
, NULL
), NULL
);
605 static const char * const options
[] =
606 { /* List of standard options */
612 CUPS_PRINT_COLOR_MODE
,
617 puts("No job-creation-attributes-supported attribute, probing instead.");
619 for (i
= 0; i
< (int)(sizeof(options
) / sizeof(options
[0])); i
++)
620 if (cupsCheckDestSupported(http
, dest
, dinfo
, options
[i
], NULL
))
621 show_supported(http
, dest
, dinfo
, options
[i
], NULL
);
626 printf("%s (%s - %s)\n", option
, cupsLocalizeDestOption(http
, dest
, dinfo
, option
), cupsCheckDestSupported(http
, dest
, dinfo
, option
, NULL
) ? "supported" : "not-supported");
628 if ((attr
= cupsFindDestSupported(http
, dest
, dinfo
, option
)) != NULL
)
630 count
= ippGetCount(attr
);
632 switch (ippGetValueTag(attr
))
634 case IPP_TAG_INTEGER
:
635 for (i
= 0; i
< count
; i
++)
636 printf(" %d\n", ippGetInteger(attr
, i
));
640 for (i
= 0; i
< count
; i
++)
642 int val
= ippGetInteger(attr
, i
);
645 snprintf(valstr
, sizeof(valstr
), "%d", val
);
646 printf(" %s (%s)\n", ippEnumString(option
, ippGetInteger(attr
, i
)), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, valstr
));
651 for (i
= 0; i
< count
; i
++)
653 int upper
, lower
= ippGetRange(attr
, i
, &upper
);
655 printf(" %d-%d\n", lower
, upper
);
659 case IPP_TAG_RESOLUTION
:
660 for (i
= 0; i
< count
; i
++)
664 xres
= ippGetResolution(attr
, i
, &yres
, &units
);
667 printf(" %d%s\n", xres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
669 printf(" %dx%d%s\n", xres
, yres
, units
== IPP_RES_PER_INCH
? "dpi" : "dpcm");
673 case IPP_TAG_KEYWORD
:
674 for (i
= 0; i
< count
; i
++)
675 printf(" %s (%s)\n", ippGetString(attr
, i
, NULL
), cupsLocalizeDestValue(http
, dest
, dinfo
, option
, ippGetString(attr
, i
, NULL
)));
678 case IPP_TAG_TEXTLANG
:
679 case IPP_TAG_NAMELANG
:
683 case IPP_TAG_URISCHEME
:
684 case IPP_TAG_CHARSET
:
685 case IPP_TAG_LANGUAGE
:
686 case IPP_TAG_MIMETYPE
:
687 for (i
= 0; i
< count
; i
++)
688 printf(" %s\n", ippGetString(attr
, i
, NULL
));
691 case IPP_TAG_STRING
:
692 for (i
= 0; i
< count
; i
++)
695 unsigned char *data
= ippGetOctetString(attr
, i
, &len
);
698 for (j
= 0; j
< len
; j
++)
700 if (data
[j
] < ' ' || data
[j
] >= 0x7f)
701 printf("<%02X>", data
[j
]);
709 case IPP_TAG_BOOLEAN
:
713 printf(" %s\n", ippTagString(ippGetValueTag(attr
)));
719 else if (cupsCheckDestSupported(http
, dest
, dinfo
, option
, value
))
727 * 'usage()' - Show program usage.
731 usage(const char *arg
) /* I - Argument for usage message */
734 printf("testdest: Unknown option \"%s\".\n", arg
);
737 puts(" ./testdest name [operation ...]");
738 puts(" ./testdest ipp://... [operation ...]");
739 puts(" ./testdest ipps://... [operation ...]");
740 puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n"
741 " [medium] [large]");
744 puts(" conflicts options");
745 puts(" default option");
746 puts(" localize option [value]");
747 puts(" media [borderless] [duplex] [exact] [ready] [name or size]");
748 puts(" print filename [options]");
749 puts(" supported [option [value]]");