]> git.ipfire.org Git - thirdparty/cups.git/blob - berkeley/lpc.c
bfa3c1c40f96c87da7760ae77daaf5827817c6ac
[thirdparty/cups.git] / berkeley / lpc.c
1 /*
2 * "lpc" command for CUPS.
3 *
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #include <cups/cups-private.h>
15
16
17 /*
18 * Local functions...
19 */
20
21 static int compare_strings(const char *, const char *, size_t);
22 static void do_command(http_t *, const char *, const char *);
23 static void show_help(const char *);
24 static void show_status(http_t *, const char *);
25
26
27 /*
28 * 'main()' - Parse options and commands.
29 */
30
31 int
32 main(int argc, /* I - Number of command-line arguments */
33 char *argv[]) /* I - Command-line arguments */
34 {
35 http_t *http; /* Connection to server */
36 char line[1024], /* Input line from user */
37 *params; /* Pointer to parameters */
38
39
40 _cupsSetLocale(argv);
41
42 /*
43 * Connect to the scheduler...
44 */
45
46 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
47
48 if (argc > 1)
49 {
50 /*
51 * Process a single command on the command-line...
52 */
53
54 do_command(http, argv[1], argv[2]);
55 }
56 else
57 {
58 /*
59 * Do the command prompt thing...
60 */
61
62 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no-newline version */
63 while (fgets(line, sizeof(line), stdin) != NULL)
64 {
65 /*
66 * Strip trailing whitespace...
67 */
68
69 for (params = line + strlen(line) - 1; params >= line;)
70 if (!isspace(*params & 255))
71 break;
72 else
73 *params-- = '\0';
74
75 /*
76 * Strip leading whitespace...
77 */
78
79 for (params = line; isspace(*params & 255); params ++);
80
81 if (params > line)
82 _cups_strcpy(line, params);
83
84 if (!line[0])
85 {
86 /*
87 * Nothing left, just show a prompt...
88 */
89
90 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */
91 continue;
92 }
93
94 /*
95 * Find any options in the string...
96 */
97
98 for (params = line; *params != '\0'; params ++)
99 if (isspace(*params & 255))
100 break;
101
102 /*
103 * Remove whitespace between the command and parameters...
104 */
105
106 while (isspace(*params & 255))
107 *params++ = '\0';
108
109 /*
110 * The "quit" and "exit" commands exit; otherwise, process as needed...
111 */
112
113 if (!compare_strings(line, "quit", 1) ||
114 !compare_strings(line, "exit", 2))
115 break;
116
117 if (*params == '\0')
118 do_command(http, line, NULL);
119 else
120 do_command(http, line, params);
121
122 /*
123 * Put another prompt out to the user...
124 */
125
126 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */
127 }
128 }
129
130 /*
131 * Close the connection to the server and return...
132 */
133
134 httpClose(http);
135
136 return (0);
137 }
138
139
140 /*
141 * 'compare_strings()' - Compare two command-line strings.
142 */
143
144 static int /* O - -1 or 1 = no match, 0 = match */
145 compare_strings(const char *s, /* I - Command-line string */
146 const char *t, /* I - Option string */
147 size_t tmin) /* I - Minimum number of unique chars in option */
148 {
149 size_t slen; /* Length of command-line string */
150
151
152 slen = strlen(s);
153 if (slen < tmin)
154 return (-1);
155 else
156 return (strncmp(s, t, slen));
157 }
158
159
160 /*
161 * 'do_command()' - Do an lpc command...
162 */
163
164 static void
165 do_command(http_t *http, /* I - HTTP connection to server */
166 const char *command, /* I - Command string */
167 const char *params) /* I - Parameters for command */
168 {
169 if (!compare_strings(command, "status", 4))
170 show_status(http, params);
171 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?"))
172 show_help(params);
173 else
174 _cupsLangPrintf(stdout,
175 _("%s is not implemented by the CUPS version of lpc."),
176 command);
177 }
178
179
180 /*
181 * 'show_help()' - Show help messages.
182 */
183
184 static void
185 show_help(const char *command) /* I - Command to describe or NULL */
186 {
187 if (!command)
188 {
189 _cupsLangPrintf(stdout,
190 _("Commands may be abbreviated. Commands are:\n"
191 "\n"
192 "exit help quit status ?"));
193 }
194 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?"))
195 _cupsLangPrintf(stdout, _("help\t\tGet help on commands."));
196 else if (!compare_strings(command, "status", 4))
197 _cupsLangPrintf(stdout, _("status\t\tShow status of daemon and queue."));
198 else
199 _cupsLangPrintf(stdout, _("?Invalid help command unknown."));
200 }
201
202
203 /*
204 * 'show_status()' - Show printers.
205 */
206
207 static void
208 show_status(http_t *http, /* I - HTTP connection to server */
209 const char *dests) /* I - Destinations */
210 {
211 ipp_t *request, /* IPP Request */
212 *response; /* IPP Response */
213 ipp_attribute_t *attr; /* Current attribute */
214 char *printer, /* Printer name */
215 *device, /* Device URI */
216 *delimiter; /* Char search result */
217 ipp_pstate_t pstate; /* Printer state */
218 int accepting; /* Is printer accepting jobs? */
219 int jobcount; /* Count of current jobs */
220 const char *dptr, /* Pointer into destination list */
221 *ptr; /* Pointer into printer name */
222 int match; /* Non-zero if this job matches */
223 static const char *requested[] = /* Requested attributes */
224 {
225 "device-uri",
226 "printer-is-accepting-jobs",
227 "printer-name",
228 "printer-state",
229 "queued-job-count"
230 };
231
232
233 DEBUG_printf(("show_status(http=%p, dests=\"%s\")\n", http, dests));
234
235 if (http == NULL)
236 return;
237
238 /*
239 * Build a CUPS_GET_PRINTERS request, which requires the following
240 * attributes:
241 *
242 * attributes-charset
243 * attributes-natural-language
244 */
245
246 request = ippNewRequest(CUPS_GET_PRINTERS);
247
248 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
249 "requested-attributes", sizeof(requested) / sizeof(requested[0]),
250 NULL, requested);
251
252 /*
253 * Do the request and get back a response...
254 */
255
256 if ((response = cupsDoRequest(http, request, "/")) != NULL)
257 {
258 DEBUG_puts("show_status: request succeeded...");
259
260 /*
261 * Loop through the printers returned in the list and display
262 * their status...
263 */
264
265 for (attr = response->attrs; attr != NULL; attr = attr->next)
266 {
267 /*
268 * Skip leading attributes until we hit a job...
269 */
270
271 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
272 attr = attr->next;
273
274 if (attr == NULL)
275 break;
276
277 /*
278 * Pull the needed attributes from this job...
279 */
280
281 printer = NULL;
282 device = "file:/dev/null";
283 pstate = IPP_PRINTER_IDLE;
284 jobcount = 0;
285 accepting = 1;
286
287 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
288 {
289 if (!strcmp(attr->name, "device-uri") &&
290 attr->value_tag == IPP_TAG_URI)
291 device = attr->values[0].string.text;
292 else if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
293 attr->value_tag == IPP_TAG_BOOLEAN)
294 accepting = attr->values[0].boolean;
295 else if (!strcmp(attr->name, "printer-name") &&
296 attr->value_tag == IPP_TAG_NAME)
297 printer = attr->values[0].string.text;
298 else if (!strcmp(attr->name, "printer-state") &&
299 attr->value_tag == IPP_TAG_ENUM)
300 pstate = (ipp_pstate_t)attr->values[0].integer;
301 else if (!strcmp(attr->name, "queued-job-count") &&
302 attr->value_tag == IPP_TAG_INTEGER)
303 jobcount = attr->values[0].integer;
304
305 attr = attr->next;
306 }
307
308 /*
309 * See if we have everything needed...
310 */
311
312 if (printer == NULL)
313 {
314 if (attr == NULL)
315 break;
316 else
317 continue;
318 }
319
320 /*
321 * A single 'all' printer name is special, meaning all printers.
322 */
323
324 if (dests != NULL && !strcmp(dests, "all"))
325 dests = NULL;
326
327 /*
328 * See if this is a printer we're interested in...
329 */
330
331 match = dests == NULL;
332
333 if (dests != NULL)
334 {
335 for (dptr = dests; *dptr != '\0';)
336 {
337 /*
338 * Skip leading whitespace and commas...
339 */
340
341 while (isspace(*dptr & 255) || *dptr == ',')
342 dptr ++;
343
344 if (*dptr == '\0')
345 break;
346
347 /*
348 * Compare names...
349 */
350
351 for (ptr = printer;
352 *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
353 ptr ++, dptr ++)
354 /* do nothing */;
355
356 if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' ||
357 isspace(*dptr & 255)))
358 {
359 match = 1;
360 break;
361 }
362
363 /*
364 * Skip trailing junk...
365 */
366
367 while (!isspace(*dptr & 255) && *dptr != '\0')
368 dptr ++;
369 while (isspace(*dptr & 255) || *dptr == ',')
370 dptr ++;
371
372 if (*dptr == '\0')
373 break;
374 }
375 }
376
377 /*
378 * Display the printer entry if needed...
379 */
380
381 if (match)
382 {
383 /*
384 * Display it...
385 */
386
387 printf("%s:\n", printer);
388 if (!strncmp(device, "file:", 5))
389 _cupsLangPrintf(stdout,
390 _("\tprinter is on device \'%s\' speed -1"),
391 device + 5);
392 else
393 {
394 /*
395 * Just show the scheme...
396 */
397
398 if ((delimiter = strchr(device, ':')) != NULL )
399 {
400 *delimiter = '\0';
401 _cupsLangPrintf(stdout,
402 _("\tprinter is on device \'%s\' speed -1"),
403 device);
404 }
405 }
406
407 if (accepting)
408 _cupsLangPuts(stdout, _("\tqueuing is enabled"));
409 else
410 _cupsLangPuts(stdout, _("\tqueuing is disabled"));
411
412 if (pstate != IPP_PRINTER_STOPPED)
413 _cupsLangPuts(stdout, _("\tprinting is enabled"));
414 else
415 _cupsLangPuts(stdout, _("\tprinting is disabled"));
416
417 if (jobcount == 0)
418 _cupsLangPuts(stdout, _("\tno entries"));
419 else
420 _cupsLangPrintf(stdout, _("\t%d entries"), jobcount);
421
422 _cupsLangPuts(stdout, _("\tdaemon present"));
423 }
424
425 if (attr == NULL)
426 break;
427 }
428
429 ippDelete(response);
430 }
431 }