]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/lpoptions.c
Merge changes from CUPS 1.6svn-r9968.
[thirdparty/cups.git] / systemv / lpoptions.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: lpoptions.c 7720 2008-07-11 22:46:21Z mike $"
ef416fc2 3 *
71e16022 4 * Printer option program for CUPS.
ef416fc2 5 *
88f9aafc 6 * Copyright 2007-2011 by Apple Inc.
ef416fc2 7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 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
71e16022 27#include <cups/cups-private.h>
ef416fc2 28
29
30/*
31 * Local functions...
32 */
33
dd1abb6b
MS
34static void list_group(ppd_file_t *ppd, ppd_group_t *group);
35static void list_options(cups_dest_t *dest);
85dda01c 36static void usage(void) __attribute__((noreturn));
ef416fc2 37
38
39/*
40 * 'main()' - Main entry.
41 */
42
43int /* O - Exit status */
44main(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 */
88f9aafc 55 *instance, /* Instance name */
ef416fc2 56 *option; /* Current option */
57
58
07725fee 59 _cupsSetLocale(argv);
d09495fa 60
ef416fc2 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
1f0275e3
MS
95 if (num_dests == 0 || !dests ||
96 (dest = cupsGetDest(printer, instance, num_dests,
97 dests)) == NULL)
ef416fc2 98 {
0837b7e8 99 _cupsLangPuts(stderr, _("lpoptions: Unknown printer or class."));
ef416fc2 100 return (1);
101 }
102
103 /*
104 * Set the default destination...
105 */
106
107 for (j = 0; j < num_dests; j ++)
108 dests[j].is_default = 0;
109
110 dest->is_default = 1;
111
112 cupsSetDests(num_dests, dests);
113
114 for (j = 0; j < dest->num_options; j ++)
0837b7e8
MS
115 if (cupsGetOption(dest->options[j].name, num_options,
116 options) == NULL)
ef416fc2 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)
0837b7e8 150 _cupsLangPuts(stderr, _("lpoptions: No printers."));
ef416fc2 151 else
152 list_options(dest);
153
154 changes = -1;
155 break;
156
157 case 'o' : /* -o option[=value] */
8ca02f3c 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
7594b224 166 if (dest == NULL)
167 {
0837b7e8 168 _cupsLangPuts(stderr, _("lpoptions: No printers."));
7594b224 169 return (1);
170 }
171
8ca02f3c 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
ef416fc2 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 {
fa73b229 218 _cupsLangPrintf(stderr,
ef416fc2 219 _("lpoptions: Unable to add printer or "
0837b7e8 220 "instance: %s"),
ef416fc2 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) */
8ca02f3c 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
7594b224 242 if (dest == NULL)
243 {
0837b7e8 244 _cupsLangPuts(stderr, _("lpoptions: No printers."));
7594b224 245 return (1);
246 }
247
8ca02f3c 248 for (j = 0; j < dest->num_options; j ++)
0837b7e8
MS
249 if (cupsGetOption(dest->options[j].name, num_options,
250 options) == NULL)
8ca02f3c 251 num_options = cupsAddOption(dest->options[j].name,
252 dest->options[j].value,
253 num_options, &options);
254 }
255
ef416fc2 256 if (argv[i][2])
257 option = argv[i] + 2;
258 else
259 {
260 i ++;
261 if (i >= argc)
262 usage();
263
264 option = argv[i];
265 }
266
267 for (j = 0; j < num_options; j ++)
88f9aafc 268 if (!_cups_strcasecmp(options[j].name, option))
ef416fc2 269 {
270 /*
271 * Remove this option...
272 */
273
274 num_options --;
275
276 if (j < num_options)
277 memcpy(options + j, options + j + 1,
278 sizeof(cups_option_t) * (num_options - j));
279 break;
280 }
281
282 changes = 1;
283 break;
284
285 case 'x' : /* -x printer */
286 if (argv[i][2])
287 printer = argv[i] + 2;
288 else
289 {
290 i ++;
291 if (i >= argc)
292 usage();
293
294 printer = argv[i];
295 }
296
297 if ((instance = strrchr(printer, '/')) != NULL)
298 *instance++ = '\0';
299
300 if (num_dests == 0)
301 num_dests = cupsGetDests(&dests);
302
0837b7e8
MS
303 if ((dest = cupsGetDest(printer, instance, num_dests,
304 dests)) != NULL)
ef416fc2 305 {
306 cupsFreeOptions(dest->num_options, dest->options);
307
308 /*
309 * If we are "deleting" the default printer, then just set the
310 * number of options to 0; if it is also the system default
311 * then cupsSetDests() will remove it for us...
312 */
313
314 if (dest->is_default)
315 {
316 dest->num_options = 0;
317 dest->options = NULL;
318 }
319 else
320 {
321 num_dests --;
322
323 j = dest - dests;
324 if (j < num_dests)
325 memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
326 }
327 }
328
329 cupsSetDests(num_dests, dests);
330 dest = NULL;
331 changes = -1;
332 break;
333
334 default :
335 usage();
336 }
337 }
338 else
339 usage();
340
341 if (num_dests == 0)
342 num_dests = cupsGetDests(&dests);
343
344 if (dest == NULL)
345 {
346 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
347 {
348 for (j = 0; j < dest->num_options; j ++)
349 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
350 num_options = cupsAddOption(dest->options[j].name,
351 dest->options[j].value,
352 num_options, &options);
353 }
354 }
355
356 if (dest == NULL)
357 return (0);
358
359 if (changes > 0)
360 {
361 /*
362 * Set printer options...
363 */
364
365 cupsFreeOptions(dest->num_options, dest->options);
366
367 dest->num_options = num_options;
368 dest->options = options;
369
370 cupsSetDests(num_dests, dests);
371 }
372 else if (changes == 0)
373 {
0837b7e8
MS
374 char buffer[10240], /* String for options */
375 *ptr; /* Pointer into string */
376
ef416fc2 377 num_options = dest->num_options;
378 options = dest->options;
379
0837b7e8
MS
380 for (i = 0, ptr = buffer;
381 ptr < (buffer + sizeof(buffer) - 1) && i < num_options;
382 i ++)
ef416fc2 383 {
384 if (i)
0837b7e8 385 *ptr++ = ' ';
ef416fc2 386
387 if (!options[i].value[0])
0837b7e8 388 strlcpy(ptr, options[i].name, sizeof(buffer) - (ptr - buffer));
ef416fc2 389 else if (strchr(options[i].value, ' ') != NULL ||
390 strchr(options[i].value, '\t') != NULL)
0837b7e8
MS
391 snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s=\'%s\'",
392 options[i].name, options[i].value);
ef416fc2 393 else
0837b7e8
MS
394 snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s=%s",
395 options[i].name, options[i].value);
396
397 ptr += strlen(ptr);
ef416fc2 398 }
399
0837b7e8 400 _cupsLangPuts(stdout, buffer);
ef416fc2 401 }
402
403 return (0);
404}
405
406/*
407 * 'list_group()' - List printer-specific options from the PPD group.
408 */
409
dd1abb6b
MS
410static void
411list_group(ppd_file_t *ppd, /* I - PPD file */
412 ppd_group_t *group) /* I - Group to show */
ef416fc2 413{
dd1abb6b
MS
414 int i, j; /* Looping vars */
415 ppd_option_t *option; /* Current option */
416 ppd_choice_t *choice; /* Current choice */
417 ppd_group_t *subgroup; /* Current subgroup */
0837b7e8
MS
418 char buffer[10240], /* Option string buffer */
419 *ptr; /* Pointer into option string */
ef416fc2 420
421
422 for (i = group->num_options, option = group->options; i > 0; i --, option ++)
423 {
88f9aafc 424 if (!_cups_strcasecmp(option->keyword, "PageRegion"))
dd1abb6b
MS
425 continue;
426
0837b7e8 427 snprintf(buffer, sizeof(buffer), "%s/%s:", option->keyword, option->text);
ef416fc2 428
0837b7e8
MS
429 for (j = option->num_choices, choice = option->choices,
430 ptr = buffer + strlen(buffer);
431 j > 0 && ptr < (buffer + sizeof(buffer) - 1);
dd1abb6b 432 j --, choice ++)
0837b7e8 433 {
88f9aafc 434 if (!_cups_strcasecmp(choice->choice, "Custom"))
dd1abb6b
MS
435 {
436 ppd_coption_t *coption; /* Custom option */
437 ppd_cparam_t *cparam; /* Custom parameter */
438 static const char * const types[] =
439 { /* Parameter types */
440 "CURVE",
441 "INTEGER",
442 "INVCURVE",
443 "PASSCODE",
444 "PASSWORD",
445 "POINTS",
446 "REAL",
447 "STRING"
448 };
449
450
451 if ((coption = ppdFindCustomOption(ppd, option->keyword)) == NULL ||
452 cupsArrayCount(coption->params) == 0)
0837b7e8
MS
453 snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %sCustom",
454 choice->marked ? "*" : "");
88f9aafc
MS
455 else if (!_cups_strcasecmp(option->keyword, "PageSize") ||
456 !_cups_strcasecmp(option->keyword, "PageRegion"))
0837b7e8
MS
457 snprintf(ptr, sizeof(buffer) - (ptr - buffer),
458 " %sCustom.WIDTHxHEIGHT", choice->marked ? "*" : "");
dd1abb6b
MS
459 else
460 {
461 cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
462
463 if (cupsArrayCount(coption->params) == 1)
0837b7e8
MS
464 snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %sCustom.%s",
465 choice->marked ? "*" : "", types[cparam->type]);
dd1abb6b
MS
466 else
467 {
468 const char *prefix; /* Prefix string */
469
470
471 if (choice->marked)
472 prefix = " *{";
473 else
474 prefix = " {";
475
476 while (cparam)
477 {
0837b7e8
MS
478 snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s%s=%s", prefix,
479 cparam->name, types[cparam->type]);
dd1abb6b
MS
480 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params);
481 prefix = " ";
0837b7e8 482 ptr += strlen(ptr);
dd1abb6b
MS
483 }
484
0837b7e8
MS
485 if (ptr < (buffer + sizeof(buffer) - 1))
486 strlcpy(ptr, "}", sizeof(buffer) - (ptr - buffer));
dd1abb6b
MS
487 }
488 }
489 }
490 else if (choice->marked)
0837b7e8 491 snprintf(ptr, sizeof(buffer) - (ptr - buffer), " *%s", choice->choice);
ef416fc2 492 else
0837b7e8
MS
493 snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %s", choice->choice);
494
495 ptr += strlen(ptr);
496 }
ef416fc2 497
0837b7e8 498 _cupsLangPuts(stdout, buffer);
ef416fc2 499 }
500
501 for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
dd1abb6b 502 list_group(ppd, subgroup);
ef416fc2 503}
504
505
506/*
507 * 'list_options()' - List printer-specific options from the PPD file.
508 */
509
dd1abb6b
MS
510static void
511list_options(cups_dest_t *dest) /* I - Destination to list */
ef416fc2 512{
dd1abb6b
MS
513 int i; /* Looping var */
514 const char *filename; /* PPD filename */
515 ppd_file_t *ppd; /* PPD data */
516 ppd_group_t *group; /* Current group */
ef416fc2 517
518
519 if ((filename = cupsGetPPD(dest->name)) == NULL)
520 {
0837b7e8 521 _cupsLangPrintf(stderr, _("lpoptions: Unable to get PPD file for %s: %s"),
b86bc4cf 522 dest->name, cupsLastErrorString());
ef416fc2 523 return;
524 }
525
526 if ((ppd = ppdOpenFile(filename)) == NULL)
527 {
528 unlink(filename);
0837b7e8 529 _cupsLangPrintf(stderr, _("lpoptions: Unable to open PPD file for %s."),
ef416fc2 530 dest->name);
531 return;
532 }
533
534 ppdMarkDefaults(ppd);
535 cupsMarkOptions(ppd, dest->num_options, dest->options);
536
537 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
dd1abb6b 538 list_group(ppd, group);
ef416fc2 539
540 ppdClose(ppd);
541 unlink(filename);
542}
543
544
545/*
546 * 'usage()' - Show program usage and exit.
547 */
548
dd1abb6b 549static void
ef416fc2 550usage(void)
551{
fa73b229 552 _cupsLangPuts(stdout,
ef416fc2 553 _("Usage: lpoptions [-h server] [-E] -d printer\n"
554 " lpoptions [-h server] [-E] [-p printer] -l\n"
555 " lpoptions [-h server] [-E] -p printer -o "
556 "option[=value] ...\n"
0837b7e8 557 " lpoptions [-h server] [-E] -x printer"));
ef416fc2 558
559 exit(1);
560}
561
562
563/*
b19ccc9e 564 * End of "$Id: lpoptions.c 7720 2008-07-11 22:46:21Z mike $".
ef416fc2 565 */