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