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