Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/systemv/lpadmin.c
1090 views
1
/*
2
* "lpadmin" command for CUPS.
3
*
4
* Copyright © 2021-2022 by OpenPrinting.
5
* Copyright © 2007-2021 by Apple Inc.
6
* Copyright © 1997-2006 by Easy Software Products.
7
*
8
* Licensed under Apache License v2.0. See the file "LICENSE" for more
9
* information.
10
*/
11
12
/*
13
* Include necessary headers...
14
*/
15
16
#include <cups/cups-private.h>
17
#include <cups/ppd-private.h>
18
19
20
/*
21
* Local functions...
22
*/
23
24
static int add_printer_to_class(http_t *http, char *printer, char *pclass);
25
static int default_printer(http_t *http, char *printer);
26
static int delete_printer(http_t *http, char *printer);
27
static int delete_printer_from_class(http_t *http, char *printer,
28
char *pclass);
29
static int delete_printer_option(http_t *http, char *printer,
30
char *option);
31
static int enable_printer(http_t *http, char *printer);
32
static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri,
33
size_t urisize);
34
static int set_printer_options(http_t *http, char *printer,
35
int num_options, cups_option_t *options,
36
char *file, int enable);
37
static void usage(void) _CUPS_NORETURN;
38
static int validate_name(const char *name);
39
40
41
/*
42
* 'main()' - Parse options and configure the scheduler.
43
*/
44
45
int /* O - Exit status */
46
main(int argc, /* I - Number of command-line arguments */
47
char *argv[]) /* I - Command-line arguments */
48
{
49
int i; /* Looping var */
50
http_t *http; /* Connection to server */
51
char *printer, /* Destination printer */
52
*pclass, /* Printer class name */
53
*opt, /* Option pointer */
54
*val; /* Pointer to allow/deny value */
55
int enable = 0; /* Enable/resume printer? */
56
int num_options; /* Number of options */
57
cups_option_t *options; /* Options */
58
char *file, /* New PPD file */
59
evefile[1024] = ""; /* IPP Everywhere PPD */
60
const char *ppd_name, /* ppd-name value */
61
*device_uri; /* device-uri value */
62
63
64
_cupsSetLocale(argv);
65
66
http = NULL;
67
printer = NULL;
68
num_options = 0;
69
options = NULL;
70
file = NULL;
71
72
for (i = 1; i < argc; i ++)
73
{
74
if (!strcmp(argv[i], "--help"))
75
usage();
76
else if (argv[i][0] == '-')
77
{
78
for (opt = argv[i] + 1; *opt; opt ++)
79
{
80
switch (*opt)
81
{
82
case 'c' : /* Add printer to class */
83
if (!http)
84
{
85
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
86
87
if (http == NULL)
88
{
89
_cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
90
return (1);
91
}
92
}
93
94
if (printer == NULL)
95
{
96
_cupsLangPuts(stderr,
97
_("lpadmin: Unable to add a printer to the class:\n"
98
" You must specify a printer name first."));
99
return (1);
100
}
101
102
if (opt[1] != '\0')
103
{
104
pclass = opt + 1;
105
opt += strlen(opt) - 1;
106
}
107
else
108
{
109
i ++;
110
111
if (i >= argc)
112
{
113
_cupsLangPuts(stderr, _("lpadmin: Expected class name after \"-c\" option."));
114
usage();
115
}
116
117
pclass = argv[i];
118
}
119
120
if (!validate_name(pclass))
121
{
122
_cupsLangPuts(stderr,
123
_("lpadmin: Class name can only contain printable "
124
"characters."));
125
return (1);
126
}
127
128
if (add_printer_to_class(http, printer, pclass))
129
return (1);
130
break;
131
132
case 'd' : /* Set as default destination */
133
if (!http)
134
{
135
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
136
137
if (http == NULL)
138
{
139
_cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
140
return (1);
141
}
142
}
143
144
if (opt[1] != '\0')
145
{
146
printer = opt + 1;
147
opt += strlen(opt) - 1;
148
}
149
else
150
{
151
i ++;
152
153
if (i >= argc)
154
{
155
_cupsLangPuts(stderr, _("lpadmin: Expected printer name after \"-d\" option."));
156
usage();
157
}
158
159
printer = argv[i];
160
}
161
162
if (!validate_name(printer))
163
{
164
_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
165
return (1);
166
}
167
168
if (default_printer(http, printer))
169
return (1);
170
171
i = argc;
172
break;
173
174
case 'h' : /* Connect to host */
175
if (http)
176
{
177
httpClose(http);
178
http = NULL;
179
}
180
181
if (opt[1] != '\0')
182
{
183
cupsSetServer(opt + 1);
184
opt += strlen(opt) - 1;
185
}
186
else
187
{
188
i ++;
189
190
if (i >= argc)
191
{
192
_cupsLangPuts(stderr, _("lpadmin: Expected hostname after \"-h\" option."));
193
usage();
194
}
195
196
cupsSetServer(argv[i]);
197
}
198
break;
199
200
case 'P' : /* Use the specified PPD file */
201
case 'i' : /* Use the specified PPD file */
202
if (opt[1] != '\0')
203
{
204
file = opt + 1;
205
opt += strlen(opt) - 1;
206
}
207
else
208
{
209
i ++;
210
211
if (i >= argc)
212
{
213
_cupsLangPrintf(stderr, _("lpadmin: Expected PPD after \"-%c\" option."), argv[i - 1][1]);
214
usage();
215
}
216
217
file = argv[i];
218
}
219
220
if (*opt == 'i')
221
{
222
/*
223
* Check to see that the specified file is, in fact, a PPD...
224
*/
225
226
cups_file_t *fp = cupsFileOpen(file, "r");
227
char line[256];
228
229
if (!cupsFileGets(fp, line, sizeof(line)) || strncmp(line, "*PPD-Adobe", 10))
230
{
231
_cupsLangPuts(stderr, _("lpadmin: System V interface scripts are no longer supported for security reasons."));
232
cupsFileClose(fp);
233
return (1);
234
}
235
236
cupsFileClose(fp);
237
}
238
break;
239
240
case 'E' : /* Enable the printer/enable encryption */
241
if (printer == NULL)
242
{
243
#ifdef HAVE_TLS
244
cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
245
246
if (http)
247
httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
248
#else
249
_cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
250
#endif /* HAVE_TLS */
251
break;
252
}
253
254
if (!http)
255
{
256
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
257
258
if (http == NULL)
259
{
260
_cupsLangPrintf(stderr,
261
_("lpadmin: Unable to connect to server: %s"),
262
strerror(errno));
263
return (1);
264
}
265
}
266
267
enable = 1;
268
break;
269
270
case 'm' : /* Use the specified standard script/PPD file */
271
if (opt[1] != '\0')
272
{
273
num_options = cupsAddOption("ppd-name", opt + 1, num_options, &options);
274
opt += strlen(opt) - 1;
275
}
276
else
277
{
278
i ++;
279
280
if (i >= argc)
281
{
282
_cupsLangPuts(stderr, _("lpadmin: Expected model after \"-m\" option."));
283
usage();
284
}
285
286
num_options = cupsAddOption("ppd-name", argv[i], num_options, &options);
287
}
288
break;
289
290
case 'o' : /* Set option */
291
if (opt[1] != '\0')
292
{
293
num_options = cupsParseOptions(opt + 1, num_options, &options);
294
opt += strlen(opt) - 1;
295
}
296
else
297
{
298
i ++;
299
300
if (i >= argc)
301
{
302
_cupsLangPuts(stderr, _("lpadmin: Expected name=value after \"-o\" option."));
303
usage();
304
}
305
306
num_options = cupsParseOptions(argv[i], num_options, &options);
307
}
308
break;
309
310
case 'p' : /* Add/modify a printer */
311
if (opt[1] != '\0')
312
{
313
printer = opt + 1;
314
opt += strlen(opt) - 1;
315
}
316
else
317
{
318
i ++;
319
320
if (i >= argc)
321
{
322
_cupsLangPuts(stderr, _("lpadmin: Expected printer after \"-p\" option."));
323
usage();
324
}
325
326
printer = argv[i];
327
}
328
329
if (!validate_name(printer))
330
{
331
_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
332
return (1);
333
}
334
break;
335
336
case 'r' : /* Remove printer from class */
337
if (!http)
338
{
339
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
340
341
if (http == NULL)
342
{
343
_cupsLangPrintf(stderr,
344
_("lpadmin: Unable to connect to server: %s"),
345
strerror(errno));
346
return (1);
347
}
348
}
349
350
if (printer == NULL)
351
{
352
_cupsLangPuts(stderr,
353
_("lpadmin: Unable to remove a printer from the class:\n"
354
" You must specify a printer name first."));
355
return (1);
356
}
357
358
if (opt[1] != '\0')
359
{
360
pclass = opt + 1;
361
opt += strlen(opt) - 1;
362
}
363
else
364
{
365
i ++;
366
367
if (i >= argc)
368
{
369
_cupsLangPuts(stderr, _("lpadmin: Expected class after \"-r\" option."));
370
usage();
371
}
372
373
pclass = argv[i];
374
}
375
376
if (!validate_name(pclass))
377
{
378
_cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable characters."));
379
return (1);
380
}
381
382
if (delete_printer_from_class(http, printer, pclass))
383
return (1);
384
break;
385
386
case 'R' : /* Remove option */
387
if (!http)
388
{
389
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
390
391
if (http == NULL)
392
{
393
_cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
394
return (1);
395
}
396
}
397
398
if (printer == NULL)
399
{
400
_cupsLangPuts(stderr,
401
_("lpadmin: Unable to delete option:\n"
402
" You must specify a printer name first."));
403
return (1);
404
}
405
406
if (opt[1] != '\0')
407
{
408
val = opt + 1;
409
opt += strlen(opt) - 1;
410
}
411
else
412
{
413
i ++;
414
415
if (i >= argc)
416
{
417
_cupsLangPuts(stderr, _("lpadmin: Expected name after \"-R\" option."));
418
usage();
419
}
420
421
val = argv[i];
422
}
423
424
if (delete_printer_option(http, printer, val))
425
return (1);
426
break;
427
428
case 'U' : /* Username */
429
if (opt[1] != '\0')
430
{
431
cupsSetUser(opt + 1);
432
opt += strlen(opt) - 1;
433
}
434
else
435
{
436
i ++;
437
if (i >= argc)
438
{
439
_cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]);
440
usage();
441
}
442
443
cupsSetUser(argv[i]);
444
}
445
break;
446
447
case 'u' : /* Allow/deny users */
448
if (opt[1] != '\0')
449
{
450
val = opt + 1;
451
opt += strlen(opt) - 1;
452
}
453
else
454
{
455
i ++;
456
457
if (i >= argc)
458
{
459
_cupsLangPuts(stderr, _("lpadmin: Expected allow/deny:userlist after \"-u\" option."));
460
usage();
461
}
462
463
val = argv[i];
464
}
465
466
if (!_cups_strncasecmp(val, "allow:", 6))
467
num_options = cupsAddOption("requesting-user-name-allowed", val + 6, num_options, &options);
468
else if (!_cups_strncasecmp(val, "deny:", 5))
469
num_options = cupsAddOption("requesting-user-name-denied", val + 5, num_options, &options);
470
else
471
{
472
_cupsLangPrintf(stderr, _("lpadmin: Unknown allow/deny option \"%s\"."), val);
473
return (1);
474
}
475
break;
476
477
case 'v' : /* Set the device-uri attribute */
478
if (opt[1] != '\0')
479
{
480
num_options = cupsAddOption("device-uri", opt + 1, num_options, &options);
481
opt += strlen(opt) - 1;
482
}
483
else
484
{
485
i ++;
486
487
if (i >= argc)
488
{
489
_cupsLangPuts(stderr, _("lpadmin: Expected device URI after \"-v\" option."));
490
usage();
491
}
492
493
num_options = cupsAddOption("device-uri", argv[i], num_options, &options);
494
}
495
break;
496
497
case 'x' : /* Delete a printer */
498
if (!http)
499
{
500
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
501
502
if (http == NULL)
503
{
504
_cupsLangPrintf(stderr,
505
_("lpadmin: Unable to connect to server: %s"),
506
strerror(errno));
507
return (1);
508
}
509
}
510
511
if (opt[1] != '\0')
512
{
513
printer = opt + 1;
514
opt += strlen(opt) - 1;
515
}
516
else
517
{
518
i ++;
519
520
if (i >= argc)
521
{
522
_cupsLangPuts(stderr, _("lpadmin: Expected printer or class after \"-x\" option."));
523
usage();
524
}
525
526
printer = argv[i];
527
}
528
529
if (!validate_name(printer))
530
{
531
_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
532
return (1);
533
}
534
535
if (delete_printer(http, printer))
536
return (1);
537
538
i = argc;
539
break;
540
541
case 'D' : /* Set the printer-info attribute */
542
if (opt[1] != '\0')
543
{
544
num_options = cupsAddOption("printer-info", opt + 1, num_options, &options);
545
opt += strlen(opt) - 1;
546
}
547
else
548
{
549
i ++;
550
551
if (i >= argc)
552
{
553
_cupsLangPuts(stderr, _("lpadmin: Expected description after \"-D\" option."));
554
usage();
555
}
556
557
num_options = cupsAddOption("printer-info", argv[i], num_options, &options);
558
}
559
break;
560
561
case 'I' : /* Set the supported file types (ignored) */
562
i ++;
563
564
if (i >= argc)
565
{
566
_cupsLangPuts(stderr, _("lpadmin: Expected file type(s) after \"-I\" option."));
567
usage();
568
}
569
570
_cupsLangPuts(stderr, _("lpadmin: Warning - content type list ignored."));
571
break;
572
573
case 'L' : /* Set the printer-location attribute */
574
if (opt[1] != '\0')
575
{
576
num_options = cupsAddOption("printer-location", opt + 1, num_options, &options);
577
opt += strlen(opt) - 1;
578
}
579
else
580
{
581
i ++;
582
583
if (i >= argc)
584
{
585
_cupsLangPuts(stderr, _("lpadmin: Expected location after \"-L\" option."));
586
usage();
587
}
588
589
num_options = cupsAddOption("printer-location", argv[i], num_options, &options);
590
}
591
break;
592
593
default :
594
_cupsLangPrintf(stderr, _("lpadmin: Unknown option \"%c\"."), *opt);
595
usage();
596
}
597
}
598
}
599
else
600
{
601
_cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), argv[i]);
602
usage();
603
}
604
}
605
606
/*
607
* Set options as needed...
608
*/
609
610
ppd_name = cupsGetOption("ppd-name", num_options, options);
611
device_uri = cupsGetOption("device-uri", num_options, options);
612
613
if (ppd_name && !strcmp(ppd_name, "raw"))
614
{
615
#ifdef __APPLE__
616
_cupsLangPuts(stderr, _("lpadmin: Raw queues are no longer supported on macOS."));
617
#else
618
_cupsLangPuts(stderr, _("lpadmin: Raw queues are deprecated and will stop working in a future version of CUPS."));
619
#endif /* __APPLE__ */
620
621
if (device_uri && (!strncmp(device_uri, "ipp://", 6) || !strncmp(device_uri, "ipps://", 7)) && strstr(device_uri, "/printers/"))
622
_cupsLangPuts(stderr, _("lpadmin: Use the 'everywhere' model for shared printers."));
623
624
#ifdef __APPLE__
625
return (1);
626
#endif /* __APPLE__ */
627
}
628
else if ((ppd_name && strcmp(ppd_name, "everywhere") && strncmp(ppd_name, "driverless:", 11)) || file)
629
{
630
_cupsLangPuts(stderr, _("lpadmin: Printer drivers are deprecated and will stop working in a future version of CUPS."));
631
}
632
633
if (num_options || file)
634
{
635
if (printer == NULL)
636
{
637
_cupsLangPuts(stderr,
638
_("lpadmin: Unable to set the printer options:\n"
639
" You must specify a printer name first."));
640
return (1);
641
}
642
643
if (!http)
644
{
645
http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
646
cupsEncryption(), 1, 30000, NULL);
647
648
if (http == NULL) {
649
_cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"),
650
strerror(errno));
651
return (1);
652
}
653
}
654
655
if (set_printer_options(http, printer, num_options, options, file, enable))
656
return (1);
657
}
658
else if (enable && enable_printer(http, printer))
659
return (1);
660
661
if (evefile[0])
662
unlink(evefile);
663
664
if (printer == NULL)
665
usage();
666
667
if (http)
668
httpClose(http);
669
670
return (0);
671
}
672
673
674
/*
675
* 'add_printer_to_class()' - Add a printer to a class.
676
*/
677
678
static int /* O - 0 on success, 1 on fail */
679
add_printer_to_class(http_t *http, /* I - Server connection */
680
char *printer, /* I - Printer to add */
681
char *pclass) /* I - Class to add to */
682
{
683
int i; /* Looping var */
684
ipp_t *request, /* IPP Request */
685
*response; /* IPP Response */
686
ipp_attribute_t *attr, /* Current attribute */
687
*members; /* Members in class */
688
char uri[HTTP_MAX_URI]; /* URI for printer/class */
689
690
691
/*
692
* Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
693
* attributes:
694
*
695
* attributes-charset
696
* attributes-natural-language
697
* printer-uri
698
* requesting-user-name
699
*/
700
701
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
702
703
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
704
"localhost", 0, "/classes/%s", pclass);
705
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
706
"printer-uri", NULL, uri);
707
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
708
NULL, cupsUser());
709
710
/*
711
* Do the request and get back a response...
712
*/
713
714
response = cupsDoRequest(http, request, "/");
715
716
/*
717
* Build a CUPS-Add-Modify-Class request, which requires the following
718
* attributes:
719
*
720
* attributes-charset
721
* attributes-natural-language
722
* printer-uri
723
* requesting-user-name
724
* member-uris
725
*/
726
727
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
728
729
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
730
"printer-uri", NULL, uri);
731
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
732
NULL, cupsUser());
733
734
/*
735
* See if the printer is already in the class...
736
*/
737
738
if (response != NULL &&
739
(members = ippFindAttribute(response, "member-names",
740
IPP_TAG_NAME)) != NULL)
741
for (i = 0; i < members->num_values; i ++)
742
if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
743
{
744
_cupsLangPrintf(stderr,
745
_("lpadmin: Printer %s is already a member of class "
746
"%s."), printer, pclass);
747
ippDelete(request);
748
ippDelete(response);
749
return (0);
750
}
751
752
/*
753
* OK, the printer isn't part of the class, so add it...
754
*/
755
756
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
757
"localhost", 0, "/printers/%s", printer);
758
759
if (response != NULL &&
760
(members = ippFindAttribute(response, "member-uris",
761
IPP_TAG_URI)) != NULL)
762
{
763
/*
764
* Add the printer to the existing list...
765
*/
766
767
attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
768
"member-uris", members->num_values + 1, NULL, NULL);
769
for (i = 0; i < members->num_values; i ++)
770
attr->values[i].string.text =
771
_cupsStrAlloc(members->values[i].string.text);
772
773
attr->values[i].string.text = _cupsStrAlloc(uri);
774
}
775
else
776
ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
777
uri);
778
779
/*
780
* Then send the request...
781
*/
782
783
ippDelete(response);
784
785
ippDelete(cupsDoRequest(http, request, "/admin/"));
786
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
787
{
788
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
789
790
return (1);
791
}
792
else
793
return (0);
794
}
795
796
797
/*
798
* 'default_printer()' - Set the default printing destination.
799
*/
800
801
static int /* O - 0 on success, 1 on fail */
802
default_printer(http_t *http, /* I - Server connection */
803
char *printer) /* I - Printer name */
804
{
805
ipp_t *request; /* IPP Request */
806
char uri[HTTP_MAX_URI]; /* URI for printer/class */
807
808
809
/*
810
* Build a CUPS-Set-Default request, which requires the following
811
* attributes:
812
*
813
* attributes-charset
814
* attributes-natural-language
815
* printer-uri
816
* requesting-user-name
817
*/
818
819
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
820
"localhost", 0, "/printers/%s", printer);
821
822
request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
823
824
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
825
"printer-uri", NULL, uri);
826
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
827
NULL, cupsUser());
828
829
/*
830
* Do the request and get back a response...
831
*/
832
833
ippDelete(cupsDoRequest(http, request, "/admin/"));
834
835
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
836
{
837
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
838
839
return (1);
840
}
841
else
842
return (0);
843
}
844
845
846
/*
847
* 'delete_printer()' - Delete a printer from the system...
848
*/
849
850
static int /* O - 0 on success, 1 on fail */
851
delete_printer(http_t *http, /* I - Server connection */
852
char *printer) /* I - Printer to delete */
853
{
854
ipp_t *request; /* IPP Request */
855
char uri[HTTP_MAX_URI]; /* URI for printer/class */
856
857
858
/*
859
* Build a CUPS-Delete-Printer request, which requires the following
860
* attributes:
861
*
862
* attributes-charset
863
* attributes-natural-language
864
* printer-uri
865
* requesting-user-name
866
*/
867
868
request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
869
870
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
871
"localhost", 0, "/printers/%s", printer);
872
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
873
"printer-uri", NULL, uri);
874
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
875
NULL, cupsUser());
876
877
/*
878
* Do the request and get back a response...
879
*/
880
881
ippDelete(cupsDoRequest(http, request, "/admin/"));
882
883
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
884
{
885
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
886
887
return (1);
888
}
889
else
890
return (0);
891
}
892
893
894
/*
895
* 'delete_printer_from_class()' - Delete a printer from a class.
896
*/
897
898
static int /* O - 0 on success, 1 on fail */
899
delete_printer_from_class(
900
http_t *http, /* I - Server connection */
901
char *printer, /* I - Printer to remove */
902
char *pclass) /* I - Class to remove from */
903
{
904
int i, j, k; /* Looping vars */
905
ipp_t *request, /* IPP Request */
906
*response; /* IPP Response */
907
ipp_attribute_t *attr, /* Current attribute */
908
*members; /* Members in class */
909
char uri[HTTP_MAX_URI]; /* URI for printer/class */
910
911
912
/*
913
* Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
914
* attributes:
915
*
916
* attributes-charset
917
* attributes-natural-language
918
* printer-uri
919
* requesting-user-name
920
*/
921
922
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
923
924
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
925
"localhost", 0, "/classes/%s", pclass);
926
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
927
"printer-uri", NULL, uri);
928
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
929
NULL, cupsUser());
930
931
/*
932
* Do the request and get back a response...
933
*/
934
935
if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
936
response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND)
937
{
938
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
939
940
ippDelete(response);
941
942
return (1);
943
}
944
945
/*
946
* See if the printer is already in the class...
947
*/
948
949
if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
950
{
951
_cupsLangPuts(stderr, _("lpadmin: No member names were seen."));
952
953
ippDelete(response);
954
955
return (1);
956
}
957
958
for (i = 0; i < members->num_values; i ++)
959
if (!_cups_strcasecmp(printer, members->values[i].string.text))
960
break;
961
962
if (i >= members->num_values)
963
{
964
_cupsLangPrintf(stderr,
965
_("lpadmin: Printer %s is not a member of class %s."),
966
printer, pclass);
967
968
ippDelete(response);
969
970
return (1);
971
}
972
973
if (members->num_values == 1)
974
{
975
/*
976
* Build a CUPS-Delete-Class request, which requires the following
977
* attributes:
978
*
979
* attributes-charset
980
* attributes-natural-language
981
* printer-uri
982
* requesting-user-name
983
*/
984
985
request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS);
986
987
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
988
"printer-uri", NULL, uri);
989
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
990
"requesting-user-name", NULL, cupsUser());
991
}
992
else
993
{
994
/*
995
* Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following
996
* attributes:
997
*
998
* attributes-charset
999
* attributes-natural-language
1000
* printer-uri
1001
* requesting-user-name
1002
* member-uris
1003
*/
1004
1005
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1006
1007
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1008
"printer-uri", NULL, uri);
1009
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1010
"requesting-user-name", NULL, cupsUser());
1011
1012
/*
1013
* Delete the printer from the class...
1014
*/
1015
1016
members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
1017
attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
1018
"member-uris", members->num_values - 1, NULL, NULL);
1019
1020
for (j = 0, k = 0; j < members->num_values; j ++)
1021
if (j != i)
1022
attr->values[k ++].string.text =
1023
_cupsStrAlloc(members->values[j].string.text);
1024
}
1025
1026
/*
1027
* Then send the request...
1028
*/
1029
1030
ippDelete(response);
1031
1032
ippDelete(cupsDoRequest(http, request, "/admin/"));
1033
1034
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1035
{
1036
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1037
1038
return (1);
1039
}
1040
else
1041
return (0);
1042
}
1043
1044
1045
/*
1046
* 'delete_printer_option()' - Delete a printer option.
1047
*/
1048
1049
static int /* O - 0 on success, 1 on fail */
1050
delete_printer_option(http_t *http, /* I - Server connection */
1051
char *printer, /* I - Printer */
1052
char *option) /* I - Option to delete */
1053
{
1054
ipp_t *request; /* IPP request */
1055
char uri[HTTP_MAX_URI]; /* URI for printer/class */
1056
1057
1058
/*
1059
* Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
1060
* requires the following attributes:
1061
*
1062
* attributes-charset
1063
* attributes-natural-language
1064
* printer-uri
1065
* requesting-user-name
1066
* option with deleteAttr tag
1067
*/
1068
1069
if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1070
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1071
else
1072
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1073
1074
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1075
"printer-uri", NULL, uri);
1076
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1077
"requesting-user-name", NULL, cupsUser());
1078
ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);
1079
1080
/*
1081
* Do the request and get back a response...
1082
*/
1083
1084
ippDelete(cupsDoRequest(http, request, "/admin/"));
1085
1086
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1087
{
1088
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1089
1090
return (1);
1091
}
1092
else
1093
return (0);
1094
}
1095
1096
1097
/*
1098
* 'enable_printer()' - Enable a printer...
1099
*/
1100
1101
static int /* O - 0 on success, 1 on fail */
1102
enable_printer(http_t *http, /* I - Server connection */
1103
char *printer) /* I - Printer to enable */
1104
{
1105
ipp_t *request; /* IPP Request */
1106
char uri[HTTP_MAX_URI]; /* URI for printer/class */
1107
1108
1109
/*
1110
* Send IPP_OP_ENABLE_PRINTER and IPP_OP_RESUME_PRINTER requests, which
1111
* require the following attributes:
1112
*
1113
* attributes-charset
1114
* attributes-natural-language
1115
* printer-uri
1116
* requesting-user-name
1117
*/
1118
1119
request = ippNewRequest(IPP_OP_ENABLE_PRINTER);
1120
1121
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
1122
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1123
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
1124
1125
ippDelete(cupsDoRequest(http, request, "/admin/"));
1126
1127
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1128
{
1129
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1130
1131
return (1);
1132
}
1133
1134
request = ippNewRequest(IPP_OP_RESUME_PRINTER);
1135
1136
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1137
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
1138
1139
ippDelete(cupsDoRequest(http, request, "/admin/"));
1140
1141
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1142
{
1143
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1144
1145
return (1);
1146
}
1147
1148
return (0);
1149
}
1150
1151
1152
/*
1153
* 'get_printer_type()' - Determine the printer type and URI.
1154
*/
1155
1156
static cups_ptype_t /* O - printer-type value */
1157
get_printer_type(http_t *http, /* I - Server connection */
1158
char *printer, /* I - Printer name */
1159
char *uri, /* I - URI buffer */
1160
size_t urisize) /* I - Size of URI buffer */
1161
{
1162
ipp_t *request, /* IPP request */
1163
*response; /* IPP response */
1164
ipp_attribute_t *attr; /* printer-type attribute */
1165
cups_ptype_t type; /* printer-type value */
1166
1167
1168
/*
1169
* Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1170
* attributes:
1171
*
1172
* attributes-charset
1173
* attributes-natural-language
1174
* printer-uri
1175
* requested-attributes
1176
* requesting-user-name
1177
*/
1178
1179
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
1180
1181
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
1182
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1183
"printer-uri", NULL, uri);
1184
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1185
"requested-attributes", NULL, "printer-type");
1186
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1187
"requesting-user-name", NULL, cupsUser());
1188
1189
/*
1190
* Do the request...
1191
*/
1192
1193
response = cupsDoRequest(http, request, "/");
1194
if ((attr = ippFindAttribute(response, "printer-type",
1195
IPP_TAG_ENUM)) != NULL)
1196
{
1197
type = (cups_ptype_t)attr->values[0].integer;
1198
1199
if (type & CUPS_PRINTER_CLASS)
1200
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer);
1201
}
1202
else
1203
type = CUPS_PRINTER_LOCAL;
1204
1205
ippDelete(response);
1206
1207
return (type);
1208
}
1209
1210
1211
/*
1212
* 'set_printer_options()' - Set the printer options.
1213
*/
1214
1215
static int /* O - 0 on success, 1 on fail */
1216
set_printer_options(
1217
http_t *http, /* I - Server connection */
1218
char *printer, /* I - Printer */
1219
int num_options, /* I - Number of options */
1220
cups_option_t *options, /* I - Options */
1221
char *file, /* I - PPD file */
1222
int enable) /* I - Enable printer? */
1223
{
1224
ipp_t *request; /* IPP Request */
1225
const char *ppdfile; /* PPD filename */
1226
int ppdchanged = 0; /* PPD changed? */
1227
ppd_file_t *ppd; /* PPD file */
1228
ppd_choice_t *choice; /* Marked choice */
1229
char uri[HTTP_MAX_URI], /* URI for printer/class */
1230
line[1024], /* Line from PPD file */
1231
keyword[1024], /* Keyword from Default line */
1232
*keyptr, /* Pointer into keyword... */
1233
tempfile[1024]; /* Temporary filename */
1234
cups_file_t *in, /* PPD file */
1235
*out; /* Temporary file */
1236
const char *ppdname, /* ppd-name value */
1237
*protocol, /* Old protocol option */
1238
*customval, /* Custom option value */
1239
*boolval; /* Boolean value */
1240
int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */
1241
wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */
1242
copied_options = 0; /* Copied options? */
1243
1244
1245
/*
1246
* Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request,
1247
* which requires the following attributes:
1248
*
1249
* attributes-charset
1250
* attributes-natural-language
1251
* printer-uri
1252
* requesting-user-name
1253
* other options
1254
*/
1255
1256
if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
1257
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
1258
else
1259
request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1260
1261
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1262
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
1263
1264
/*
1265
* Add the options...
1266
*/
1267
1268
if (file)
1269
ppdfile = file;
1270
else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "everywhere") && strcmp(ppdname, "raw") && num_options > 1)
1271
{
1272
if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL)
1273
{
1274
/*
1275
* Copy options array and remove ppd-name from it...
1276
*/
1277
1278
cups_option_t *temp = NULL, *optr;
1279
int i, num_temp = 0;
1280
for (i = num_options, optr = options; i > 0; i --, optr ++)
1281
if (strcmp(optr->name, "ppd-name"))
1282
num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp);
1283
1284
copied_options = 1;
1285
ppdchanged = 1;
1286
num_options = num_temp;
1287
options = temp;
1288
}
1289
}
1290
else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER)
1291
ppdfile = cupsGetPPD(printer);
1292
else
1293
ppdfile = NULL;
1294
1295
cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
1296
1297
if (enable)
1298
{
1299
ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PSTATE_IDLE);
1300
ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1301
}
1302
1303
cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
1304
1305
if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
1306
{
1307
if (!_cups_strcasecmp(protocol, "bcp"))
1308
ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1309
NULL, "bcp");
1310
else if (!_cups_strcasecmp(protocol, "tbcp"))
1311
ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
1312
NULL, "tbcp");
1313
}
1314
1315
if (ppdfile)
1316
{
1317
/*
1318
* Set default options in the PPD file...
1319
*/
1320
1321
if ((ppd = ppdOpenFile(ppdfile)) == NULL)
1322
{
1323
int linenum; /* Line number of error */
1324
ppd_status_t status = ppdLastError(&linenum);
1325
/* Status code */
1326
1327
_cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum);
1328
goto error;
1329
}
1330
1331
ppdMarkDefaults(ppd);
1332
cupsMarkOptions(ppd, num_options, options);
1333
1334
if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
1335
{
1336
_cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
1337
goto error;
1338
}
1339
1340
if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
1341
{
1342
_cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s"), ppdfile, strerror(errno));
1343
cupsFileClose(out);
1344
unlink(tempfile);
1345
goto error;
1346
}
1347
1348
while (cupsFileGets(in, line, sizeof(line)))
1349
{
1350
if (!strncmp(line, "*cupsIPPSupplies:", 17) &&
1351
(boolval = cupsGetOption("cupsIPPSupplies", num_options,
1352
options)) != NULL)
1353
{
1354
ppdchanged = 1;
1355
wrote_ipp_supplies = 1;
1356
cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1357
(!_cups_strcasecmp(boolval, "true") ||
1358
!_cups_strcasecmp(boolval, "yes") ||
1359
!_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1360
}
1361
else if (!strncmp(line, "*cupsSNMPSupplies:", 18) &&
1362
(boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1363
options)) != NULL)
1364
{
1365
ppdchanged = 1;
1366
wrote_snmp_supplies = 1;
1367
cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1368
(!_cups_strcasecmp(boolval, "true") ||
1369
!_cups_strcasecmp(boolval, "yes") ||
1370
!_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1371
}
1372
else if (strncmp(line, "*Default", 8))
1373
cupsFilePrintf(out, "%s\n", line);
1374
else
1375
{
1376
/*
1377
* Get default option name...
1378
*/
1379
1380
strlcpy(keyword, line + 8, sizeof(keyword));
1381
1382
for (keyptr = keyword; *keyptr; keyptr ++)
1383
if (*keyptr == ':' || isspace(*keyptr & 255))
1384
break;
1385
1386
*keyptr++ = '\0';
1387
while (isspace(*keyptr & 255))
1388
keyptr ++;
1389
1390
if (!strcmp(keyword, "PageRegion") ||
1391
!strcmp(keyword, "PageSize") ||
1392
!strcmp(keyword, "PaperDimension") ||
1393
!strcmp(keyword, "ImageableArea"))
1394
{
1395
if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
1396
choice = ppdFindMarkedChoice(ppd, "PageRegion");
1397
}
1398
else
1399
choice = ppdFindMarkedChoice(ppd, keyword);
1400
1401
if (choice && strcmp(choice->choice, keyptr))
1402
{
1403
if (strcmp(choice->choice, "Custom"))
1404
{
1405
cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
1406
ppdchanged = 1;
1407
}
1408
else if ((customval = cupsGetOption(keyword, num_options,
1409
options)) != NULL)
1410
{
1411
cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
1412
ppdchanged = 1;
1413
}
1414
else
1415
cupsFilePrintf(out, "%s\n", line);
1416
}
1417
else
1418
cupsFilePrintf(out, "%s\n", line);
1419
}
1420
}
1421
1422
if (!wrote_ipp_supplies &&
1423
(boolval = cupsGetOption("cupsIPPSupplies", num_options,
1424
options)) != NULL)
1425
{
1426
ppdchanged = 1;
1427
1428
cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
1429
(!_cups_strcasecmp(boolval, "true") ||
1430
!_cups_strcasecmp(boolval, "yes") ||
1431
!_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1432
}
1433
1434
if (!wrote_snmp_supplies &&
1435
(boolval = cupsGetOption("cupsSNMPSupplies", num_options,
1436
options)) != NULL)
1437
{
1438
ppdchanged = 1;
1439
1440
cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
1441
(!_cups_strcasecmp(boolval, "true") ||
1442
!_cups_strcasecmp(boolval, "yes") ||
1443
!_cups_strcasecmp(boolval, "on")) ? "True" : "False");
1444
}
1445
1446
cupsFileClose(in);
1447
cupsFileClose(out);
1448
ppdClose(ppd);
1449
1450
/*
1451
* Do the request...
1452
*/
1453
1454
ippDelete(cupsDoFileRequest(http, request, "/admin/", ppdchanged ? tempfile : file));
1455
1456
/*
1457
* Clean up temp files... (TODO: catch signals in case we CTRL-C during
1458
* lpadmin)
1459
*/
1460
1461
if (ppdfile != file)
1462
unlink(ppdfile);
1463
unlink(tempfile);
1464
}
1465
else
1466
{
1467
/*
1468
* No PPD file - just set the options...
1469
*/
1470
1471
ippDelete(cupsDoRequest(http, request, "/admin/"));
1472
}
1473
1474
if (copied_options)
1475
cupsFreeOptions(num_options, options);
1476
1477
/*
1478
* Check the response...
1479
*/
1480
1481
if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1482
{
1483
_cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
1484
1485
return (1);
1486
}
1487
else
1488
return (0);
1489
1490
/*
1491
* Error handling...
1492
*/
1493
1494
error:
1495
1496
ippDelete(request);
1497
1498
if (ppdfile != file)
1499
unlink(ppdfile);
1500
1501
if (copied_options)
1502
cupsFreeOptions(num_options, options);
1503
1504
return (1);
1505
}
1506
1507
1508
/*
1509
* 'usage()' - Show program usage and exit.
1510
*/
1511
1512
static void
1513
usage(void)
1514
{
1515
_cupsLangPuts(stdout, _("Usage: lpadmin [options] -d destination\n"
1516
" lpadmin [options] -p destination\n"
1517
" lpadmin [options] -p destination -c class\n"
1518
" lpadmin [options] -p destination -r class\n"
1519
" lpadmin [options] -x destination"));
1520
_cupsLangPuts(stdout, _("Options:"));
1521
_cupsLangPuts(stdout, _("-c class Add the named destination to a class"));
1522
_cupsLangPuts(stdout, _("-d destination Set the named destination as the server default"));
1523
_cupsLangPuts(stdout, _("-D description Specify the textual description of the printer"));
1524
_cupsLangPuts(stdout, _("-E Encrypt the connection to the server"));
1525
_cupsLangPuts(stdout, _("-E Enable and accept jobs on the printer (after -p)"));
1526
_cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port"));
1527
_cupsLangPuts(stdout, _("-i ppd-file Specify a PPD file for the printer"));
1528
_cupsLangPuts(stdout, _("-L location Specify the textual location of the printer"));
1529
_cupsLangPuts(stdout, _("-m model Specify a standard model/PPD file for the printer"));
1530
_cupsLangPuts(stdout, _("-m everywhere Specify the printer is compatible with IPP Everywhere"));
1531
_cupsLangPuts(stdout, _("-o name-default=value Specify the default value for the named option"));
1532
_cupsLangPuts(stdout, _("-o Name=Value Specify the default value for the named PPD option "));
1533
_cupsLangPuts(stdout, _("-o cupsIPPSupplies=false\n"
1534
" Disable supply level reporting via IPP"));
1535
_cupsLangPuts(stdout, _("-o cupsSNMPSupplies=false\n"
1536
" Disable supply level reporting via SNMP"));
1537
_cupsLangPuts(stdout, _("-o job-k-limit=N Specify the kilobyte limit for per-user quotas"));
1538
_cupsLangPuts(stdout, _("-o job-page-limit=N Specify the page limit for per-user quotas"));
1539
_cupsLangPuts(stdout, _("-o job-quota-period=N Specify the per-user quota period in seconds"));
1540
_cupsLangPuts(stdout, _("-o printer-error-policy=name\n"
1541
" Specify the printer error policy"));
1542
_cupsLangPuts(stdout, _("-o printer-is-shared=true\n"
1543
" Share the printer"));
1544
_cupsLangPuts(stdout, _("-o printer-op-policy=name\n"
1545
" Specify the printer operation policy"));
1546
_cupsLangPuts(stdout, _("-p destination Specify/add the named destination"));
1547
_cupsLangPuts(stdout, _("-r class Remove the named destination from a class"));
1548
_cupsLangPuts(stdout, _("-R name-default Remove the default value for the named option"));
1549
_cupsLangPuts(stdout, _("-u allow:all Allow all users to print"));
1550
_cupsLangPuts(stdout, _("-u allow:list Allow the list of users or groups (@name) to print"));
1551
_cupsLangPuts(stdout, _("-u deny:list Prevent the list of users or groups (@name) to print"));
1552
_cupsLangPuts(stdout, _("-U username Specify the username to use for authentication"));
1553
_cupsLangPuts(stdout, _("-v device-uri Specify the device URI for the printer"));
1554
_cupsLangPuts(stdout, _("-x destination Remove the named destination"));
1555
1556
exit(1);
1557
}
1558
1559
1560
/*
1561
* 'validate_name()' - Make sure the printer name only contains valid chars.
1562
*/
1563
1564
static int /* O - 0 if name is no good, 1 if name is good */
1565
validate_name(const char *name) /* I - Name to check */
1566
{
1567
const char *ptr; /* Pointer into name */
1568
1569
1570
/*
1571
* Scan the whole name...
1572
*/
1573
1574
for (ptr = name; *ptr; ptr ++)
1575
if (*ptr == '@')
1576
break;
1577
else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '\\' || *ptr == '?' || *ptr == '\'' || *ptr == '\"' || *ptr == '#')
1578
return (0);
1579
1580
/*
1581
* All the characters are good; validate the length, too...
1582
*/
1583
1584
return ((ptr - name) < 128);
1585
}
1586
1587