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