]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpoptions.c
Merge changes from CUPS 1.5svn-r8849.
[thirdparty/cups.git] / systemv / lpoptions.c
1 /*
2 * "$Id: lpoptions.c 7720 2008-07-11 22:46:21Z mike $"
3 *
4 * Printer option program for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007-2009 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() - Main entry.
18 * list_group() - List printer-specific options from the PPD group.
19 * list_options() - List printer-specific options from the PPD file.
20 * usage() - Show program usage and exit.
21 */
22
23 /*
24 * Include necessary headers...
25 */
26
27 #include <cups/string.h>
28 #include <cups/cups.h>
29 #include <cups/i18n.h>
30 #include <stdlib.h>
31 #include <errno.h>
32
33
34 /*
35 * Local functions...
36 */
37
38 static void list_group(ppd_file_t *ppd, ppd_group_t *group);
39 static void list_options(cups_dest_t *dest);
40 static void usage(void);
41
42
43 /*
44 * 'main()' - Main entry.
45 */
46
47 int /* O - Exit status */
48 main(int argc, /* I - Number of command-line arguments */
49 char *argv[]) /* I - Command-line arguments */
50 {
51 int i, j; /* Looping vars */
52 int changes; /* Did we make changes? */
53 int num_options; /* Number of options */
54 cups_option_t *options; /* Options */
55 int num_dests; /* Number of destinations */
56 cups_dest_t *dests; /* Destinations */
57 cups_dest_t *dest; /* Current destination */
58 char *printer, /* Printer name */
59 *instance, /* Instance name */
60 *option; /* Current option */
61
62
63 _cupsSetLocale(argv);
64
65 /*
66 * Loop through the command-line arguments...
67 */
68
69 dest = NULL;
70 num_dests = 0;
71 dests = NULL;
72 num_options = 0;
73 options = NULL;
74 changes = 0;
75
76 for (i = 1; i < argc; i ++)
77 if (argv[i][0] == '-')
78 {
79 switch (argv[i][1])
80 {
81 case 'd' : /* -d printer */
82 if (argv[i][2])
83 printer = argv[i] + 2;
84 else
85 {
86 i ++;
87 if (i >= argc)
88 usage();
89
90 printer = argv[i];
91 }
92
93 if ((instance = strrchr(printer, '/')) != NULL)
94 *instance++ = '\0';
95
96 if (num_dests == 0)
97 num_dests = cupsGetDests(&dests);
98
99 if (num_dests == 0 || !dests ||
100 (dest = cupsGetDest(printer, instance, num_dests,
101 dests)) == NULL)
102 {
103 _cupsLangPuts(stderr,
104 _("lpoptions: Unknown printer or class\n"));
105 return (1);
106 }
107
108 /*
109 * Set the default destination...
110 */
111
112 for (j = 0; j < num_dests; j ++)
113 dests[j].is_default = 0;
114
115 dest->is_default = 1;
116
117 cupsSetDests(num_dests, dests);
118
119 for (j = 0; j < dest->num_options; j ++)
120 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
121 num_options = cupsAddOption(dest->options[j].name,
122 dest->options[j].value,
123 num_options, &options);
124 break;
125
126 case 'h' : /* -h server */
127 if (argv[i][2])
128 cupsSetServer(argv[i] + 2);
129 else
130 {
131 i ++;
132 if (i >= argc)
133 usage();
134
135 cupsSetServer(argv[i]);
136 }
137 break;
138
139 case 'E' : /* Encrypt connection */
140 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
141 break;
142
143 case 'l' : /* -l (list options) */
144 if (dest == NULL)
145 {
146 if (num_dests == 0)
147 num_dests = cupsGetDests(&dests);
148
149 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
150 dest = dests;
151 }
152
153 if (dest == NULL)
154 _cupsLangPuts(stderr, _("lpoptions: No printers\n"));
155 else
156 list_options(dest);
157
158 changes = -1;
159 break;
160
161 case 'o' : /* -o option[=value] */
162 if (dest == NULL)
163 {
164 if (num_dests == 0)
165 num_dests = cupsGetDests(&dests);
166
167 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
168 dest = dests;
169
170 if (dest == NULL)
171 {
172 _cupsLangPuts(stderr, _("lpoptions: No printers\n"));
173 return (1);
174 }
175
176 for (j = 0; j < dest->num_options; j ++)
177 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
178 num_options = cupsAddOption(dest->options[j].name,
179 dest->options[j].value,
180 num_options, &options);
181 }
182
183 if (argv[i][2])
184 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
185 else
186 {
187 i ++;
188 if (i >= argc)
189 usage();
190
191 num_options = cupsParseOptions(argv[i], num_options, &options);
192 }
193
194 changes = 1;
195 break;
196
197 case 'p' : /* -p printer */
198 if (argv[i][2])
199 printer = argv[i] + 2;
200 else
201 {
202 i ++;
203 if (i >= argc)
204 usage();
205
206 printer = argv[i];
207 }
208
209 if ((instance = strrchr(printer, '/')) != NULL)
210 *instance++ = '\0';
211
212 if (num_dests == 0)
213 num_dests = cupsGetDests(&dests);
214
215 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
216 {
217 num_dests = cupsAddDest(printer, instance, num_dests, &dests);
218 dest = cupsGetDest(printer, instance, num_dests, dests);
219
220 if (dest == NULL)
221 {
222 _cupsLangPrintf(stderr,
223 _("lpoptions: Unable to add printer or "
224 "instance: %s\n"),
225 strerror(errno));
226 return (1);
227 }
228 }
229
230 for (j = 0; j < dest->num_options; j ++)
231 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
232 num_options = cupsAddOption(dest->options[j].name,
233 dest->options[j].value,
234 num_options, &options);
235 break;
236
237 case 'r' : /* -r option (remove) */
238 if (dest == NULL)
239 {
240 if (num_dests == 0)
241 num_dests = cupsGetDests(&dests);
242
243 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
244 dest = dests;
245
246 if (dest == NULL)
247 {
248 _cupsLangPuts(stderr, _("lpoptions: No printers\n"));
249 return (1);
250 }
251
252 for (j = 0; j < dest->num_options; j ++)
253 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
254 num_options = cupsAddOption(dest->options[j].name,
255 dest->options[j].value,
256 num_options, &options);
257 }
258
259 if (argv[i][2])
260 option = argv[i] + 2;
261 else
262 {
263 i ++;
264 if (i >= argc)
265 usage();
266
267 option = argv[i];
268 }
269
270 for (j = 0; j < num_options; j ++)
271 if (!strcasecmp(options[j].name, option))
272 {
273 /*
274 * Remove this option...
275 */
276
277 num_options --;
278
279 if (j < num_options)
280 memcpy(options + j, options + j + 1,
281 sizeof(cups_option_t) * (num_options - j));
282 break;
283 }
284
285 changes = 1;
286 break;
287
288 case 'x' : /* -x printer */
289 if (argv[i][2])
290 printer = argv[i] + 2;
291 else
292 {
293 i ++;
294 if (i >= argc)
295 usage();
296
297 printer = argv[i];
298 }
299
300 if ((instance = strrchr(printer, '/')) != NULL)
301 *instance++ = '\0';
302
303 if (num_dests == 0)
304 num_dests = cupsGetDests(&dests);
305
306 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
307 {
308 cupsFreeOptions(dest->num_options, dest->options);
309
310 /*
311 * If we are "deleting" the default printer, then just set the
312 * number of options to 0; if it is also the system default
313 * then cupsSetDests() will remove it for us...
314 */
315
316 if (dest->is_default)
317 {
318 dest->num_options = 0;
319 dest->options = NULL;
320 }
321 else
322 {
323 num_dests --;
324
325 j = dest - dests;
326 if (j < num_dests)
327 memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
328 }
329 }
330
331 cupsSetDests(num_dests, dests);
332 dest = NULL;
333 changes = -1;
334 break;
335
336 default :
337 usage();
338 }
339 }
340 else
341 usage();
342
343 if (num_dests == 0)
344 num_dests = cupsGetDests(&dests);
345
346 if (dest == NULL)
347 {
348 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
349 {
350 for (j = 0; j < dest->num_options; j ++)
351 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
352 num_options = cupsAddOption(dest->options[j].name,
353 dest->options[j].value,
354 num_options, &options);
355 }
356 }
357
358 if (dest == NULL)
359 return (0);
360
361 if (changes > 0)
362 {
363 /*
364 * Set printer options...
365 */
366
367 cupsFreeOptions(dest->num_options, dest->options);
368
369 dest->num_options = num_options;
370 dest->options = options;
371
372 cupsSetDests(num_dests, dests);
373 }
374 else if (changes == 0)
375 {
376 num_options = dest->num_options;
377 options = dest->options;
378
379 for (i = 0; i < num_options; i ++)
380 {
381 if (i)
382 _cupsLangPuts(stdout, " ");
383
384 if (!options[i].value[0])
385 _cupsLangPrintf(stdout, "%s", options[i].name);
386 else if (strchr(options[i].value, ' ') != NULL ||
387 strchr(options[i].value, '\t') != NULL)
388 _cupsLangPrintf(stdout, "%s=\'%s\'", options[i].name,
389 options[i].value);
390 else
391 _cupsLangPrintf(stdout, "%s=%s", options[i].name,
392 options[i].value);
393 }
394
395 _cupsLangPuts(stdout, "\n");
396 }
397
398 return (0);
399 }
400
401 /*
402 * 'list_group()' - List printer-specific options from the PPD group.
403 */
404
405 static void
406 list_group(ppd_file_t *ppd, /* I - PPD file */
407 ppd_group_t *group) /* I - Group to show */
408 {
409 int i, j; /* Looping vars */
410 ppd_option_t *option; /* Current option */
411 ppd_choice_t *choice; /* Current choice */
412 ppd_group_t *subgroup; /* Current subgroup */
413
414
415 for (i = group->num_options, option = group->options; i > 0; i --, option ++)
416 {
417 if (!strcasecmp(option->keyword, "PageRegion"))
418 continue;
419
420 _cupsLangPrintf(stdout, "%s/%s:", option->keyword, option->text);
421
422 for (j = option->num_choices, choice = option->choices;
423 j > 0;
424 j --, choice ++)
425 if (!strcasecmp(choice->choice, "Custom"))
426 {
427 ppd_coption_t *coption; /* Custom option */
428 ppd_cparam_t *cparam; /* Custom parameter */
429 static const char * const types[] =
430 { /* Parameter types */
431 "CURVE",
432 "INTEGER",
433 "INVCURVE",
434 "PASSCODE",
435 "PASSWORD",
436 "POINTS",
437 "REAL",
438 "STRING"
439 };
440
441
442 if ((coption = ppdFindCustomOption(ppd, option->keyword)) == NULL ||
443 cupsArrayCount(coption->params) == 0)
444 _cupsLangPrintf(stdout, " %sCustom", choice->marked ? "*" : "");
445 else if (!strcasecmp(option->keyword, "PageSize") ||
446 !strcasecmp(option->keyword, "PageRegion"))
447 _cupsLangPrintf(stdout, " %sCustom.WIDTHxHEIGHT",
448 choice->marked ? "*" : "");
449 else
450 {
451 cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
452
453 if (cupsArrayCount(coption->params) == 1)
454 _cupsLangPrintf(stdout, " %sCustom.%s", choice->marked ? "*" : "",
455 types[cparam->type]);
456 else
457 {
458 const char *prefix; /* Prefix string */
459
460
461 if (choice->marked)
462 prefix = " *{";
463 else
464 prefix = " {";
465
466 while (cparam)
467 {
468 _cupsLangPrintf(stdout, "%s%s=%s", prefix, cparam->name,
469 types[cparam->type]);
470 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params);
471 prefix = " ";
472 }
473
474 _cupsLangPuts(stdout, "}");
475 }
476 }
477 }
478 else if (choice->marked)
479 _cupsLangPrintf(stdout, " *%s", choice->choice);
480 else
481 _cupsLangPrintf(stdout, " %s", choice->choice);
482
483 _cupsLangPuts(stdout, "\n");
484 }
485
486 for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
487 list_group(ppd, subgroup);
488 }
489
490
491 /*
492 * 'list_options()' - List printer-specific options from the PPD file.
493 */
494
495 static void
496 list_options(cups_dest_t *dest) /* I - Destination to list */
497 {
498 int i; /* Looping var */
499 const char *filename; /* PPD filename */
500 ppd_file_t *ppd; /* PPD data */
501 ppd_group_t *group; /* Current group */
502
503
504 if ((filename = cupsGetPPD(dest->name)) == NULL)
505 {
506 _cupsLangPrintf(stderr,
507 _("lpoptions: Unable to get PPD file for %s: %s\n"),
508 dest->name, cupsLastErrorString());
509 return;
510 }
511
512 if ((ppd = ppdOpenFile(filename)) == NULL)
513 {
514 unlink(filename);
515 _cupsLangPrintf(stderr,
516 _("lpoptions: Unable to open PPD file for %s\n"),
517 dest->name);
518 return;
519 }
520
521 ppdMarkDefaults(ppd);
522 cupsMarkOptions(ppd, dest->num_options, dest->options);
523
524 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
525 list_group(ppd, group);
526
527 ppdClose(ppd);
528 unlink(filename);
529 }
530
531
532 /*
533 * 'usage()' - Show program usage and exit.
534 */
535
536 static void
537 usage(void)
538 {
539 _cupsLangPuts(stdout,
540 _("Usage: lpoptions [-h server] [-E] -d printer\n"
541 " lpoptions [-h server] [-E] [-p printer] -l\n"
542 " lpoptions [-h server] [-E] -p printer -o "
543 "option[=value] ...\n"
544 " lpoptions [-h server] [-E] -x printer\n"));
545
546 exit(1);
547 }
548
549
550 /*
551 * End of "$Id: lpoptions.c 7720 2008-07-11 22:46:21Z mike $".
552 */