]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpoptions.c
Load cups into easysw/current.
[thirdparty/cups.git] / systemv / lpoptions.c
1 /*
2 * "$Id: lpoptions.c 5833 2006-08-16 20:05:58Z mike $"
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 _cupsSetLocale();
73
74 /*
75 * Loop through the command-line arguments...
76 */
77
78 dest = NULL;
79 num_dests = 0;
80 dests = NULL;
81 num_options = 0;
82 options = NULL;
83 changes = 0;
84
85 for (i = 1; i < argc; i ++)
86 if (argv[i][0] == '-')
87 {
88 switch (argv[i][1])
89 {
90 case 'd' : /* -d printer */
91 if (argv[i][2])
92 printer = argv[i] + 2;
93 else
94 {
95 i ++;
96 if (i >= argc)
97 usage();
98
99 printer = argv[i];
100 }
101
102 if ((instance = strrchr(printer, '/')) != NULL)
103 *instance++ = '\0';
104
105 if (num_dests == 0)
106 num_dests = cupsGetDests(&dests);
107
108 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
109 {
110 _cupsLangPuts(stderr,
111 _("lpoptions: Unknown printer or class!\n"));
112 return (1);
113 }
114
115 /*
116 * Set the default destination...
117 */
118
119 for (j = 0; j < num_dests; j ++)
120 dests[j].is_default = 0;
121
122 dest->is_default = 1;
123
124 cupsSetDests(num_dests, dests);
125
126 for (j = 0; j < dest->num_options; j ++)
127 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
128 num_options = cupsAddOption(dest->options[j].name,
129 dest->options[j].value,
130 num_options, &options);
131 break;
132
133 case 'h' : /* -h server */
134 if (argv[i][2])
135 cupsSetServer(argv[i] + 2);
136 else
137 {
138 i ++;
139 if (i >= argc)
140 usage();
141
142 cupsSetServer(argv[i]);
143 }
144 break;
145
146 case 'E' : /* Encrypt connection */
147 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
148 break;
149
150 case 'l' : /* -l (list options) */
151 if (dest == NULL)
152 {
153 if (num_dests == 0)
154 num_dests = cupsGetDests(&dests);
155
156 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
157 dest = dests;
158 }
159
160 if (dest == NULL)
161 _cupsLangPuts(stderr, _("lpoptions: No printers!?!\n"));
162 else
163 list_options(dest);
164
165 changes = -1;
166 break;
167
168 case 'o' : /* -o option[=value] */
169 if (dest == NULL)
170 {
171 if (num_dests == 0)
172 num_dests = cupsGetDests(&dests);
173
174 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
175 dest = dests;
176
177 for (j = 0; j < dest->num_options; j ++)
178 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
179 num_options = cupsAddOption(dest->options[j].name,
180 dest->options[j].value,
181 num_options, &options);
182 }
183
184 if (argv[i][2])
185 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
186 else
187 {
188 i ++;
189 if (i >= argc)
190 usage();
191
192 num_options = cupsParseOptions(argv[i], num_options, &options);
193 }
194
195 changes = 1;
196 break;
197
198 case 'p' : /* -p printer */
199 if (argv[i][2])
200 printer = argv[i] + 2;
201 else
202 {
203 i ++;
204 if (i >= argc)
205 usage();
206
207 printer = argv[i];
208 }
209
210 if ((instance = strrchr(printer, '/')) != NULL)
211 *instance++ = '\0';
212
213 if (num_dests == 0)
214 num_dests = cupsGetDests(&dests);
215
216 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
217 {
218 num_dests = cupsAddDest(printer, instance, num_dests, &dests);
219 dest = cupsGetDest(printer, instance, num_dests, dests);
220
221 if (dest == NULL)
222 {
223 _cupsLangPrintf(stderr,
224 _("lpoptions: Unable to add printer or "
225 "instance: %s\n"),
226 strerror(errno));
227 return (1);
228 }
229 }
230
231 for (j = 0; j < dest->num_options; j ++)
232 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
233 num_options = cupsAddOption(dest->options[j].name,
234 dest->options[j].value,
235 num_options, &options);
236 break;
237
238 case 'r' : /* -r option (remove) */
239 if (dest == NULL)
240 {
241 if (num_dests == 0)
242 num_dests = cupsGetDests(&dests);
243
244 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
245 dest = dests;
246
247 for (j = 0; j < dest->num_options; j ++)
248 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
249 num_options = cupsAddOption(dest->options[j].name,
250 dest->options[j].value,
251 num_options, &options);
252 }
253
254 if (argv[i][2])
255 option = argv[i] + 2;
256 else
257 {
258 i ++;
259 if (i >= argc)
260 usage();
261
262 option = argv[i];
263 }
264
265 for (j = 0; j < num_options; j ++)
266 if (!strcasecmp(options[j].name, option))
267 {
268 /*
269 * Remove this option...
270 */
271
272 num_options --;
273
274 if (j < num_options)
275 memcpy(options + j, options + j + 1,
276 sizeof(cups_option_t) * (num_options - j));
277 break;
278 }
279
280 changes = 1;
281 break;
282
283 case 'x' : /* -x printer */
284 if (argv[i][2])
285 printer = argv[i] + 2;
286 else
287 {
288 i ++;
289 if (i >= argc)
290 usage();
291
292 printer = argv[i];
293 }
294
295 if ((instance = strrchr(printer, '/')) != NULL)
296 *instance++ = '\0';
297
298 if (num_dests == 0)
299 num_dests = cupsGetDests(&dests);
300
301 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
302 {
303 cupsFreeOptions(dest->num_options, dest->options);
304
305 /*
306 * If we are "deleting" the default printer, then just set the
307 * number of options to 0; if it is also the system default
308 * then cupsSetDests() will remove it for us...
309 */
310
311 if (dest->is_default)
312 {
313 dest->num_options = 0;
314 dest->options = NULL;
315 }
316 else
317 {
318 num_dests --;
319
320 j = dest - dests;
321 if (j < num_dests)
322 memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
323 }
324 }
325
326 cupsSetDests(num_dests, dests);
327 dest = NULL;
328 changes = -1;
329 break;
330
331 default :
332 usage();
333 }
334 }
335 else
336 usage();
337
338 if (num_dests == 0)
339 num_dests = cupsGetDests(&dests);
340
341 if (dest == NULL)
342 {
343 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
344 {
345 for (j = 0; j < dest->num_options; j ++)
346 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
347 num_options = cupsAddOption(dest->options[j].name,
348 dest->options[j].value,
349 num_options, &options);
350 }
351 }
352
353 if (dest == NULL)
354 return (0);
355
356 if (changes > 0)
357 {
358 /*
359 * Set printer options...
360 */
361
362 cupsFreeOptions(dest->num_options, dest->options);
363
364 dest->num_options = num_options;
365 dest->options = options;
366
367 cupsSetDests(num_dests, dests);
368 }
369 else if (changes == 0)
370 {
371 num_options = dest->num_options;
372 options = dest->options;
373
374 for (i = 0; i < num_options; i ++)
375 {
376 if (i)
377 _cupsLangPuts(stdout, " ");
378
379 if (!options[i].value[0])
380 _cupsLangPrintf(stdout, "%s", options[i].name);
381 else if (strchr(options[i].value, ' ') != NULL ||
382 strchr(options[i].value, '\t') != NULL)
383 _cupsLangPrintf(stdout, "%s=\'%s\'", options[i].name,
384 options[i].value);
385 else
386 _cupsLangPrintf(stdout, "%s=%s", options[i].name,
387 options[i].value);
388 }
389
390 _cupsLangPuts(stdout, "\n");
391 }
392
393 return (0);
394 }
395
396 /*
397 * 'list_group()' - List printer-specific options from the PPD group.
398 */
399
400 void
401 list_group(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
408
409 for (i = group->num_options, option = group->options; i > 0; i --, option ++)
410 {
411 _cupsLangPrintf(stdout, "%s/%s:", option->keyword, option->text);
412
413 for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
414 if (choice->marked)
415 _cupsLangPrintf(stdout, " *%s", choice->choice);
416 else
417 _cupsLangPrintf(stdout, " %s", choice->choice);
418
419 _cupsLangPuts(stdout, "\n");
420 }
421
422 for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
423 list_group(subgroup);
424 }
425
426
427 /*
428 * 'list_options()' - List printer-specific options from the PPD file.
429 */
430
431 void
432 list_options(cups_dest_t *dest) /* I - Destination to list */
433 {
434 int i; /* Looping var */
435 const char *filename; /* PPD filename */
436 ppd_file_t *ppd; /* PPD data */
437 ppd_group_t *group; /* Current group */
438
439
440 if ((filename = cupsGetPPD(dest->name)) == NULL)
441 {
442 _cupsLangPrintf(stderr,
443 _("lpoptions: Destination %s has no PPD file!\n"),
444 dest->name);
445 return;
446 }
447
448 if ((ppd = ppdOpenFile(filename)) == NULL)
449 {
450 unlink(filename);
451 _cupsLangPrintf(stderr,
452 _("lpoptions: Unable to open PPD file for %s!\n"),
453 dest->name);
454 return;
455 }
456
457 ppdMarkDefaults(ppd);
458 cupsMarkOptions(ppd, dest->num_options, dest->options);
459
460 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
461 list_group(group);
462
463 ppdClose(ppd);
464 unlink(filename);
465 }
466
467
468 /*
469 * 'usage()' - Show program usage and exit.
470 */
471
472 void
473 usage(void)
474 {
475 _cupsLangPuts(stdout,
476 _("Usage: lpoptions [-h server] [-E] -d printer\n"
477 " lpoptions [-h server] [-E] [-p printer] -l\n"
478 " lpoptions [-h server] [-E] -p printer -o "
479 "option[=value] ...\n"
480 " lpoptions [-h server] [-E] -x printer\n"));
481
482 exit(1);
483 }
484
485
486 /*
487 * End of "$Id: lpoptions.c 5833 2006-08-16 20:05:58Z mike $".
488 */