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