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