2 * "$Id: lpq.c 4906 2006-01-10 20:53:28Z mike $"
4 * "lpq" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Parse options and commands.
27 * show_jobs() - Show jobs.
28 * show_printer() - Show printer status.
29 * usage() - Show program usage.
33 * Include necessary headers...
37 * Include necessary headers...
42 #include <cups/string.h>
43 #include <cups/cups.h>
44 #include <cups/i18n.h>
45 #include <cups/debug.h>
52 static int show_jobs(http_t
*, const char *, const char *, const int,
54 static void show_printer(http_t
*, const char *);
55 static void usage(void);
59 * 'main()' - Parse options and commands.
63 main(int argc
, /* I - Number of command-line arguments */
64 char *argv
[]) /* I - Command-line arguments */
66 int i
; /* Looping var */
67 http_t
*http
; /* Connection to server */
68 const char *dest
, /* Desired printer */
69 *user
, /* Desired user */
70 *val
; /* Environment variable name */
71 char *instance
; /* Printer instance */
72 int id
, /* Desired job ID */
73 all
, /* All printers */
74 interval
, /* Reporting interval */
75 longstatus
; /* Show file details */
76 int num_dests
; /* Number of destinations */
77 cups_dest_t
*dests
; /* Destinations */
78 cups_lang_t
*language
; /* Language */
80 http_encryption_t encryption
; /* Encryption? */
84 language
= cupsLangDefault();
87 * Connect to the scheduler...
90 if ((http
= httpConnectEncrypt(cupsServer(), ippPort(),
91 cupsEncryption())) == NULL
)
93 _cupsLangPuts(stderr
, language
,
94 _("lpq: Unable to contact server!\n"));
99 * Check for command-line options...
108 num_dests
= cupsGetDests(&dests
);
110 for (i
= 1; i
< argc
; i
++)
111 if (argv
[i
][0] == '+')
112 interval
= atoi(argv
[i
] + 1);
113 else if (argv
[i
][0] == '-')
117 case 'E' : /* Encrypt */
119 encryption
= HTTP_ENCRYPT_REQUIRED
;
122 httpEncryption(http
, encryption
);
124 _cupsLangPrintf(stderr
, language
,
125 _("%s: Sorry, no encryption support compiled in!\n"),
127 #endif /* HAVE_SSL */
130 case 'P' : /* Printer */
140 cupsFreeDests(num_dests
, dests
);
148 if ((instance
= strchr(dest
, '/')) != NULL
)
151 if (cupsGetDest(dest
, instance
, num_dests
, dests
) == NULL
)
154 _cupsLangPrintf(stderr
, language
,
155 _("lpq: Unknown destination \"%s/%s\"!\n"),
158 _cupsLangPrintf(stderr
, language
,
159 _("lpq: Unknown destination \"%s\"!\n"), dest
);
165 case 'a' : /* All printers */
169 case 'l' : /* Long status */
175 cupsFreeDests(num_dests
, dests
);
181 else if (isdigit(argv
[i
][0] & 255))
186 if (dest
== NULL
&& !all
)
188 for (i
= 0; i
< num_dests
; i
++)
189 if (dests
[i
].is_default
)
190 dest
= dests
[i
].name
;
196 if ((dest
= getenv("LPDEST")) == NULL
)
198 if ((dest
= getenv("PRINTER")) != NULL
)
200 if (!strcmp(dest
, "lp"))
209 if (dest
&& !cupsGetDest(dest
, NULL
, num_dests
, dests
))
210 _cupsLangPrintf(stderr
, language
,
211 _("lp: error - %s environment variable names "
212 "non-existent destination \"%s\"!\n"),
215 _cupsLangPuts(stderr
, language
,
216 _("lpq: error - no default destination available.\n"));
218 cupsFreeDests(num_dests
, dests
);
224 * Show the status in a loop...
230 show_printer(http
, dest
);
232 i
= show_jobs(http
, dest
, user
, id
, longstatus
);
244 * Close the connection to the server and return...
247 cupsFreeDests(num_dests
, dests
);
255 * 'show_jobs()' - Show jobs.
258 static int /* O - Number of jobs in queue */
259 show_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 */
265 ipp_t
*request
, /* IPP Request */
266 *response
; /* IPP Response */
267 ipp_attribute_t
*attr
; /* Current attribute */
268 cups_lang_t
*language
; /* Default language */
269 const char *jobdest
, /* Pointer into job-printer-uri */
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 */
276 jobpriority
, /* job-priority */
278 jobcount
, /* Number of jobs */
279 jobcopies
, /* Number of copies */
280 rank
; /* Rank of job */
281 char resource
[1024]; /* Resource string */
282 char rankstr
[255]; /* Rank string */
283 char namestr
[1024]; /* Job name string */
284 static const char *ranks
[10] =/* Ranking strings */
299 DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http
, dest
, user
, id
,
306 * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
307 * the following attributes:
310 * attributes-natural-language
311 * job-uri or printer-uri
316 request
->request
.op
.operation_id
= id
? IPP_GET_JOB_ATTRIBUTES
: IPP_GET_JOBS
;
317 request
->request
.op
.request_id
= 1;
319 language
= cupsLangDefault();
321 attr
= ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
322 "attributes-charset", NULL
, cupsLangEncoding(language
));
324 attr
= ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
325 "attributes-natural-language", NULL
, language
->language
);
330 sprintf(resource
, "ipp://localhost/jobs/%d", id
);
332 strcpy(resource
, "ipp://localhost/jobs");
334 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri",
339 httpAssembleURIf(resource
, sizeof(resource
), "ipp", NULL
, "localhost", 0,
340 "/printers/%s", dest
);
342 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
348 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
349 "requesting-user-name", NULL
, user
);
350 ippAddBoolean(request
, IPP_TAG_OPERATION
, "my-jobs", 1);
354 * Do the request and get back a response...
359 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
361 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
363 _cupsLangPrintf(stderr
, language
, _("lpq: get-jobs failed: %s\n"),
364 ippErrorString(response
->request
.status
.status_code
));
372 * Loop through the job list and display them...
375 for (attr
= response
->attrs
; attr
!= NULL
; attr
= attr
->next
)
378 * Skip leading attributes until we hit a job...
381 while (attr
!= NULL
&& attr
->group_tag
!= IPP_TAG_JOB
)
388 * Pull the needed attributes from this job...
396 jobstate
= IPP_JOB_PENDING
;
397 jobname
= "untitled";
402 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_JOB
)
404 if (strcmp(attr
->name
, "job-id") == 0 &&
405 attr
->value_tag
== IPP_TAG_INTEGER
)
406 jobid
= attr
->values
[0].integer
;
408 if (strcmp(attr
->name
, "job-k-octets") == 0 &&
409 attr
->value_tag
== IPP_TAG_INTEGER
)
410 jobsize
= attr
->values
[0].integer
;
413 if (strcmp(attr
->name
, "job-priority") == 0 &&
414 attr
->value_tag
== IPP_TAG_INTEGER
)
415 jobpriority
= attr
->values
[0].integer
;
418 if (strcmp(attr
->name
, "job-state") == 0 &&
419 attr
->value_tag
== IPP_TAG_ENUM
)
420 jobstate
= (ipp_jstate_t
)attr
->values
[0].integer
;
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
)
427 if (strcmp(attr
->name
, "job-originating-user-name") == 0 &&
428 attr
->value_tag
== IPP_TAG_NAME
)
429 jobuser
= attr
->values
[0].string
.text
;
431 if (strcmp(attr
->name
, "job-name") == 0 &&
432 attr
->value_tag
== IPP_TAG_NAME
)
433 jobname
= attr
->values
[0].string
.text
;
435 if (strcmp(attr
->name
, "copies") == 0 &&
436 attr
->value_tag
== IPP_TAG_INTEGER
)
437 jobcopies
= attr
->values
[0].integer
;
443 * See if we have everything needed...
446 if (jobdest
== NULL
|| jobid
== 0)
454 if (!longstatus
&& jobcount
== 0)
456 _cupsLangPuts(stdout
, language
,
457 _("Rank Owner Pri Job Files"
460 _cupsLangPuts(stdout
, language
,
461 _("Rank Owner Job File(s)"
471 if (jobstate
== IPP_JOB_PROCESSING
)
472 strcpy(rankstr
, "active");
476 * Make the rank show the "correct" suffix for each number
477 * (11-13 are the only special cases, for English anyways...)
480 if ((rank
% 100) >= 11 && (rank
% 100) <= 13)
481 snprintf(rankstr
, sizeof(rankstr
), "%dth", rank
);
483 snprintf(rankstr
, sizeof(rankstr
), "%d%s", rank
, ranks
[rank
% 10]);
490 _cupsLangPuts(stdout
, language
, "");
493 snprintf(namestr
, sizeof(namestr
), "%d copies of %s", jobcopies
,
496 strlcpy(namestr
, jobname
, sizeof(namestr
));
498 _cupsLangPrintf(stdout
, language
, _("%s: %-33.33s [job %d localhost]\n"),
499 jobuser
, rankstr
, jobid
);
500 _cupsLangPrintf(stdout
, language
, _(" %-39.39s %.0f bytes\n"),
501 namestr
, 1024.0 * jobsize
);
505 _cupsLangPrintf(stdout
, language
,
506 _("%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes\n"),
507 rankstr
, jobuser
, jobpriority
, jobid
, jobname
,
510 _cupsLangPrintf(stdout
, language
,
511 _("%-7s %-7.7s %-7d %-31.31s %.0f bytes\n"),
512 rankstr
, jobuser
, jobid
, jobname
, 1024.0 * jobsize
);
523 _cupsLangPrintf(stderr
, language
, _("lpq: get-jobs failed: %s\n"),
524 ippErrorString(cupsLastError()));
529 _cupsLangPuts(stdout
, language
, _("no entries\n"));
536 * 'show_printer()' - Show printer status.
540 show_printer(http_t
*http
, /* I - HTTP connection to server */
541 const char *dest
) /* I - Destination */
543 ipp_t
*request
, /* IPP Request */
544 *response
; /* IPP Response */
545 ipp_attribute_t
*attr
; /* Current attribute */
546 cups_lang_t
*language
; /* Default language */
547 ipp_pstate_t state
; /* Printer state */
548 char uri
[HTTP_MAX_URI
];
556 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
560 * attributes-natural-language
566 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
567 request
->request
.op
.request_id
= 1;
569 language
= cupsLangDefault();
571 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
572 "attributes-charset", NULL
, cupsLangEncoding(language
));
574 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
575 "attributes-natural-language", NULL
, language
->language
);
577 httpAssembleURIf(uri
, sizeof(uri
), "ipp", NULL
, "localhost", 0,
578 "/printers/%s", dest
);
579 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
580 "printer-uri", NULL
, uri
);
583 * Do the request and get back a response...
586 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
588 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
590 _cupsLangPrintf(stderr
, language
,
591 _("lpq: get-printer-attributes failed: %s\n"),
592 ippErrorString(response
->request
.status
.status_code
));
597 if ((attr
= ippFindAttribute(response
, "printer-state", IPP_TAG_ENUM
)) != NULL
)
598 state
= (ipp_pstate_t
)attr
->values
[0].integer
;
600 state
= IPP_PRINTER_STOPPED
;
604 case IPP_PRINTER_IDLE
:
605 _cupsLangPrintf(stdout
, language
, _("%s is ready\n"), dest
);
607 case IPP_PRINTER_PROCESSING
:
608 _cupsLangPrintf(stdout
, language
, _("%s is ready and printing\n"),
611 case IPP_PRINTER_STOPPED
:
612 _cupsLangPrintf(stdout
, language
, _("%s is not ready\n"), dest
);
619 _cupsLangPrintf(stderr
, language
,
620 _("lpq: get-printer-attributes failed: %s\n"),
621 ippErrorString(cupsLastError()));
626 * 'usage()' - Show program usage.
632 _cupsLangPuts(stderr
, cupsLangDefault(),
633 _("Usage: lpq [-P dest] [-l] [+interval]\n"));
639 * End of "$Id: lpq.c 4906 2006-01-10 20:53:28Z mike $".