]> git.ipfire.org Git - thirdparty/cups.git/blob - berkeley/lpc.c
71402294eb773ee8ff6dc7844d97057315b6fcbc
[thirdparty/cups.git] / berkeley / lpc.c
1 /*
2 * "$Id$"
3 *
4 * "lpc" command for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 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 USA
19 *
20 * Voice: (301) 373-9600
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>
39 #include <cups/cups.h>
40 #include <cups/i18n.h>
41 #include <cups/debug.h>
42 #include <cups/string.h>
43
44
45 /*
46 * Local functions...
47 */
48
49 static int compare_strings(const char *, const char *, int);
50 static void do_command(http_t *, const char *, const char *);
51 static void show_help(const char *);
52 static void show_status(http_t *, const 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 {
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
72 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
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 _cupsLangPuts(stdout, _("lpc> "));
89 while (fgets(line, sizeof(line), stdin) != NULL)
90 {
91 /*
92 * Strip trailing whitespace...
93 */
94
95 for (params = line + strlen(line) - 1; params >= line;)
96 if (!isspace(*params & 255))
97 break;
98 else
99 *params-- = '\0';
100
101 /*
102 * Strip leading whitespace...
103 */
104
105 for (params = line; isspace(*params & 255); params ++);
106
107 if (params > line)
108 _cups_strcpy(line, params);
109
110 if (!line[0])
111 {
112 /*
113 * Nothing left, just show a prompt...
114 */
115
116 _cupsLangPuts(stdout, _("lpc> "));
117 continue;
118 }
119
120 /*
121 * Find any options in the string...
122 */
123
124 for (params = line; *params != '\0'; params ++)
125 if (isspace(*params & 255))
126 break;
127
128 /*
129 * Remove whitespace between the command and parameters...
130 */
131
132 while (isspace(*params & 255))
133 *params++ = '\0';
134
135 /*
136 * The "quit" and "exit" commands exit; otherwise, process as needed...
137 */
138
139 if (!compare_strings(line, "quit", 1) ||
140 !compare_strings(line, "exit", 2))
141 break;
142
143 if (*params == '\0')
144 do_command(http, line, NULL);
145 else
146 do_command(http, line, params);
147
148 /*
149 * Put another prompt out to the user...
150 */
151
152 _cupsLangPuts(stdout, _("lpc> "));
153 }
154 }
155
156 /*
157 * Close the connection to the server and return...
158 */
159
160 httpClose(http);
161
162 return (0);
163 }
164
165
166 /*
167 * 'compare_strings()' - Compare two command-line strings.
168 */
169
170 static int /* O - -1 or 1 = no match, 0 = match */
171 compare_strings(const char *s, /* I - Command-line string */
172 const char *t, /* I - Option string */
173 int tmin) /* I - Minimum number of unique chars in option */
174 {
175 int slen; /* Length of command-line string */
176
177
178 slen = strlen(s);
179 if (slen < tmin)
180 return (-1);
181 else
182 return (strncmp(s, t, slen));
183 }
184
185
186 /*
187 * 'do_command()' - Do an lpc command...
188 */
189
190 static void
191 do_command(http_t *http, /* I - HTTP connection to server */
192 const char *command, /* I - Command string */
193 const char *params) /* I - Parameters for command */
194 {
195 if (!compare_strings(command, "status", 4))
196 show_status(http, params);
197 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?"))
198 show_help(params);
199 else
200 _cupsLangPrintf(stdout,
201 _("%s is not implemented by the CUPS version of lpc.\n"),
202 command);
203 }
204
205
206 /*
207 * 'show_help()' - Show help messages.
208 */
209
210 static void
211 show_help(const char *command) /* I - Command to describe or NULL */
212 {
213 if (!command)
214 {
215 _cupsLangPrintf(stdout,
216 _("Commands may be abbreviated. Commands are:\n"
217 "\n"
218 "exit help quit status ?\n"));
219 }
220 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?"))
221 _cupsLangPrintf(stdout, _("help\t\tget help on commands\n"));
222 else if (!compare_strings(command, "status", 4))
223 _cupsLangPrintf(stdout, _("status\t\tshow status of daemon and queue\n"));
224 else
225 _cupsLangPrintf(stdout, _("?Invalid help command unknown\n"));
226 }
227
228
229 /*
230 * 'show_status()' - Show printers.
231 */
232
233 static void
234 show_status(http_t *http, /* I - HTTP connection to server */
235 const char *dests) /* I - Destinations */
236 {
237 ipp_t *request, /* IPP Request */
238 *response, /* IPP Response */
239 *jobs; /* IPP Get Jobs response */
240 ipp_attribute_t *attr, /* Current attribute */
241 *jattr; /* Current job attribute */
242 cups_lang_t *language; /* Default language */
243 char *printer, /* Printer name */
244 *device, /* Device URI */
245 *delimiter; /* Char search result */
246 ipp_pstate_t pstate; /* Printer state */
247 int accepting; /* Is printer accepting jobs? */
248 int jobcount; /* Count of current jobs */
249 const char *dptr, /* Pointer into destination list */
250 *ptr; /* Pointer into printer name */
251 int match; /* Non-zero if this job matches */
252 char printer_uri[HTTP_MAX_URI];
253 /* Printer URI */
254 static const char *requested[] = /* Requested attributes */
255 {
256 "printer-name",
257 "device-uri",
258 "printer-state",
259 "printer-is-accepting-jobs"
260 };
261
262
263 DEBUG_printf(("show_status(http=%p, dests=\"%s\")\n", http, dests));
264
265 if (http == NULL)
266 return;
267
268 /*
269 * Build a CUPS_GET_PRINTERS request, which requires the following
270 * attributes:
271 *
272 * attributes-charset
273 * attributes-natural-language
274 */
275
276 request = ippNew();
277
278 request->request.op.operation_id = CUPS_GET_PRINTERS;
279 request->request.op.request_id = 1;
280
281 language = cupsLangDefault();
282
283 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
284 "attributes-charset", NULL, cupsLangEncoding(language));
285
286 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
287 "attributes-natural-language", NULL, language->language);
288
289 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
290 "requested-attributes", sizeof(requested) / sizeof(requested[0]),
291 NULL, requested);
292
293 /*
294 * Do the request and get back a response...
295 */
296
297 if ((response = cupsDoRequest(http, request, "/")) != NULL)
298 {
299 DEBUG_puts("show_status: request succeeded...");
300
301 /*
302 * Loop through the printers returned in the list and display
303 * their status...
304 */
305
306 for (attr = response->attrs; attr != NULL; attr = attr->next)
307 {
308 /*
309 * Skip leading attributes until we hit a job...
310 */
311
312 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
313 attr = attr->next;
314
315 if (attr == NULL)
316 break;
317
318 /*
319 * Pull the needed attributes from this job...
320 */
321
322 printer = NULL;
323 device = "file:/dev/null";
324 pstate = IPP_PRINTER_IDLE;
325 jobcount = 0;
326 accepting = 1;
327
328 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
329 {
330 if (!strcmp(attr->name, "printer-name") &&
331 attr->value_tag == IPP_TAG_NAME)
332 printer = attr->values[0].string.text;
333
334 if (!strcmp(attr->name, "device-uri") &&
335 attr->value_tag == IPP_TAG_URI)
336 device = attr->values[0].string.text;
337
338 if (!strcmp(attr->name, "printer-state") &&
339 attr->value_tag == IPP_TAG_ENUM)
340 pstate = (ipp_pstate_t)attr->values[0].integer;
341
342 if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
343 attr->value_tag == IPP_TAG_BOOLEAN)
344 accepting = attr->values[0].boolean;
345
346 attr = attr->next;
347 }
348
349 /*
350 * See if we have everything needed...
351 */
352
353 if (printer == NULL)
354 {
355 if (attr == NULL)
356 break;
357 else
358 continue;
359 }
360
361 /*
362 * A single 'all' printer name is special, meaning all printers.
363 */
364
365 if (dests != NULL && !strcmp(dests, "all"))
366 dests = NULL;
367
368 /*
369 * See if this is a printer we're interested in...
370 */
371
372 match = dests == NULL;
373
374 if (dests != NULL)
375 {
376 for (dptr = dests; *dptr != '\0';)
377 {
378 /*
379 * Skip leading whitespace and commas...
380 */
381
382 while (isspace(*dptr & 255) || *dptr == ',')
383 dptr ++;
384
385 if (*dptr == '\0')
386 break;
387
388 /*
389 * Compare names...
390 */
391
392 for (ptr = printer;
393 *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
394 ptr ++, dptr ++);
395
396 if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
397 {
398 match = 1;
399 break;
400 }
401
402 /*
403 * Skip trailing junk...
404 */
405
406 while (!isspace(*dptr & 255) && *dptr != '\0')
407 dptr ++;
408 while (isspace(*dptr & 255) || *dptr == ',')
409 dptr ++;
410
411 if (*dptr == '\0')
412 break;
413 }
414 }
415
416 /*
417 * Display the printer entry if needed...
418 */
419
420 if (match)
421 {
422 /*
423 * Build an IPP_GET_JOBS request, which requires the following
424 * attributes:
425 *
426 * attributes-charset
427 * attributes-natural-language
428 * printer-uri
429 * limit
430 */
431
432 request = ippNew();
433
434 request->request.op.operation_id = IPP_GET_JOBS;
435 request->request.op.request_id = 1;
436
437 language = cupsLangDefault();
438
439 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
440 "attributes-charset", NULL,
441 cupsLangEncoding(language));
442
443 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
444 "attributes-natural-language", NULL,
445 language->language);
446
447 httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
448 "ipp", NULL, "localhost", 631, "/printers/%s",
449 printer);
450 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
451 "printer-uri", NULL, printer_uri);
452
453 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
454 "requested-attributes", NULL, "job-id");
455
456 if ((jobs = cupsDoRequest(http, request, "/")) != NULL)
457 {
458 /*
459 * Grab the number of jobs for the printer.
460 */
461
462 for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next)
463 if (jattr->name && !strcmp(jattr->name, "job-id"))
464 jobcount ++;
465
466 ippDelete(jobs);
467 }
468
469 /*
470 * Display it...
471 */
472
473 printf("%s:\n", printer);
474 if (!strncmp(device, "file:", 5))
475 _cupsLangPrintf(stdout,
476 _("\tprinter is on device \'%s\' speed -1\n"),
477 device + 5);
478 else
479 {
480 /*
481 * Just show the scheme...
482 */
483
484 if ((delimiter = strchr(device, ':')) != NULL )
485 {
486 *delimiter = '\0';
487 _cupsLangPrintf(stdout,
488 _("\tprinter is on device \'%s\' speed -1\n"),
489 device);
490 }
491 }
492
493 if (accepting)
494 _cupsLangPuts(stdout, _("\tqueuing is enabled\n"));
495 else
496 _cupsLangPuts(stdout, _("\tqueuing is disabled\n"));
497
498 if (pstate != IPP_PRINTER_STOPPED)
499 _cupsLangPuts(stdout, _("\tprinting is enabled\n"));
500 else
501 _cupsLangPuts(stdout, _("\tprinting is disabled\n"));
502
503 if (jobcount == 0)
504 _cupsLangPuts(stdout, _("\tno entries\n"));
505 else
506 _cupsLangPrintf(stdout, _("\t%d entries\n"), jobcount);
507
508 _cupsLangPuts(stdout, _("\tdaemon present\n"));
509 }
510
511 if (attr == NULL)
512 break;
513 }
514
515 ippDelete(response);
516 }
517 }
518
519
520 /*
521 * End of "$Id$".
522 */