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