]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lpoptions.c
30d57aa48f24af954c642c637df0003aa3768bb0
[thirdparty/cups.git] / systemv / lpoptions.c
1 /*
2 * "$Id: lpoptions.c 5753 2006-07-18 19:53:24Z 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 /*
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 {
108 _cupsLangPuts(stderr,
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)
159 _cupsLangPuts(stderr, _("lpoptions: No printers!?!\n"));
160 else
161 list_options(dest);
162
163 changes = -1;
164 break;
165
166 case 'o' : /* -o option[=value] */
167 if (dest == NULL)
168 {
169 if (num_dests == 0)
170 num_dests = cupsGetDests(&dests);
171
172 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
173 dest = dests;
174
175 for (j = 0; j < dest->num_options; j ++)
176 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
177 num_options = cupsAddOption(dest->options[j].name,
178 dest->options[j].value,
179 num_options, &options);
180 }
181
182 if (argv[i][2])
183 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
184 else
185 {
186 i ++;
187 if (i >= argc)
188 usage();
189
190 num_options = cupsParseOptions(argv[i], num_options, &options);
191 }
192
193 changes = 1;
194 break;
195
196 case 'p' : /* -p printer */
197 if (argv[i][2])
198 printer = argv[i] + 2;
199 else
200 {
201 i ++;
202 if (i >= argc)
203 usage();
204
205 printer = argv[i];
206 }
207
208 if ((instance = strrchr(printer, '/')) != NULL)
209 *instance++ = '\0';
210
211 if (num_dests == 0)
212 num_dests = cupsGetDests(&dests);
213
214 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
215 {
216 num_dests = cupsAddDest(printer, instance, num_dests, &dests);
217 dest = cupsGetDest(printer, instance, num_dests, dests);
218
219 if (dest == NULL)
220 {
221 _cupsLangPrintf(stderr,
222 _("lpoptions: Unable to add printer or "
223 "instance: %s\n"),
224 strerror(errno));
225 return (1);
226 }
227 }
228
229 for (j = 0; j < dest->num_options; j ++)
230 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
231 num_options = cupsAddOption(dest->options[j].name,
232 dest->options[j].value,
233 num_options, &options);
234 break;
235
236 case 'r' : /* -r option (remove) */
237 if (dest == NULL)
238 {
239 if (num_dests == 0)
240 num_dests = cupsGetDests(&dests);
241
242 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
243 dest = dests;
244
245 for (j = 0; j < dest->num_options; j ++)
246 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
247 num_options = cupsAddOption(dest->options[j].name,
248 dest->options[j].value,
249 num_options, &options);
250 }
251
252 if (argv[i][2])
253 option = argv[i] + 2;
254 else
255 {
256 i ++;
257 if (i >= argc)
258 usage();
259
260 option = argv[i];
261 }
262
263 for (j = 0; j < num_options; j ++)
264 if (!strcasecmp(options[j].name, option))
265 {
266 /*
267 * Remove this option...
268 */
269
270 num_options --;
271
272 if (j < num_options)
273 memcpy(options + j, options + j + 1,
274 sizeof(cups_option_t) * (num_options - j));
275 break;
276 }
277
278 changes = 1;
279 break;
280
281 case 'x' : /* -x printer */
282 if (argv[i][2])
283 printer = argv[i] + 2;
284 else
285 {
286 i ++;
287 if (i >= argc)
288 usage();
289
290 printer = argv[i];
291 }
292
293 if ((instance = strrchr(printer, '/')) != NULL)
294 *instance++ = '\0';
295
296 if (num_dests == 0)
297 num_dests = cupsGetDests(&dests);
298
299 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
300 {
301 cupsFreeOptions(dest->num_options, dest->options);
302
303 /*
304 * If we are "deleting" the default printer, then just set the
305 * number of options to 0; if it is also the system default
306 * then cupsSetDests() will remove it for us...
307 */
308
309 if (dest->is_default)
310 {
311 dest->num_options = 0;
312 dest->options = NULL;
313 }
314 else
315 {
316 num_dests --;
317
318 j = dest - dests;
319 if (j < num_dests)
320 memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
321 }
322 }
323
324 cupsSetDests(num_dests, dests);
325 dest = NULL;
326 changes = -1;
327 break;
328
329 default :
330 usage();
331 }
332 }
333 else
334 usage();
335
336 if (num_dests == 0)
337 num_dests = cupsGetDests(&dests);
338
339 if (dest == NULL)
340 {
341 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
342 {
343 for (j = 0; j < dest->num_options; j ++)
344 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
345 num_options = cupsAddOption(dest->options[j].name,
346 dest->options[j].value,
347 num_options, &options);
348 }
349 }
350
351 if (dest == NULL)
352 return (0);
353
354 if (changes > 0)
355 {
356 /*
357 * Set printer options...
358 */
359
360 cupsFreeOptions(dest->num_options, dest->options);
361
362 dest->num_options = num_options;
363 dest->options = options;
364
365 cupsSetDests(num_dests, dests);
366 }
367 else if (changes == 0)
368 {
369 num_options = dest->num_options;
370 options = dest->options;
371
372 for (i = 0; i < num_options; i ++)
373 {
374 if (i)
375 _cupsLangPuts(stdout, " ");
376
377 if (!options[i].value[0])
378 _cupsLangPrintf(stdout, "%s", options[i].name);
379 else if (strchr(options[i].value, ' ') != NULL ||
380 strchr(options[i].value, '\t') != NULL)
381 _cupsLangPrintf(stdout, "%s=\'%s\'", options[i].name,
382 options[i].value);
383 else
384 _cupsLangPrintf(stdout, "%s=%s", options[i].name,
385 options[i].value);
386 }
387
388 _cupsLangPuts(stdout, "\n");
389 }
390
391 return (0);
392 }
393
394 /*
395 * 'list_group()' - List printer-specific options from the PPD group.
396 */
397
398 void
399 list_group(ppd_group_t *group) /* I - Group to show */
400 {
401 int i, j; /* Looping vars */
402 ppd_option_t *option; /* Current option */
403 ppd_choice_t *choice; /* Current choice */
404 ppd_group_t *subgroup; /* Current subgroup */
405
406
407 for (i = group->num_options, option = group->options; i > 0; i --, option ++)
408 {
409 _cupsLangPrintf(stdout, "%s/%s:", option->keyword, option->text);
410
411 for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
412 if (choice->marked)
413 _cupsLangPrintf(stdout, " *%s", choice->choice);
414 else
415 _cupsLangPrintf(stdout, " %s", choice->choice);
416
417 _cupsLangPuts(stdout, "\n");
418 }
419
420 for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
421 list_group(subgroup);
422 }
423
424
425 /*
426 * 'list_options()' - List printer-specific options from the PPD file.
427 */
428
429 void
430 list_options(cups_dest_t *dest) /* I - Destination to list */
431 {
432 int i; /* Looping var */
433 const char *filename; /* PPD filename */
434 ppd_file_t *ppd; /* PPD data */
435 ppd_group_t *group; /* Current group */
436
437
438 if ((filename = cupsGetPPD(dest->name)) == NULL)
439 {
440 _cupsLangPrintf(stderr,
441 _("lpoptions: Destination %s has no PPD file!\n"),
442 dest->name);
443 return;
444 }
445
446 if ((ppd = ppdOpenFile(filename)) == NULL)
447 {
448 unlink(filename);
449 _cupsLangPrintf(stderr,
450 _("lpoptions: Unable to open PPD file for %s!\n"),
451 dest->name);
452 return;
453 }
454
455 ppdMarkDefaults(ppd);
456 cupsMarkOptions(ppd, dest->num_options, dest->options);
457
458 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
459 list_group(group);
460
461 ppdClose(ppd);
462 unlink(filename);
463 }
464
465
466 /*
467 * 'usage()' - Show program usage and exit.
468 */
469
470 void
471 usage(void)
472 {
473 _cupsLangPuts(stdout,
474 _("Usage: lpoptions [-h server] [-E] -d printer\n"
475 " lpoptions [-h server] [-E] [-p printer] -l\n"
476 " lpoptions [-h server] [-E] -p printer -o "
477 "option[=value] ...\n"
478 " lpoptions [-h server] [-E] -x printer\n"));
479
480 exit(1);
481 }
482
483
484 /*
485 * End of "$Id: lpoptions.c 5753 2006-07-18 19:53:24Z mike $".
486 */