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