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