]> git.ipfire.org Git - thirdparty/cups.git/blob - berkeley/lpq.c
Load cups into easysw/current.
[thirdparty/cups.git] / berkeley / lpq.c
1 /*
2 * "$Id: lpq.c 5925 2006-09-05 19:43:11Z mike $"
3 *
4 * "lpq" 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 commands.
27 * show_jobs() - Show jobs.
28 * show_printer() - Show printer status.
29 * usage() - Show program usage.
30 */
31
32 /*
33 * Include necessary headers...
34 */
35
36 /*
37 * Include necessary headers...
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <cups/string.h>
43 #include <cups/cups.h>
44 #include <cups/i18n.h>
45 #include <cups/debug.h>
46
47
48 /*
49 * Local functions...
50 */
51
52 static http_t *connect_server(const char *, http_t *);
53 static int show_jobs(const char *, http_t *, const char *,
54 const char *, const int, const int);
55 static void show_printer(const char *, http_t *, const char *);
56 static void usage(void);
57
58
59 /*
60 * 'main()' - Parse options and commands.
61 */
62
63 int
64 main(int argc, /* I - Number of command-line arguments */
65 char *argv[]) /* I - Command-line arguments */
66 {
67 int i; /* Looping var */
68 http_t *http; /* Connection to server */
69 const char *dest, /* Desired printer */
70 *user, /* Desired user */
71 *val; /* Environment variable name */
72 char *instance; /* Printer instance */
73 int id, /* Desired job ID */
74 all, /* All printers */
75 interval, /* Reporting interval */
76 longstatus; /* Show file details */
77 int num_dests; /* Number of destinations */
78 cups_dest_t *dests; /* Destinations */
79
80
81 _cupsSetLocale(argv);
82
83 /*
84 * Check for command-line options...
85 */
86
87 http = NULL;
88 dest = NULL;
89 user = NULL;
90 id = 0;
91 interval = 0;
92 longstatus = 0;
93 all = 0;
94 num_dests = 0;
95 dests = NULL;
96
97 for (i = 1; i < argc; i ++)
98 if (argv[i][0] == '+')
99 interval = atoi(argv[i] + 1);
100 else if (argv[i][0] == '-')
101 {
102 switch (argv[i][1])
103 {
104 case 'E' : /* Encrypt */
105 #ifdef HAVE_SSL
106 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
107
108 if (http)
109 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
110 #else
111 _cupsLangPrintf(stderr,
112 _("%s: Sorry, no encryption support compiled in!\n"),
113 argv[0]);
114 #endif /* HAVE_SSL */
115 break;
116
117 case 'U' : /* Username */
118 if (argv[i][2] != '\0')
119 cupsSetUser(argv[i] + 2);
120 else
121 {
122 i ++;
123 if (i >= argc)
124 {
125 _cupsLangPrintf(stderr,
126 _("%s: Error - expected username after "
127 "\'-U\' option!\n"),
128 argv[0]);
129 return (1);
130 }
131
132 cupsSetUser(argv[i]);
133 }
134 break;
135
136 case 'P' : /* Printer */
137 if (argv[i][2])
138 dest = argv[i] + 2;
139 else
140 {
141 i ++;
142
143 if (i >= argc)
144 {
145 httpClose(http);
146 cupsFreeDests(num_dests, dests);
147
148 usage();
149 }
150
151 dest = argv[i];
152 }
153
154 if ((instance = strchr(dest, '/')) != NULL)
155 *instance++ = '\0';
156
157 http = connect_server(argv[0], http);
158
159 if (num_dests == 0)
160 num_dests = cupsGetDests2(http, &dests);
161
162 if (cupsGetDest(dest, instance, num_dests, dests) == NULL)
163 {
164 if (instance)
165 _cupsLangPrintf(stderr,
166 _("%s: Error - unknown destination \"%s/%s\"!\n"),
167 argv[0], dest, instance);
168 else
169 _cupsLangPrintf(stderr,
170 _("%s: Unknown destination \"%s\"!\n"),
171 argv[0], dest);
172
173 return (1);
174 }
175 break;
176
177 case 'a' : /* All printers */
178 all = 1;
179 break;
180
181 case 'h' : /* Connect to host */
182 if (http)
183 {
184 httpClose(http);
185 http = NULL;
186 }
187
188 if (argv[i][2] != '\0')
189 cupsSetServer(argv[i] + 2);
190 else
191 {
192 i ++;
193
194 if (i >= argc)
195 {
196 _cupsLangPrintf(stderr,
197 _("%s: Error - expected hostname after "
198 "\'-h\' option!\n"),
199 argv[0]);
200 return (1);
201 }
202 else
203 cupsSetServer(argv[i]);
204 }
205 break;
206
207 case 'l' : /* Long status */
208 longstatus = 1;
209 break;
210
211 default :
212 httpClose(http);
213 cupsFreeDests(num_dests, dests);
214
215 usage();
216 break;
217 }
218 }
219 else if (isdigit(argv[i][0] & 255))
220 id = atoi(argv[i]);
221 else
222 user = argv[i];
223
224 http = connect_server(argv[0], http);
225
226 if (dest == NULL && !all)
227 {
228 if (num_dests == 0)
229 num_dests = cupsGetDests2(http, &dests);
230
231 for (i = 0; i < num_dests; i ++)
232 if (dests[i].is_default)
233 dest = dests[i].name;
234
235 if (dest == NULL)
236 {
237 val = NULL;
238
239 if ((dest = getenv("LPDEST")) == NULL)
240 {
241 if ((dest = getenv("PRINTER")) != NULL)
242 {
243 if (!strcmp(dest, "lp"))
244 dest = NULL;
245 else
246 val = "PRINTER";
247 }
248 }
249 else
250 val = "LPDEST";
251
252 if (dest && !cupsGetDest(dest, NULL, num_dests, dests))
253 _cupsLangPrintf(stderr,
254 _("%s: error - %s environment variable names "
255 "non-existent destination \"%s\"!\n"),
256 argv[0], val, dest);
257 else
258 _cupsLangPrintf(stderr,
259 _("%s: error - no default destination available.\n"),
260 argv[0]);
261 httpClose(http);
262 cupsFreeDests(num_dests, dests);
263 return (1);
264 }
265 }
266
267 /*
268 * Show the status in a loop...
269 */
270
271 for (;;)
272 {
273 if (dest)
274 show_printer(argv[0], http, dest);
275
276 i = show_jobs(argv[0], http, dest, user, id, longstatus);
277
278 if (i && interval)
279 {
280 fflush(stdout);
281 sleep(interval);
282 }
283 else
284 break;
285 }
286
287 /*
288 * Close the connection to the server and return...
289 */
290
291 cupsFreeDests(num_dests, dests);
292 httpClose(http);
293
294 return (0);
295 }
296
297
298 /*
299 * 'connect_server()' - Connect to the server as necessary...
300 */
301
302 static http_t * /* O - New HTTP connection */
303 connect_server(const char *command, /* I - Command name */
304 http_t *http) /* I - Current HTTP connection */
305 {
306 if (!http)
307 {
308 http = httpConnectEncrypt(cupsServer(), ippPort(),
309 cupsEncryption());
310
311 if (http == NULL)
312 {
313 _cupsLangPrintf(stderr, _("%s: Unable to connect to server\n"), command);
314 exit(1);
315 }
316 }
317
318 return (http);
319 }
320
321
322 /*
323 * 'show_jobs()' - Show jobs.
324 */
325
326 static int /* O - Number of jobs in queue */
327 show_jobs(const char *command, /* I - Command name */
328 http_t *http, /* I - HTTP connection to server */
329 const char *dest, /* I - Destination */
330 const char *user, /* I - User */
331 const int id, /* I - Job ID */
332 const int longstatus) /* I - 1 if long report desired */
333 {
334 ipp_t *request, /* IPP Request */
335 *response; /* IPP Response */
336 ipp_attribute_t *attr; /* Current attribute */
337 const char *jobdest, /* Pointer into job-printer-uri */
338 *jobuser, /* Pointer to job-originating-user-name */
339 *jobname; /* Pointer to job-name */
340 ipp_jstate_t jobstate; /* job-state */
341 int jobid, /* job-id */
342 jobsize, /* job-k-octets */
343 #ifdef __osf__
344 jobpriority, /* job-priority */
345 #endif /* __osf__ */
346 jobcount, /* Number of jobs */
347 jobcopies, /* Number of copies */
348 rank; /* Rank of job */
349 char resource[1024]; /* Resource string */
350 char rankstr[255]; /* Rank string */
351 char namestr[1024]; /* Job name string */
352 static const char *ranks[10] = /* Ranking strings */
353 {
354 "th",
355 "st",
356 "nd",
357 "rd",
358 "th",
359 "th",
360 "th",
361 "th",
362 "th",
363 "th"
364 };
365
366
367 DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id,
368 longstatus));
369
370 if (http == NULL)
371 return (0);
372
373 /*
374 * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
375 * the following attributes:
376 *
377 * attributes-charset
378 * attributes-natural-language
379 * job-uri or printer-uri
380 */
381
382 request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS);
383
384 if (dest == NULL)
385 {
386 if (id)
387 sprintf(resource, "ipp://localhost/jobs/%d", id);
388 else
389 strcpy(resource, "ipp://localhost/jobs");
390
391 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
392 NULL, resource);
393 }
394 else
395 {
396 httpAssembleURIf(HTTP_URI_CODING_ALL, resource, sizeof(resource), "ipp",
397 NULL, "localhost", 0, "/printers/%s", dest);
398
399 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
400 NULL, resource);
401 }
402
403 if (user)
404 {
405 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
406 "requesting-user-name", NULL, user);
407 ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
408 }
409
410 /*
411 * Do the request and get back a response...
412 */
413
414 jobcount = 0;
415
416 if ((response = cupsDoRequest(http, request, "/")) != NULL)
417 {
418 if (response->request.status.status_code > IPP_OK_CONFLICT)
419 {
420 _cupsLangPrintf(stderr, "%s: %s\n", command, cupsLastErrorString());
421 ippDelete(response);
422 return (0);
423 }
424
425 rank = 1;
426
427 /*
428 * Loop through the job list and display them...
429 */
430
431 for (attr = response->attrs; attr != NULL; attr = attr->next)
432 {
433 /*
434 * Skip leading attributes until we hit a job...
435 */
436
437 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
438 attr = attr->next;
439
440 if (attr == NULL)
441 break;
442
443 /*
444 * Pull the needed attributes from this job...
445 */
446
447 jobid = 0;
448 jobsize = 0;
449 #ifdef __osf__
450 jobpriority = 50;
451 #endif /* __osf__ */
452 jobstate = IPP_JOB_PENDING;
453 jobname = "untitled";
454 jobuser = NULL;
455 jobdest = NULL;
456 jobcopies = 1;
457
458 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
459 {
460 if (!strcmp(attr->name, "job-id") &&
461 attr->value_tag == IPP_TAG_INTEGER)
462 jobid = attr->values[0].integer;
463
464 if (!strcmp(attr->name, "job-k-octets") &&
465 attr->value_tag == IPP_TAG_INTEGER)
466 jobsize = attr->values[0].integer;
467
468 #ifdef __osf__
469 if (!strcmp(attr->name, "job-priority") &&
470 attr->value_tag == IPP_TAG_INTEGER)
471 jobpriority = attr->values[0].integer;
472 #endif /* __osf__ */
473
474 if (!strcmp(attr->name, "job-state") &&
475 attr->value_tag == IPP_TAG_ENUM)
476 jobstate = (ipp_jstate_t)attr->values[0].integer;
477
478 if (!strcmp(attr->name, "job-printer-uri") &&
479 attr->value_tag == IPP_TAG_URI)
480 if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
481 jobdest ++;
482
483 if (!strcmp(attr->name, "job-originating-user-name") &&
484 attr->value_tag == IPP_TAG_NAME)
485 jobuser = attr->values[0].string.text;
486
487 if (!strcmp(attr->name, "job-name") &&
488 attr->value_tag == IPP_TAG_NAME)
489 jobname = attr->values[0].string.text;
490
491 if (!strcmp(attr->name, "copies") &&
492 attr->value_tag == IPP_TAG_INTEGER)
493 jobcopies = attr->values[0].integer;
494
495 attr = attr->next;
496 }
497
498 /*
499 * See if we have everything needed...
500 */
501
502 if (jobdest == NULL || jobid == 0)
503 {
504 if (attr == NULL)
505 break;
506 else
507 continue;
508 }
509
510 if (!longstatus && jobcount == 0)
511 #ifdef __osf__
512 _cupsLangPuts(stdout,
513 _("Rank Owner Pri Job Files"
514 " Total Size\n"));
515 #else
516 _cupsLangPuts(stdout,
517 _("Rank Owner Job File(s)"
518 " Total Size\n"));
519 #endif /* __osf__ */
520
521 jobcount ++;
522
523 /*
524 * Display the job...
525 */
526
527 if (jobstate == IPP_JOB_PROCESSING)
528 strcpy(rankstr, "active");
529 else
530 {
531 /*
532 * Make the rank show the "correct" suffix for each number
533 * (11-13 are the only special cases, for English anyways...)
534 */
535
536 if ((rank % 100) >= 11 && (rank % 100) <= 13)
537 snprintf(rankstr, sizeof(rankstr), "%dth", rank);
538 else
539 snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
540
541 rank ++;
542 }
543
544 if (longstatus)
545 {
546 _cupsLangPuts(stdout, "\n");
547
548 if (jobcopies > 1)
549 snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
550 jobname);
551 else
552 strlcpy(namestr, jobname, sizeof(namestr));
553
554 _cupsLangPrintf(stdout, _("%s: %-33.33s [job %d localhost]\n"),
555 jobuser, rankstr, jobid);
556 _cupsLangPrintf(stdout, _(" %-39.39s %.0f bytes\n"),
557 namestr, 1024.0 * jobsize);
558 }
559 else
560 #ifdef __osf__
561 _cupsLangPrintf(stdout,
562 _("%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes\n"),
563 rankstr, jobuser, jobpriority, jobid, jobname,
564 1024.0 * jobsize);
565 #else
566 _cupsLangPrintf(stdout,
567 _("%-7s %-7.7s %-7d %-31.31s %.0f bytes\n"),
568 rankstr, jobuser, jobid, jobname, 1024.0 * jobsize);
569 #endif /* __osf */
570
571 if (attr == NULL)
572 break;
573 }
574
575 ippDelete(response);
576 }
577 else
578 {
579 _cupsLangPrintf(stderr, "%s: %s\n", command, cupsLastErrorString());
580 return (0);
581 }
582
583 if (jobcount == 0)
584 _cupsLangPuts(stdout, _("no entries\n"));
585
586 return (jobcount);
587 }
588
589
590 /*
591 * 'show_printer()' - Show printer status.
592 */
593
594 static void
595 show_printer(const char *command, /* I - Command name */
596 http_t *http, /* I - HTTP connection to server */
597 const char *dest) /* I - Destination */
598 {
599 ipp_t *request, /* IPP Request */
600 *response; /* IPP Response */
601 ipp_attribute_t *attr; /* Current attribute */
602 ipp_pstate_t state; /* Printer state */
603 char uri[HTTP_MAX_URI]; /* Printer URI */
604
605
606 if (http == NULL)
607 return;
608
609 /*
610 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
611 * attributes:
612 *
613 * attributes-charset
614 * attributes-natural-language
615 * printer-uri
616 */
617
618 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
619
620 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
621 "localhost", 0, "/printers/%s", dest);
622 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
623 "printer-uri", NULL, uri);
624
625 /*
626 * Do the request and get back a response...
627 */
628
629 if ((response = cupsDoRequest(http, request, "/")) != NULL)
630 {
631 if (response->request.status.status_code > IPP_OK_CONFLICT)
632 {
633 _cupsLangPrintf(stderr, "%s: %s\n", command, cupsLastErrorString());
634 ippDelete(response);
635 return;
636 }
637
638 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
639 state = (ipp_pstate_t)attr->values[0].integer;
640 else
641 state = IPP_PRINTER_STOPPED;
642
643 switch (state)
644 {
645 case IPP_PRINTER_IDLE :
646 _cupsLangPrintf(stdout, _("%s is ready\n"), dest);
647 break;
648 case IPP_PRINTER_PROCESSING :
649 _cupsLangPrintf(stdout, _("%s is ready and printing\n"),
650 dest);
651 break;
652 case IPP_PRINTER_STOPPED :
653 _cupsLangPrintf(stdout, _("%s is not ready\n"), dest);
654 break;
655 }
656
657 ippDelete(response);
658 }
659 else
660 _cupsLangPrintf(stderr, "%s: %s\n", command, cupsLastErrorString());
661 }
662
663
664 /*
665 * 'usage()' - Show program usage.
666 */
667
668 static void
669 usage(void)
670 {
671 _cupsLangPuts(stderr,
672 _("Usage: lpq [-P dest] [-U username] [-h hostname[:port]] "
673 "[-l] [+interval]\n"));
674 exit(1);
675 }
676
677
678 /*
679 * End of "$Id: lpq.c 5925 2006-09-05 19:43:11Z mike $".
680 */