]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
5a1d7a17 | 2 | * "lpstat" command for CUPS. |
ef416fc2 | 3 | * |
bdbfacc7 | 4 | * Copyright 2007-2016 by Apple Inc. |
5a1d7a17 | 5 | * Copyright 1997-2006 by Easy Software Products. |
ef416fc2 | 6 | * |
5a1d7a17 MS |
7 | * These coded instructions, statements, and computer programs are the |
8 | * property of Apple Inc. and are protected by Federal copyright | |
9 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
10 | * which should have been included with this file. If this file is | |
57b7b66b | 11 | * missing or damaged, see the license at "http://www.cups.org/". |
ef416fc2 | 12 | */ |
13 | ||
14 | /* | |
15 | * Include necessary headers... | |
16 | */ | |
17 | ||
71e16022 | 18 | #include <cups/cups-private.h> |
ef416fc2 | 19 | |
20 | ||
21 | /* | |
22 | * Local functions... | |
23 | */ | |
24 | ||
61cf44e2 MS |
25 | static void check_dest(const char *command, const char *name, |
26 | int *num_dests, cups_dest_t **dests); | |
27 | static int match_list(const char *list, const char *name); | |
28 | static int show_accepting(const char *printers, int num_dests, | |
29 | cups_dest_t *dests); | |
30 | static int show_classes(const char *dests); | |
31 | static void show_default(cups_dest_t *dest); | |
32 | static int show_devices(const char *printers, int num_dests, | |
33 | cups_dest_t *dests); | |
34 | static int show_jobs(const char *dests, const char *users, int long_status, | |
35 | int ranking, const char *which); | |
36 | static int show_printers(const char *printers, int num_dests, | |
37 | cups_dest_t *dests, int long_status); | |
38 | static void show_scheduler(void); | |
ef416fc2 | 39 | |
40 | ||
41 | /* | |
42 | * 'main()' - Parse options and show status information. | |
43 | */ | |
44 | ||
45 | int | |
ed486911 | 46 | main(int argc, /* I - Number of command-line arguments */ |
47 | char *argv[]) /* I - Command-line arguments */ | |
ef416fc2 | 48 | { |
ed486911 | 49 | int i, /* Looping var */ |
50 | status; /* Exit status */ | |
bdbfacc7 | 51 | char *opt; /* Option pointer */ |
ed486911 | 52 | int num_dests; /* Number of user destinations */ |
53 | cups_dest_t *dests; /* User destinations */ | |
54 | int long_status; /* Long status report? */ | |
55 | int ranking; /* Show job ranking? */ | |
56 | const char *which; /* Which jobs to show? */ | |
57 | char op; /* Last operation on command-line */ | |
ef416fc2 | 58 | |
59 | ||
07725fee | 60 | _cupsSetLocale(argv); |
ed486911 | 61 | |
ed486911 | 62 | /* |
63 | * Parse command-line options... | |
64 | */ | |
65 | ||
ef416fc2 | 66 | num_dests = 0; |
67 | dests = NULL; | |
68 | long_status = 0; | |
69 | ranking = 0; | |
70 | status = 0; | |
71 | which = "not-completed"; | |
72 | op = 0; | |
73 | ||
74 | for (i = 1; i < argc; i ++) | |
bdbfacc7 | 75 | { |
ef416fc2 | 76 | if (argv[i][0] == '-') |
bdbfacc7 MS |
77 | { |
78 | for (opt = argv[i] + 1; *opt; opt ++) | |
ef416fc2 | 79 | { |
bdbfacc7 MS |
80 | switch (argv[i][1]) |
81 | { | |
82 | case 'D' : /* Show description */ | |
83 | long_status = 1; | |
84 | break; | |
ef416fc2 | 85 | |
bdbfacc7 | 86 | case 'E' : /* Encrypt */ |
ef416fc2 | 87 | #ifdef HAVE_SSL |
bdbfacc7 | 88 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); |
ef416fc2 | 89 | #else |
bdbfacc7 MS |
90 | _cupsLangPrintf(stderr, |
91 | _("%s: Sorry, no encryption support."), | |
92 | argv[0]); | |
ef416fc2 | 93 | #endif /* HAVE_SSL */ |
bdbfacc7 MS |
94 | break; |
95 | ||
96 | case 'H' : /* Show server and port */ | |
97 | if (cupsServer()[0] == '/') | |
98 | _cupsLangPuts(stdout, cupsServer()); | |
99 | else | |
100 | _cupsLangPrintf(stdout, "%s:%d", cupsServer(), ippPort()); | |
101 | op = 'H'; | |
102 | break; | |
103 | ||
104 | case 'P' : /* Show paper types */ | |
105 | op = 'P'; | |
106 | break; | |
107 | ||
108 | case 'R' : /* Show ranking */ | |
109 | ranking = 1; | |
110 | break; | |
111 | ||
112 | case 'S' : /* Show charsets */ | |
113 | op = 'S'; | |
114 | if (!argv[i][2]) | |
115 | i ++; | |
116 | break; | |
117 | ||
118 | case 'U' : /* Username */ | |
119 | if (opt[1] != '\0') | |
fa73b229 | 120 | { |
bdbfacc7 MS |
121 | cupsSetUser(opt + 1); |
122 | opt += strlen(opt) - 1; | |
fa73b229 | 123 | } |
bdbfacc7 MS |
124 | else |
125 | { | |
126 | i ++; | |
127 | if (i >= argc) | |
128 | { | |
129 | _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]); | |
130 | return (1); | |
131 | } | |
fa73b229 | 132 | |
bdbfacc7 MS |
133 | cupsSetUser(argv[i]); |
134 | } | |
135 | break; | |
88f9aafc | 136 | |
bdbfacc7 MS |
137 | case 'W' : /* Show which jobs? */ |
138 | if (opt[1] != '\0') | |
139 | { | |
140 | which = opt + 1; | |
141 | opt += strlen(opt) - 1; | |
142 | } | |
143 | else | |
144 | { | |
145 | i ++; | |
146 | ||
147 | if (i >= argc) | |
148 | { | |
149 | _cupsLangPrintf(stderr, _("%s: Error - need \"completed\", \"not-completed\", or \"all\" after \"-W\" option."), argv[0]); | |
150 | return (1); | |
151 | } | |
ef416fc2 | 152 | |
bdbfacc7 MS |
153 | which = argv[i]; |
154 | } | |
155 | ||
156 | if (strcmp(which, "completed") && strcmp(which, "not-completed") && strcmp(which, "all")) | |
ef416fc2 | 157 | { |
bdbfacc7 | 158 | _cupsLangPrintf(stderr, _("%s: Error - need \"completed\", \"not-completed\", or \"all\" after \"-W\" option."), argv[0]); |
ef416fc2 | 159 | return (1); |
bdbfacc7 MS |
160 | } |
161 | break; | |
ef416fc2 | 162 | |
bdbfacc7 MS |
163 | case 'a' : /* Show acceptance status */ |
164 | op = 'a'; | |
ef416fc2 | 165 | |
bdbfacc7 MS |
166 | if (opt[1] != '\0') |
167 | { | |
168 | check_dest(argv[0], opt + 1, &num_dests, &dests); | |
169 | ||
170 | status |= show_accepting(opt + 1, num_dests, dests); | |
171 | opt += strlen(opt) - 1; | |
172 | } | |
173 | else if ((i + 1) < argc && argv[i + 1][0] != '-') | |
174 | { | |
175 | i ++; | |
176 | ||
177 | check_dest(argv[0], argv[i], &num_dests, &dests); | |
178 | ||
179 | status |= show_accepting(argv[i], num_dests, dests); | |
180 | } | |
181 | else | |
182 | { | |
183 | if (num_dests <= 1) | |
184 | { | |
185 | cupsFreeDests(num_dests, dests); | |
186 | num_dests = cupsGetDests(&dests); | |
187 | ||
188 | if (num_dests == 0 && (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
189 | { | |
190 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); | |
191 | return (1); | |
192 | } | |
193 | } | |
194 | ||
195 | status |= show_accepting(NULL, num_dests, dests); | |
196 | } | |
197 | break; | |
ef416fc2 | 198 | |
bdbfacc7 MS |
199 | case 'c' : /* Show classes and members */ |
200 | op = 'c'; | |
ef416fc2 | 201 | |
bdbfacc7 MS |
202 | if (opt[1] != '\0') |
203 | { | |
204 | check_dest(argv[0], opt + 1, &num_dests, &dests); | |
ef416fc2 | 205 | |
bdbfacc7 MS |
206 | status |= show_classes(opt + 1); |
207 | opt += strlen(opt) - 1; | |
208 | } | |
209 | else if ((i + 1) < argc && argv[i + 1][0] != '-') | |
210 | { | |
211 | i ++; | |
ef416fc2 | 212 | |
bdbfacc7 | 213 | check_dest(argv[0], argv[i], &num_dests, &dests); |
ef416fc2 | 214 | |
bdbfacc7 MS |
215 | status |= show_classes(argv[i]); |
216 | } | |
217 | else | |
218 | status |= show_classes(NULL); | |
219 | break; | |
220 | ||
221 | case 'd' : /* Show default destination */ | |
222 | op = 'd'; | |
223 | ||
224 | if (num_dests != 1 || !dests[0].is_default) | |
61cf44e2 | 225 | { |
bdbfacc7 MS |
226 | cupsFreeDests(num_dests, dests); |
227 | ||
228 | dests = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL); | |
229 | num_dests = dests ? 1 : 0; | |
c606bcae MS |
230 | |
231 | if (num_dests == 0 && | |
232 | (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
233 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
234 | { | |
bdbfacc7 | 235 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); |
c606bcae MS |
236 | return (1); |
237 | } | |
61cf44e2 | 238 | } |
ef416fc2 | 239 | |
bdbfacc7 MS |
240 | show_default(dests); |
241 | break; | |
ef416fc2 | 242 | |
bdbfacc7 MS |
243 | case 'f' : /* Show forms */ |
244 | op = 'f'; | |
245 | if (opt[1] != '\0') | |
246 | { | |
247 | opt += strlen(opt) - 1; | |
248 | } | |
249 | else | |
250 | { | |
251 | i ++; | |
252 | if (i >= argc) | |
253 | return (1); | |
254 | } | |
255 | break; | |
ef416fc2 | 256 | |
bdbfacc7 MS |
257 | case 'h' : /* Connect to host */ |
258 | if (opt[1] != '\0') | |
259 | { | |
260 | cupsSetServer(opt + 1); | |
261 | opt += strlen(opt) - 1; | |
262 | } | |
263 | else | |
264 | { | |
265 | i ++; | |
ef416fc2 | 266 | |
bdbfacc7 MS |
267 | if (i >= argc) |
268 | { | |
269 | _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), argv[0]); | |
270 | return (1); | |
271 | } | |
ef416fc2 | 272 | |
bdbfacc7 MS |
273 | cupsSetServer(argv[i]); |
274 | } | |
275 | break; | |
ef416fc2 | 276 | |
bdbfacc7 MS |
277 | case 'l' : /* Long status or long job status */ |
278 | long_status = 2; | |
279 | break; | |
ef416fc2 | 280 | |
bdbfacc7 MS |
281 | case 'o' : /* Show jobs by destination */ |
282 | op = 'o'; | |
c606bcae | 283 | |
bdbfacc7 | 284 | if (opt[1]) |
c606bcae | 285 | { |
bdbfacc7 MS |
286 | check_dest(argv[0], opt + 1, &num_dests, &dests); |
287 | ||
288 | status |= show_jobs(opt + 1, NULL, long_status, ranking, which); | |
289 | opt += strlen(opt) - 1; | |
c606bcae | 290 | } |
bdbfacc7 MS |
291 | else if ((i + 1) < argc && argv[i + 1][0] != '-') |
292 | { | |
293 | i ++; | |
61cf44e2 | 294 | |
bdbfacc7 | 295 | check_dest(argv[0], argv[i], &num_dests, &dests); |
ef416fc2 | 296 | |
bdbfacc7 MS |
297 | status |= show_jobs(argv[i], NULL, long_status, ranking, which); |
298 | } | |
299 | else | |
300 | status |= show_jobs(NULL, NULL, long_status, ranking, which); | |
301 | break; | |
ef416fc2 | 302 | |
bdbfacc7 MS |
303 | case 'p' : /* Show printers */ |
304 | op = 'p'; | |
ef416fc2 | 305 | |
bdbfacc7 | 306 | if (opt[1] != '\0') |
ef416fc2 | 307 | { |
bdbfacc7 | 308 | check_dest(argv[0], opt + 1, &num_dests, &dests); |
ef416fc2 | 309 | |
bdbfacc7 MS |
310 | status |= show_printers(opt + 1, num_dests, dests, |
311 | long_status); | |
312 | opt += strlen(opt) - 1; | |
313 | } | |
314 | else if ((i + 1) < argc && argv[i + 1][0] != '-') | |
315 | { | |
316 | i ++; | |
ef416fc2 | 317 | |
bdbfacc7 | 318 | check_dest(argv[0], argv[i], &num_dests, &dests); |
ef416fc2 | 319 | |
bdbfacc7 MS |
320 | status |= show_printers(argv[i], num_dests, dests, long_status); |
321 | } | |
322 | else | |
323 | { | |
324 | if (num_dests <= 1) | |
325 | { | |
326 | cupsFreeDests(num_dests, dests); | |
327 | num_dests = cupsGetDests(&dests); | |
328 | ||
329 | if (num_dests == 0 && | |
330 | (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
331 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
332 | { | |
333 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); | |
334 | return (1); | |
335 | } | |
336 | } | |
ef416fc2 | 337 | |
bdbfacc7 MS |
338 | status |= show_printers(NULL, num_dests, dests, long_status); |
339 | } | |
340 | break; | |
ef416fc2 | 341 | |
bdbfacc7 MS |
342 | case 'r' : /* Show scheduler status */ |
343 | op = 'r'; | |
ef416fc2 | 344 | |
bdbfacc7 MS |
345 | show_scheduler(); |
346 | break; | |
ef416fc2 | 347 | |
bdbfacc7 MS |
348 | case 's' : /* Show summary */ |
349 | op = 's'; | |
ef416fc2 | 350 | |
bdbfacc7 MS |
351 | if (num_dests <= 1) |
352 | { | |
353 | cupsFreeDests(num_dests, dests); | |
354 | num_dests = cupsGetDests(&dests); | |
ef416fc2 | 355 | |
bdbfacc7 MS |
356 | if (num_dests == 0 && |
357 | (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
358 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
359 | { | |
360 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); | |
361 | return (1); | |
362 | } | |
363 | } | |
ef416fc2 | 364 | |
bdbfacc7 MS |
365 | show_default(cupsGetDest(NULL, NULL, num_dests, dests)); |
366 | status |= show_classes(NULL); | |
367 | status |= show_devices(NULL, num_dests, dests); | |
368 | break; | |
ef416fc2 | 369 | |
bdbfacc7 MS |
370 | case 't' : /* Show all info */ |
371 | op = 't'; | |
ef416fc2 | 372 | |
bdbfacc7 | 373 | if (num_dests <= 1) |
61cf44e2 | 374 | { |
bdbfacc7 | 375 | cupsFreeDests(num_dests, dests); |
61cf44e2 | 376 | num_dests = cupsGetDests(&dests); |
c606bcae MS |
377 | |
378 | if (num_dests == 0 && | |
379 | (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
380 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
381 | { | |
bdbfacc7 | 382 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); |
c606bcae MS |
383 | return (1); |
384 | } | |
61cf44e2 | 385 | } |
ef416fc2 | 386 | |
bdbfacc7 MS |
387 | show_scheduler(); |
388 | show_default(cupsGetDest(NULL, NULL, num_dests, dests)); | |
389 | status |= show_classes(NULL); | |
390 | status |= show_devices(NULL, num_dests, dests); | |
391 | status |= show_accepting(NULL, num_dests, dests); | |
61cf44e2 | 392 | status |= show_printers(NULL, num_dests, dests, long_status); |
bdbfacc7 MS |
393 | status |= show_jobs(NULL, NULL, long_status, ranking, which); |
394 | break; | |
ef416fc2 | 395 | |
bdbfacc7 MS |
396 | case 'u' : /* Show jobs by user */ |
397 | op = 'u'; | |
c606bcae | 398 | |
bdbfacc7 | 399 | if (opt[1] != '\0') |
c606bcae | 400 | { |
bdbfacc7 MS |
401 | status |= show_jobs(NULL, opt + 1, long_status, ranking, which); |
402 | opt += strlen(opt) - 1; | |
c606bcae | 403 | } |
bdbfacc7 | 404 | else if ((i + 1) < argc && argv[i + 1][0] != '-') |
c606bcae | 405 | { |
bdbfacc7 MS |
406 | i ++; |
407 | status |= show_jobs(NULL, argv[i], long_status, ranking, which); | |
c606bcae | 408 | } |
bdbfacc7 MS |
409 | else |
410 | status |= show_jobs(NULL, NULL, long_status, ranking, which); | |
411 | break; | |
ef416fc2 | 412 | |
bdbfacc7 MS |
413 | case 'v' : /* Show printer devices */ |
414 | op = 'v'; | |
ef416fc2 | 415 | |
bdbfacc7 MS |
416 | if (opt[1] != '\0') |
417 | { | |
418 | check_dest(argv[0], opt + 1, &num_dests, &dests); | |
ef416fc2 | 419 | |
bdbfacc7 MS |
420 | status |= show_devices(opt + 1, num_dests, dests); |
421 | opt += strlen(opt) - 1; | |
422 | } | |
423 | else if ((i + 1) < argc && argv[i + 1][0] != '-') | |
424 | { | |
425 | i ++; | |
ef416fc2 | 426 | |
bdbfacc7 | 427 | check_dest(argv[0], argv[i], &num_dests, &dests); |
ef416fc2 | 428 | |
bdbfacc7 MS |
429 | status |= show_devices(argv[i], num_dests, dests); |
430 | } | |
431 | else | |
61cf44e2 | 432 | { |
bdbfacc7 | 433 | if (num_dests <= 1) |
c606bcae | 434 | { |
bdbfacc7 MS |
435 | cupsFreeDests(num_dests, dests); |
436 | num_dests = cupsGetDests(&dests); | |
437 | ||
438 | if (num_dests == 0 && | |
439 | (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
440 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)) | |
441 | { | |
442 | _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); | |
443 | return (1); | |
444 | } | |
c606bcae | 445 | } |
bdbfacc7 MS |
446 | |
447 | status |= show_devices(NULL, num_dests, dests); | |
61cf44e2 | 448 | } |
bdbfacc7 | 449 | break; |
ef416fc2 | 450 | |
bdbfacc7 MS |
451 | default : |
452 | _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], argv[i][1]); | |
453 | return (1); | |
454 | } | |
ef416fc2 | 455 | } |
bdbfacc7 | 456 | } |
ef416fc2 | 457 | else |
458 | { | |
61cf44e2 | 459 | status |= show_jobs(argv[i], NULL, long_status, ranking, which); |
ef416fc2 | 460 | op = 'o'; |
461 | } | |
bdbfacc7 | 462 | } |
ef416fc2 | 463 | |
464 | if (!op) | |
61cf44e2 | 465 | status |= show_jobs(NULL, cupsUser(), long_status, ranking, which); |
ef416fc2 | 466 | |
467 | return (status); | |
468 | } | |
469 | ||
470 | ||
471 | /* | |
472 | * 'check_dest()' - Verify that the named destination(s) exists. | |
473 | */ | |
474 | ||
475 | static void | |
fa73b229 | 476 | check_dest(const char *command, /* I - Command name */ |
61cf44e2 | 477 | const char *name, /* I - List of printer/class names */ |
ef416fc2 | 478 | int *num_dests, /* IO - Number of destinations */ |
479 | cups_dest_t **dests) /* IO - Destinations */ | |
480 | { | |
61cf44e2 MS |
481 | const char *dptr; /* Pointer into name */ |
482 | char *pptr, /* Pointer into printer */ | |
483 | printer[1024]; /* Current printer/class name */ | |
ef416fc2 | 484 | |
485 | ||
486 | /* | |
487 | * Load the destination list as necessary... | |
488 | */ | |
489 | ||
61cf44e2 MS |
490 | if (*num_dests <= 1) |
491 | { | |
492 | if (*num_dests) | |
493 | cupsFreeDests(*num_dests, *dests); | |
494 | ||
495 | if (strchr(name, ',')) | |
496 | *num_dests = cupsGetDests(dests); | |
497 | else | |
498 | { | |
499 | strlcpy(printer, name, sizeof(printer)); | |
500 | if ((pptr = strchr(printer, '/')) != NULL) | |
501 | *pptr++ = '\0'; | |
502 | ||
503 | if ((*dests = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, pptr)) == NULL) | |
504 | { | |
c606bcae MS |
505 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || |
506 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
507 | _cupsLangPrintf(stderr, | |
508 | _("%s: Error - add '/version=1.1' to server name."), | |
509 | command); | |
510 | else | |
511 | _cupsLangPrintf(stderr, | |
512 | _("%s: Invalid destination name in list \"%s\"."), | |
513 | command, name); | |
514 | ||
61cf44e2 MS |
515 | exit(1); |
516 | } | |
517 | else | |
518 | { | |
519 | *num_dests = 1; | |
520 | return; | |
521 | } | |
522 | } | |
523 | } | |
ef416fc2 | 524 | |
525 | /* | |
526 | * Scan the name string for printer/class name(s)... | |
527 | */ | |
528 | ||
88f9aafc | 529 | for (dptr = name; *dptr;) |
ef416fc2 | 530 | { |
531 | /* | |
532 | * Skip leading whitespace and commas... | |
533 | */ | |
534 | ||
535 | while (isspace(*dptr & 255) || *dptr == ',') | |
536 | dptr ++; | |
537 | ||
61cf44e2 | 538 | if (!*dptr) |
ef416fc2 | 539 | break; |
540 | ||
541 | /* | |
542 | * Extract a single destination name from the name string... | |
543 | */ | |
544 | ||
61cf44e2 | 545 | for (pptr = printer; !isspace(*dptr & 255) && *dptr != ',' && *dptr;) |
ef416fc2 | 546 | { |
68c4690a | 547 | if ((size_t)(pptr - printer) < (sizeof(printer) - 1)) |
ef416fc2 | 548 | *pptr++ = *dptr++; |
549 | else | |
550 | { | |
fa73b229 | 551 | _cupsLangPrintf(stderr, |
0837b7e8 | 552 | _("%s: Invalid destination name in list \"%s\"."), |
fa73b229 | 553 | command, name); |
ef416fc2 | 554 | exit(1); |
555 | } | |
556 | } | |
557 | ||
558 | *pptr = '\0'; | |
559 | ||
560 | /* | |
561 | * Check the destination... | |
562 | */ | |
563 | ||
61cf44e2 | 564 | if (!cupsGetDest(printer, NULL, *num_dests, *dests)) |
ef416fc2 | 565 | { |
c606bcae MS |
566 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || |
567 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
568 | _cupsLangPrintf(stderr, | |
569 | _("%s: Error - add '/version=1.1' to server name."), | |
570 | command); | |
571 | else | |
572 | _cupsLangPrintf(stderr, | |
573 | _("%s: Unknown destination \"%s\"."), command, printer); | |
574 | ||
ef416fc2 | 575 | exit(1); |
576 | } | |
577 | } | |
578 | } | |
579 | ||
580 | ||
581 | /* | |
61cf44e2 | 582 | * 'match_list()' - Match a name from a list of comma or space-separated names. |
ef416fc2 | 583 | */ |
584 | ||
61cf44e2 MS |
585 | static int /* O - 1 on match, 0 on no match */ |
586 | match_list(const char *list, /* I - List of names */ | |
587 | const char *name) /* I - Name to find */ | |
ef416fc2 | 588 | { |
61cf44e2 MS |
589 | const char *nameptr; /* Pointer into name */ |
590 | ||
591 | ||
592 | /* | |
cc754834 | 593 | * An empty list always matches... |
61cf44e2 MS |
594 | */ |
595 | ||
596 | if (!list || !*list) | |
cc754834 | 597 | return (1); |
61cf44e2 | 598 | |
a2326b5b MS |
599 | if (!name) |
600 | return (0); | |
601 | ||
61cf44e2 | 602 | while (*list) |
ef416fc2 | 603 | { |
61cf44e2 MS |
604 | /* |
605 | * Skip leading whitespace and commas... | |
606 | */ | |
ef416fc2 | 607 | |
61cf44e2 MS |
608 | while (isspace(*list & 255) || *list == ',') |
609 | list ++; | |
610 | ||
611 | if (!*list) | |
612 | break; | |
613 | ||
614 | /* | |
615 | * Compare names... | |
616 | */ | |
617 | ||
618 | for (nameptr = name; | |
619 | *nameptr && *list && tolower(*nameptr & 255) == tolower(*list & 255); | |
620 | nameptr ++, list ++); | |
621 | ||
622 | if (!*nameptr && (!*list || *list == ',' || isspace(*list & 255))) | |
623 | return (1); | |
624 | ||
625 | while (*list && !isspace(*list & 255) && *list != ',') | |
626 | list ++; | |
ef416fc2 | 627 | } |
628 | ||
61cf44e2 | 629 | return (0); |
ef416fc2 | 630 | } |
631 | ||
632 | ||
633 | /* | |
634 | * 'show_accepting()' - Show acceptance status. | |
635 | */ | |
636 | ||
637 | static int /* O - 0 on success, 1 on fail */ | |
61cf44e2 | 638 | show_accepting(const char *printers, /* I - Destinations */ |
ef416fc2 | 639 | int num_dests, /* I - Number of user-defined dests */ |
640 | cups_dest_t *dests) /* I - User-defined destinations */ | |
641 | { | |
642 | int i; /* Looping var */ | |
643 | ipp_t *request, /* IPP Request */ | |
644 | *response; /* IPP Response */ | |
645 | ipp_attribute_t *attr; /* Current attribute */ | |
646 | const char *printer, /* Printer name */ | |
647 | *message; /* Printer device URI */ | |
648 | int accepting; /* Accepting requests? */ | |
fa73b229 | 649 | time_t ptime; /* Printer state time */ |
fa73b229 | 650 | char printer_state_time[255];/* Printer state time */ |
ef416fc2 | 651 | static const char *pattrs[] = /* Attributes we need for printers... */ |
652 | { | |
653 | "printer-name", | |
fa73b229 | 654 | "printer-state-change-time", |
ef416fc2 | 655 | "printer-state-message", |
656 | "printer-is-accepting-jobs" | |
657 | }; | |
658 | ||
659 | ||
61cf44e2 | 660 | DEBUG_printf(("show_accepting(printers=\"%s\")\n", printers)); |
ef416fc2 | 661 | |
fa73b229 | 662 | if (printers != NULL && !strcmp(printers, "all")) |
ef416fc2 | 663 | printers = NULL; |
664 | ||
665 | /* | |
666 | * Build a CUPS_GET_PRINTERS request, which requires the following | |
667 | * attributes: | |
668 | * | |
669 | * attributes-charset | |
670 | * attributes-natural-language | |
671 | * requested-attributes | |
fa73b229 | 672 | * requesting-user-name |
ef416fc2 | 673 | */ |
674 | ||
675 | request = ippNewRequest(CUPS_GET_PRINTERS); | |
676 | ||
677 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
678 | "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), | |
679 | NULL, pattrs); | |
680 | ||
fa73b229 | 681 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
682 | NULL, cupsUser()); | |
683 | ||
ef416fc2 | 684 | /* |
685 | * Do the request and get back a response... | |
686 | */ | |
687 | ||
c606bcae MS |
688 | response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"); |
689 | ||
690 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
691 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
ef416fc2 | 692 | { |
c606bcae MS |
693 | _cupsLangPrintf(stderr, |
694 | _("%s: Error - add '/version=1.1' to server name."), | |
695 | "lpstat"); | |
696 | ippDelete(response); | |
697 | return (1); | |
698 | } | |
699 | else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) | |
700 | { | |
701 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); | |
702 | ippDelete(response); | |
703 | return (1); | |
704 | } | |
ef416fc2 | 705 | |
c606bcae MS |
706 | if (response) |
707 | { | |
708 | DEBUG_puts("show_accepting: request succeeded..."); | |
ef416fc2 | 709 | |
710 | /* | |
711 | * Loop through the printers returned in the list and display | |
712 | * their devices... | |
713 | */ | |
714 | ||
715 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
716 | { | |
717 | /* | |
718 | * Skip leading attributes until we hit a printer... | |
719 | */ | |
720 | ||
721 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
722 | attr = attr->next; | |
723 | ||
724 | if (attr == NULL) | |
725 | break; | |
726 | ||
727 | /* | |
728 | * Pull the needed attributes from this printer... | |
729 | */ | |
730 | ||
731 | printer = NULL; | |
732 | message = NULL; | |
733 | accepting = 1; | |
fa73b229 | 734 | ptime = 0; |
ef416fc2 | 735 | |
736 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
737 | { | |
738 | if (!strcmp(attr->name, "printer-name") && | |
739 | attr->value_tag == IPP_TAG_NAME) | |
740 | printer = attr->values[0].string.text; | |
fa73b229 | 741 | else if (!strcmp(attr->name, "printer-state-change-time") && |
742 | attr->value_tag == IPP_TAG_INTEGER) | |
743 | ptime = (time_t)attr->values[0].integer; | |
744 | else if (!strcmp(attr->name, "printer-state-message") && | |
745 | attr->value_tag == IPP_TAG_TEXT) | |
ef416fc2 | 746 | message = attr->values[0].string.text; |
fa73b229 | 747 | else if (!strcmp(attr->name, "printer-is-accepting-jobs") && |
748 | attr->value_tag == IPP_TAG_BOOLEAN) | |
ef416fc2 | 749 | accepting = attr->values[0].boolean; |
750 | ||
751 | attr = attr->next; | |
752 | } | |
753 | ||
754 | /* | |
755 | * See if we have everything needed... | |
756 | */ | |
757 | ||
758 | if (printer == NULL) | |
759 | { | |
760 | if (attr == NULL) | |
761 | break; | |
762 | else | |
763 | continue; | |
764 | } | |
765 | ||
ef416fc2 | 766 | /* |
767 | * Display the printer entry if needed... | |
768 | */ | |
769 | ||
61cf44e2 | 770 | if (match_list(printers, printer)) |
ef416fc2 | 771 | { |
554aa7b7 | 772 | _cupsStrDate(printer_state_time, sizeof(printer_state_time), ptime); |
fa73b229 | 773 | |
ef416fc2 | 774 | if (accepting) |
0837b7e8 | 775 | _cupsLangPrintf(stdout, _("%s accepting requests since %s"), |
fa73b229 | 776 | printer, printer_state_time); |
ef416fc2 | 777 | else |
0837b7e8 MS |
778 | { |
779 | _cupsLangPrintf(stdout, _("%s not accepting requests since %s -"), | |
780 | printer, printer_state_time); | |
781 | _cupsLangPrintf(stdout, _("\t%s"), | |
61cf44e2 MS |
782 | (message == NULL || !*message) ? |
783 | "reason unknown" : message); | |
0837b7e8 | 784 | } |
ef416fc2 | 785 | |
786 | for (i = 0; i < num_dests; i ++) | |
88f9aafc | 787 | if (!_cups_strcasecmp(dests[i].name, printer) && dests[i].instance) |
ef416fc2 | 788 | { |
789 | if (accepting) | |
0837b7e8 | 790 | _cupsLangPrintf(stdout, _("%s/%s accepting requests since %s"), |
fa73b229 | 791 | printer, dests[i].instance, printer_state_time); |
ef416fc2 | 792 | else |
0837b7e8 MS |
793 | { |
794 | _cupsLangPrintf(stdout, | |
795 | _("%s/%s not accepting requests since %s -"), | |
796 | printer, dests[i].instance, printer_state_time); | |
797 | _cupsLangPrintf(stdout, _("\t%s"), | |
61cf44e2 MS |
798 | (message == NULL || !*message) ? |
799 | "reason unknown" : message); | |
0837b7e8 | 800 | } |
ef416fc2 | 801 | } |
802 | } | |
803 | ||
804 | if (attr == NULL) | |
805 | break; | |
806 | } | |
807 | ||
808 | ippDelete(response); | |
809 | } | |
ef416fc2 | 810 | |
811 | return (0); | |
812 | } | |
813 | ||
814 | ||
815 | /* | |
816 | * 'show_classes()' - Show printer classes. | |
817 | */ | |
818 | ||
819 | static int /* O - 0 on success, 1 on fail */ | |
61cf44e2 | 820 | show_classes(const char *dests) /* I - Destinations */ |
ef416fc2 | 821 | { |
822 | int i; /* Looping var */ | |
823 | ipp_t *request, /* IPP Request */ | |
824 | *response, /* IPP Response */ | |
825 | *response2; /* IPP response from remote server */ | |
826 | http_t *http2; /* Remote server */ | |
827 | ipp_attribute_t *attr; /* Current attribute */ | |
828 | const char *printer, /* Printer class name */ | |
829 | *printer_uri; /* Printer class URI */ | |
830 | ipp_attribute_t *members; /* Printer members */ | |
831 | char method[HTTP_MAX_URI], /* Request method */ | |
832 | username[HTTP_MAX_URI], /* Username:password */ | |
833 | server[HTTP_MAX_URI], /* Server name */ | |
834 | resource[HTTP_MAX_URI]; /* Resource name */ | |
835 | int port; /* Port number */ | |
ef416fc2 | 836 | static const char *cattrs[] = /* Attributes we need for classes... */ |
837 | { | |
838 | "printer-name", | |
839 | "printer-uri-supported", | |
840 | "member-names" | |
841 | }; | |
842 | ||
843 | ||
61cf44e2 | 844 | DEBUG_printf(("show_classes(dests=\"%s\")\n", dests)); |
ef416fc2 | 845 | |
fa73b229 | 846 | if (dests != NULL && !strcmp(dests, "all")) |
ef416fc2 | 847 | dests = NULL; |
848 | ||
849 | /* | |
850 | * Build a CUPS_GET_CLASSES request, which requires the following | |
851 | * attributes: | |
852 | * | |
853 | * attributes-charset | |
854 | * attributes-natural-language | |
855 | * requested-attributes | |
fa73b229 | 856 | * requesting-user-name |
ef416fc2 | 857 | */ |
858 | ||
859 | request = ippNewRequest(CUPS_GET_CLASSES); | |
860 | ||
861 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
862 | "requested-attributes", sizeof(cattrs) / sizeof(cattrs[0]), | |
863 | NULL, cattrs); | |
864 | ||
fa73b229 | 865 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
866 | NULL, cupsUser()); | |
867 | ||
ef416fc2 | 868 | /* |
869 | * Do the request and get back a response... | |
870 | */ | |
871 | ||
c606bcae MS |
872 | response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"); |
873 | ||
874 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
875 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
876 | { | |
877 | _cupsLangPrintf(stderr, | |
878 | _("%s: Error - add '/version=1.1' to server name."), | |
879 | "lpstat"); | |
880 | ippDelete(response); | |
881 | return (1); | |
882 | } | |
883 | else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) | |
884 | { | |
885 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); | |
886 | ippDelete(response); | |
887 | return (1); | |
888 | } | |
889 | ||
890 | if (response) | |
ef416fc2 | 891 | { |
892 | DEBUG_puts("show_classes: request succeeded..."); | |
893 | ||
894 | if (response->request.status.status_code > IPP_OK_CONFLICT) | |
895 | { | |
0837b7e8 | 896 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); |
ef416fc2 | 897 | ippDelete(response); |
898 | return (1); | |
899 | } | |
900 | ||
901 | /* | |
902 | * Loop through the printers returned in the list and display | |
903 | * their devices... | |
904 | */ | |
905 | ||
906 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
907 | { | |
908 | /* | |
909 | * Skip leading attributes until we hit a job... | |
910 | */ | |
911 | ||
912 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
913 | attr = attr->next; | |
914 | ||
915 | if (attr == NULL) | |
916 | break; | |
917 | ||
918 | /* | |
919 | * Pull the needed attributes from this job... | |
920 | */ | |
921 | ||
922 | printer = NULL; | |
923 | printer_uri = NULL; | |
924 | members = NULL; | |
925 | ||
926 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
927 | { | |
928 | if (!strcmp(attr->name, "printer-name") && | |
929 | attr->value_tag == IPP_TAG_NAME) | |
930 | printer = attr->values[0].string.text; | |
931 | ||
932 | if (!strcmp(attr->name, "printer-uri-supported") && | |
933 | attr->value_tag == IPP_TAG_URI) | |
934 | printer_uri = attr->values[0].string.text; | |
935 | ||
936 | if (!strcmp(attr->name, "member-names") && | |
937 | attr->value_tag == IPP_TAG_NAME) | |
938 | members = attr; | |
939 | ||
940 | attr = attr->next; | |
941 | } | |
942 | ||
943 | /* | |
944 | * If this is a remote class, grab the class info from the | |
945 | * remote server... | |
946 | */ | |
947 | ||
948 | response2 = NULL; | |
949 | if (members == NULL && printer_uri != NULL) | |
950 | { | |
a4d04587 | 951 | httpSeparateURI(HTTP_URI_CODING_ALL, printer_uri, method, sizeof(method), |
ef416fc2 | 952 | username, sizeof(username), server, sizeof(server), |
953 | &port, resource, sizeof(resource)); | |
954 | ||
88f9aafc | 955 | if (!_cups_strcasecmp(server, cupsServer())) |
61cf44e2 | 956 | http2 = CUPS_HTTP_DEFAULT; |
ef416fc2 | 957 | else |
958 | http2 = httpConnectEncrypt(server, port, cupsEncryption()); | |
959 | ||
61cf44e2 MS |
960 | /* |
961 | * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the | |
962 | * following attributes: | |
963 | * | |
964 | * attributes-charset | |
965 | * attributes-natural-language | |
966 | * printer-uri | |
967 | * requested-attributes | |
968 | */ | |
ef416fc2 | 969 | |
61cf44e2 | 970 | request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); |
ef416fc2 | 971 | |
61cf44e2 MS |
972 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
973 | "printer-uri", NULL, printer_uri); | |
ef416fc2 | 974 | |
61cf44e2 MS |
975 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, |
976 | "requested-attributes", | |
977 | sizeof(cattrs) / sizeof(cattrs[0]), | |
978 | NULL, cattrs); | |
ef416fc2 | 979 | |
61cf44e2 MS |
980 | if ((response2 = cupsDoRequest(http2, request, "/")) != NULL) |
981 | members = ippFindAttribute(response2, "member-names", IPP_TAG_NAME); | |
ef416fc2 | 982 | |
61cf44e2 MS |
983 | if (http2) |
984 | httpClose(http2); | |
ef416fc2 | 985 | } |
986 | ||
987 | /* | |
988 | * See if we have everything needed... | |
989 | */ | |
990 | ||
991 | if (printer == NULL) | |
992 | { | |
993 | if (response2) | |
994 | ippDelete(response2); | |
995 | ||
996 | if (attr == NULL) | |
997 | break; | |
998 | else | |
999 | continue; | |
1000 | } | |
1001 | ||
ef416fc2 | 1002 | /* |
1003 | * Display the printer entry if needed... | |
1004 | */ | |
1005 | ||
61cf44e2 | 1006 | if (match_list(dests, printer)) |
ef416fc2 | 1007 | { |
0837b7e8 | 1008 | _cupsLangPrintf(stdout, _("members of class %s:"), printer); |
ef416fc2 | 1009 | |
1010 | if (members) | |
1011 | { | |
1012 | for (i = 0; i < members->num_values; i ++) | |
0837b7e8 | 1013 | _cupsLangPrintf(stdout, "\t%s", members->values[i].string.text); |
ef416fc2 | 1014 | } |
1015 | else | |
0837b7e8 | 1016 | _cupsLangPuts(stdout, "\tunknown"); |
ef416fc2 | 1017 | } |
1018 | ||
1019 | if (response2) | |
1020 | ippDelete(response2); | |
1021 | ||
1022 | if (attr == NULL) | |
1023 | break; | |
1024 | } | |
1025 | ||
1026 | ippDelete(response); | |
1027 | } | |
ef416fc2 | 1028 | |
1029 | return (0); | |
1030 | } | |
1031 | ||
1032 | ||
1033 | /* | |
1034 | * 'show_default()' - Show default destination. | |
1035 | */ | |
1036 | ||
1037 | static void | |
61cf44e2 | 1038 | show_default(cups_dest_t *dest) /* I - Default destination */ |
ef416fc2 | 1039 | { |
ef416fc2 | 1040 | const char *printer, /* Printer name */ |
1041 | *val; /* Environment variable name */ | |
1042 | ||
61cf44e2 MS |
1043 | |
1044 | if (dest) | |
ef416fc2 | 1045 | { |
1046 | if (dest->instance) | |
0837b7e8 | 1047 | _cupsLangPrintf(stdout, _("system default destination: %s/%s"), |
ef416fc2 | 1048 | dest->name, dest->instance); |
1049 | else | |
0837b7e8 | 1050 | _cupsLangPrintf(stdout, _("system default destination: %s"), |
ef416fc2 | 1051 | dest->name); |
1052 | } | |
1053 | else | |
1054 | { | |
1055 | val = NULL; | |
1056 | ||
1057 | if ((printer = getenv("LPDEST")) == NULL) | |
1058 | { | |
1059 | if ((printer = getenv("PRINTER")) != NULL) | |
1060 | { | |
1061 | if (!strcmp(printer, "lp")) | |
1062 | printer = NULL; | |
1063 | else | |
1064 | val = "PRINTER"; | |
1065 | } | |
1066 | } | |
1067 | else | |
1068 | val = "LPDEST"; | |
1069 | ||
61cf44e2 | 1070 | if (printer) |
fa73b229 | 1071 | _cupsLangPrintf(stdout, |
ef416fc2 | 1072 | _("lpstat: error - %s environment variable names " |
0837b7e8 | 1073 | "non-existent destination \"%s\"."), |
ef416fc2 | 1074 | val, printer); |
1075 | else | |
0837b7e8 | 1076 | _cupsLangPuts(stdout, _("no system default destination")); |
ef416fc2 | 1077 | } |
1078 | } | |
1079 | ||
1080 | ||
1081 | /* | |
1082 | * 'show_devices()' - Show printer devices. | |
1083 | */ | |
1084 | ||
1085 | static int /* O - 0 on success, 1 on fail */ | |
61cf44e2 | 1086 | show_devices(const char *printers, /* I - Destinations */ |
ef416fc2 | 1087 | int num_dests, /* I - Number of user-defined dests */ |
1088 | cups_dest_t *dests) /* I - User-defined destinations */ | |
1089 | { | |
1090 | int i; /* Looping var */ | |
1091 | ipp_t *request, /* IPP Request */ | |
1092 | *response; /* IPP Response */ | |
1093 | ipp_attribute_t *attr; /* Current attribute */ | |
1094 | const char *printer, /* Printer name */ | |
1095 | *uri, /* Printer URI */ | |
61cf44e2 | 1096 | *device; /* Printer device URI */ |
ef416fc2 | 1097 | static const char *pattrs[] = /* Attributes we need for printers... */ |
1098 | { | |
1099 | "printer-name", | |
1100 | "printer-uri-supported", | |
1101 | "device-uri" | |
1102 | }; | |
1103 | ||
1104 | ||
61cf44e2 | 1105 | DEBUG_printf(("show_devices(printers=\"%s\")\n", printers)); |
ef416fc2 | 1106 | |
fa73b229 | 1107 | if (printers != NULL && !strcmp(printers, "all")) |
ef416fc2 | 1108 | printers = NULL; |
1109 | ||
1110 | /* | |
1111 | * Build a CUPS_GET_PRINTERS request, which requires the following | |
1112 | * attributes: | |
1113 | * | |
1114 | * attributes-charset | |
1115 | * attributes-natural-language | |
1116 | * requested-attributes | |
fa73b229 | 1117 | * requesting-user-name |
ef416fc2 | 1118 | */ |
1119 | ||
1120 | request = ippNewRequest(CUPS_GET_PRINTERS); | |
1121 | ||
1122 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
1123 | "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), | |
1124 | NULL, pattrs); | |
1125 | ||
fa73b229 | 1126 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
1127 | NULL, cupsUser()); | |
1128 | ||
ef416fc2 | 1129 | /* |
1130 | * Do the request and get back a response... | |
1131 | */ | |
1132 | ||
c606bcae MS |
1133 | response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"); |
1134 | ||
1135 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
1136 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
ef416fc2 | 1137 | { |
c606bcae MS |
1138 | _cupsLangPrintf(stderr, |
1139 | _("%s: Error - add '/version=1.1' to server name."), | |
1140 | "lpstat"); | |
1141 | ippDelete(response); | |
1142 | return (1); | |
1143 | } | |
1144 | else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) | |
1145 | { | |
1146 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); | |
1147 | ippDelete(response); | |
1148 | return (1); | |
1149 | } | |
ef416fc2 | 1150 | |
c606bcae MS |
1151 | if (response) |
1152 | { | |
1153 | DEBUG_puts("show_devices: request succeeded..."); | |
ef416fc2 | 1154 | |
1155 | /* | |
1156 | * Loop through the printers returned in the list and display | |
1157 | * their devices... | |
1158 | */ | |
1159 | ||
1160 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
1161 | { | |
1162 | /* | |
1163 | * Skip leading attributes until we hit a job... | |
1164 | */ | |
1165 | ||
1166 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
1167 | attr = attr->next; | |
1168 | ||
1169 | if (attr == NULL) | |
1170 | break; | |
1171 | ||
1172 | /* | |
1173 | * Pull the needed attributes from this job... | |
1174 | */ | |
1175 | ||
1176 | printer = NULL; | |
1177 | device = NULL; | |
1178 | uri = NULL; | |
1179 | ||
1180 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
1181 | { | |
1182 | if (!strcmp(attr->name, "printer-name") && | |
1183 | attr->value_tag == IPP_TAG_NAME) | |
1184 | printer = attr->values[0].string.text; | |
1185 | ||
1186 | if (!strcmp(attr->name, "printer-uri-supported") && | |
1187 | attr->value_tag == IPP_TAG_URI) | |
1188 | uri = attr->values[0].string.text; | |
1189 | ||
1190 | if (!strcmp(attr->name, "device-uri") && | |
1191 | attr->value_tag == IPP_TAG_URI) | |
1192 | device = attr->values[0].string.text; | |
1193 | ||
1194 | attr = attr->next; | |
1195 | } | |
1196 | ||
1197 | /* | |
1198 | * See if we have everything needed... | |
1199 | */ | |
1200 | ||
1201 | if (printer == NULL) | |
1202 | { | |
1203 | if (attr == NULL) | |
1204 | break; | |
1205 | else | |
1206 | continue; | |
1207 | } | |
1208 | ||
ef416fc2 | 1209 | /* |
1210 | * Display the printer entry if needed... | |
1211 | */ | |
1212 | ||
61cf44e2 | 1213 | if (match_list(printers, printer)) |
ef416fc2 | 1214 | { |
ef416fc2 | 1215 | if (device == NULL) |
0837b7e8 | 1216 | _cupsLangPrintf(stdout, _("device for %s: %s"), |
ef416fc2 | 1217 | printer, uri); |
1218 | else if (!strncmp(device, "file:", 5)) | |
0837b7e8 | 1219 | _cupsLangPrintf(stdout, _("device for %s: %s"), |
ef416fc2 | 1220 | printer, device + 5); |
1221 | else | |
0837b7e8 | 1222 | _cupsLangPrintf(stdout, _("device for %s: %s"), |
ef416fc2 | 1223 | printer, device); |
1224 | ||
1225 | for (i = 0; i < num_dests; i ++) | |
5a1d7a17 | 1226 | { |
88f9aafc | 1227 | if (!_cups_strcasecmp(printer, dests[i].name) && dests[i].instance) |
ef416fc2 | 1228 | { |
1229 | if (device == NULL) | |
0837b7e8 | 1230 | _cupsLangPrintf(stdout, _("device for %s/%s: %s"), |
ef416fc2 | 1231 | printer, dests[i].instance, uri); |
1232 | else if (!strncmp(device, "file:", 5)) | |
0837b7e8 | 1233 | _cupsLangPrintf(stdout, _("device for %s/%s: %s"), |
ef416fc2 | 1234 | printer, dests[i].instance, device + 5); |
1235 | else | |
0837b7e8 | 1236 | _cupsLangPrintf(stdout, _("device for %s/%s: %s"), |
ef416fc2 | 1237 | printer, dests[i].instance, device); |
1238 | } | |
5a1d7a17 | 1239 | } |
ef416fc2 | 1240 | } |
1241 | ||
1242 | if (attr == NULL) | |
1243 | break; | |
1244 | } | |
1245 | ||
1246 | ippDelete(response); | |
1247 | } | |
ef416fc2 | 1248 | |
1249 | return (0); | |
1250 | } | |
1251 | ||
1252 | ||
1253 | /* | |
1254 | * 'show_jobs()' - Show active print jobs. | |
1255 | */ | |
1256 | ||
1257 | static int /* O - 0 on success, 1 on fail */ | |
61cf44e2 | 1258 | show_jobs(const char *dests, /* I - Destinations */ |
ef416fc2 | 1259 | const char *users, /* I - Users */ |
1260 | int long_status, /* I - Show long status? */ | |
1261 | int ranking, /* I - Show job ranking? */ | |
1262 | const char *which) /* I - Show which jobs? */ | |
1263 | { | |
09a101d6 | 1264 | int i; /* Looping var */ |
ef416fc2 | 1265 | ipp_t *request, /* IPP Request */ |
1266 | *response; /* IPP Response */ | |
09a101d6 | 1267 | ipp_attribute_t *attr, /* Current attribute */ |
1268 | *reasons; /* Job state reasons attribute */ | |
ef416fc2 | 1269 | const char *dest, /* Pointer into job-printer-uri */ |
1270 | *username, /* Pointer to job-originating-user-name */ | |
eec1fbc3 MS |
1271 | *message, /* Pointer to job-printer-state-message */ |
1272 | *time_at; /* time-at-xxx attribute name to use */ | |
ef416fc2 | 1273 | int rank, /* Rank in queue */ |
1274 | jobid, /* job-id */ | |
1275 | size; /* job-k-octets */ | |
1276 | time_t jobtime; /* time-at-creation */ | |
ef416fc2 | 1277 | char temp[255], /* Temporary buffer */ |
1278 | date[255]; /* Date buffer */ | |
1279 | static const char *jattrs[] = /* Attributes we need for jobs... */ | |
1280 | { | |
1281 | "job-id", | |
1282 | "job-k-octets", | |
1283 | "job-name", | |
09a101d6 | 1284 | "job-originating-user-name", |
229681c1 | 1285 | "job-printer-state-message", |
5a662dc0 MS |
1286 | "job-printer-uri", |
1287 | "job-state-reasons", | |
eec1fbc3 MS |
1288 | "time-at-creation", |
1289 | "time-at-completed" | |
ef416fc2 | 1290 | }; |
1291 | ||
1292 | ||
61cf44e2 MS |
1293 | DEBUG_printf(("show_jobs(dests=\"%s\", users=\"%s\", long_status=%d, " |
1294 | "ranking=%d, which=\"%s\")\n", dests, users, long_status, | |
1295 | ranking, which)); | |
ef416fc2 | 1296 | |
fa73b229 | 1297 | if (dests != NULL && !strcmp(dests, "all")) |
ef416fc2 | 1298 | dests = NULL; |
1299 | ||
1300 | /* | |
1301 | * Build a IPP_GET_JOBS request, which requires the following | |
1302 | * attributes: | |
1303 | * | |
1304 | * attributes-charset | |
1305 | * attributes-natural-language | |
52f6f666 | 1306 | * printer-uri |
ef416fc2 | 1307 | * requested-attributes |
52f6f666 MS |
1308 | * requesting-user-name |
1309 | * which-jobs | |
ef416fc2 | 1310 | */ |
1311 | ||
1312 | request = ippNewRequest(IPP_GET_JOBS); | |
1313 | ||
52f6f666 MS |
1314 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", |
1315 | NULL, "ipp://localhost/"); | |
1316 | ||
ef416fc2 | 1317 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, |
1318 | "requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]), | |
1319 | NULL, jattrs); | |
1320 | ||
52f6f666 MS |
1321 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
1322 | NULL, cupsUser()); | |
ef416fc2 | 1323 | |
1324 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", | |
1325 | NULL, which); | |
1326 | ||
1327 | /* | |
1328 | * Do the request and get back a response... | |
1329 | */ | |
1330 | ||
c606bcae MS |
1331 | response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"); |
1332 | ||
1333 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
1334 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
1335 | { | |
1336 | _cupsLangPrintf(stderr, | |
1337 | _("%s: Error - add '/version=1.1' to server name."), | |
1338 | "lpstat"); | |
1339 | ippDelete(response); | |
1340 | return (1); | |
1341 | } | |
1342 | else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) | |
1343 | { | |
1344 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); | |
1345 | ippDelete(response); | |
1346 | return (1); | |
1347 | } | |
1348 | ||
1349 | if (response) | |
ef416fc2 | 1350 | { |
1351 | /* | |
1352 | * Loop through the job list and display them... | |
1353 | */ | |
1354 | ||
eec1fbc3 MS |
1355 | if (!strcmp(which, "aborted") || |
1356 | !strcmp(which, "canceled") || | |
1357 | !strcmp(which, "completed")) | |
1358 | time_at = "time-at-completed"; | |
1359 | else | |
1360 | time_at = "time-at-creation"; | |
1361 | ||
ef416fc2 | 1362 | rank = -1; |
1363 | ||
1364 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
1365 | { | |
1366 | /* | |
1367 | * Skip leading attributes until we hit a job... | |
1368 | */ | |
1369 | ||
1370 | while (attr != NULL && attr->group_tag != IPP_TAG_JOB) | |
1371 | attr = attr->next; | |
1372 | ||
1373 | if (attr == NULL) | |
1374 | break; | |
1375 | ||
1376 | /* | |
1377 | * Pull the needed attributes from this job... | |
1378 | */ | |
1379 | ||
1380 | jobid = 0; | |
1381 | size = 0; | |
1382 | username = NULL; | |
1383 | dest = NULL; | |
1384 | jobtime = 0; | |
229681c1 | 1385 | message = NULL; |
09a101d6 | 1386 | reasons = NULL; |
ef416fc2 | 1387 | |
1388 | while (attr != NULL && attr->group_tag == IPP_TAG_JOB) | |
1389 | { | |
fa73b229 | 1390 | if (!strcmp(attr->name, "job-id") && |
ef416fc2 | 1391 | attr->value_tag == IPP_TAG_INTEGER) |
1392 | jobid = attr->values[0].integer; | |
229681c1 MS |
1393 | else if (!strcmp(attr->name, "job-k-octets") && |
1394 | attr->value_tag == IPP_TAG_INTEGER) | |
ef416fc2 | 1395 | size = attr->values[0].integer; |
eec1fbc3 | 1396 | else if (!strcmp(attr->name, time_at) && attr->value_tag == IPP_TAG_INTEGER) |
ef416fc2 | 1397 | jobtime = attr->values[0].integer; |
229681c1 MS |
1398 | else if (!strcmp(attr->name, "job-printer-state-message") && |
1399 | attr->value_tag == IPP_TAG_TEXT) | |
1400 | message = attr->values[0].string.text; | |
1401 | else if (!strcmp(attr->name, "job-printer-uri") && | |
1402 | attr->value_tag == IPP_TAG_URI) | |
1403 | { | |
ef416fc2 | 1404 | if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL) |
1405 | dest ++; | |
229681c1 MS |
1406 | } |
1407 | else if (!strcmp(attr->name, "job-originating-user-name") && | |
1408 | attr->value_tag == IPP_TAG_NAME) | |
ef416fc2 | 1409 | username = attr->values[0].string.text; |
229681c1 MS |
1410 | else if (!strcmp(attr->name, "job-state-reasons") && |
1411 | attr->value_tag == IPP_TAG_KEYWORD) | |
09a101d6 | 1412 | reasons = attr; |
1413 | ||
ef416fc2 | 1414 | attr = attr->next; |
1415 | } | |
1416 | ||
1417 | /* | |
1418 | * See if we have everything needed... | |
1419 | */ | |
1420 | ||
1421 | if (dest == NULL || jobid == 0) | |
1422 | { | |
1423 | if (attr == NULL) | |
1424 | break; | |
1425 | else | |
1426 | continue; | |
1427 | } | |
1428 | ||
1429 | /* | |
61cf44e2 | 1430 | * Display the job... |
ef416fc2 | 1431 | */ |
1432 | ||
ef416fc2 | 1433 | rank ++; |
1434 | ||
cc754834 | 1435 | if (match_list(dests, dest) && match_list(users, username)) |
ef416fc2 | 1436 | { |
ef416fc2 | 1437 | snprintf(temp, sizeof(temp), "%s-%d", dest, jobid); |
1438 | ||
554aa7b7 | 1439 | _cupsStrDate(date, sizeof(date), jobtime); |
ef416fc2 | 1440 | |
554aa7b7 MS |
1441 | if (ranking) |
1442 | _cupsLangPrintf(stdout, "%3d %-21s %-13s %8.0f %s", | |
1443 | rank, temp, username ? username : "unknown", | |
1444 | 1024.0 * size, date); | |
ef416fc2 | 1445 | else |
554aa7b7 MS |
1446 | _cupsLangPrintf(stdout, "%-23s %-13s %8.0f %s", |
1447 | temp, username ? username : "unknown", | |
1448 | 1024.0 * size, date); | |
1449 | if (long_status) | |
ef416fc2 | 1450 | { |
554aa7b7 MS |
1451 | if (message) |
1452 | _cupsLangPrintf(stdout, _("\tStatus: %s"), message); | |
0837b7e8 | 1453 | |
554aa7b7 MS |
1454 | if (reasons) |
1455 | { | |
1456 | char alerts[1024], /* Alerts string */ | |
1457 | *aptr; /* Pointer into alerts string */ | |
0837b7e8 | 1458 | |
554aa7b7 MS |
1459 | for (i = 0, aptr = alerts; i < reasons->num_values; i ++) |
1460 | { | |
1461 | if (i) | |
1462 | snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text); | |
1463 | else | |
1464 | strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts)); | |
0837b7e8 | 1465 | |
554aa7b7 | 1466 | aptr += strlen(aptr); |
09a101d6 | 1467 | } |
0837b7e8 | 1468 | |
554aa7b7 | 1469 | _cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts); |
09a101d6 | 1470 | } |
554aa7b7 MS |
1471 | |
1472 | _cupsLangPrintf(stdout, _("\tqueued for %s"), dest); | |
ef416fc2 | 1473 | } |
1474 | } | |
1475 | ||
1476 | if (attr == NULL) | |
1477 | break; | |
1478 | } | |
1479 | ||
1480 | ippDelete(response); | |
1481 | } | |
ef416fc2 | 1482 | |
1483 | return (0); | |
1484 | } | |
1485 | ||
1486 | ||
1487 | /* | |
1488 | * 'show_printers()' - Show printers. | |
1489 | */ | |
1490 | ||
1491 | static int /* O - 0 on success, 1 on fail */ | |
61cf44e2 | 1492 | show_printers(const char *printers, /* I - Destinations */ |
ef416fc2 | 1493 | int num_dests, /* I - Number of user-defined dests */ |
1494 | cups_dest_t *dests, /* I - User-defined destinations */ | |
1495 | int long_status) /* I - Show long status? */ | |
1496 | { | |
26d47ec6 | 1497 | int i, j; /* Looping vars */ |
ef416fc2 | 1498 | ipp_t *request, /* IPP Request */ |
1499 | *response, /* IPP Response */ | |
1500 | *jobs; /* IPP Get Jobs response */ | |
1501 | ipp_attribute_t *attr, /* Current attribute */ | |
1502 | *jobattr, /* Job ID attribute */ | |
1503 | *reasons; /* Job state reasons attribute */ | |
1504 | const char *printer, /* Printer name */ | |
1505 | *message, /* Printer state message */ | |
1506 | *description, /* Description of printer */ | |
1507 | *location, /* Location of printer */ | |
1508 | *make_model, /* Make and model of printer */ | |
1509 | *uri; /* URI of printer */ | |
1510 | ipp_attribute_t *allowed, /* requesting-user-name-allowed */ | |
1511 | *denied; /* requestint-user-name-denied */ | |
1512 | ipp_pstate_t pstate; /* Printer state */ | |
1513 | cups_ptype_t ptype; /* Printer type */ | |
1514 | time_t ptime; /* Printer state time */ | |
ef416fc2 | 1515 | int jobid; /* Job ID of current job */ |
ef416fc2 | 1516 | char printer_uri[HTTP_MAX_URI], |
1517 | /* Printer URI */ | |
1518 | printer_state_time[255];/* Printer state time */ | |
f8b3a85b | 1519 | _cups_globals_t *cg = _cupsGlobals(); /* Global data */ |
ef416fc2 | 1520 | static const char *pattrs[] = /* Attributes we need for printers... */ |
1521 | { | |
1522 | "printer-name", | |
1523 | "printer-state", | |
1524 | "printer-state-message", | |
1525 | "printer-state-reasons", | |
1526 | "printer-state-change-time", | |
1527 | "printer-type", | |
1528 | "printer-info", | |
1529 | "printer-location", | |
1530 | "printer-make-and-model", | |
1531 | "printer-uri-supported", | |
1532 | "requesting-user-name-allowed", | |
1533 | "requesting-user-name-denied" | |
1534 | }; | |
1535 | static const char *jattrs[] = /* Attributes we need for jobs... */ | |
1536 | { | |
7cf5915e MS |
1537 | "job-id", |
1538 | "job-state" | |
ef416fc2 | 1539 | }; |
1540 | ||
1541 | ||
bf3816c7 MS |
1542 | DEBUG_printf(("show_printers(printers=\"%s\", num_dests=%d, dests=%p, " |
1543 | "long_status=%d)\n", printers, num_dests, dests, long_status)); | |
ef416fc2 | 1544 | |
fa73b229 | 1545 | if (printers != NULL && !strcmp(printers, "all")) |
ef416fc2 | 1546 | printers = NULL; |
1547 | ||
1548 | /* | |
1549 | * Build a CUPS_GET_PRINTERS request, which requires the following | |
1550 | * attributes: | |
1551 | * | |
1552 | * attributes-charset | |
1553 | * attributes-natural-language | |
1554 | * requested-attributes | |
fa73b229 | 1555 | * requesting-user-name |
ef416fc2 | 1556 | */ |
1557 | ||
1558 | request = ippNewRequest(CUPS_GET_PRINTERS); | |
1559 | ||
1560 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
1561 | "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), | |
1562 | NULL, pattrs); | |
1563 | ||
fa73b229 | 1564 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", |
1565 | NULL, cupsUser()); | |
1566 | ||
ef416fc2 | 1567 | /* |
1568 | * Do the request and get back a response... | |
1569 | */ | |
1570 | ||
c606bcae MS |
1571 | response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"); |
1572 | ||
1573 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
1574 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
ef416fc2 | 1575 | { |
c606bcae MS |
1576 | _cupsLangPrintf(stderr, |
1577 | _("%s: Error - add '/version=1.1' to server name."), | |
1578 | "lpstat"); | |
1579 | ippDelete(response); | |
1580 | return (1); | |
1581 | } | |
1582 | else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) | |
1583 | { | |
1584 | _cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString()); | |
1585 | ippDelete(response); | |
1586 | return (1); | |
1587 | } | |
ef416fc2 | 1588 | |
c606bcae MS |
1589 | if (response) |
1590 | { | |
1591 | DEBUG_puts("show_printers: request succeeded..."); | |
ef416fc2 | 1592 | |
1593 | /* | |
1594 | * Loop through the printers returned in the list and display | |
1595 | * their status... | |
1596 | */ | |
1597 | ||
1598 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
1599 | { | |
1600 | /* | |
1601 | * Skip leading attributes until we hit a job... | |
1602 | */ | |
1603 | ||
1604 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
1605 | attr = attr->next; | |
1606 | ||
1607 | if (attr == NULL) | |
1608 | break; | |
1609 | ||
1610 | /* | |
1611 | * Pull the needed attributes from this job... | |
1612 | */ | |
1613 | ||
1614 | printer = NULL; | |
1615 | ptime = 0; | |
1616 | ptype = CUPS_PRINTER_LOCAL; | |
1617 | pstate = IPP_PRINTER_IDLE; | |
1618 | message = NULL; | |
1619 | description = NULL; | |
1620 | location = NULL; | |
1621 | make_model = NULL; | |
1622 | reasons = NULL; | |
1623 | uri = NULL; | |
1624 | jobid = 0; | |
1625 | allowed = NULL; | |
1626 | denied = NULL; | |
1627 | ||
1628 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
1629 | { | |
1630 | if (!strcmp(attr->name, "printer-name") && | |
1631 | attr->value_tag == IPP_TAG_NAME) | |
1632 | printer = attr->values[0].string.text; | |
1633 | else if (!strcmp(attr->name, "printer-state") && | |
1634 | attr->value_tag == IPP_TAG_ENUM) | |
1635 | pstate = (ipp_pstate_t)attr->values[0].integer; | |
1636 | else if (!strcmp(attr->name, "printer-type") && | |
1637 | attr->value_tag == IPP_TAG_ENUM) | |
1638 | ptype = (cups_ptype_t)attr->values[0].integer; | |
1639 | else if (!strcmp(attr->name, "printer-state-message") && | |
1640 | attr->value_tag == IPP_TAG_TEXT) | |
1641 | message = attr->values[0].string.text; | |
1642 | else if (!strcmp(attr->name, "printer-state-change-time") && | |
1643 | attr->value_tag == IPP_TAG_INTEGER) | |
1644 | ptime = (time_t)attr->values[0].integer; | |
1645 | else if (!strcmp(attr->name, "printer-info") && | |
1646 | attr->value_tag == IPP_TAG_TEXT) | |
1647 | description = attr->values[0].string.text; | |
1648 | else if (!strcmp(attr->name, "printer-location") && | |
1649 | attr->value_tag == IPP_TAG_TEXT) | |
1650 | location = attr->values[0].string.text; | |
1651 | else if (!strcmp(attr->name, "printer-make-and-model") && | |
1652 | attr->value_tag == IPP_TAG_TEXT) | |
1653 | make_model = attr->values[0].string.text; | |
1654 | else if (!strcmp(attr->name, "printer-uri-supported") && | |
1655 | attr->value_tag == IPP_TAG_URI) | |
1656 | uri = attr->values[0].string.text; | |
1657 | else if (!strcmp(attr->name, "printer-state-reasons") && | |
1658 | attr->value_tag == IPP_TAG_KEYWORD) | |
1659 | reasons = attr; | |
1660 | else if (!strcmp(attr->name, "requesting-user-name-allowed") && | |
1661 | attr->value_tag == IPP_TAG_NAME) | |
1662 | allowed = attr; | |
1663 | else if (!strcmp(attr->name, "requesting-user-name-denied") && | |
1664 | attr->value_tag == IPP_TAG_NAME) | |
1665 | denied = attr; | |
1666 | ||
1667 | attr = attr->next; | |
1668 | } | |
1669 | ||
1670 | /* | |
1671 | * See if we have everything needed... | |
1672 | */ | |
1673 | ||
1674 | if (printer == NULL) | |
1675 | { | |
1676 | if (attr == NULL) | |
1677 | break; | |
1678 | else | |
1679 | continue; | |
1680 | } | |
1681 | ||
ef416fc2 | 1682 | /* |
1683 | * Display the printer entry if needed... | |
1684 | */ | |
1685 | ||
61cf44e2 | 1686 | if (match_list(printers, printer)) |
ef416fc2 | 1687 | { |
1688 | /* | |
1689 | * If the printer state is "IPP_PRINTER_PROCESSING", then grab the | |
1690 | * current job for the printer. | |
1691 | */ | |
1692 | ||
1693 | if (pstate == IPP_PRINTER_PROCESSING) | |
1694 | { | |
1695 | /* | |
1696 | * Build an IPP_GET_JOBS request, which requires the following | |
1697 | * attributes: | |
1698 | * | |
1699 | * attributes-charset | |
1700 | * attributes-natural-language | |
1701 | * printer-uri | |
1702 | * limit | |
1703 | * requested-attributes | |
1704 | */ | |
1705 | ||
1706 | request = ippNewRequest(IPP_GET_JOBS); | |
1707 | ||
1708 | request->request.op.operation_id = IPP_GET_JOBS; | |
1709 | request->request.op.request_id = 1; | |
1710 | ||
1711 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
1712 | "requested-attributes", | |
1713 | sizeof(jattrs) / sizeof(jattrs[0]), NULL, jattrs); | |
1714 | ||
a4d04587 | 1715 | httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), |
1716 | "ipp", NULL, "localhost", 0, "/printers/%s", printer); | |
ef416fc2 | 1717 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
1718 | "printer-uri", NULL, printer_uri); | |
1719 | ||
61cf44e2 | 1720 | if ((jobs = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL) |
ef416fc2 | 1721 | { |
1722 | /* | |
1723 | * Get the current active job on this queue... | |
1724 | */ | |
1725 | ||
c934a06c | 1726 | ipp_jstate_t jobstate = IPP_JOB_PENDING; |
ef416fc2 | 1727 | jobid = 0; |
1728 | ||
1729 | for (jobattr = jobs->attrs; jobattr; jobattr = jobattr->next) | |
1730 | { | |
1731 | if (!jobattr->name) | |
c934a06c MS |
1732 | { |
1733 | if (jobstate == IPP_JOB_PROCESSING) | |
1734 | break; | |
1735 | else | |
1736 | continue; | |
1737 | } | |
ef416fc2 | 1738 | |
1739 | if (!strcmp(jobattr->name, "job-id") && | |
1740 | jobattr->value_tag == IPP_TAG_INTEGER) | |
1741 | jobid = jobattr->values[0].integer; | |
1742 | else if (!strcmp(jobattr->name, "job-state") && | |
c934a06c | 1743 | jobattr->value_tag == IPP_TAG_ENUM) |
7e86f2f6 | 1744 | jobstate = (ipp_jstate_t)jobattr->values[0].integer; |
ef416fc2 | 1745 | } |
1746 | ||
c934a06c MS |
1747 | if (jobstate != IPP_JOB_PROCESSING) |
1748 | jobid = 0; | |
1749 | ||
ef416fc2 | 1750 | ippDelete(jobs); |
1751 | } | |
1752 | } | |
1753 | ||
1754 | /* | |
1755 | * Display it... | |
1756 | */ | |
1757 | ||
554aa7b7 | 1758 | _cupsStrDate(printer_state_time, sizeof(printer_state_time), ptime); |
ef416fc2 | 1759 | |
1760 | switch (pstate) | |
1761 | { | |
1762 | case IPP_PRINTER_IDLE : | |
fa73b229 | 1763 | _cupsLangPrintf(stdout, |
0837b7e8 | 1764 | _("printer %s is idle. enabled since %s"), |
ef416fc2 | 1765 | printer, printer_state_time); |
1766 | break; | |
1767 | case IPP_PRINTER_PROCESSING : | |
fa73b229 | 1768 | _cupsLangPrintf(stdout, |
ef416fc2 | 1769 | _("printer %s now printing %s-%d. " |
0837b7e8 | 1770 | "enabled since %s"), |
ef416fc2 | 1771 | printer, printer, jobid, printer_state_time); |
1772 | break; | |
1773 | case IPP_PRINTER_STOPPED : | |
fa73b229 | 1774 | _cupsLangPrintf(stdout, |
0837b7e8 | 1775 | _("printer %s disabled since %s -"), |
ef416fc2 | 1776 | printer, printer_state_time); |
1777 | break; | |
1778 | } | |
1779 | ||
1780 | if ((message && *message) || pstate == IPP_PRINTER_STOPPED) | |
1781 | { | |
1782 | if (!message || !*message) | |
0837b7e8 | 1783 | _cupsLangPuts(stdout, _("\treason unknown")); |
ef416fc2 | 1784 | else |
0837b7e8 | 1785 | _cupsLangPrintf(stdout, "\t%s", message); |
ef416fc2 | 1786 | } |
1787 | ||
1788 | if (long_status > 1) | |
0837b7e8 MS |
1789 | { |
1790 | _cupsLangPuts(stdout, _("\tForm mounted:")); | |
1791 | _cupsLangPuts(stdout, _("\tContent types: any")); | |
1792 | _cupsLangPuts(stdout, _("\tPrinter types: unknown")); | |
1793 | } | |
ef416fc2 | 1794 | |
1795 | if (long_status) | |
1796 | { | |
0837b7e8 | 1797 | _cupsLangPrintf(stdout, _("\tDescription: %s"), |
ef416fc2 | 1798 | description ? description : ""); |
1799 | ||
1800 | if (reasons) | |
1801 | { | |
0837b7e8 MS |
1802 | char alerts[1024], /* Alerts string */ |
1803 | *aptr; /* Pointer into alerts string */ | |
1804 | ||
1805 | for (i = 0, aptr = alerts; i < reasons->num_values; i ++) | |
1806 | { | |
1807 | if (i) | |
7e86f2f6 | 1808 | snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text); |
0837b7e8 | 1809 | else |
7e86f2f6 | 1810 | strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts)); |
0837b7e8 MS |
1811 | |
1812 | aptr += strlen(aptr); | |
1813 | } | |
1814 | ||
1815 | _cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts); | |
ef416fc2 | 1816 | } |
1817 | } | |
1818 | if (long_status > 1) | |
1819 | { | |
0837b7e8 | 1820 | _cupsLangPrintf(stdout, _("\tLocation: %s"), |
ef416fc2 | 1821 | location ? location : ""); |
1822 | ||
1823 | if (ptype & CUPS_PRINTER_REMOTE) | |
1824 | { | |
0837b7e8 | 1825 | _cupsLangPuts(stdout, _("\tConnection: remote")); |
ef416fc2 | 1826 | |
1827 | if (make_model && !strstr(make_model, "System V Printer") && | |
1828 | !strstr(make_model, "Raw Printer") && uri) | |
0837b7e8 | 1829 | _cupsLangPrintf(stdout, _("\tInterface: %s.ppd"), |
ef416fc2 | 1830 | uri); |
1831 | } | |
1832 | else | |
1833 | { | |
0837b7e8 | 1834 | _cupsLangPuts(stdout, _("\tConnection: direct")); |
ef416fc2 | 1835 | |
e67e2f9e | 1836 | if (make_model && !strstr(make_model, "Raw Printer")) |
fa73b229 | 1837 | _cupsLangPrintf(stdout, |
0837b7e8 | 1838 | _("\tInterface: %s/ppd/%s.ppd"), |
f8b3a85b | 1839 | cg->cups_serverroot, printer); |
ef416fc2 | 1840 | } |
0837b7e8 MS |
1841 | _cupsLangPuts(stdout, _("\tOn fault: no alert")); |
1842 | _cupsLangPuts(stdout, _("\tAfter fault: continue")); | |
b423cd4c | 1843 | /* TODO update to use printer-error-policy */ |
ef416fc2 | 1844 | if (allowed) |
1845 | { | |
0837b7e8 | 1846 | _cupsLangPuts(stdout, _("\tUsers allowed:")); |
26d47ec6 | 1847 | for (j = 0; j < allowed->num_values; j ++) |
0837b7e8 | 1848 | _cupsLangPrintf(stdout, "\t\t%s", |
26d47ec6 | 1849 | allowed->values[j].string.text); |
ef416fc2 | 1850 | } |
1851 | else if (denied) | |
1852 | { | |
0837b7e8 | 1853 | _cupsLangPuts(stdout, _("\tUsers denied:")); |
26d47ec6 | 1854 | for (j = 0; j < denied->num_values; j ++) |
0837b7e8 | 1855 | _cupsLangPrintf(stdout, "\t\t%s", |
26d47ec6 | 1856 | denied->values[j].string.text); |
ef416fc2 | 1857 | } |
1858 | else | |
1859 | { | |
0837b7e8 MS |
1860 | _cupsLangPuts(stdout, _("\tUsers allowed:")); |
1861 | _cupsLangPuts(stdout, _("\t\t(all)")); | |
ef416fc2 | 1862 | } |
0837b7e8 MS |
1863 | _cupsLangPuts(stdout, _("\tForms allowed:")); |
1864 | _cupsLangPuts(stdout, _("\t\t(none)")); | |
1865 | _cupsLangPuts(stdout, _("\tBanner required")); | |
1866 | _cupsLangPuts(stdout, _("\tCharset sets:")); | |
1867 | _cupsLangPuts(stdout, _("\t\t(none)")); | |
1868 | _cupsLangPuts(stdout, _("\tDefault pitch:")); | |
1869 | _cupsLangPuts(stdout, _("\tDefault page size:")); | |
1870 | _cupsLangPuts(stdout, _("\tDefault port settings:")); | |
ef416fc2 | 1871 | } |
1872 | ||
1873 | for (i = 0; i < num_dests; i ++) | |
88f9aafc | 1874 | if (!_cups_strcasecmp(printer, dests[i].name) && dests[i].instance) |
ef416fc2 | 1875 | { |
1876 | switch (pstate) | |
1877 | { | |
1878 | case IPP_PRINTER_IDLE : | |
fa73b229 | 1879 | _cupsLangPrintf(stdout, |
ef416fc2 | 1880 | _("printer %s/%s is idle. " |
0837b7e8 | 1881 | "enabled since %s"), |
ef416fc2 | 1882 | printer, dests[i].instance, |
1883 | printer_state_time); | |
1884 | break; | |
1885 | case IPP_PRINTER_PROCESSING : | |
fa73b229 | 1886 | _cupsLangPrintf(stdout, |
ef416fc2 | 1887 | _("printer %s/%s now printing %s-%d. " |
0837b7e8 | 1888 | "enabled since %s"), |
ef416fc2 | 1889 | printer, dests[i].instance, printer, jobid, |
1890 | printer_state_time); | |
1891 | break; | |
1892 | case IPP_PRINTER_STOPPED : | |
fa73b229 | 1893 | _cupsLangPrintf(stdout, |
0837b7e8 | 1894 | _("printer %s/%s disabled since %s -"), |
ef416fc2 | 1895 | printer, dests[i].instance, |
1896 | printer_state_time); | |
1897 | break; | |
1898 | } | |
1899 | ||
1900 | if ((message && *message) || pstate == IPP_PRINTER_STOPPED) | |
1901 | { | |
1902 | if (!message || !*message) | |
0837b7e8 | 1903 | _cupsLangPuts(stdout, _("\treason unknown")); |
ef416fc2 | 1904 | else |
0837b7e8 | 1905 | _cupsLangPrintf(stdout, "\t%s", message); |
ef416fc2 | 1906 | } |
1907 | ||
1908 | if (long_status > 1) | |
0837b7e8 MS |
1909 | { |
1910 | _cupsLangPuts(stdout, _("\tForm mounted:")); | |
1911 | _cupsLangPuts(stdout, _("\tContent types: any")); | |
1912 | _cupsLangPuts(stdout, _("\tPrinter types: unknown")); | |
1913 | } | |
ef416fc2 | 1914 | |
1915 | if (long_status) | |
1916 | { | |
0837b7e8 | 1917 | _cupsLangPrintf(stdout, _("\tDescription: %s"), |
ef416fc2 | 1918 | description ? description : ""); |
1919 | ||
1920 | if (reasons) | |
1921 | { | |
0837b7e8 MS |
1922 | char alerts[1024], /* Alerts string */ |
1923 | *aptr; /* Pointer into alerts string */ | |
1924 | ||
1925 | for (i = 0, aptr = alerts; i < reasons->num_values; i ++) | |
1926 | { | |
1927 | if (i) | |
7e86f2f6 | 1928 | snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text); |
0837b7e8 | 1929 | else |
7e86f2f6 | 1930 | strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts)); |
0837b7e8 MS |
1931 | |
1932 | aptr += strlen(aptr); | |
1933 | } | |
1934 | ||
1935 | _cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts); | |
ef416fc2 | 1936 | } |
1937 | } | |
1938 | if (long_status > 1) | |
1939 | { | |
0837b7e8 | 1940 | _cupsLangPrintf(stdout, _("\tLocation: %s"), |
ef416fc2 | 1941 | location ? location : ""); |
1942 | ||
1943 | if (ptype & CUPS_PRINTER_REMOTE) | |
1944 | { | |
0837b7e8 | 1945 | _cupsLangPuts(stdout, _("\tConnection: remote")); |
ef416fc2 | 1946 | |
1947 | if (make_model && !strstr(make_model, "System V Printer") && | |
1948 | !strstr(make_model, "Raw Printer") && uri) | |
0837b7e8 | 1949 | _cupsLangPrintf(stdout, _("\tInterface: %s.ppd"), uri); |
ef416fc2 | 1950 | } |
1951 | else | |
1952 | { | |
0837b7e8 | 1953 | _cupsLangPuts(stdout, _("\tConnection: direct")); |
ef416fc2 | 1954 | |
e67e2f9e | 1955 | if (make_model && !strstr(make_model, "Raw Printer")) |
fa73b229 | 1956 | _cupsLangPrintf(stdout, |
0837b7e8 | 1957 | _("\tInterface: %s/ppd/%s.ppd"), |
f8b3a85b | 1958 | cg->cups_serverroot, printer); |
ef416fc2 | 1959 | } |
0837b7e8 MS |
1960 | _cupsLangPuts(stdout, _("\tOn fault: no alert")); |
1961 | _cupsLangPuts(stdout, _("\tAfter fault: continue")); | |
b423cd4c | 1962 | /* TODO update to use printer-error-policy */ |
ef416fc2 | 1963 | if (allowed) |
1964 | { | |
0837b7e8 | 1965 | _cupsLangPuts(stdout, _("\tUsers allowed:")); |
26d47ec6 | 1966 | for (j = 0; j < allowed->num_values; j ++) |
0837b7e8 | 1967 | _cupsLangPrintf(stdout, "\t\t%s", |
26d47ec6 | 1968 | allowed->values[j].string.text); |
ef416fc2 | 1969 | } |
1970 | else if (denied) | |
1971 | { | |
0837b7e8 | 1972 | _cupsLangPuts(stdout, _("\tUsers denied:")); |
26d47ec6 | 1973 | for (j = 0; j < denied->num_values; j ++) |
0837b7e8 | 1974 | _cupsLangPrintf(stdout, "\t\t%s", |
26d47ec6 | 1975 | denied->values[j].string.text); |
ef416fc2 | 1976 | } |
1977 | else | |
1978 | { | |
0837b7e8 MS |
1979 | _cupsLangPuts(stdout, _("\tUsers allowed:")); |
1980 | _cupsLangPuts(stdout, _("\t\t(all)")); | |
ef416fc2 | 1981 | } |
0837b7e8 MS |
1982 | _cupsLangPuts(stdout, _("\tForms allowed:")); |
1983 | _cupsLangPuts(stdout, _("\t\t(none)")); | |
1984 | _cupsLangPuts(stdout, _("\tBanner required")); | |
1985 | _cupsLangPuts(stdout, _("\tCharset sets:")); | |
1986 | _cupsLangPuts(stdout, _("\t\t(none)")); | |
1987 | _cupsLangPuts(stdout, _("\tDefault pitch:")); | |
1988 | _cupsLangPuts(stdout, _("\tDefault page size:")); | |
1989 | _cupsLangPuts(stdout, _("\tDefault port settings:")); | |
ef416fc2 | 1990 | } |
1991 | } | |
1992 | } | |
1993 | ||
1994 | if (attr == NULL) | |
1995 | break; | |
1996 | } | |
1997 | ||
1998 | ippDelete(response); | |
1999 | } | |
ef416fc2 | 2000 | |
2001 | return (0); | |
2002 | } | |
2003 | ||
2004 | ||
2005 | /* | |
2006 | * 'show_scheduler()' - Show scheduler status. | |
2007 | */ | |
2008 | ||
2009 | static void | |
61cf44e2 | 2010 | show_scheduler(void) |
ef416fc2 | 2011 | { |
61cf44e2 MS |
2012 | http_t *http; /* Connection to server */ |
2013 | ||
2014 | ||
2015 | if ((http = httpConnectEncrypt(cupsServer(), ippPort(), | |
2016 | cupsEncryption())) != NULL) | |
2017 | { | |
0837b7e8 | 2018 | _cupsLangPuts(stdout, _("scheduler is running")); |
61cf44e2 MS |
2019 | httpClose(http); |
2020 | } | |
ef416fc2 | 2021 | else |
0837b7e8 | 2022 | _cupsLangPuts(stdout, _("scheduler is not running")); |
ef416fc2 | 2023 | } |