Load cups into easysw/current.
[thirdparty/cups.git] / systemv / lpoptions.c
1 /*
2  * "$Id: lpoptions.c 4906 2006-01-10 20:53:28Z mike $"
3  *
4  *   Printer option program 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()         - Main entry.
27  *   list_group()   - List printer-specific options from the PPD group.
28  *   list_options() - List printer-specific options from the PPD file.
29  *   usage()        - Show program usage and exit.
30  */
31
32 /*
33  * Include necessary headers...
34  */
35
36 #include <cups/string.h>
37 #include <cups/cups.h>
38 #include <cups/i18n.h>
39 #include <stdlib.h>
40 #include <errno.h>
41
42
43 /*
44  * Local functions...
45  */
46
47 void    list_group(ppd_group_t *group);
48 void    list_options(cups_dest_t *dest);
49 void    usage(void);
50
51
52 /*
53  * 'main()' - Main entry.
54  */
55
56 int                                     /* O - Exit status */
57 main(int  argc,                         /* I - Number of command-line arguments */
58      char *argv[])                      /* I - Command-line arguments */
59 {
60   int           i, j;                   /* Looping vars */
61   int           changes;                /* Did we make changes? */
62   int           num_options;            /* Number of options */
63   cups_option_t *options;               /* Options */
64   int           num_dests;              /* Number of destinations */
65   cups_dest_t   *dests;                 /* Destinations */
66   cups_dest_t   *dest;                  /* Current destination */
67   char          *printer,               /* Printer name */
68                 *instance,              /* Instance name */ 
69                 *option;                /* Current option */
70
71
72  /*
73   * Loop through the command-line arguments...
74   */
75
76   dest        = NULL;
77   num_dests   = 0;
78   dests       = NULL;
79   num_options = 0;
80   options     = NULL;
81   changes     = 0;
82
83   for (i = 1; i < argc; i ++)
84     if (argv[i][0] == '-')
85     {
86       switch (argv[i][1])
87       {
88         case 'd' : /* -d printer */
89             if (argv[i][2])
90               printer = argv[i] + 2;
91             else
92             {
93               i ++;
94               if (i >= argc)
95                 usage();
96
97               printer = argv[i];
98             }
99
100             if ((instance = strrchr(printer, '/')) != NULL)
101               *instance++ = '\0';
102
103             if (num_dests == 0)
104               num_dests = cupsGetDests(&dests);
105
106             if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
107             {
108               _cupsLangPuts(stderr, NULL,
109                             _("lpoptions: Unknown printer or class!\n"));
110               return (1);
111             }
112
113            /*
114             * Set the default destination...
115             */
116
117             for (j = 0; j < num_dests; j ++)
118               dests[j].is_default = 0;
119
120             dest->is_default = 1;
121
122             cupsSetDests(num_dests, dests);
123
124             for (j = 0; j < dest->num_options; j ++)
125               if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
126                 num_options = cupsAddOption(dest->options[j].name,
127                                             dest->options[j].value,
128                                             num_options, &options);
129             break;
130
131         case 'h' : /* -h server */
132             if (argv[i][2])
133               cupsSetServer(argv[i] + 2);
134             else
135             {
136               i ++;
137               if (i >= argc)
138                 usage();
139
140               cupsSetServer(argv[i]);
141             }
142             break;
143
144         case 'E' : /* Encrypt connection */
145             cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
146             break;
147
148         case 'l' : /* -l (list options) */
149             if (dest == NULL)
150             {
151               if (num_dests == 0)
152                 num_dests = cupsGetDests(&dests);
153
154               if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
155                 dest = dests;
156             }
157
158             if (dest == NULL)
159               _cupsLangPuts(stderr, NULL, _("lpoptions: No printers!?!\n"));
160             else
161               list_options(dest);
162
163             changes = -1;
164             break;
165
166         case 'o' : /* -o option[=value] */
167             if (argv[i][2])
168               num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
169             else
170             {
171               i ++;
172               if (i >= argc)
173                 usage();
174
175               num_options = cupsParseOptions(argv[i], num_options, &options);
176             }
177
178             changes = 1;
179             break;
180
181         case 'p' : /* -p printer */
182             if (argv[i][2])
183               printer = argv[i] + 2;
184             else
185             {
186               i ++;
187               if (i >= argc)
188                 usage();
189
190               printer = argv[i];
191             }
192
193             if ((instance = strrchr(printer, '/')) != NULL)
194               *instance++ = '\0';
195
196             if (num_dests == 0)
197               num_dests = cupsGetDests(&dests);
198
199             if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
200             {
201               num_dests = cupsAddDest(printer, instance, num_dests, &dests);
202               dest      = cupsGetDest(printer, instance, num_dests, dests);
203
204               if (dest == NULL)
205               {
206                 _cupsLangPrintf(stderr, NULL,
207                                 _("lpoptions: Unable to add printer or "
208                                   "instance: %s\n"),
209                                 strerror(errno));
210                 return (1);
211               }
212             }
213
214             for (j = 0; j < dest->num_options; j ++)
215               if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
216                 num_options = cupsAddOption(dest->options[j].name,
217                                             dest->options[j].value,
218                                             num_options, &options);
219             break;
220
221         case 'r' : /* -r option (remove) */
222             if (argv[i][2])
223               option = argv[i] + 2;
224             else
225             {
226               i ++;
227               if (i >= argc)
228                 usage();
229
230               option = argv[i];
231             }
232
233             for (j = 0; j < num_options; j ++)
234               if (strcasecmp(options[j].name, option) == 0)
235               {
236                /*
237                 * Remove this option...
238                 */
239
240                 num_options --;
241
242                 if (j < num_options)
243                   memcpy(options + j, options + j + 1,
244                          sizeof(cups_option_t) * (num_options - j));
245                 break;
246               }
247
248             changes = 1;
249             break;
250
251         case 'x' : /* -x printer */
252             if (argv[i][2])
253               printer = argv[i] + 2;
254             else
255             {
256               i ++;
257               if (i >= argc)
258                 usage();
259
260               printer = argv[i];
261             }
262
263             if ((instance = strrchr(printer, '/')) != NULL)
264               *instance++ = '\0';
265
266             if (num_dests == 0)
267               num_dests = cupsGetDests(&dests);
268
269             if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
270             {
271               cupsFreeOptions(dest->num_options, dest->options);
272
273              /*
274               * If we are "deleting" the default printer, then just set the
275               * number of options to 0; if it is also the system default
276               * then cupsSetDests() will remove it for us...
277               */
278
279               if (dest->is_default)
280               {
281                 dest->num_options = 0;
282                 dest->options     = NULL;
283               }
284               else
285               {
286                 num_dests --;
287
288                 j = dest - dests;
289                 if (j < num_dests)
290                   memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
291               }
292             }
293
294             cupsSetDests(num_dests, dests);
295             dest    = NULL;
296             changes = -1;
297             break;
298
299         default :
300             usage();
301       }
302     }
303     else
304       usage();
305
306   if (num_dests == 0)
307     num_dests = cupsGetDests(&dests);
308
309   if (dest == NULL)
310   {
311     if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
312     {
313       for (j = 0; j < dest->num_options; j ++)
314         if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
315           num_options = cupsAddOption(dest->options[j].name,
316                                       dest->options[j].value,
317                                       num_options, &options);
318     }
319   }
320
321   if (dest == NULL)
322     return (0);
323
324   if (changes > 0)
325   {
326    /*
327     * Set printer options...
328     */
329
330     cupsFreeOptions(dest->num_options, dest->options);
331
332     dest->num_options = num_options;
333     dest->options     = options;
334
335     cupsSetDests(num_dests, dests);
336   }
337   else if (changes == 0)
338   {
339     num_options = dest->num_options;
340     options     = dest->options;
341
342     for (i = 0; i < num_options; i ++)
343     {
344       if (i)
345         _cupsLangPuts(stdout, NULL, " ");
346
347       if (!options[i].value[0])
348         _cupsLangPrintf(stdout, NULL, "%s", options[i].name);
349       else if (strchr(options[i].value, ' ') != NULL ||
350                strchr(options[i].value, '\t') != NULL)
351         _cupsLangPrintf(stdout, NULL, "%s=\'%s\'", options[i].name,
352                         options[i].value);
353       else
354         _cupsLangPrintf(stdout, NULL, "%s=%s", options[i].name,
355                         options[i].value);
356     }
357
358     _cupsLangPuts(stdout, NULL, "\n");
359   }
360
361   return (0);
362 }
363
364 /*
365  * 'list_group()' - List printer-specific options from the PPD group.
366  */
367
368 void
369 list_group(ppd_group_t *group)  /* I - Group to show */
370 {
371   int           i, j;           /* Looping vars */
372   ppd_option_t  *option;        /* Current option */
373   ppd_choice_t  *choice;        /* Current choice */
374   ppd_group_t   *subgroup;      /* Current subgroup */
375
376
377   for (i = group->num_options, option = group->options; i > 0; i --, option ++)
378   {
379     _cupsLangPrintf(stdout, NULL, "%s/%s:", option->keyword, option->text);
380
381     for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
382       if (choice->marked)
383         _cupsLangPrintf(stdout, NULL, " *%s", choice->choice);
384       else
385         _cupsLangPrintf(stdout, NULL, " %s", choice->choice);
386
387     _cupsLangPuts(stdout, NULL, "\n");
388   }
389
390   for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
391     list_group(subgroup);
392 }
393
394
395 /*
396  * 'list_options()' - List printer-specific options from the PPD file.
397  */
398
399 void
400 list_options(cups_dest_t *dest) /* I - Destination to list */
401 {
402   int           i;              /* Looping var */
403   const char    *filename;      /* PPD filename */
404   ppd_file_t    *ppd;           /* PPD data */
405   ppd_group_t   *group;         /* Current group */
406
407
408   if ((filename = cupsGetPPD(dest->name)) == NULL)
409   {
410     _cupsLangPrintf(stderr, NULL,
411                     _("lpoptions: Destination %s has no PPD file!\n"),
412                     dest->name);
413     return;
414   }
415
416   if ((ppd = ppdOpenFile(filename)) == NULL)
417   {
418     unlink(filename);
419     _cupsLangPrintf(stderr, NULL,
420                     _("lpoptions: Unable to open PPD file for %s!\n"),
421                     dest->name);
422     return;
423   }
424
425   ppdMarkDefaults(ppd);
426   cupsMarkOptions(ppd, dest->num_options, dest->options);
427
428   for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
429     list_group(group);
430
431   ppdClose(ppd);
432   unlink(filename);
433 }
434
435
436 /*
437  * 'usage()' - Show program usage and exit.
438  */
439
440 void
441 usage(void)
442 {
443   _cupsLangPuts(stdout, NULL,
444                 _("Usage: lpoptions [-h server] [-E] -d printer\n"
445                   "       lpoptions [-h server] [-E] [-p printer] -l\n"
446                   "       lpoptions [-h server] [-E] -p printer -o "
447                   "option[=value] ...\n"
448                   "       lpoptions [-h server] [-E] -x printer\n"));
449
450   exit(1);
451 }
452
453
454 /*
455  * End of "$Id: lpoptions.c 4906 2006-01-10 20:53:28Z mike $".
456  */