#include <stdio.h>
#include <errno.h>
#include <cups/cups.h>
#include <cups/thread-private.h>
static int enum_dests_cb(void *_name, unsigned flags, cups_dest_t *dest);
static void *run_query(cups_dest_t *dest);
static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value);
int
main(int argc,
char *argv[])
{
(void)argc;
cupsEnumDests(CUPS_DEST_FLAGS_NONE, -1, NULL, 0, 0, enum_dests_cb, argv[1]);
return (0);
}
static int
enum_dests_cb(void *_name,
unsigned flags,
cups_dest_t *dest)
{
const char *name = (const char *)_name;
cups_dest_t *cdest;
(void)flags;
if (name && strcasecmp(name, dest->name))
return (1);
cupsCopyDest(dest, 0, &cdest);
_cupsThreadWait(_cupsThreadCreate((_cups_thread_func_t)run_query, cdest));
cupsFreeDests(1, cdest);
return (!name || !strcasecmp(name, dest->name));
}
static void *
run_query(cups_dest_t *dest)
{
http_t *http;
cups_dinfo_t *dinfo;
unsigned dflags = CUPS_DEST_FLAGS_NONE;
if ((http = cupsConnectDest(dest, dflags, 300, NULL, NULL, 0, NULL, NULL)) == NULL)
{
printf("testthreads: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString());
return (NULL);
}
if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL)
{
printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString());
return (NULL);
}
printf("\n%s:\n", dest->name);
show_supported(http, dest, dinfo, NULL, NULL);
return (NULL);
}
static void
show_supported(http_t *http,
cups_dest_t *dest,
cups_dinfo_t *dinfo,
const char *option,
const char *value)
{
ipp_attribute_t *attr;
int i,
count;
if (!option)
{
attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
if (attr)
{
count = ippGetCount(attr);
for (i = 0; i < count; i ++)
show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
}
else
{
static const char * const options[] =
{
CUPS_COPIES,
CUPS_FINISHINGS,
CUPS_MEDIA,
CUPS_NUMBER_UP,
CUPS_ORIENTATION,
CUPS_PRINT_COLOR_MODE,
CUPS_PRINT_QUALITY,
CUPS_SIDES
};
puts(" No job-creation-attributes-supported attribute, probing instead.");
for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++)
if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL))
show_supported(http, dest, dinfo, options[i], NULL);
}
}
else if (!value)
{
printf(" %s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported");
if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
{
count = ippGetCount(attr);
switch (ippGetValueTag(attr))
{
case IPP_TAG_INTEGER :
for (i = 0; i < count; i ++)
printf(" %d\n", ippGetInteger(attr, i));
break;
case IPP_TAG_ENUM :
for (i = 0; i < count; i ++)
{
int val = ippGetInteger(attr, i);
char valstr[256];
snprintf(valstr, sizeof(valstr), "%d", val);
printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr));
}
break;
case IPP_TAG_RANGE :
for (i = 0; i < count; i ++)
{
int upper, lower = ippGetRange(attr, i, &upper);
printf(" %d-%d\n", lower, upper);
}
break;
case IPP_TAG_RESOLUTION :
for (i = 0; i < count; i ++)
{
int xres, yres;
ipp_res_t units;
xres = ippGetResolution(attr, i, &yres, &units);
if (xres == yres)
printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
else
printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
}
break;
case IPP_TAG_KEYWORD :
for (i = 0; i < count; i ++)
printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL)));
break;
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
for (i = 0; i < count; i ++)
printf(" %s\n", ippGetString(attr, i, NULL));
break;
case IPP_TAG_STRING :
for (i = 0; i < count; i ++)
{
int j, len;
unsigned char *data = ippGetOctetString(attr, i, &len);
fputs(" ", stdout);
for (j = 0; j < len; j ++)
{
if (data[j] < ' ' || data[j] >= 0x7f)
printf("<%02X>", data[j]);
else
putchar(data[j]);
}
putchar('\n');
}
break;
case IPP_TAG_BOOLEAN :
break;
default :
printf(" %s\n", ippTagString(ippGetValueTag(attr)));
break;
}
}
}
else if (cupsCheckDestSupported(http, dest, dinfo, option, value))
puts("YES");
else
puts("NO");
}