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