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