]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f7faf1f5 | 2 | * "$Id: lpoptions.c 4924 2006-01-13 01:55:20Z mike $" |
ef416fc2 | 3 | * |
4 | * Printer option program for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 1997-2006 by Easy Software Products. | |
7 | * | |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
18 | * Hollywood, Maryland 20636 USA | |
19 | * | |
20 | * Voice: (301) 373-9600 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
26 | * main() - Main entry. | |
27 | * list_group() - List printer-specific options from the PPD group. | |
28 | * list_options() - List printer-specific options from the PPD file. | |
29 | * usage() - Show program usage and exit. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Include necessary headers... | |
34 | */ | |
35 | ||
36 | #include <cups/string.h> | |
37 | #include <cups/cups.h> | |
38 | #include <cups/i18n.h> | |
39 | #include <stdlib.h> | |
40 | #include <errno.h> | |
41 | ||
42 | ||
43 | /* | |
44 | * Local functions... | |
45 | */ | |
46 | ||
47 | void list_group(ppd_group_t *group); | |
48 | void list_options(cups_dest_t *dest); | |
49 | void usage(void); | |
50 | ||
51 | ||
52 | /* | |
53 | * 'main()' - Main entry. | |
54 | */ | |
55 | ||
56 | int /* O - Exit status */ | |
57 | main(int argc, /* I - Number of command-line arguments */ | |
58 | char *argv[]) /* I - Command-line arguments */ | |
59 | { | |
60 | int i, j; /* Looping vars */ | |
61 | int changes; /* Did we make changes? */ | |
62 | int num_options; /* Number of options */ | |
63 | cups_option_t *options; /* Options */ | |
64 | int num_dests; /* Number of destinations */ | |
65 | cups_dest_t *dests; /* Destinations */ | |
66 | cups_dest_t *dest; /* Current destination */ | |
67 | char *printer, /* Printer name */ | |
68 | *instance, /* Instance name */ | |
69 | *option; /* Current option */ | |
70 | ||
71 | ||
72 | /* | |
73 | * Loop through the command-line arguments... | |
74 | */ | |
75 | ||
76 | dest = NULL; | |
77 | num_dests = 0; | |
78 | dests = NULL; | |
79 | num_options = 0; | |
80 | options = NULL; | |
81 | changes = 0; | |
82 | ||
83 | for (i = 1; i < argc; i ++) | |
84 | if (argv[i][0] == '-') | |
85 | { | |
86 | switch (argv[i][1]) | |
87 | { | |
88 | case 'd' : /* -d printer */ | |
89 | if (argv[i][2]) | |
90 | printer = argv[i] + 2; | |
91 | else | |
92 | { | |
93 | i ++; | |
94 | if (i >= argc) | |
95 | usage(); | |
96 | ||
97 | printer = argv[i]; | |
98 | } | |
99 | ||
100 | if ((instance = strrchr(printer, '/')) != NULL) | |
101 | *instance++ = '\0'; | |
102 | ||
103 | if (num_dests == 0) | |
104 | num_dests = cupsGetDests(&dests); | |
105 | ||
106 | if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL) | |
107 | { | |
fa73b229 | 108 | _cupsLangPuts(stderr, |
ef416fc2 | 109 | _("lpoptions: Unknown printer or class!\n")); |
110 | return (1); | |
111 | } | |
112 | ||
113 | /* | |
114 | * Set the default destination... | |
115 | */ | |
116 | ||
117 | for (j = 0; j < num_dests; j ++) | |
118 | dests[j].is_default = 0; | |
119 | ||
120 | dest->is_default = 1; | |
121 | ||
122 | cupsSetDests(num_dests, dests); | |
123 | ||
124 | for (j = 0; j < dest->num_options; j ++) | |
125 | if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) | |
126 | num_options = cupsAddOption(dest->options[j].name, | |
127 | dest->options[j].value, | |
128 | num_options, &options); | |
129 | break; | |
130 | ||
131 | case 'h' : /* -h server */ | |
132 | if (argv[i][2]) | |
133 | cupsSetServer(argv[i] + 2); | |
134 | else | |
135 | { | |
136 | i ++; | |
137 | if (i >= argc) | |
138 | usage(); | |
139 | ||
140 | cupsSetServer(argv[i]); | |
141 | } | |
142 | break; | |
143 | ||
144 | case 'E' : /* Encrypt connection */ | |
145 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); | |
146 | break; | |
147 | ||
148 | case 'l' : /* -l (list options) */ | |
149 | if (dest == NULL) | |
150 | { | |
151 | if (num_dests == 0) | |
152 | num_dests = cupsGetDests(&dests); | |
153 | ||
154 | if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) | |
155 | dest = dests; | |
156 | } | |
157 | ||
158 | if (dest == NULL) | |
fa73b229 | 159 | _cupsLangPuts(stderr, _("lpoptions: No printers!?!\n")); |
ef416fc2 | 160 | else |
161 | list_options(dest); | |
162 | ||
163 | changes = -1; | |
164 | break; | |
165 | ||
166 | case 'o' : /* -o option[=value] */ | |
167 | if (argv[i][2]) | |
168 | num_options = cupsParseOptions(argv[i] + 2, num_options, &options); | |
169 | else | |
170 | { | |
171 | i ++; | |
172 | if (i >= argc) | |
173 | usage(); | |
174 | ||
175 | num_options = cupsParseOptions(argv[i], num_options, &options); | |
176 | } | |
177 | ||
178 | changes = 1; | |
179 | break; | |
180 | ||
181 | case 'p' : /* -p printer */ | |
182 | if (argv[i][2]) | |
183 | printer = argv[i] + 2; | |
184 | else | |
185 | { | |
186 | i ++; | |
187 | if (i >= argc) | |
188 | usage(); | |
189 | ||
190 | printer = argv[i]; | |
191 | } | |
192 | ||
193 | if ((instance = strrchr(printer, '/')) != NULL) | |
194 | *instance++ = '\0'; | |
195 | ||
196 | if (num_dests == 0) | |
197 | num_dests = cupsGetDests(&dests); | |
198 | ||
199 | if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL) | |
200 | { | |
201 | num_dests = cupsAddDest(printer, instance, num_dests, &dests); | |
202 | dest = cupsGetDest(printer, instance, num_dests, dests); | |
203 | ||
204 | if (dest == NULL) | |
205 | { | |
fa73b229 | 206 | _cupsLangPrintf(stderr, |
ef416fc2 | 207 | _("lpoptions: Unable to add printer or " |
208 | "instance: %s\n"), | |
209 | strerror(errno)); | |
210 | return (1); | |
211 | } | |
212 | } | |
213 | ||
214 | for (j = 0; j < dest->num_options; j ++) | |
215 | if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) | |
216 | num_options = cupsAddOption(dest->options[j].name, | |
217 | dest->options[j].value, | |
218 | num_options, &options); | |
219 | break; | |
220 | ||
221 | case 'r' : /* -r option (remove) */ | |
222 | if (argv[i][2]) | |
223 | option = argv[i] + 2; | |
224 | else | |
225 | { | |
226 | i ++; | |
227 | if (i >= argc) | |
228 | usage(); | |
229 | ||
230 | option = argv[i]; | |
231 | } | |
232 | ||
233 | for (j = 0; j < num_options; j ++) | |
234 | if (strcasecmp(options[j].name, option) == 0) | |
235 | { | |
236 | /* | |
237 | * Remove this option... | |
238 | */ | |
239 | ||
240 | num_options --; | |
241 | ||
242 | if (j < num_options) | |
243 | memcpy(options + j, options + j + 1, | |
244 | sizeof(cups_option_t) * (num_options - j)); | |
245 | break; | |
246 | } | |
247 | ||
248 | changes = 1; | |
249 | break; | |
250 | ||
251 | case 'x' : /* -x printer */ | |
252 | if (argv[i][2]) | |
253 | printer = argv[i] + 2; | |
254 | else | |
255 | { | |
256 | i ++; | |
257 | if (i >= argc) | |
258 | usage(); | |
259 | ||
260 | printer = argv[i]; | |
261 | } | |
262 | ||
263 | if ((instance = strrchr(printer, '/')) != NULL) | |
264 | *instance++ = '\0'; | |
265 | ||
266 | if (num_dests == 0) | |
267 | num_dests = cupsGetDests(&dests); | |
268 | ||
269 | if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) | |
270 | { | |
271 | cupsFreeOptions(dest->num_options, dest->options); | |
272 | ||
273 | /* | |
274 | * If we are "deleting" the default printer, then just set the | |
275 | * number of options to 0; if it is also the system default | |
276 | * then cupsSetDests() will remove it for us... | |
277 | */ | |
278 | ||
279 | if (dest->is_default) | |
280 | { | |
281 | dest->num_options = 0; | |
282 | dest->options = NULL; | |
283 | } | |
284 | else | |
285 | { | |
286 | num_dests --; | |
287 | ||
288 | j = dest - dests; | |
289 | if (j < num_dests) | |
290 | memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t)); | |
291 | } | |
292 | } | |
293 | ||
294 | cupsSetDests(num_dests, dests); | |
295 | dest = NULL; | |
296 | changes = -1; | |
297 | break; | |
298 | ||
299 | default : | |
300 | usage(); | |
301 | } | |
302 | } | |
303 | else | |
304 | usage(); | |
305 | ||
306 | if (num_dests == 0) | |
307 | num_dests = cupsGetDests(&dests); | |
308 | ||
309 | if (dest == NULL) | |
310 | { | |
311 | if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) | |
312 | { | |
313 | for (j = 0; j < dest->num_options; j ++) | |
314 | if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) | |
315 | num_options = cupsAddOption(dest->options[j].name, | |
316 | dest->options[j].value, | |
317 | num_options, &options); | |
318 | } | |
319 | } | |
320 | ||
321 | if (dest == NULL) | |
322 | return (0); | |
323 | ||
324 | if (changes > 0) | |
325 | { | |
326 | /* | |
327 | * Set printer options... | |
328 | */ | |
329 | ||
330 | cupsFreeOptions(dest->num_options, dest->options); | |
331 | ||
332 | dest->num_options = num_options; | |
333 | dest->options = options; | |
334 | ||
335 | cupsSetDests(num_dests, dests); | |
336 | } | |
337 | else if (changes == 0) | |
338 | { | |
339 | num_options = dest->num_options; | |
340 | options = dest->options; | |
341 | ||
342 | for (i = 0; i < num_options; i ++) | |
343 | { | |
344 | if (i) | |
fa73b229 | 345 | _cupsLangPuts(stdout, " "); |
ef416fc2 | 346 | |
347 | if (!options[i].value[0]) | |
fa73b229 | 348 | _cupsLangPrintf(stdout, "%s", options[i].name); |
ef416fc2 | 349 | else if (strchr(options[i].value, ' ') != NULL || |
350 | strchr(options[i].value, '\t') != NULL) | |
fa73b229 | 351 | _cupsLangPrintf(stdout, "%s=\'%s\'", options[i].name, |
ef416fc2 | 352 | options[i].value); |
353 | else | |
fa73b229 | 354 | _cupsLangPrintf(stdout, "%s=%s", options[i].name, |
ef416fc2 | 355 | options[i].value); |
356 | } | |
357 | ||
fa73b229 | 358 | _cupsLangPuts(stdout, "\n"); |
ef416fc2 | 359 | } |
360 | ||
361 | return (0); | |
362 | } | |
363 | ||
364 | /* | |
365 | * 'list_group()' - List printer-specific options from the PPD group. | |
366 | */ | |
367 | ||
368 | void | |
369 | list_group(ppd_group_t *group) /* I - Group to show */ | |
370 | { | |
371 | int i, j; /* Looping vars */ | |
372 | ppd_option_t *option; /* Current option */ | |
373 | ppd_choice_t *choice; /* Current choice */ | |
374 | ppd_group_t *subgroup; /* Current subgroup */ | |
375 | ||
376 | ||
377 | for (i = group->num_options, option = group->options; i > 0; i --, option ++) | |
378 | { | |
fa73b229 | 379 | _cupsLangPrintf(stdout, "%s/%s:", option->keyword, option->text); |
ef416fc2 | 380 | |
381 | for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++) | |
382 | if (choice->marked) | |
fa73b229 | 383 | _cupsLangPrintf(stdout, " *%s", choice->choice); |
ef416fc2 | 384 | else |
fa73b229 | 385 | _cupsLangPrintf(stdout, " %s", choice->choice); |
ef416fc2 | 386 | |
fa73b229 | 387 | _cupsLangPuts(stdout, "\n"); |
ef416fc2 | 388 | } |
389 | ||
390 | for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++) | |
391 | list_group(subgroup); | |
392 | } | |
393 | ||
394 | ||
395 | /* | |
396 | * 'list_options()' - List printer-specific options from the PPD file. | |
397 | */ | |
398 | ||
399 | void | |
400 | list_options(cups_dest_t *dest) /* I - Destination to list */ | |
401 | { | |
402 | int i; /* Looping var */ | |
403 | const char *filename; /* PPD filename */ | |
404 | ppd_file_t *ppd; /* PPD data */ | |
405 | ppd_group_t *group; /* Current group */ | |
406 | ||
407 | ||
408 | if ((filename = cupsGetPPD(dest->name)) == NULL) | |
409 | { | |
fa73b229 | 410 | _cupsLangPrintf(stderr, |
ef416fc2 | 411 | _("lpoptions: Destination %s has no PPD file!\n"), |
412 | dest->name); | |
413 | return; | |
414 | } | |
415 | ||
416 | if ((ppd = ppdOpenFile(filename)) == NULL) | |
417 | { | |
418 | unlink(filename); | |
fa73b229 | 419 | _cupsLangPrintf(stderr, |
ef416fc2 | 420 | _("lpoptions: Unable to open PPD file for %s!\n"), |
421 | dest->name); | |
422 | return; | |
423 | } | |
424 | ||
425 | ppdMarkDefaults(ppd); | |
426 | cupsMarkOptions(ppd, dest->num_options, dest->options); | |
427 | ||
428 | for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) | |
429 | list_group(group); | |
430 | ||
431 | ppdClose(ppd); | |
432 | unlink(filename); | |
433 | } | |
434 | ||
435 | ||
436 | /* | |
437 | * 'usage()' - Show program usage and exit. | |
438 | */ | |
439 | ||
440 | void | |
441 | usage(void) | |
442 | { | |
fa73b229 | 443 | _cupsLangPuts(stdout, |
ef416fc2 | 444 | _("Usage: lpoptions [-h server] [-E] -d printer\n" |
445 | " lpoptions [-h server] [-E] [-p printer] -l\n" | |
446 | " lpoptions [-h server] [-E] -p printer -o " | |
447 | "option[=value] ...\n" | |
448 | " lpoptions [-h server] [-E] -x printer\n")); | |
449 | ||
450 | exit(1); | |
451 | } | |
452 | ||
453 | ||
454 | /* | |
f7faf1f5 | 455 | * End of "$Id: lpoptions.c 4924 2006-01-13 01:55:20Z mike $". |
ef416fc2 | 456 | */ |