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