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