• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
main(int argc,char * argv[])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 */
compare_strings(const char * s,const char * t,size_t tmin)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
do_command(http_t * http,const char * command,const char * params)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
show_help(const char * command)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
show_status(http_t * http,const char * dests)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   if (http == NULL)
234     return;
235 
236  /*
237   * Build a CUPS_GET_PRINTERS request, which requires the following
238   * attributes:
239   *
240   *    attributes-charset
241   *    attributes-natural-language
242   */
243 
244   request = ippNewRequest(CUPS_GET_PRINTERS);
245 
246   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
247                 "requested-attributes", sizeof(requested) / sizeof(requested[0]),
248 		NULL, requested);
249 
250  /*
251   * Do the request and get back a response...
252   */
253 
254   if ((response = cupsDoRequest(http, request, "/")) != NULL)
255   {
256    /*
257     * Loop through the printers returned in the list and display
258     * their status...
259     */
260 
261     for (attr = response->attrs; attr != NULL; attr = attr->next)
262     {
263      /*
264       * Skip leading attributes until we hit a job...
265       */
266 
267       while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
268         attr = attr->next;
269 
270       if (attr == NULL)
271         break;
272 
273      /*
274       * Pull the needed attributes from this job...
275       */
276 
277       printer   = NULL;
278       device    = "file:/dev/null";
279       pstate    = IPP_PRINTER_IDLE;
280       jobcount  = 0;
281       accepting = 1;
282 
283       while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
284       {
285         if (!strcmp(attr->name, "device-uri") &&
286 	    attr->value_tag == IPP_TAG_URI)
287 	  device = attr->values[0].string.text;
288         else if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
289 	         attr->value_tag == IPP_TAG_BOOLEAN)
290 	  accepting = attr->values[0].boolean;
291         else if (!strcmp(attr->name, "printer-name") &&
292 	         attr->value_tag == IPP_TAG_NAME)
293 	  printer = attr->values[0].string.text;
294         else if (!strcmp(attr->name, "printer-state") &&
295 	         attr->value_tag == IPP_TAG_ENUM)
296 	  pstate = (ipp_pstate_t)attr->values[0].integer;
297         else if (!strcmp(attr->name, "queued-job-count") &&
298 	         attr->value_tag == IPP_TAG_INTEGER)
299 	  jobcount = attr->values[0].integer;
300 
301         attr = attr->next;
302       }
303 
304      /*
305       * See if we have everything needed...
306       */
307 
308       if (printer == NULL)
309       {
310         if (attr == NULL)
311 	  break;
312 	else
313           continue;
314       }
315 
316      /*
317       * A single 'all' printer name is special, meaning all printers.
318       */
319 
320       if (dests != NULL && !strcmp(dests, "all"))
321         dests = NULL;
322 
323      /*
324       * See if this is a printer we're interested in...
325       */
326 
327       match = dests == NULL;
328 
329       if (dests != NULL)
330       {
331         for (dptr = dests; *dptr != '\0';)
332 	{
333 	 /*
334 	  * Skip leading whitespace and commas...
335 	  */
336 
337 	  while (isspace(*dptr & 255) || *dptr == ',')
338 	    dptr ++;
339 
340 	  if (*dptr == '\0')
341 	    break;
342 
343          /*
344 	  * Compare names...
345 	  */
346 
347 	  for (ptr = printer;
348 	       *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
349 	       ptr ++, dptr ++)
350 	    /* do nothing */;
351 
352           if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' ||
353 	                       isspace(*dptr & 255)))
354 	  {
355 	    match = 1;
356 	    break;
357 	  }
358 
359          /*
360 	  * Skip trailing junk...
361 	  */
362 
363           while (!isspace(*dptr & 255) && *dptr != '\0')
364 	    dptr ++;
365 	  while (isspace(*dptr & 255) || *dptr == ',')
366 	    dptr ++;
367 
368 	  if (*dptr == '\0')
369 	    break;
370         }
371       }
372 
373      /*
374       * Display the printer entry if needed...
375       */
376 
377       if (match)
378       {
379        /*
380         * Display it...
381 	*/
382 
383         printf("%s:\n", printer);
384 	if (!strncmp(device, "file:", 5))
385 	  _cupsLangPrintf(stdout,
386 	                  _("\tprinter is on device \'%s\' speed -1"),
387 			  device + 5);
388 	else
389 	{
390 	 /*
391 	  * Just show the scheme...
392 	  */
393 
394 	  if ((delimiter = strchr(device, ':')) != NULL )
395 	  {
396 	    *delimiter = '\0';
397 	    _cupsLangPrintf(stdout,
398 	                    _("\tprinter is on device \'%s\' speed -1"),
399 			    device);
400 	  }
401 	}
402 
403         if (accepting)
404 	  _cupsLangPuts(stdout, _("\tqueuing is enabled"));
405 	else
406 	  _cupsLangPuts(stdout, _("\tqueuing is disabled"));
407 
408         if (pstate != IPP_PRINTER_STOPPED)
409 	  _cupsLangPuts(stdout, _("\tprinting is enabled"));
410 	else
411 	  _cupsLangPuts(stdout, _("\tprinting is disabled"));
412 
413 	if (jobcount == 0)
414 	  _cupsLangPuts(stdout, _("\tno entries"));
415 	else
416 	  _cupsLangPrintf(stdout, _("\t%d entries"), jobcount);
417 
418 	_cupsLangPuts(stdout, _("\tdaemon present"));
419       }
420 
421       if (attr == NULL)
422         break;
423     }
424 
425     ippDelete(response);
426   }
427 }
428