]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpoptions.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / systemv / lpoptions.c
1 /*
2 * Printer option program for CUPS.
3 *
4 * Copyright 2007-2015 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
6 *
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/".
12 */
13
14 /*
15 * Include necessary headers...
16 */
17
18 #include <cups/cups-private.h>
19 #include <cups/ppd-private.h>
20
21
22 /*
23 * Local functions...
24 */
25
26 static void list_group(ppd_file_t *ppd, ppd_group_t *group);
27 static void list_options(cups_dest_t *dest);
28 static void usage(void) __attribute__((noreturn));
29
30
31 /*
32 * 'main()' - Main entry.
33 */
34
35 int /* O - Exit status */
36 main(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 */
47 *instance, /* Instance name */
48 *option; /* Current option */
49
50
51 _cupsSetLocale(argv);
52
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
87 if (num_dests == 0 || !dests ||
88 (dest = cupsGetDest(printer, instance, num_dests,
89 dests)) == NULL)
90 {
91 _cupsLangPuts(stderr, _("lpoptions: Unknown printer or class."));
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 ++)
107 if (cupsGetOption(dest->options[j].name, num_options,
108 options) == NULL)
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)
142 _cupsLangPuts(stderr, _("lpoptions: No printers."));
143 else
144 list_options(dest);
145
146 changes = -1;
147 break;
148
149 case 'o' : /* -o option[=value] */
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
158 if (dest == NULL)
159 {
160 _cupsLangPuts(stderr, _("lpoptions: No printers."));
161 return (1);
162 }
163
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
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 {
210 _cupsLangPrintf(stderr,
211 _("lpoptions: Unable to add printer or "
212 "instance: %s"),
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) */
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
234 if (dest == NULL)
235 {
236 _cupsLangPuts(stderr, _("lpoptions: No printers."));
237 return (1);
238 }
239
240 for (j = 0; j < dest->num_options; j ++)
241 if (cupsGetOption(dest->options[j].name, num_options,
242 options) == NULL)
243 num_options = cupsAddOption(dest->options[j].name,
244 dest->options[j].value,
245 num_options, &options);
246 }
247
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 ++)
260 if (!_cups_strcasecmp(options[j].name, option))
261 {
262 /*
263 * Remove this option...
264 */
265
266 num_options --;
267
268 if (j < num_options)
269 memmove(options + j, options + j + 1, sizeof(cups_option_t) * (size_t)(num_options - j));
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
294 if ((dest = cupsGetDest(printer, instance, num_dests,
295 dests)) != NULL)
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)
316 memmove(dest, dest + 1, (size_t)(num_dests - j) * sizeof(cups_dest_t));
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 {
365 char buffer[10240], /* String for options */
366 *ptr; /* Pointer into string */
367
368 num_options = dest->num_options;
369 options = dest->options;
370
371 for (i = 0, ptr = buffer;
372 ptr < (buffer + sizeof(buffer) - 1) && i < num_options;
373 i ++)
374 {
375 if (i)
376 *ptr++ = ' ';
377
378 if (!options[i].value[0])
379 strlcpy(ptr, options[i].name, sizeof(buffer) - (size_t)(ptr - buffer));
380 else if (strchr(options[i].value, ' ') != NULL ||
381 strchr(options[i].value, '\t') != NULL)
382 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), "%s=\'%s\'", options[i].name, options[i].value);
383 else
384 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), "%s=%s", options[i].name, options[i].value);
385
386 ptr += strlen(ptr);
387 }
388
389 _cupsLangPuts(stdout, buffer);
390 }
391
392 return (0);
393 }
394
395 /*
396 * 'list_group()' - List printer-specific options from the PPD group.
397 */
398
399 static void
400 list_group(ppd_file_t *ppd, /* I - PPD file */
401 ppd_group_t *group) /* I - Group to show */
402 {
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 */
407 char buffer[10240], /* Option string buffer */
408 *ptr; /* Pointer into option string */
409
410
411 for (i = group->num_options, option = group->options; i > 0; i --, option ++)
412 {
413 if (!_cups_strcasecmp(option->keyword, "PageRegion"))
414 continue;
415
416 snprintf(buffer, sizeof(buffer), "%s/%s:", option->keyword, option->text);
417
418 for (j = option->num_choices, choice = option->choices,
419 ptr = buffer + strlen(buffer);
420 j > 0 && ptr < (buffer + sizeof(buffer) - 1);
421 j --, choice ++)
422 {
423 if (!_cups_strcasecmp(choice->choice, "Custom"))
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)
442 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), " %sCustom", choice->marked ? "*" : "");
443 else if (!_cups_strcasecmp(option->keyword, "PageSize") ||
444 !_cups_strcasecmp(option->keyword, "PageRegion"))
445 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), " %sCustom.WIDTHxHEIGHT", choice->marked ? "*" : "");
446 else
447 {
448 cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
449
450 if (cupsArrayCount(coption->params) == 1)
451 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), " %sCustom.%s", choice->marked ? "*" : "", 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 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), "%s%s=%s", prefix, cparam->name, types[cparam->type]);
465 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params);
466 prefix = " ";
467 ptr += strlen(ptr);
468 }
469
470 if (ptr < (buffer + sizeof(buffer) - 1))
471 strlcpy(ptr, "}", sizeof(buffer) - (size_t)(ptr - buffer));
472 }
473 }
474 }
475 else if (choice->marked)
476 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), " *%s", choice->choice);
477 else
478 snprintf(ptr, sizeof(buffer) - (size_t)(ptr - buffer), " %s", choice->choice);
479
480 ptr += strlen(ptr);
481 }
482
483 _cupsLangPuts(stdout, buffer);
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, _("lpoptions: Unable to get PPD file for %s: %s"),
507 dest->name, cupsLastErrorString());
508 return;
509 }
510
511 if ((ppd = ppdOpenFile(filename)) == NULL)
512 {
513 unlink(filename);
514 _cupsLangPrintf(stderr, _("lpoptions: Unable to open PPD file for %s."),
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 ++)
523 list_group(ppd, group);
524
525 ppdClose(ppd);
526 unlink(filename);
527 }
528
529
530 /*
531 * 'usage()' - Show program usage and exit.
532 */
533
534 static void
535 usage(void)
536 {
537 _cupsLangPuts(stdout,
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"
542 " lpoptions [-h server] [-E] -x printer"));
543
544 exit(1);
545 }