2 * "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $"
4 * "lpadmin" command for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
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/".
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.
20 * delete_printer() - Delete a printer from the system.
21 * delete_printer_from_class() - Delete a printer from a class.
22 * enable_printer() - Enable a printer.
23 * set_printer_options() - Set the printer options and/or file.
24 * validate_name() - Make sure the printer name only contains
29 * Include necessary headers...
32 #include <cups/cups-private.h>
39 static int add_printer_to_class(http_t
*http
, char *printer
, char *pclass
);
40 static int default_printer(http_t
*http
, char *printer
);
41 static int delete_printer(http_t
*http
, char *printer
);
42 static int delete_printer_from_class(http_t
*http
, char *printer
,
44 static int enable_printer(http_t
*http
, char *printer
);
45 static int set_printer_options(http_t
*http
, char *printer
,
46 int num_options
, cups_option_t
*options
,
48 static int validate_name(const char *name
);
52 * 'main()' - Parse options and configure the scheduler.
56 main(int argc
, /* I - Number of command-line arguments */
57 char *argv
[]) /* I - Command-line arguments */
59 int i
; /* Looping var */
60 http_t
*http
; /* Connection to server */
61 char *printer
, /* Destination printer */
62 *pclass
, /* Printer class name */
63 *val
; /* Pointer to allow/deny value */
64 int num_options
; /* Number of options */
65 cups_option_t
*options
; /* Options */
66 char *file
; /* New PPD file/interface script */
77 for (i
= 1; i
< argc
; i
++)
78 if (argv
[i
][0] == '-')
81 case 'c' : /* Add printer to class */
84 http
= httpConnectEncrypt(cupsServer(), ippPort(),
89 _cupsLangPrintf(stderr
,
90 _("lpadmin: Unable to connect to server: %s"),
99 _("lpadmin: Unable to add a printer to the class:\n"
100 " You must specify a printer name "
106 pclass
= argv
[i
] + 2;
113 _cupsLangPuts(stderr
,
114 _("lpadmin: Expected class name after \"-c\" "
122 if (!validate_name(pclass
))
124 _cupsLangPuts(stderr
,
125 _("lpadmin: Class name can only contain printable "
130 if (add_printer_to_class(http
, printer
, pclass
))
134 case 'd' : /* Set as default destination */
137 http
= httpConnectEncrypt(cupsServer(), ippPort(),
142 _cupsLangPrintf(stderr
,
143 _("lpadmin: Unable to connect to server: %s"),
150 printer
= argv
[i
] + 2;
157 _cupsLangPuts(stderr
,
158 _("lpadmin: Expected printer name after \"-d\" "
166 if (!validate_name(printer
))
168 _cupsLangPuts(stderr
,
169 _("lpadmin: Printer name can only contain "
170 "printable characters."));
174 if (default_printer(http
, printer
))
180 case 'h' : /* Connect to host */
187 if (argv
[i
][2] != '\0')
188 cupsSetServer(argv
[i
] + 2);
195 _cupsLangPuts(stderr
,
196 _("lpadmin: Expected hostname after \"-h\" "
201 cupsSetServer(argv
[i
]);
205 case 'i' : /* Use the specified interface script */
214 _cupsLangPuts(stderr
,
215 _("lpadmin: Expected interface after \"-i\" "
224 case 'E' : /* Enable the printer */
228 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
231 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
233 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."),
235 #endif /* HAVE_SSL */
241 http
= httpConnectEncrypt(cupsServer(), ippPort(),
246 _cupsLangPrintf(stderr
,
247 _("lpadmin: Unable to connect to server: %s"),
253 if (enable_printer(http
, printer
))
257 case 'm' : /* Use the specified standard script/PPD file */
259 num_options
= cupsAddOption("ppd-name", argv
[i
] + 2, num_options
,
267 _cupsLangPuts(stderr
,
268 _("lpadmin: Expected model after \"-m\" "
273 num_options
= cupsAddOption("ppd-name", argv
[i
], num_options
,
278 case 'o' : /* Set option */
280 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
287 _cupsLangPuts(stderr
,
288 _("lpadmin: Expected name=value after \"-o\" "
293 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
297 case 'p' : /* Add/modify a printer */
299 printer
= argv
[i
] + 2;
306 _cupsLangPuts(stderr
,
307 _("lpadmin: Expected printer after \"-p\" "
315 if (!validate_name(printer
))
317 _cupsLangPuts(stderr
,
318 _("lpadmin: Printer name can only contain "
319 "printable characters."));
324 case 'r' : /* Remove printer from class */
327 http
= httpConnectEncrypt(cupsServer(), ippPort(),
332 _cupsLangPrintf(stderr
,
333 _("lpadmin: Unable to connect to server: %s"),
341 _cupsLangPuts(stderr
,
342 _("lpadmin: Unable to remove a printer from the "
344 " You must specify a printer name "
350 pclass
= argv
[i
] + 2;
357 _cupsLangPuts(stderr
,
358 _("lpadmin: Expected class after \"-r\" "
366 if (!validate_name(pclass
))
368 _cupsLangPuts(stderr
,
369 _("lpadmin: Class name can only contain printable "
374 if (delete_printer_from_class(http
, printer
, pclass
))
378 case 'U' : /* Username */
379 if (argv
[i
][2] != '\0')
380 cupsSetUser(argv
[i
] + 2);
386 _cupsLangPrintf(stderr
,
387 _("%s: Error - expected username after "
388 "\"-U\" option."), argv
[0]);
392 cupsSetUser(argv
[i
]);
396 case 'u' : /* Allow/deny users */
405 _cupsLangPuts(stderr
,
406 _("lpadmin: Expected allow/deny:userlist after "
414 if (!strncasecmp(val
, "allow:", 6))
415 num_options
= cupsAddOption("requesting-user-name-allowed",
416 val
+ 6, num_options
, &options
);
417 else if (!strncasecmp(val
, "deny:", 5))
418 num_options
= cupsAddOption("requesting-user-name-denied",
419 val
+ 5, num_options
, &options
);
422 _cupsLangPrintf(stderr
,
423 _("lpadmin: Unknown allow/deny option \"%s\"."),
429 case 'v' : /* Set the device-uri attribute */
431 num_options
= cupsAddOption("device-uri", argv
[i
] + 2,
432 num_options
, &options
);
439 _cupsLangPuts(stderr
,
440 _("lpadmin: Expected device URI after \"-v\" "
445 num_options
= cupsAddOption("device-uri", argv
[i
],
446 num_options
, &options
);
450 case 'x' : /* Delete a printer */
453 http
= httpConnectEncrypt(cupsServer(), ippPort(),
458 _cupsLangPrintf(stderr
,
459 _("lpadmin: Unable to connect to server: %s"),
466 printer
= argv
[i
] + 2;
473 _cupsLangPuts(stderr
,
474 _("lpadmin: Expected printer or class after "
482 if (!validate_name(printer
))
484 _cupsLangPuts(stderr
,
485 _("lpadmin: Printer name can only contain "
486 "printable characters."));
490 if (delete_printer(http
, printer
))
496 case 'D' : /* Set the printer-info attribute */
498 num_options
= cupsAddOption("printer-info", argv
[i
] + 2,
499 num_options
, &options
);
506 _cupsLangPuts(stderr
,
507 _("lpadmin: Expected description after "
512 num_options
= cupsAddOption("printer-info", argv
[i
],
513 num_options
, &options
);
517 case 'I' : /* Set the supported file types (ignored) */
522 _cupsLangPuts(stderr
,
523 _("lpadmin: Expected file type(s) after \"-I\" "
528 _cupsLangPuts(stderr
,
529 _("lpadmin: Warning - content type list ignored."));
532 case 'L' : /* Set the printer-location attribute */
534 num_options
= cupsAddOption("printer-location", argv
[i
] + 2,
535 num_options
, &options
);
542 _cupsLangPuts(stderr
,
543 _("lpadmin: Expected location after \"-L\" "
548 num_options
= cupsAddOption("printer-location", argv
[i
],
549 num_options
, &options
);
553 case 'P' : /* Use the specified PPD file */
562 _cupsLangPuts(stderr
,
563 _("lpadmin: Expected PPD after \"-P\" option."));
572 _cupsLangPrintf(stderr
,
573 _("lpadmin: Unknown option \"%c\"."), argv
[i
][1]);
578 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \"%s\"."),
584 * Set options as needed...
587 if (num_options
|| file
)
591 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
595 _cupsLangPrintf(stderr
,
596 _("lpadmin: Unable to connect to server: %s"),
604 _cupsLangPuts(stderr
,
605 _("lpadmin: Unable to set the printer options:\n"
606 " You must specify a printer name first."));
610 if (set_printer_options(http
, printer
, num_options
, options
, file
))
616 _cupsLangPuts(stdout
,
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] "
625 " [-P ppd-file] [-o name=value]\n"
626 " [-u allow:user,user] "
627 "[-u deny:user,user]"));
638 * 'add_printer_to_class()' - Add a printer to a class.
641 static int /* O - 0 on success, 1 on fail */
642 add_printer_to_class(http_t
*http
, /* I - Server connection */
643 char *printer
, /* I - Printer to add */
644 char *pclass
) /* I - Class to add to */
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 */
651 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
654 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
658 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
662 * attributes-natural-language
666 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
668 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
669 "localhost", 0, "/classes/%s", pclass
);
670 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
671 "printer-uri", NULL
, uri
);
674 * Do the request and get back a response...
677 response
= cupsDoRequest(http
, request
, "/");
680 * Build a CUPS_ADD_CLASS request, which requires the following
684 * attributes-natural-language
689 request
= ippNewRequest(CUPS_ADD_CLASS
);
691 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
692 "printer-uri", NULL
, uri
);
695 * See if the printer is already in the class...
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)
703 _cupsLangPrintf(stderr
,
704 _("lpadmin: Printer %s is already a member of class "
705 "%s."), printer
, pclass
);
712 * OK, the printer isn't part of the class, so add it...
715 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
716 "localhost", 0, "/printers/%s", printer
);
718 if (response
!= NULL
&&
719 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
722 * Add the printer to the existing list...
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
++)
728 attr
->values
[i
].string
.text
= _cupsStrAlloc(members
->values
[i
].string
.text
);
730 attr
->values
[i
].string
.text
= _cupsStrAlloc(uri
);
733 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
,
737 * Then send the request...
742 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
744 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
748 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
750 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
766 * 'default_printer()' - Set the default printing destination.
769 static int /* O - 0 on success, 1 on fail */
770 default_printer(http_t
*http
, /* I - Server connection */
771 char *printer
) /* I - Printer name */
773 ipp_t
*request
, /* IPP Request */
774 *response
; /* IPP Response */
775 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
778 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
781 * Build a CUPS_SET_DEFAULT request, which requires the following
785 * attributes-natural-language
789 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
790 "localhost", 0, "/printers/%s", printer
);
792 request
= ippNewRequest(CUPS_SET_DEFAULT
);
794 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
795 "printer-uri", NULL
, uri
);
798 * Do the request and get back a response...
801 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
803 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
807 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
809 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
825 * 'delete_printer()' - Delete a printer from the system...
828 static int /* O - 0 on success, 1 on fail */
829 delete_printer(http_t
*http
, /* I - Server connection */
830 char *printer
) /* I - Printer to delete */
832 ipp_t
*request
, /* IPP Request */
833 *response
; /* IPP Response */
834 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
837 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
840 * Build a CUPS_DELETE_PRINTER request, which requires the following
844 * attributes-natural-language
848 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
850 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
851 "localhost", 0, "/printers/%s", printer
);
852 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
853 "printer-uri", NULL
, uri
);
856 * Do the request and get back a response...
859 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
861 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
865 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
867 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
883 * 'delete_printer_from_class()' - Delete a printer from a class.
886 static int /* O - 0 on success, 1 on fail */
887 delete_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 */
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 */
897 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
900 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
904 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
908 * attributes-natural-language
912 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
914 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
915 "localhost", 0, "/classes/%s", pclass
);
916 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
917 "printer-uri", NULL
, uri
);
920 * Do the request and get back a response...
923 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
924 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
926 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
934 * See if the printer is already in the class...
937 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
939 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen."));
946 for (i
= 0; i
< members
->num_values
; i
++)
947 if (!strcasecmp(printer
, members
->values
[i
].string
.text
))
950 if (i
>= members
->num_values
)
952 _cupsLangPrintf(stderr
,
953 _("lpadmin: Printer %s is not a member of class %s."),
961 if (members
->num_values
== 1)
964 * Build a CUPS_DELETE_CLASS request, which requires the following
968 * attributes-natural-language
972 request
= ippNewRequest(CUPS_DELETE_CLASS
);
974 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
975 "printer-uri", NULL
, uri
);
980 * Build a CUPS_ADD_CLASS request, which requires the following
984 * attributes-natural-language
989 request
= ippNewRequest(CUPS_ADD_CLASS
);
991 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
992 "printer-uri", NULL
, uri
);
995 * Delete the printer from the class...
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
);
1002 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1004 attr
->values
[k
++].string
.text
=
1005 _cupsStrAlloc(members
->values
[j
].string
.text
);
1009 * Then send the request...
1012 ippDelete(response
);
1014 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1016 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
1020 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1022 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
1024 ippDelete(response
);
1030 ippDelete(response
);
1038 * 'enable_printer()' - Enable a printer...
1041 static int /* O - 0 on success, 1 on fail */
1042 enable_printer(http_t
*http
, /* I - Server connection */
1043 char *printer
) /* I - Printer to enable */
1045 ipp_t
*request
, /* IPP Request */
1046 *response
; /* IPP Response */
1047 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1050 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1053 * Build a CUPS_ADD_PRINTER request, which requires the following
1056 * attributes-charset
1057 * attributes-natural-language
1060 * printer-is-accepting-jobs
1063 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1065 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1066 "localhost", 0, "/printers/%s", printer
);
1067 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1068 "printer-uri", NULL
, uri
);
1070 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1073 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1076 * Do the request and get back a response...
1079 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1081 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
1085 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1087 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
1089 ippDelete(response
);
1095 ippDelete(response
);
1103 * 'set_printer_options()' - Set the printer options.
1106 static int /* O - 0 on success, 1 on fail */
1107 set_printer_options(
1108 http_t
*http
, /* I - Server connection */
1109 char *printer
, /* I - Printer */
1110 int num_options
, /* I - Number of options */
1111 cups_option_t
*options
, /* I - Options */
1112 char *file
) /* I - PPD file/interface script */
1114 ipp_t
*request
, /* IPP Request */
1115 *response
; /* IPP Response */
1116 ipp_attribute_t
*attr
; /* IPP attribute */
1117 ipp_op_t op
; /* Operation to perform */
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 */
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 */
1127 cups_file_t
*in
, /* PPD file */
1128 *out
; /* Temporary file */
1129 const char *protocol
, /* Old protocol option */
1130 *customval
; /* Custom option value */
1133 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1134 "options=%p, file=\"%s\")\n", http
, printer
, num_options
,
1137 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1138 "localhost", 0, "/printers/%s", printer
);
1141 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1144 * attributes-charset
1145 * attributes-natural-language
1147 * requested-attributes
1150 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1152 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1153 "printer-uri", NULL
, uri
);
1154 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1155 "requested-attributes", NULL
, "printer-type");
1161 op
= CUPS_ADD_MODIFY_PRINTER
;
1163 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1166 * See what kind of printer or class it is...
1169 if ((attr
= ippFindAttribute(response
, "printer-type",
1170 IPP_TAG_ENUM
)) != NULL
)
1172 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1174 op
= CUPS_ADD_MODIFY_CLASS
;
1175 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1176 "localhost", 0, "/classes/%s", printer
);
1180 ippDelete(response
);
1184 * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
1185 * requires the following attributes:
1187 * attributes-charset
1188 * attributes-natural-language
1193 request
= ippNewRequest(op
);
1195 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1196 "printer-uri", NULL
, uri
);
1197 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1198 "requesting-user-name", NULL
, cupsUser());
1201 * Add the options...
1204 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1206 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1208 if (!strcasecmp(protocol
, "bcp"))
1209 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1211 else if (!strcasecmp(protocol
, "tbcp"))
1212 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1218 else if (op
== CUPS_ADD_MODIFY_PRINTER
)
1219 ppdfile
= cupsGetPPD(printer
);
1223 if (ppdfile
!= NULL
)
1226 * Set default options in the PPD file...
1229 ppd
= ppdOpenFile(ppdfile
);
1230 ppdMarkDefaults(ppd
);
1231 cupsMarkOptions(ppd
, num_options
, options
);
1233 if ((out
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
1235 _cupsLangPrintError(NULL
, _("lpadmin: Unable to create temporary file"));
1237 if (ppdfile
!= file
)
1242 if ((in
= cupsFileOpen(ppdfile
, "r")) == NULL
)
1244 _cupsLangPrintf(stderr
,
1245 _("lpadmin: Unable to open PPD file \"%s\" - %s"),
1246 ppdfile
, strerror(errno
));
1248 if (ppdfile
!= file
)
1257 while (cupsFileGets(in
, line
, sizeof(line
)))
1259 if (strncmp(line
, "*Default", 8))
1260 cupsFilePrintf(out
, "%s\n", line
);
1264 * Get default option name...
1267 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1269 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1270 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1274 while (isspace(*keyptr
& 255))
1277 if (!strcmp(keyword
, "PageRegion") ||
1278 !strcmp(keyword
, "PageSize") ||
1279 !strcmp(keyword
, "PaperDimension") ||
1280 !strcmp(keyword
, "ImageableArea"))
1282 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1283 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1286 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1288 if (choice
&& strcmp(choice
->choice
, keyptr
))
1290 if (strcmp(choice
->choice
, "Custom"))
1292 cupsFilePrintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1295 else if ((customval
= cupsGetOption(keyword
, num_options
,
1298 cupsFilePrintf(out
, "*Default%s: %s\n", keyword
, customval
);
1302 cupsFilePrintf(out
, "%s\n", line
);
1305 cupsFilePrintf(out
, "%s\n", line
);
1317 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1318 ppdchanged
? tempfile
: file
));
1321 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1325 if (ppdfile
!= file
)
1332 * No PPD file - just set the options...
1335 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1339 * Check the response...
1342 if (cupsLastError() > IPP_OK_CONFLICT
)
1344 _cupsLangPrintf(stderr
, "lpadmin: %s", cupsLastErrorString());
1354 * 'validate_name()' - Make sure the printer name only contains valid chars.
1357 static int /* O - 0 if name is no good, 1 if name is good */
1358 validate_name(const char *name
) /* I - Name to check */
1360 const char *ptr
; /* Pointer into name */
1364 * Scan the whole name...
1367 for (ptr
= name
; *ptr
; ptr
++)
1370 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1375 * All the characters are good; validate the length, too...
1378 return ((ptr
- name
) < 128);
1383 * End of "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $".