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