1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Threaded test program for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2012-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker *
6*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
7*5e7646d2SAndroid Build Coastguard Worker * information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker #include <stdio.h>
15*5e7646d2SAndroid Build Coastguard Worker #include <errno.h>
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/cups.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/thread-private.h>
18*5e7646d2SAndroid Build Coastguard Worker
19*5e7646d2SAndroid Build Coastguard Worker
20*5e7646d2SAndroid Build Coastguard Worker /*
21*5e7646d2SAndroid Build Coastguard Worker * Local functions...
22*5e7646d2SAndroid Build Coastguard Worker */
23*5e7646d2SAndroid Build Coastguard Worker
24*5e7646d2SAndroid Build Coastguard Worker static int enum_dests_cb(void *_name, unsigned flags, cups_dest_t *dest);
25*5e7646d2SAndroid Build Coastguard Worker static void *run_query(cups_dest_t *dest);
26*5e7646d2SAndroid Build Coastguard Worker static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value);
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker /*
30*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Main entry.
31*5e7646d2SAndroid Build Coastguard Worker */
32*5e7646d2SAndroid Build Coastguard Worker
33*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
main(int argc,char * argv[])34*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line arguments */
35*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
36*5e7646d2SAndroid Build Coastguard Worker {
37*5e7646d2SAndroid Build Coastguard Worker /*
38*5e7646d2SAndroid Build Coastguard Worker * Go through all the available destinations to find the requested one...
39*5e7646d2SAndroid Build Coastguard Worker */
40*5e7646d2SAndroid Build Coastguard Worker
41*5e7646d2SAndroid Build Coastguard Worker (void)argc;
42*5e7646d2SAndroid Build Coastguard Worker
43*5e7646d2SAndroid Build Coastguard Worker cupsEnumDests(CUPS_DEST_FLAGS_NONE, -1, NULL, 0, 0, enum_dests_cb, argv[1]);
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker return (0);
46*5e7646d2SAndroid Build Coastguard Worker }
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker
49*5e7646d2SAndroid Build Coastguard Worker /*
50*5e7646d2SAndroid Build Coastguard Worker * 'enum_dests_cb()' - Destination enumeration function...
51*5e7646d2SAndroid Build Coastguard Worker */
52*5e7646d2SAndroid Build Coastguard Worker
53*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 to continue, 0 to stop */
enum_dests_cb(void * _name,unsigned flags,cups_dest_t * dest)54*5e7646d2SAndroid Build Coastguard Worker enum_dests_cb(void *_name, /* I - Printer name, if any */
55*5e7646d2SAndroid Build Coastguard Worker unsigned flags, /* I - Enumeration flags */
56*5e7646d2SAndroid Build Coastguard Worker cups_dest_t *dest) /* I - Found destination */
57*5e7646d2SAndroid Build Coastguard Worker {
58*5e7646d2SAndroid Build Coastguard Worker const char *name = (const char *)_name;
59*5e7646d2SAndroid Build Coastguard Worker /* Printer name */
60*5e7646d2SAndroid Build Coastguard Worker cups_dest_t *cdest; /* Copied destination */
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker
63*5e7646d2SAndroid Build Coastguard Worker (void)flags;
64*5e7646d2SAndroid Build Coastguard Worker
65*5e7646d2SAndroid Build Coastguard Worker /*
66*5e7646d2SAndroid Build Coastguard Worker * If a name was specified, compare it...
67*5e7646d2SAndroid Build Coastguard Worker */
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker if (name && strcasecmp(name, dest->name))
70*5e7646d2SAndroid Build Coastguard Worker return (1); /* Continue */
71*5e7646d2SAndroid Build Coastguard Worker
72*5e7646d2SAndroid Build Coastguard Worker /*
73*5e7646d2SAndroid Build Coastguard Worker * Copy the destination and run the query on a separate thread...
74*5e7646d2SAndroid Build Coastguard Worker */
75*5e7646d2SAndroid Build Coastguard Worker
76*5e7646d2SAndroid Build Coastguard Worker cupsCopyDest(dest, 0, &cdest);
77*5e7646d2SAndroid Build Coastguard Worker _cupsThreadWait(_cupsThreadCreate((_cups_thread_func_t)run_query, cdest));
78*5e7646d2SAndroid Build Coastguard Worker
79*5e7646d2SAndroid Build Coastguard Worker cupsFreeDests(1, cdest);
80*5e7646d2SAndroid Build Coastguard Worker
81*5e7646d2SAndroid Build Coastguard Worker /*
82*5e7646d2SAndroid Build Coastguard Worker * Continue if no name was specified or the name matches...
83*5e7646d2SAndroid Build Coastguard Worker */
84*5e7646d2SAndroid Build Coastguard Worker
85*5e7646d2SAndroid Build Coastguard Worker return (!name || !strcasecmp(name, dest->name));
86*5e7646d2SAndroid Build Coastguard Worker }
87*5e7646d2SAndroid Build Coastguard Worker
88*5e7646d2SAndroid Build Coastguard Worker
89*5e7646d2SAndroid Build Coastguard Worker /*
90*5e7646d2SAndroid Build Coastguard Worker * 'run_query()' - Query printer capabilities on a separate thread.
91*5e7646d2SAndroid Build Coastguard Worker */
92*5e7646d2SAndroid Build Coastguard Worker
93*5e7646d2SAndroid Build Coastguard Worker static void * /* O - Return value (not used) */
run_query(cups_dest_t * dest)94*5e7646d2SAndroid Build Coastguard Worker run_query(cups_dest_t *dest) /* I - Destination to query */
95*5e7646d2SAndroid Build Coastguard Worker {
96*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* Connection to destination */
97*5e7646d2SAndroid Build Coastguard Worker cups_dinfo_t *dinfo; /* Destination info */
98*5e7646d2SAndroid Build Coastguard Worker unsigned dflags = CUPS_DEST_FLAGS_NONE;
99*5e7646d2SAndroid Build Coastguard Worker /* Destination flags */
100*5e7646d2SAndroid Build Coastguard Worker
101*5e7646d2SAndroid Build Coastguard Worker
102*5e7646d2SAndroid Build Coastguard Worker if ((http = cupsConnectDest(dest, dflags, 300, NULL, NULL, 0, NULL, NULL)) == NULL)
103*5e7646d2SAndroid Build Coastguard Worker {
104*5e7646d2SAndroid Build Coastguard Worker printf("testthreads: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString());
105*5e7646d2SAndroid Build Coastguard Worker return (NULL);
106*5e7646d2SAndroid Build Coastguard Worker }
107*5e7646d2SAndroid Build Coastguard Worker
108*5e7646d2SAndroid Build Coastguard Worker if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL)
109*5e7646d2SAndroid Build Coastguard Worker {
110*5e7646d2SAndroid Build Coastguard Worker printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString());
111*5e7646d2SAndroid Build Coastguard Worker return (NULL);
112*5e7646d2SAndroid Build Coastguard Worker }
113*5e7646d2SAndroid Build Coastguard Worker
114*5e7646d2SAndroid Build Coastguard Worker printf("\n%s:\n", dest->name);
115*5e7646d2SAndroid Build Coastguard Worker
116*5e7646d2SAndroid Build Coastguard Worker show_supported(http, dest, dinfo, NULL, NULL);
117*5e7646d2SAndroid Build Coastguard Worker
118*5e7646d2SAndroid Build Coastguard Worker return (NULL);
119*5e7646d2SAndroid Build Coastguard Worker }
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker /*
124*5e7646d2SAndroid Build Coastguard Worker * 'show_supported()' - Show supported options, values, etc.
125*5e7646d2SAndroid Build Coastguard Worker */
126*5e7646d2SAndroid Build Coastguard Worker
127*5e7646d2SAndroid Build Coastguard Worker static void
show_supported(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * option,const char * value)128*5e7646d2SAndroid Build Coastguard Worker show_supported(http_t *http, /* I - Connection to destination */
129*5e7646d2SAndroid Build Coastguard Worker cups_dest_t *dest, /* I - Destination */
130*5e7646d2SAndroid Build Coastguard Worker cups_dinfo_t *dinfo, /* I - Destination information */
131*5e7646d2SAndroid Build Coastguard Worker const char *option, /* I - Option, if any */
132*5e7646d2SAndroid Build Coastguard Worker const char *value) /* I - Value, if any */
133*5e7646d2SAndroid Build Coastguard Worker {
134*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute */
135*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
136*5e7646d2SAndroid Build Coastguard Worker count; /* Number of values */
137*5e7646d2SAndroid Build Coastguard Worker
138*5e7646d2SAndroid Build Coastguard Worker
139*5e7646d2SAndroid Build Coastguard Worker if (!option)
140*5e7646d2SAndroid Build Coastguard Worker {
141*5e7646d2SAndroid Build Coastguard Worker attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
142*5e7646d2SAndroid Build Coastguard Worker if (attr)
143*5e7646d2SAndroid Build Coastguard Worker {
144*5e7646d2SAndroid Build Coastguard Worker count = ippGetCount(attr);
145*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
146*5e7646d2SAndroid Build Coastguard Worker show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
147*5e7646d2SAndroid Build Coastguard Worker }
148*5e7646d2SAndroid Build Coastguard Worker else
149*5e7646d2SAndroid Build Coastguard Worker {
150*5e7646d2SAndroid Build Coastguard Worker static const char * const options[] =
151*5e7646d2SAndroid Build Coastguard Worker { /* List of standard options */
152*5e7646d2SAndroid Build Coastguard Worker CUPS_COPIES,
153*5e7646d2SAndroid Build Coastguard Worker CUPS_FINISHINGS,
154*5e7646d2SAndroid Build Coastguard Worker CUPS_MEDIA,
155*5e7646d2SAndroid Build Coastguard Worker CUPS_NUMBER_UP,
156*5e7646d2SAndroid Build Coastguard Worker CUPS_ORIENTATION,
157*5e7646d2SAndroid Build Coastguard Worker CUPS_PRINT_COLOR_MODE,
158*5e7646d2SAndroid Build Coastguard Worker CUPS_PRINT_QUALITY,
159*5e7646d2SAndroid Build Coastguard Worker CUPS_SIDES
160*5e7646d2SAndroid Build Coastguard Worker };
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker puts(" No job-creation-attributes-supported attribute, probing instead.");
163*5e7646d2SAndroid Build Coastguard Worker
164*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++)
165*5e7646d2SAndroid Build Coastguard Worker if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL))
166*5e7646d2SAndroid Build Coastguard Worker show_supported(http, dest, dinfo, options[i], NULL);
167*5e7646d2SAndroid Build Coastguard Worker }
168*5e7646d2SAndroid Build Coastguard Worker }
169*5e7646d2SAndroid Build Coastguard Worker else if (!value)
170*5e7646d2SAndroid Build Coastguard Worker {
171*5e7646d2SAndroid Build Coastguard Worker printf(" %s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported");
172*5e7646d2SAndroid Build Coastguard Worker
173*5e7646d2SAndroid Build Coastguard Worker if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
174*5e7646d2SAndroid Build Coastguard Worker {
175*5e7646d2SAndroid Build Coastguard Worker count = ippGetCount(attr);
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker switch (ippGetValueTag(attr))
178*5e7646d2SAndroid Build Coastguard Worker {
179*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_INTEGER :
180*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
181*5e7646d2SAndroid Build Coastguard Worker printf(" %d\n", ippGetInteger(attr, i));
182*5e7646d2SAndroid Build Coastguard Worker break;
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_ENUM :
185*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
186*5e7646d2SAndroid Build Coastguard Worker {
187*5e7646d2SAndroid Build Coastguard Worker int val = ippGetInteger(attr, i);
188*5e7646d2SAndroid Build Coastguard Worker char valstr[256];
189*5e7646d2SAndroid Build Coastguard Worker
190*5e7646d2SAndroid Build Coastguard Worker snprintf(valstr, sizeof(valstr), "%d", val);
191*5e7646d2SAndroid Build Coastguard Worker printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr));
192*5e7646d2SAndroid Build Coastguard Worker }
193*5e7646d2SAndroid Build Coastguard Worker break;
194*5e7646d2SAndroid Build Coastguard Worker
195*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RANGE :
196*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
197*5e7646d2SAndroid Build Coastguard Worker {
198*5e7646d2SAndroid Build Coastguard Worker int upper, lower = ippGetRange(attr, i, &upper);
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker printf(" %d-%d\n", lower, upper);
201*5e7646d2SAndroid Build Coastguard Worker }
202*5e7646d2SAndroid Build Coastguard Worker break;
203*5e7646d2SAndroid Build Coastguard Worker
204*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RESOLUTION :
205*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
206*5e7646d2SAndroid Build Coastguard Worker {
207*5e7646d2SAndroid Build Coastguard Worker int xres, yres;
208*5e7646d2SAndroid Build Coastguard Worker ipp_res_t units;
209*5e7646d2SAndroid Build Coastguard Worker xres = ippGetResolution(attr, i, &yres, &units);
210*5e7646d2SAndroid Build Coastguard Worker
211*5e7646d2SAndroid Build Coastguard Worker if (xres == yres)
212*5e7646d2SAndroid Build Coastguard Worker printf(" %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
213*5e7646d2SAndroid Build Coastguard Worker else
214*5e7646d2SAndroid Build Coastguard Worker printf(" %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
215*5e7646d2SAndroid Build Coastguard Worker }
216*5e7646d2SAndroid Build Coastguard Worker break;
217*5e7646d2SAndroid Build Coastguard Worker
218*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_KEYWORD :
219*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
220*5e7646d2SAndroid Build Coastguard Worker printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL)));
221*5e7646d2SAndroid Build Coastguard Worker break;
222*5e7646d2SAndroid Build Coastguard Worker
223*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_TEXTLANG :
224*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NAMELANG :
225*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_TEXT :
226*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NAME :
227*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_URI :
228*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_URISCHEME :
229*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_CHARSET :
230*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_LANGUAGE :
231*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_MIMETYPE :
232*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
233*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", ippGetString(attr, i, NULL));
234*5e7646d2SAndroid Build Coastguard Worker break;
235*5e7646d2SAndroid Build Coastguard Worker
236*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_STRING :
237*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < count; i ++)
238*5e7646d2SAndroid Build Coastguard Worker {
239*5e7646d2SAndroid Build Coastguard Worker int j, len;
240*5e7646d2SAndroid Build Coastguard Worker unsigned char *data = ippGetOctetString(attr, i, &len);
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker fputs(" ", stdout);
243*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < len; j ++)
244*5e7646d2SAndroid Build Coastguard Worker {
245*5e7646d2SAndroid Build Coastguard Worker if (data[j] < ' ' || data[j] >= 0x7f)
246*5e7646d2SAndroid Build Coastguard Worker printf("<%02X>", data[j]);
247*5e7646d2SAndroid Build Coastguard Worker else
248*5e7646d2SAndroid Build Coastguard Worker putchar(data[j]);
249*5e7646d2SAndroid Build Coastguard Worker }
250*5e7646d2SAndroid Build Coastguard Worker putchar('\n');
251*5e7646d2SAndroid Build Coastguard Worker }
252*5e7646d2SAndroid Build Coastguard Worker break;
253*5e7646d2SAndroid Build Coastguard Worker
254*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_BOOLEAN :
255*5e7646d2SAndroid Build Coastguard Worker break;
256*5e7646d2SAndroid Build Coastguard Worker
257*5e7646d2SAndroid Build Coastguard Worker default :
258*5e7646d2SAndroid Build Coastguard Worker printf(" %s\n", ippTagString(ippGetValueTag(attr)));
259*5e7646d2SAndroid Build Coastguard Worker break;
260*5e7646d2SAndroid Build Coastguard Worker }
261*5e7646d2SAndroid Build Coastguard Worker }
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker }
264*5e7646d2SAndroid Build Coastguard Worker else if (cupsCheckDestSupported(http, dest, dinfo, option, value))
265*5e7646d2SAndroid Build Coastguard Worker puts("YES");
266*5e7646d2SAndroid Build Coastguard Worker else
267*5e7646d2SAndroid Build Coastguard Worker puts("NO");
268*5e7646d2SAndroid Build Coastguard Worker }
269