]>
Commit | Line | Data |
---|---|---|
bd0b97ff | 1 | /* |
64bbab09 | 2 | * "$Id: lpc.c,v 1.11.2.9 2004/02/25 16:58:31 mike Exp $" |
bd0b97ff | 3 | * |
4 | * "lpc" command for the Common UNIX Printing System (CUPS). | |
5 | * | |
1d9595ab | 6 | * Copyright 1997-2003 by Easy Software Products. |
bd0b97ff | 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 | * compare_strings() - Compare two command-line strings. | |
28 | * do_command() - Do an lpc command... | |
29 | * show_help() - Show help messages. | |
30 | * show_status() - Show printers. | |
31 | */ | |
32 | ||
33 | /* | |
34 | * Include necessary headers... | |
35 | */ | |
36 | ||
37 | #include <stdio.h> | |
38 | #include <stdlib.h> | |
bd0b97ff | 39 | #include <cups/cups.h> |
40 | #include <cups/language.h> | |
41 | #include <cups/debug.h> | |
7680b71d | 42 | #include <cups/string.h> |
bd0b97ff | 43 | |
44 | ||
45 | /* | |
46 | * Local functions... | |
47 | */ | |
48 | ||
49 | static int compare_strings(char *, char *, int); | |
50 | static void do_command(http_t *, char *, char *); | |
51 | static void show_help(char *); | |
52 | static void show_status(http_t *, char *); | |
53 | ||
54 | ||
55 | /* | |
56 | * 'main()' - Parse options and commands. | |
57 | */ | |
58 | ||
59 | int | |
60 | main(int argc, /* I - Number of command-line arguments */ | |
61 | char *argv[]) /* I - Command-line arguments */ | |
62 | { | |
bd0b97ff | 63 | http_t *http; /* Connection to server */ |
64 | char line[1024], /* Input line from user */ | |
65 | *params; /* Pointer to parameters */ | |
66 | ||
67 | ||
68 | /* | |
69 | * Connect to the scheduler... | |
70 | */ | |
71 | ||
b5cb0608 | 72 | http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); |
bd0b97ff | 73 | |
74 | if (argc > 1) | |
75 | { | |
76 | /* | |
77 | * Process a single command on the command-line... | |
78 | */ | |
79 | ||
80 | do_command(http, argv[1], argv[2]); | |
81 | } | |
82 | else | |
83 | { | |
84 | /* | |
85 | * Do the command prompt thing... | |
86 | */ | |
87 | ||
88 | printf("lpc> "); | |
9c255021 | 89 | while (fgets(line, sizeof(line), stdin) != NULL) |
bd0b97ff | 90 | { |
9c255021 | 91 | /* |
92 | * Strip the trailing newline... | |
93 | */ | |
94 | ||
95 | line[strlen(line) - 1] = '\0'; | |
96 | ||
bd0b97ff | 97 | /* |
98 | * Find any options in the string... | |
99 | */ | |
100 | ||
64bbab09 | 101 | while (isspace(line[0] & 255)) |
ff40b65e | 102 | cups_strcpy(line, line + 1); |
bd0b97ff | 103 | |
104 | for (params = line; *params != '\0'; params ++) | |
64bbab09 | 105 | if (isspace(*params & 255)) |
bd0b97ff | 106 | break; |
107 | ||
108 | /* | |
109 | * Remove whitespace between the command and parameters... | |
110 | */ | |
111 | ||
64bbab09 | 112 | while (isspace(*params & 255)) |
bd0b97ff | 113 | *params++ = '\0'; |
114 | ||
115 | /* | |
116 | * The "quit" and "exit" commands exit; otherwise, process as needed... | |
117 | */ | |
118 | ||
119 | if (compare_strings(line, "quit", 1) == 0 || | |
120 | compare_strings(line, "exit", 2) == 0) | |
121 | break; | |
122 | ||
123 | if (*params == '\0') | |
124 | do_command(http, line, NULL); | |
125 | else | |
126 | do_command(http, line, params); | |
127 | ||
128 | /* | |
129 | * Put another prompt out to the user... | |
130 | */ | |
131 | ||
132 | printf("lpc> "); | |
133 | } | |
134 | } | |
135 | ||
136 | /* | |
137 | * Close the connection to the server and return... | |
138 | */ | |
139 | ||
140 | httpClose(http); | |
141 | ||
142 | return (0); | |
143 | } | |
144 | ||
145 | ||
146 | /* | |
147 | * 'compare_strings()' - Compare two command-line strings. | |
148 | */ | |
149 | ||
150 | static int /* O - -1 or 1 = no match, 0 = match */ | |
151 | compare_strings(char *s, /* I - Command-line string */ | |
152 | char *t, /* I - Option string */ | |
153 | int tmin) /* I - Minimum number of unique chars in option */ | |
154 | { | |
155 | int slen; /* Length of command-line string */ | |
156 | ||
157 | ||
158 | slen = strlen(s); | |
159 | if (slen < tmin) | |
160 | return (-1); | |
161 | else | |
162 | return (strncmp(s, t, slen)); | |
163 | } | |
164 | ||
165 | ||
166 | /* | |
167 | * 'do_command()' - Do an lpc command... | |
168 | */ | |
169 | ||
170 | static void | |
171 | do_command(http_t *http, /* I - HTTP connection to server */ | |
172 | char *command, /* I - Command string */ | |
173 | char *params) /* I - Parameters for command */ | |
174 | { | |
175 | if (compare_strings(command, "status", 4) == 0) | |
176 | show_status(http, params); | |
177 | else if (compare_strings(command, "help", 1) == 0 || | |
178 | strcmp(command, "?") == 0) | |
179 | show_help(params); | |
180 | else | |
1cb10d96 | 181 | printf("%s is not implemented by the CUPS version of lpc.\n", command); |
bd0b97ff | 182 | } |
183 | ||
184 | ||
185 | /* | |
186 | * 'show_help()' - Show help messages. | |
187 | */ | |
188 | ||
189 | static void | |
190 | show_help(char *command) /* I - Command to describe or NULL */ | |
191 | { | |
192 | if (command == NULL) | |
193 | { | |
194 | puts("Commands may be abbreviated. Commands are:"); | |
195 | puts(""); | |
196 | puts("exit help quit status ?"); | |
197 | } | |
198 | else if (compare_strings(command, "help", 1) == 0 || | |
199 | strcmp(command, "?") == 0) | |
200 | puts("help\t\tget help on commands"); | |
201 | else if (compare_strings(command, "status", 4) == 0) | |
202 | puts("status\t\tshow status of daemon and queue"); | |
203 | else | |
204 | puts("?Invalid help command unknown"); | |
205 | } | |
206 | ||
207 | ||
208 | /* | |
209 | * 'show_status()' - Show printers. | |
210 | */ | |
211 | ||
212 | static void | |
213 | show_status(http_t *http, /* I - HTTP connection to server */ | |
214 | char *dests) /* I - Destinations */ | |
215 | { | |
216 | ipp_t *request, /* IPP Request */ | |
217 | *response, /* IPP Response */ | |
218 | *jobs; /* IPP Get Jobs response */ | |
92db514a | 219 | ipp_attribute_t *attr, /* Current attribute */ |
220 | *jattr; /* Current job attribute */ | |
bd0b97ff | 221 | cups_lang_t *language; /* Default language */ |
222 | char *printer, /* Printer name */ | |
6f83172d | 223 | *device, /* Device URI */ |
224 | *delimiter; /* Char search result */ | |
bd0b97ff | 225 | ipp_pstate_t pstate; /* Printer state */ |
226 | int accepting; /* Is printer accepting jobs? */ | |
227 | int jobcount; /* Count of current jobs */ | |
228 | char *dptr, /* Pointer into destination list */ | |
229 | *ptr; /* Pointer into printer name */ | |
230 | int match; /* Non-zero if this job matches */ | |
231 | char printer_uri[HTTP_MAX_URI]; | |
232 | /* Printer URI */ | |
92db514a | 233 | static const char *requested[] = |
234 | { /* Requested attributes */ | |
235 | "printer-name", | |
236 | "device-uri", | |
237 | "printer-state", | |
238 | "printer-is-accepting-jobs" | |
239 | }; | |
bd0b97ff | 240 | |
241 | ||
f8ab8b97 | 242 | DEBUG_printf(("show_status(%08x, %08x)\n", http, dests)); |
bd0b97ff | 243 | |
244 | if (http == NULL) | |
245 | return; | |
246 | ||
247 | /* | |
248 | * Build a CUPS_GET_PRINTERS request, which requires the following | |
249 | * attributes: | |
250 | * | |
251 | * attributes-charset | |
252 | * attributes-natural-language | |
253 | */ | |
254 | ||
255 | request = ippNew(); | |
256 | ||
0a3ac972 | 257 | request->request.op.operation_id = CUPS_GET_PRINTERS; |
258 | request->request.op.request_id = 1; | |
bd0b97ff | 259 | |
260 | language = cupsLangDefault(); | |
261 | ||
92db514a | 262 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, |
263 | "attributes-charset", NULL, cupsLangEncoding(language)); | |
bd0b97ff | 264 | |
92db514a | 265 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, |
266 | "attributes-natural-language", NULL, language->language); | |
267 | ||
268 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
269 | "requested-attributes", sizeof(requested) / sizeof(requested[0]), | |
270 | NULL, requested); | |
bd0b97ff | 271 | |
272 | /* | |
273 | * Do the request and get back a response... | |
274 | */ | |
275 | ||
276 | if ((response = cupsDoRequest(http, request, "/printers/")) != NULL) | |
277 | { | |
f8ab8b97 | 278 | DEBUG_puts("show_status: request succeeded..."); |
bd0b97ff | 279 | |
280 | /* | |
281 | * Loop through the printers returned in the list and display | |
282 | * their status... | |
283 | */ | |
284 | ||
285 | for (attr = response->attrs; attr != NULL; attr = attr->next) | |
286 | { | |
287 | /* | |
288 | * Skip leading attributes until we hit a job... | |
289 | */ | |
290 | ||
291 | while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) | |
292 | attr = attr->next; | |
293 | ||
294 | if (attr == NULL) | |
295 | break; | |
296 | ||
297 | /* | |
298 | * Pull the needed attributes from this job... | |
299 | */ | |
300 | ||
301 | printer = NULL; | |
302 | device = "file:/dev/null"; | |
303 | pstate = IPP_PRINTER_IDLE; | |
304 | jobcount = 0; | |
305 | accepting = 1; | |
306 | ||
307 | while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) | |
308 | { | |
309 | if (strcmp(attr->name, "printer-name") == 0 && | |
310 | attr->value_tag == IPP_TAG_NAME) | |
311 | printer = attr->values[0].string.text; | |
312 | ||
313 | if (strcmp(attr->name, "device-uri") == 0 && | |
314 | attr->value_tag == IPP_TAG_URI) | |
315 | device = attr->values[0].string.text; | |
316 | ||
317 | if (strcmp(attr->name, "printer-state") == 0 && | |
318 | attr->value_tag == IPP_TAG_ENUM) | |
319 | pstate = (ipp_pstate_t)attr->values[0].integer; | |
320 | ||
321 | if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 && | |
322 | attr->value_tag == IPP_TAG_BOOLEAN) | |
323 | accepting = attr->values[0].boolean; | |
324 | ||
325 | attr = attr->next; | |
326 | } | |
327 | ||
328 | /* | |
329 | * See if we have everything needed... | |
330 | */ | |
331 | ||
332 | if (printer == NULL) | |
333 | { | |
334 | if (attr == NULL) | |
335 | break; | |
336 | else | |
337 | continue; | |
338 | } | |
339 | ||
340 | /* | |
341 | * See if this is a printer we're interested in... | |
342 | */ | |
343 | ||
344 | match = dests == NULL; | |
345 | ||
346 | if (dests != NULL) | |
347 | { | |
348 | for (dptr = dests; *dptr != '\0';) | |
349 | { | |
350 | /* | |
351 | * Skip leading whitespace and commas... | |
352 | */ | |
353 | ||
64bbab09 | 354 | while (isspace(*dptr & 255) || *dptr == ',') |
bd0b97ff | 355 | dptr ++; |
356 | ||
357 | if (*dptr == '\0') | |
358 | break; | |
359 | ||
360 | /* | |
361 | * Compare names... | |
362 | */ | |
363 | ||
364 | for (ptr = printer; | |
365 | *ptr != '\0' && *dptr != '\0' && *ptr == *dptr; | |
366 | ptr ++, dptr ++); | |
367 | ||
64bbab09 | 368 | if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255))) |
bd0b97ff | 369 | { |
370 | match = 1; | |
371 | break; | |
372 | } | |
373 | ||
374 | /* | |
375 | * Skip trailing junk... | |
376 | */ | |
377 | ||
64bbab09 | 378 | while (!isspace(*dptr & 255) && *dptr != '\0') |
bd0b97ff | 379 | dptr ++; |
64bbab09 | 380 | while (isspace(*dptr & 255) || *dptr == ',') |
bd0b97ff | 381 | dptr ++; |
382 | ||
383 | if (*dptr == '\0') | |
384 | break; | |
385 | } | |
386 | } | |
387 | ||
388 | /* | |
389 | * Display the printer entry if needed... | |
390 | */ | |
391 | ||
392 | if (match) | |
393 | { | |
394 | /* | |
395 | * If the printer state is "IPP_PRINTER_PROCESSING", then grab the | |
396 | * current job for the printer. | |
397 | */ | |
398 | ||
399 | if (pstate == IPP_PRINTER_PROCESSING) | |
400 | { | |
401 | /* | |
402 | * Build an IPP_GET_JOBS request, which requires the following | |
403 | * attributes: | |
404 | * | |
405 | * attributes-charset | |
406 | * attributes-natural-language | |
407 | * printer-uri | |
408 | * limit | |
409 | */ | |
410 | ||
411 | request = ippNew(); | |
412 | ||
0a3ac972 | 413 | request->request.op.operation_id = IPP_GET_JOBS; |
414 | request->request.op.request_id = 1; | |
bd0b97ff | 415 | |
416 | language = cupsLangDefault(); | |
417 | ||
f8ab8b97 | 418 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, |
419 | "attributes-charset", NULL, | |
420 | cupsLangEncoding(language)); | |
bd0b97ff | 421 | |
f8ab8b97 | 422 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, |
423 | "attributes-natural-language", NULL, | |
424 | language->language); | |
bd0b97ff | 425 | |
970017a4 | 426 | snprintf(printer_uri, sizeof(printer_uri), |
427 | "ipp://localhost/printers/%s", printer); | |
92db514a | 428 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
429 | "printer-uri", NULL, printer_uri); | |
430 | ||
431 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
432 | "requested-attributes", NULL, "job-id"); | |
bd0b97ff | 433 | |
434 | if ((jobs = cupsDoRequest(http, request, "/jobs/")) != NULL) | |
435 | { | |
92db514a | 436 | for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next) |
437 | if (jattr->name && strcmp(jattr->name, "job-id") == 0) | |
bd0b97ff | 438 | jobcount ++; |
439 | ||
440 | ippDelete(jobs); | |
441 | } | |
442 | } | |
443 | ||
444 | /* | |
445 | * Display it... | |
446 | */ | |
447 | ||
448 | printf("%s:\n", printer); | |
449 | if (strncmp(device, "file:", 5) == 0) | |
450 | printf("\tprinter is on device \'%s\' speed -1\n", device + 5); | |
451 | else | |
344de3be | 452 | { |
453 | /* | |
454 | * Just show the method... | |
455 | */ | |
456 | ||
6f83172d | 457 | if ((delimiter = strchr(device, ':')) != NULL ) |
458 | { | |
459 | *delimiter = '\0'; | |
460 | printf("\tprinter is on device \'%s\' speed -1\n", device); | |
461 | } | |
344de3be | 462 | } |
463 | ||
bd0b97ff | 464 | printf("\tqueuing is %sabled\n", accepting ? "en" : "dis"); |
465 | printf("\tprinting is %sabled\n", | |
466 | pstate == IPP_PRINTER_STOPPED ? "dis" : "en"); | |
467 | if (jobcount == 0) | |
468 | puts("\tno entries"); | |
469 | else | |
470 | printf("\t%d entries\n", jobcount); | |
471 | puts("\tdaemon present"); | |
472 | } | |
473 | ||
474 | if (attr == NULL) | |
475 | break; | |
476 | } | |
477 | ||
478 | ippDelete(response); | |
479 | } | |
480 | } | |
481 | ||
482 | ||
483 | /* | |
64bbab09 | 484 | * End of "$Id: lpc.c,v 1.11.2.9 2004/02/25 16:58:31 mike Exp $". |
bd0b97ff | 485 | */ |