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