]> git.ipfire.org Git - thirdparty/cups.git/blob - berkeley/lpq.c
Add strlcat() and strlcpy() checks and emulation functions.
[thirdparty/cups.git] / berkeley / lpq.c
1 /*
2 * "$Id: lpq.c,v 1.21 2002/05/16 13:44:51 mike Exp $"
3 *
4 * "lpq" command for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2002 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-3111 USA
19 *
20 * Voice: (301) 373-9603
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 */
30
31 /*
32 * Include necessary headers...
33 */
34
35 /*
36 * Include necessary headers...
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <cups/string.h>
42 #include <cups/cups.h>
43 #include <cups/language.h>
44 #include <cups/debug.h>
45
46
47 /*
48 * Local functions...
49 */
50
51 static int show_jobs(http_t *, const char *, const char *, const int,
52 const int);
53 static void show_printer(http_t *, const char *);
54
55
56 /*
57 * 'main()' - Parse options and commands.
58 */
59
60 int
61 main(int argc, /* I - Number of command-line arguments */
62 char *argv[]) /* I - Command-line arguments */
63 {
64 int i; /* Looping var */
65 http_t *http; /* Connection to server */
66 const char *dest, /* Desired printer */
67 *user; /* Desired user */
68 char *instance; /* Printer instance */
69 int id, /* Desired job ID */
70 interval, /* Reporting interval */
71 longstatus; /* Show file details */
72 int num_dests; /* Number of destinations */
73 cups_dest_t *dests; /* Destinations */
74 #ifdef HAVE_LIBSSL
75 http_encryption_t encryption; /* Encryption? */
76 #endif /* HAVE_LIBSSL */
77
78
79 /*
80 * Connect to the scheduler...
81 */
82
83 if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
84 cupsEncryption())) == NULL)
85 {
86 fputs("lpq: Unable to contact server!\n", stderr);
87 return (1);
88 }
89
90 /*
91 * Check for command-line options...
92 */
93
94 dest = NULL;
95 user = NULL;
96 id = 0;
97 interval = 0;
98 longstatus = 0;
99
100 num_dests = cupsGetDests(&dests);
101
102 for (i = 0; i < num_dests; i ++)
103 if (dests[i].is_default)
104 dest = dests[i].name;
105
106 for (i = 1; i < argc; i ++)
107 if (argv[i][0] == '+')
108 interval = atoi(argv[i] + 1);
109 else if (argv[i][0] == '-')
110 {
111 switch (argv[i][1])
112 {
113 case 'E' : /* Encrypt */
114 #ifdef HAVE_LIBSSL
115 encryption = HTTP_ENCRYPT_REQUIRED;
116
117 if (http)
118 httpEncryption(http, encryption);
119 #else
120 fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
121 argv[0]);
122 #endif /* HAVE_LIBSSL */
123 break;
124
125 case 'P' : /* Printer */
126 if (argv[i][2])
127 dest = argv[i] + 2;
128 else
129 {
130 i ++;
131 dest = argv[i];
132 }
133
134 if ((instance = strchr(dest, '/')) != NULL)
135 *instance = '\0';
136 break;
137
138 case 'a' : /* All printers */
139 dest = NULL;
140 break;
141
142 case 'l' : /* Long status */
143 longstatus = 1;
144 break;
145
146 default :
147 fputs("Usage: lpq [-P dest] [-l] [+interval]\n", stderr);
148 httpClose(http);
149 cupsFreeDests(num_dests, dests);
150 return (1);
151 }
152 }
153 else if (isdigit(argv[i][0]))
154 id = atoi(argv[i]);
155 else
156 user = argv[i];
157
158 /*
159 * Show the status in a loop...
160 */
161
162 for (;;)
163 {
164 if (dest)
165 show_printer(http, dest);
166
167 i = show_jobs(http, dest, user, id, longstatus);
168
169 if (i && interval)
170 {
171 fflush(stdout);
172 sleep(interval);
173 }
174 else
175 break;
176 }
177
178 /*
179 * Close the connection to the server and return...
180 */
181
182 cupsFreeDests(num_dests, dests);
183 httpClose(http);
184
185 return (0);
186 }
187
188
189 /*
190 * 'show_jobs()' - Show jobs.
191 */
192
193 static int /* O - Number of jobs in queue */
194 show_jobs(http_t *http, /* I - HTTP connection to server */
195 const char *dest, /* I - Destination */
196 const char *user, /* I - User */
197 const int id, /* I - Job ID */
198 const int longstatus)/* I - 1 if long report desired */
199 {
200 ipp_t *request, /* IPP Request */
201 *response; /* IPP Response */
202 ipp_attribute_t *attr; /* Current attribute */
203 cups_lang_t *language; /* Default language */
204 const char *jobdest, /* Pointer into job-printer-uri */
205 *jobuser, /* Pointer to job-originating-user-name */
206 *jobname; /* Pointer to job-name */
207 ipp_jstate_t jobstate; /* job-state */
208 int jobid, /* job-id */
209 jobsize, /* job-k-octets */
210 #ifdef __osf__
211 jobpriority, /* job-priority */
212 #endif /* __osf__ */
213 jobcount, /* Number of jobs */
214 jobcopies, /* Number of copies */
215 rank; /* Rank of job */
216 char resource[1024]; /* Resource string */
217 char rankstr[255]; /* Rank string */
218 char namestr[1024]; /* Job name string */
219 static const char *ranks[10] =/* Ranking strings */
220 {
221 "th",
222 "st",
223 "nd",
224 "rd",
225 "th",
226 "th",
227 "th",
228 "th",
229 "th",
230 "th"
231 };
232
233
234 DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id,
235 longstatus));
236
237 if (http == NULL)
238 return (0);
239
240 /*
241 * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
242 * the following attributes:
243 *
244 * attributes-charset
245 * attributes-natural-language
246 * job-uri or printer-uri
247 */
248
249 request = ippNew();
250
251 request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS;
252 request->request.op.request_id = 1;
253
254 language = cupsLangDefault();
255
256 attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
257 "attributes-charset", NULL, cupsLangEncoding(language));
258
259 attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
260 "attributes-natural-language", NULL, language->language);
261
262 if (dest == NULL)
263 {
264 if (id)
265 sprintf(resource, "ipp://localhost/jobs/%d", id);
266 else
267 strcpy(resource, "ipp://localhost/jobs");
268
269 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
270 NULL, resource);
271 }
272 else
273 {
274 snprintf(resource, sizeof(resource), "ipp://localhost/printers/%s", dest);
275
276 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
277 NULL, resource);
278 }
279
280 if (user)
281 {
282 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
283 "requesting-user-name", NULL, user);
284 ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
285 }
286
287 /*
288 * Do the request and get back a response...
289 */
290
291 jobcount = 0;
292
293 if ((response = cupsDoRequest(http, request, "/")) != NULL)
294 {
295 if (response->request.status.status_code > IPP_OK_CONFLICT)
296 {
297 fprintf(stderr, "lpq: get-jobs failed: %s\n",
298 ippErrorString(response->request.status.status_code));
299 ippDelete(response);
300 return (0);
301 }
302
303 rank = 1;
304
305 /*
306 * Loop through the job list and display them...
307 */
308
309 for (attr = response->attrs; attr != NULL; attr = attr->next)
310 {
311 /*
312 * Skip leading attributes until we hit a job...
313 */
314
315 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
316 attr = attr->next;
317
318 if (attr == NULL)
319 break;
320
321 /*
322 * Pull the needed attributes from this job...
323 */
324
325 jobid = 0;
326 jobsize = 0;
327 #ifdef __osf__
328 jobpriority = 50;
329 #endif /* __osf__ */
330 jobstate = IPP_JOB_PENDING;
331 jobname = "untitled";
332 jobuser = NULL;
333 jobdest = NULL;
334 jobcopies = 1;
335
336 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
337 {
338 if (strcmp(attr->name, "job-id") == 0 &&
339 attr->value_tag == IPP_TAG_INTEGER)
340 jobid = attr->values[0].integer;
341
342 if (strcmp(attr->name, "job-k-octets") == 0 &&
343 attr->value_tag == IPP_TAG_INTEGER)
344 jobsize = attr->values[0].integer * 1024;
345
346 #ifdef __osf__
347 if (strcmp(attr->name, "job-priority") == 0 &&
348 attr->value_tag == IPP_TAG_INTEGER)
349 jobpriority = attr->values[0].integer;
350 #endif /* __osf__ */
351
352 if (strcmp(attr->name, "job-state") == 0 &&
353 attr->value_tag == IPP_TAG_ENUM)
354 jobstate = (ipp_jstate_t)attr->values[0].integer;
355
356 if (strcmp(attr->name, "job-printer-uri") == 0 &&
357 attr->value_tag == IPP_TAG_URI)
358 if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
359 jobdest ++;
360
361 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
362 attr->value_tag == IPP_TAG_NAME)
363 jobuser = attr->values[0].string.text;
364
365 if (strcmp(attr->name, "job-name") == 0 &&
366 attr->value_tag == IPP_TAG_NAME)
367 jobname = attr->values[0].string.text;
368
369 if (strcmp(attr->name, "copies") == 0 &&
370 attr->value_tag == IPP_TAG_INTEGER)
371 jobcopies = attr->values[0].integer;
372
373 attr = attr->next;
374 }
375
376 /*
377 * See if we have everything needed...
378 */
379
380 if (jobdest == NULL || jobid == 0)
381 {
382 if (attr == NULL)
383 break;
384 else
385 continue;
386 }
387
388 if (!longstatus && jobcount == 0)
389 #ifdef __osf__
390 puts("Rank Owner Pri Job Files Total Size");
391 #else
392 puts("Rank Owner Job File(s) Total Size");
393 #endif /* __osf__ */
394
395 jobcount ++;
396
397 /*
398 * Display the job...
399 */
400
401 if (jobstate == IPP_JOB_PROCESSING)
402 strcpy(rankstr, "active");
403 else
404 {
405 snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
406 rank ++;
407 }
408
409 if (longstatus)
410 {
411 puts("");
412
413 if (jobcopies > 1)
414 snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
415 jobname);
416 else
417 strlcpy(namestr, jobname, sizeof(namestr));
418
419 printf("%s: %-34.34s[job %d localhost]\n", jobuser, rankstr, jobid);
420 printf(" %-40.40s%d bytes\n", namestr, jobsize);
421 }
422 else
423 #ifdef __osf__
424 printf("%-6s %-10.10s %-4d %-10d %-27.27s %d bytes\n", rankstr, jobuser,
425 jobpriority, jobid, jobname, jobsize);
426 #else
427 printf("%-7s %-8.8s%-8d%-32.32s%d bytes\n", rankstr, jobuser,
428 jobid, jobname, jobsize);
429 #endif /* __osf */
430
431 if (attr == NULL)
432 break;
433 }
434
435 ippDelete(response);
436 }
437 else
438 {
439 fprintf(stderr, "lpq: get-jobs failed: %s\n", ippErrorString(cupsLastError()));
440 return (0);
441 }
442
443 if (jobcount == 0)
444 puts("no entries");
445
446 return (jobcount);
447 }
448
449
450 /*
451 * 'show_printer()' - Show printer status.
452 */
453
454 static void
455 show_printer(http_t *http, /* I - HTTP connection to server */
456 const char *dest) /* I - Destination */
457 {
458 ipp_t *request, /* IPP Request */
459 *response; /* IPP Response */
460 ipp_attribute_t *attr; /* Current attribute */
461 cups_lang_t *language; /* Default language */
462 ipp_pstate_t state; /* Printer state */
463 char uri[HTTP_MAX_URI];
464 /* Printer URI */
465
466
467 if (http == NULL)
468 return;
469
470 /*
471 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
472 * attributes:
473 *
474 * attributes-charset
475 * attributes-natural-language
476 * printer-uri
477 */
478
479 request = ippNew();
480
481 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
482 request->request.op.request_id = 1;
483
484 language = cupsLangDefault();
485
486 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
487 "attributes-charset", NULL, cupsLangEncoding(language));
488
489 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
490 "attributes-natural-language", NULL, language->language);
491
492 snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest);
493 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
494 "printer-uri", NULL, uri);
495
496 /*
497 * Do the request and get back a response...
498 */
499
500 if ((response = cupsDoRequest(http, request, "/")) != NULL)
501 {
502 if (response->request.status.status_code > IPP_OK_CONFLICT)
503 {
504 fprintf(stderr, "lpq: get-printer-attributes failed: %s\n",
505 ippErrorString(response->request.status.status_code));
506 ippDelete(response);
507 return;
508 }
509
510 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
511 state = (ipp_pstate_t)attr->values[0].integer;
512 else
513 state = IPP_PRINTER_STOPPED;
514
515 switch (state)
516 {
517 case IPP_PRINTER_IDLE :
518 printf("%s is ready\n", dest);
519 break;
520 case IPP_PRINTER_PROCESSING :
521 printf("%s is ready and printing\n", dest);
522 break;
523 case IPP_PRINTER_STOPPED :
524 printf("%s is not ready\n", dest);
525 break;
526 }
527
528 ippDelete(response);
529 }
530 else
531 fprintf(stderr, "lpq: get-printer-attributes failed: %s\n",
532 ippErrorString(cupsLastError()));
533 }
534
535
536 /*
537 * End of "$Id: lpq.c,v 1.21 2002/05/16 13:44:51 mike Exp $".
538 */