Load cups into easysw/current.
[thirdparty/cups.git] / berkeley / lpc.c
1 /*
2  * "$Id: lpc.c 4906 2006-01-10 20:53:28Z mike $"
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     printf("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         printf("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       printf("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, cupsLangDefault(),
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, cupsLangDefault(),
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, cupsLangDefault(),
222                     _("help\t\tget help on commands\n"));
223   else if (!compare_strings(command, "status", 4))
224     _cupsLangPrintf(stdout, cupsLangDefault(),
225                     _("status\t\tshow status of daemon and queue\n"));
226   else
227     _cupsLangPrintf(stdout, cupsLangDefault(),
228                     _("?Invalid help command unknown\n"));
229 }
230
231
232 /*
233  * 'show_status()' - Show printers.
234  */
235
236 static void
237 show_status(http_t     *http,           /* I - HTTP connection to server */
238             const char *dests)          /* I - Destinations */
239 {
240   ipp_t         *request,               /* IPP Request */
241                 *response,              /* IPP Response */
242                 *jobs;                  /* IPP Get Jobs response */
243   ipp_attribute_t *attr,                /* Current attribute */
244                 *jattr;                 /* Current job attribute */
245   cups_lang_t   *language;              /* Default language */
246   char          *printer,               /* Printer name */
247                 *device,                /* Device URI */
248                 *delimiter;             /* Char search result */
249   ipp_pstate_t  pstate;                 /* Printer state */
250   int           accepting;              /* Is printer accepting jobs? */
251   int           jobcount;               /* Count of current jobs */
252   const char    *dptr,                  /* Pointer into destination list */
253                 *ptr;                   /* Pointer into printer name */
254   int           match;                  /* Non-zero if this job matches */
255   char          printer_uri[HTTP_MAX_URI];
256                                         /* Printer URI */
257   static const char *requested[] =      /* Requested attributes */
258                 {
259                   "printer-name",
260                   "device-uri",
261                   "printer-state",
262                   "printer-is-accepting-jobs"
263                 };
264
265
266   DEBUG_printf(("show_status(http=%p, dests=\"%s\")\n", http, dests));
267
268   if (http == NULL)
269     return;
270
271  /*
272   * Build a CUPS_GET_PRINTERS request, which requires the following
273   * attributes:
274   *
275   *    attributes-charset
276   *    attributes-natural-language
277   */
278
279   request = ippNew();
280
281   request->request.op.operation_id = CUPS_GET_PRINTERS;
282   request->request.op.request_id   = 1;
283
284   language = cupsLangDefault();
285
286   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
287                "attributes-charset", NULL, cupsLangEncoding(language));
288
289   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
290                "attributes-natural-language", NULL, language->language);
291
292   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
293                 "requested-attributes", sizeof(requested) / sizeof(requested[0]),
294                 NULL, requested);
295
296  /*
297   * Do the request and get back a response...
298   */
299
300   if ((response = cupsDoRequest(http, request, "/")) != NULL)
301   {
302     DEBUG_puts("show_status: request succeeded...");
303
304    /*
305     * Loop through the printers returned in the list and display
306     * their status...
307     */
308
309     for (attr = response->attrs; attr != NULL; attr = attr->next)
310     {
311      /*
312       * Skip leading attributes until we hit a job...
313       */
314
315       while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
316         attr = attr->next;
317
318       if (attr == NULL)
319         break;
320
321      /*
322       * Pull the needed attributes from this job...
323       */
324
325       printer   = NULL;
326       device    = "file:/dev/null";
327       pstate    = IPP_PRINTER_IDLE;
328       jobcount  = 0;
329       accepting = 1;
330
331       while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
332       {
333         if (!strcmp(attr->name, "printer-name") &&
334             attr->value_tag == IPP_TAG_NAME)
335           printer = attr->values[0].string.text;
336
337         if (!strcmp(attr->name, "device-uri") &&
338             attr->value_tag == IPP_TAG_URI)
339           device = attr->values[0].string.text;
340
341         if (!strcmp(attr->name, "printer-state") &&
342             attr->value_tag == IPP_TAG_ENUM)
343           pstate = (ipp_pstate_t)attr->values[0].integer;
344
345         if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
346             attr->value_tag == IPP_TAG_BOOLEAN)
347           accepting = attr->values[0].boolean;
348
349         attr = attr->next;
350       }
351
352      /*
353       * See if we have everything needed...
354       */
355
356       if (printer == NULL)
357       {
358         if (attr == NULL)
359           break;
360         else
361           continue;
362       }
363
364      /*
365       * A single 'all' printer name is special, meaning all printers.
366       */
367
368       if (dests != NULL && !strcmp(dests, "all"))
369         dests = NULL;
370
371      /*
372       * See if this is a printer we're interested in...
373       */
374
375       match = dests == NULL;
376
377       if (dests != NULL)
378       {
379         for (dptr = dests; *dptr != '\0';)
380         {
381          /*
382           * Skip leading whitespace and commas...
383           */
384
385           while (isspace(*dptr & 255) || *dptr == ',')
386             dptr ++;
387
388           if (*dptr == '\0')
389             break;
390
391          /*
392           * Compare names...
393           */
394
395           for (ptr = printer;
396                *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
397                ptr ++, dptr ++);
398
399           if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
400           {
401             match = 1;
402             break;
403           }
404
405          /*
406           * Skip trailing junk...
407           */
408
409           while (!isspace(*dptr & 255) && *dptr != '\0')
410             dptr ++;
411           while (isspace(*dptr & 255) || *dptr == ',')
412             dptr ++;
413
414           if (*dptr == '\0')
415             break;
416         }
417       }
418
419      /*
420       * Display the printer entry if needed...
421       */
422
423       if (match)
424       {
425        /*
426         * Build an IPP_GET_JOBS request, which requires the following
427         * attributes:
428         *
429         *    attributes-charset
430         *    attributes-natural-language
431         *    printer-uri
432         *    limit
433         */
434
435         request = ippNew();
436
437         request->request.op.operation_id = IPP_GET_JOBS;
438         request->request.op.request_id   = 1;
439
440         language = cupsLangDefault();
441
442         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
443                      "attributes-charset", NULL,
444                      cupsLangEncoding(language));
445
446         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
447                      "attributes-natural-language", NULL,
448                      language->language);
449
450         httpAssembleURIf(printer_uri, sizeof(printer_uri), "ipp", NULL,
451                          "localhost", 631, "/printers/%s", printer);
452         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
453                      "printer-uri", NULL, printer_uri);
454
455         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
456                      "requested-attributes", NULL, "job-id");
457
458         if ((jobs = cupsDoRequest(http, request, "/")) != NULL)
459         {
460          /*
461           * Grab the number of jobs for the printer.
462           */
463
464           for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next)
465             if (jattr->name && !strcmp(jattr->name, "job-id"))
466               jobcount ++;
467
468           ippDelete(jobs);
469         }
470
471        /*
472         * Display it...
473         */
474
475         printf("%s:\n", printer);
476         if (!strncmp(device, "file:", 5))
477           _cupsLangPrintf(stdout, language,
478                           _("\tprinter is on device \'%s\' speed -1\n"),
479                           device + 5);
480         else
481         {
482          /*
483           * Just show the scheme...
484           */
485
486           if ((delimiter = strchr(device, ':')) != NULL )
487           {
488             *delimiter = '\0';
489             _cupsLangPrintf(stdout, language,
490                             _("\tprinter is on device \'%s\' speed -1\n"),
491                             device);
492           }
493         }
494
495         if (accepting)
496           _cupsLangPuts(stdout, language, _("\tqueuing is enabled\n"));
497         else
498           _cupsLangPuts(stdout, language, _("\tqueuing is disabled\n"));
499
500         if (pstate != IPP_PRINTER_STOPPED)
501           _cupsLangPuts(stdout, language, _("\tprinting is enabled\n"));
502         else
503           _cupsLangPuts(stdout, language, _("\tprinting is disabled\n"));
504
505         if (jobcount == 0)
506           _cupsLangPuts(stdout, language, _("\tno entries\n"));
507         else
508           _cupsLangPrintf(stdout, language, _("\t%d entries\n"), jobcount);
509
510         _cupsLangPuts(stdout, language, _("\tdaemon present\n"));
511       }
512
513       if (attr == NULL)
514         break;
515     }
516
517     ippDelete(response);
518   }
519 }
520
521
522 /*
523  * End of "$Id: lpc.c 4906 2006-01-10 20:53:28Z mike $".
524  */