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