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