]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
503b54c9 | 2 | * "lpinfo" command for CUPS. |
ef416fc2 | 3 | * |
bdbfacc7 | 4 | * Copyright 2007-2016 by Apple Inc. |
503b54c9 | 5 | * Copyright 1997-2006 by Easy Software Products. |
ef416fc2 | 6 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 8 | */ |
9 | ||
10 | /* | |
11 | * Include necessary headers... | |
12 | */ | |
13 | ||
71e16022 | 14 | #include <cups/cups-private.h> |
68c4690a | 15 | #include <cups/adminutil.h> |
ef416fc2 | 16 | |
17 | ||
18 | /* | |
19 | * Local functions... | |
20 | */ | |
21 | ||
ae71f5de MS |
22 | static void device_cb(const char *device_clas, const char *device_id, |
23 | const char *device_info, | |
24 | const char *device_make_and_model, | |
749b1e90 MS |
25 | const char *device_uri, const char *device_location, |
26 | void *user_data); | |
ed6e7faf MS |
27 | static int show_devices(int long_status, int timeout, |
28 | const char *include_schemes, | |
29 | const char *exclude_schemes); | |
30 | static int show_models(int long_status, | |
58dc1933 | 31 | const char *device_id, const char *language, |
ed6e7faf MS |
32 | const char *make_model, const char *product, |
33 | const char *include_schemes, | |
34 | const char *exclude_schemes); | |
ef416fc2 | 35 | |
36 | ||
37 | /* | |
38 | * 'main()' - Parse options and show status information. | |
39 | */ | |
40 | ||
41 | int | |
42 | main(int argc, /* I - Number of command-line arguments */ | |
43 | char *argv[]) /* I - Command-line arguments */ | |
44 | { | |
45 | int i; /* Looping var */ | |
ef416fc2 | 46 | int long_status; /* Long listing? */ |
bdbfacc7 MS |
47 | const char *opt, /* Option pointer */ |
48 | *device_id, /* 1284 device ID */ | |
58dc1933 MS |
49 | *language, /* Language */ |
50 | *make_model, /* Make and model */ | |
ed6e7faf MS |
51 | *product, /* Product */ |
52 | *include_schemes, /* Schemes to include */ | |
53 | *exclude_schemes; /* Schemes to exclude */ | |
58dc1933 | 54 | int timeout; /* Device timeout */ |
ef416fc2 | 55 | |
56 | ||
07725fee | 57 | _cupsSetLocale(argv); |
d09495fa | 58 | |
ed6e7faf MS |
59 | long_status = 0; |
60 | device_id = NULL; | |
61 | language = NULL; | |
62 | make_model = NULL; | |
63 | product = NULL; | |
64 | include_schemes = CUPS_INCLUDE_ALL; | |
65 | exclude_schemes = CUPS_EXCLUDE_NONE; | |
66 | timeout = CUPS_TIMEOUT_DEFAULT; | |
ef416fc2 | 67 | |
68 | for (i = 1; i < argc; i ++) | |
bdbfacc7 MS |
69 | { |
70 | if (!strcmp(argv[i], "--device-id")) | |
71 | { | |
72 | i ++; | |
73 | ||
74 | if (i < argc) | |
75 | device_id = argv[i]; | |
76 | else | |
77 | { | |
78 | _cupsLangPuts(stderr, _("lpinfo: Expected 1284 device ID string after \"--device-id\".")); | |
79 | return (1); | |
80 | } | |
81 | } | |
82 | else if (!strncmp(argv[i], "--device-id=", 12) && argv[i][12]) | |
83 | { | |
84 | device_id = argv[i] + 12; | |
85 | } | |
86 | else if (!strcmp(argv[i], "--exclude-schemes")) | |
87 | { | |
88 | i ++; | |
89 | ||
90 | if (i < argc) | |
91 | exclude_schemes = argv[i]; | |
92 | else | |
93 | { | |
94 | _cupsLangPuts(stderr, _("lpinfo: Expected scheme list after \"--exclude-schemes\".")); | |
95 | return (1); | |
96 | } | |
97 | } | |
98 | else if (!strncmp(argv[i], "--exclude-schemes=", 18) && argv[i][18]) | |
99 | { | |
100 | exclude_schemes = argv[i] + 18; | |
101 | } | |
102 | else if (!strcmp(argv[i], "--include-schemes")) | |
103 | { | |
104 | i ++; | |
105 | ||
106 | if (i < argc) | |
107 | include_schemes = argv[i]; | |
108 | else | |
ef416fc2 | 109 | { |
bdbfacc7 MS |
110 | _cupsLangPuts(stderr, _("lpinfo: Expected scheme list after \"--include-schemes\".")); |
111 | return (1); | |
112 | } | |
113 | } | |
114 | else if (!strncmp(argv[i], "--include-schemes=", 18) && argv[i][18]) | |
115 | { | |
116 | include_schemes = argv[i] + 18; | |
117 | } | |
118 | else if (!strcmp(argv[i], "--language")) | |
119 | { | |
120 | i ++; | |
121 | if (i < argc) | |
122 | language = argv[i]; | |
123 | else | |
124 | { | |
125 | _cupsLangPuts(stderr, _("lpinfo: Expected language after \"--language\".")); | |
126 | return (1); | |
127 | } | |
128 | } | |
129 | else if (!strncmp(argv[i], "--language=", 11) && argv[i][11]) | |
130 | { | |
131 | language = argv[i] + 11; | |
132 | } | |
133 | else if (!strcmp(argv[i], "--make-and-model")) | |
134 | { | |
135 | i ++; | |
136 | if (i < argc) | |
137 | make_model= argv[i]; | |
138 | else | |
139 | { | |
140 | _cupsLangPuts(stderr, _("lpinfo: Expected make and model after \"--make-and-model\".")); | |
141 | return (1); | |
142 | } | |
143 | } | |
144 | else if (!strncmp(argv[i], "--make-and-model=", 17) && argv[i][17]) | |
145 | { | |
146 | make_model = argv[i] + 17; | |
147 | } | |
148 | else if (!strcmp(argv[i], "--product")) | |
149 | { | |
150 | i ++; | |
151 | if (i < argc) | |
152 | product = argv[i]; | |
153 | else | |
154 | { | |
155 | _cupsLangPuts(stderr, _("lpinfo: Expected product string after \"--product\".")); | |
156 | return (1); | |
157 | } | |
158 | } | |
159 | else if (!strncmp(argv[i], "--product=", 10) && argv[i][10]) | |
160 | { | |
161 | product = argv[i] + 10; | |
162 | } | |
163 | else if (!strcmp(argv[i], "--timeout")) | |
164 | { | |
165 | i ++; | |
166 | if (i < argc) | |
167 | timeout = atoi(argv[i]); | |
168 | else | |
169 | { | |
170 | _cupsLangPuts(stderr, _("lpinfo: Expected timeout after \"--timeout\".")); | |
171 | return (1); | |
172 | } | |
173 | } | |
174 | else if (!strncmp(argv[i], "--timeout=", 10) && argv[i][10]) | |
175 | { | |
176 | timeout = atoi(argv[i] + 10); | |
177 | } | |
178 | else if (argv[i][0] == '-') | |
179 | { | |
180 | for (opt = argv[i] + 1; *opt; opt ++) | |
181 | { | |
182 | switch (*opt) | |
183 | { | |
184 | case 'E' : /* Encrypt */ | |
ef416fc2 | 185 | #ifdef HAVE_SSL |
bdbfacc7 | 186 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); |
ef416fc2 | 187 | #else |
bdbfacc7 | 188 | _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); |
ef416fc2 | 189 | #endif /* HAVE_SSL */ |
bdbfacc7 | 190 | break; |
58dc1933 | 191 | |
bdbfacc7 MS |
192 | case 'h' : /* Connect to host */ |
193 | if (opt[1] != '\0') | |
58dc1933 | 194 | { |
bdbfacc7 MS |
195 | cupsSetServer(opt + 1); |
196 | opt += strlen(opt) - 1; | |
58dc1933 | 197 | } |
ed6e7faf MS |
198 | else |
199 | { | |
bdbfacc7 | 200 | i ++; |
ed6e7faf | 201 | |
bdbfacc7 MS |
202 | if (i >= argc) |
203 | { | |
204 | _cupsLangPuts(stderr, _("Error: need hostname after \"-h\" option.")); | |
205 | return (1); | |
206 | } | |
207 | ||
208 | cupsSetServer(argv[i]); | |
58dc1933 | 209 | } |
bdbfacc7 MS |
210 | break; |
211 | ||
212 | case 'l' : /* Show long listing */ | |
213 | long_status = 1; | |
214 | break; | |
215 | ||
216 | case 'm' : /* Show models */ | |
217 | if (show_models(long_status, device_id, language, make_model, product, include_schemes, exclude_schemes)) | |
58dc1933 | 218 | return (1); |
bdbfacc7 | 219 | break; |
57b7b66b | 220 | |
bdbfacc7 MS |
221 | case 'v' : /* Show available devices */ |
222 | if (show_devices(long_status, timeout, include_schemes, exclude_schemes)) | |
58dc1933 | 223 | return (1); |
bdbfacc7 | 224 | break; |
ef416fc2 | 225 | |
bdbfacc7 MS |
226 | default : |
227 | _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), argv[0], *opt); | |
228 | return (1); | |
229 | } | |
ef416fc2 | 230 | } |
bdbfacc7 | 231 | } |
ef416fc2 | 232 | else |
233 | { | |
bdbfacc7 | 234 | _cupsLangPrintf(stderr, _("%s: Unknown argument \"%s\"."), argv[0], argv[i]); |
ef416fc2 | 235 | return (1); |
236 | } | |
bdbfacc7 | 237 | } |
ef416fc2 | 238 | |
239 | return (0); | |
240 | } | |
241 | ||
242 | ||
243 | /* | |
ae71f5de | 244 | * 'device_cb()' - Device callback. |
ef416fc2 | 245 | */ |
246 | ||
ae71f5de MS |
247 | static void |
248 | device_cb( | |
249 | const char *device_class, /* I - device-class string */ | |
250 | const char *device_id, /* I - device-id string */ | |
251 | const char *device_info, /* I - device-info string */ | |
252 | const char *device_make_and_model, /* I - device-make-and-model string */ | |
253 | const char *device_uri, /* I - device-uri string */ | |
749b1e90 | 254 | const char *device_location, /* I - device-location string */ |
ae71f5de | 255 | void *user_data) /* I - User data */ |
ef416fc2 | 256 | { |
ae71f5de | 257 | int *long_status; /* Show verbose info? */ |
ef416fc2 | 258 | |
ef416fc2 | 259 | |
260 | /* | |
ae71f5de | 261 | * Display the device... |
ef416fc2 | 262 | */ |
263 | ||
ae71f5de | 264 | long_status = (int *)user_data; |
ef416fc2 | 265 | |
ae71f5de | 266 | if (*long_status) |
ef416fc2 | 267 | { |
ae71f5de MS |
268 | _cupsLangPrintf(stdout, |
269 | _("Device: uri = %s\n" | |
270 | " class = %s\n" | |
271 | " info = %s\n" | |
272 | " make-and-model = %s\n" | |
749b1e90 | 273 | " device-id = %s\n" |
0837b7e8 | 274 | " location = %s"), |
ae71f5de | 275 | device_uri, device_class, device_info, |
749b1e90 | 276 | device_make_and_model, device_id, device_location); |
ae71f5de MS |
277 | } |
278 | else | |
0837b7e8 | 279 | _cupsLangPrintf(stdout, "%s %s", device_class, device_uri); |
ae71f5de | 280 | } |
ef416fc2 | 281 | |
ef416fc2 | 282 | |
ae71f5de MS |
283 | /* |
284 | * 'show_devices()' - Show available devices. | |
285 | */ | |
ef416fc2 | 286 | |
ae71f5de | 287 | static int /* O - 0 on success, 1 on failure */ |
ed6e7faf MS |
288 | show_devices( |
289 | int long_status, /* I - Long status report? */ | |
290 | int timeout, /* I - Timeout */ | |
291 | const char *include_schemes, /* I - List of schemes to include */ | |
292 | const char *exclude_schemes) /* I - List of schemes to exclude */ | |
ae71f5de | 293 | { |
ed6e7faf MS |
294 | if (cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include_schemes, |
295 | exclude_schemes, device_cb, &long_status) != IPP_OK) | |
ef416fc2 | 296 | { |
0837b7e8 | 297 | _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); |
ef416fc2 | 298 | return (1); |
299 | } | |
300 | ||
301 | return (0); | |
302 | } | |
303 | ||
304 | ||
305 | /* | |
306 | * 'show_models()' - Show available PPDs. | |
307 | */ | |
308 | ||
309 | static int /* O - 0 on success, 1 on failure */ | |
ed6e7faf MS |
310 | show_models( |
311 | int long_status, /* I - Long status report? */ | |
312 | const char *device_id, /* I - 1284 device ID */ | |
313 | const char *language, /* I - Language */ | |
314 | const char *make_model, /* I - Make and model */ | |
315 | const char *product, /* I - Product */ | |
316 | const char *include_schemes, /* I - List of schemes to include */ | |
317 | const char *exclude_schemes) /* I - List of schemes to exclude */ | |
ef416fc2 | 318 | { |
319 | ipp_t *request, /* IPP Request */ | |
320 | *response; /* IPP Response */ | |
321 | ipp_attribute_t *attr; /* Current attribute */ | |
fa73b229 | 322 | const char *ppd_device_id, /* Pointer to ppd-device-id */ |
323 | *ppd_language, /* Pointer to ppd-natural-language */ | |
58dc1933 | 324 | *ppd_make_model, /* Pointer to ppd-make-and-model */ |
fa73b229 | 325 | *ppd_name; /* Pointer to ppd-name */ |
ed6e7faf | 326 | cups_option_t option; /* in/exclude-schemes option */ |
ef416fc2 | 327 | |
328 | ||
ef416fc2 | 329 | /* |
58dc1933 | 330 | * Build a CUPS_GET_PPDS request... |
ef416fc2 | 331 | */ |
332 | ||
fa73b229 | 333 | request = ippNewRequest(CUPS_GET_PPDS); |
ef416fc2 | 334 | |
58dc1933 MS |
335 | if (device_id) |
336 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id", | |
337 | NULL, device_id); | |
338 | if (language) | |
339 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "ppd-language", | |
340 | NULL, language); | |
341 | if (make_model) | |
342 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model", | |
343 | NULL, make_model); | |
344 | if (product) | |
345 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-product", | |
346 | NULL, product); | |
347 | ||
ed6e7faf MS |
348 | if (include_schemes) |
349 | { | |
350 | option.name = "include-schemes"; | |
351 | option.value = (char *)include_schemes; | |
352 | ||
353 | cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); | |
354 | } | |
355 | ||
356 | if (exclude_schemes) | |
357 | { | |
358 | option.name = "exclude-schemes"; | |
359 | option.value = (char *)exclude_schemes; | |
360 | ||
361 | cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); | |
362 | } | |
363 | ||
ef416fc2 | 364 | /* |
365 | * Do the request and get back a response... | |
366 | */ | |
367 | ||
ed6e7faf | 368 | if ((response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL) |
ef416fc2 | 369 | { |
370 | /* | |
371 | * Loop through the device list and display them... | |
372 | */ | |
373 | ||
374 | if (response->request.status.status_code > IPP_OK_CONFLICT) | |
375 | { | |
0837b7e8 | 376 | _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); |
ef416fc2 | 377 | ippDelete(response); |
378 | return (1); | |
379 | } | |
380 | ||
381 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
382 | { | |
383 | /* | |
384 | * Skip leading attributes until we hit a PPD... | |
385 | */ | |
386 | ||
387 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
388 | attr = attr->next; | |
389 | ||
390 | if (attr == NULL) | |
391 | break; | |
392 | ||
393 | /* | |
394 | * Pull the needed attributes from this PPD... | |
395 | */ | |
396 | ||
58dc1933 MS |
397 | ppd_device_id = "NONE"; |
398 | ppd_language = NULL; | |
399 | ppd_make_model = NULL; | |
400 | ppd_name = NULL; | |
ef416fc2 | 401 | |
402 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
403 | { | |
fa73b229 | 404 | if (!strcmp(attr->name, "ppd-device-id") && |
ef416fc2 | 405 | attr->value_tag == IPP_TAG_TEXT) |
fa73b229 | 406 | ppd_device_id = attr->values[0].string.text; |
407 | else if (!strcmp(attr->name, "ppd-natural-language") && | |
408 | attr->value_tag == IPP_TAG_LANGUAGE) | |
409 | ppd_language = attr->values[0].string.text; | |
410 | else if (!strcmp(attr->name, "ppd-make-and-model") && | |
411 | attr->value_tag == IPP_TAG_TEXT) | |
58dc1933 | 412 | ppd_make_model = attr->values[0].string.text; |
fa73b229 | 413 | else if (!strcmp(attr->name, "ppd-name") && |
414 | attr->value_tag == IPP_TAG_NAME) | |
ef416fc2 | 415 | ppd_name = attr->values[0].string.text; |
416 | ||
417 | attr = attr->next; | |
418 | } | |
419 | ||
420 | /* | |
421 | * See if we have everything needed... | |
422 | */ | |
423 | ||
58dc1933 | 424 | if (ppd_language == NULL || ppd_make_model == NULL || ppd_name == NULL) |
ef416fc2 | 425 | { |
426 | if (attr == NULL) | |
427 | break; | |
428 | else | |
429 | continue; | |
430 | } | |
431 | ||
432 | /* | |
433 | * Display the device... | |
434 | */ | |
435 | ||
436 | if (long_status) | |
437 | { | |
fa73b229 | 438 | _cupsLangPrintf(stdout, |
ef416fc2 | 439 | _("Model: name = %s\n" |
440 | " natural_language = %s\n" | |
fa73b229 | 441 | " make-and-model = %s\n" |
0837b7e8 | 442 | " device-id = %s"), |
58dc1933 | 443 | ppd_name, ppd_language, ppd_make_model, ppd_device_id); |
ef416fc2 | 444 | } |
445 | else | |
0837b7e8 | 446 | _cupsLangPrintf(stdout, "%s %s", ppd_name, ppd_make_model); |
ef416fc2 | 447 | |
448 | if (attr == NULL) | |
449 | break; | |
450 | } | |
451 | ||
452 | ippDelete(response); | |
453 | } | |
454 | else | |
455 | { | |
0837b7e8 | 456 | _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); |
ef416fc2 | 457 | |
458 | return (1); | |
459 | } | |
460 | ||
461 | return (0); | |
462 | } |