2 * "$Id: lpadmin.c 11558 2014-02-06 18:33:34Z msweet $"
4 * "lpadmin" command for CUPS.
6 * Copyright 2007-2014 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 * Include necessary headers...
20 #include <cups/cups-private.h>
27 static int add_printer_to_class(http_t
*http
, char *printer
, char *pclass
);
28 static int default_printer(http_t
*http
, char *printer
);
29 static int delete_printer(http_t
*http
, char *printer
);
30 static int delete_printer_from_class(http_t
*http
, char *printer
,
32 static int delete_printer_option(http_t
*http
, char *printer
,
34 static int enable_printer(http_t
*http
, char *printer
);
35 static cups_ptype_t
get_printer_type(http_t
*http
, char *printer
, char *uri
,
37 static int set_printer_options(http_t
*http
, char *printer
,
38 int num_options
, cups_option_t
*options
,
40 static int validate_name(const char *name
);
44 * 'main()' - Parse options and configure the scheduler.
48 main(int argc
, /* I - Number of command-line arguments */
49 char *argv
[]) /* I - Command-line arguments */
51 int i
; /* Looping var */
52 http_t
*http
; /* Connection to server */
53 char *printer
, /* Destination printer */
54 *pclass
, /* Printer class name */
55 *val
; /* Pointer to allow/deny value */
56 int num_options
; /* Number of options */
57 cups_option_t
*options
; /* Options */
58 char *file
; /* New PPD file/interface script */
69 for (i
= 1; i
< argc
; i
++)
70 if (argv
[i
][0] == '-')
73 case 'c' : /* Add printer to class */
76 http
= httpConnectEncrypt(cupsServer(), ippPort(),
81 _cupsLangPrintf(stderr
,
82 _("lpadmin: Unable to connect to server: %s"),
91 _("lpadmin: Unable to add a printer to the class:\n"
92 " You must specify a printer name "
105 _cupsLangPuts(stderr
,
106 _("lpadmin: Expected class name after \"-c\" "
114 if (!validate_name(pclass
))
116 _cupsLangPuts(stderr
,
117 _("lpadmin: Class name can only contain printable "
122 if (add_printer_to_class(http
, printer
, pclass
))
126 case 'd' : /* Set as default destination */
129 http
= httpConnectEncrypt(cupsServer(), ippPort(),
134 _cupsLangPrintf(stderr
,
135 _("lpadmin: Unable to connect to server: %s"),
142 printer
= argv
[i
] + 2;
149 _cupsLangPuts(stderr
,
150 _("lpadmin: Expected printer name after \"-d\" "
158 if (!validate_name(printer
))
160 _cupsLangPuts(stderr
,
161 _("lpadmin: Printer name can only contain "
162 "printable characters."));
166 if (default_printer(http
, printer
))
172 case 'h' : /* Connect to host */
179 if (argv
[i
][2] != '\0')
180 cupsSetServer(argv
[i
] + 2);
187 _cupsLangPuts(stderr
,
188 _("lpadmin: Expected hostname after \"-h\" "
193 cupsSetServer(argv
[i
]);
197 case 'i' : /* Use the specified interface script */
206 _cupsLangPuts(stderr
,
207 _("lpadmin: Expected interface after \"-i\" "
216 case 'E' : /* Enable the printer */
220 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
223 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
225 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."),
227 #endif /* HAVE_SSL */
233 http
= httpConnectEncrypt(cupsServer(), ippPort(),
238 _cupsLangPrintf(stderr
,
239 _("lpadmin: Unable to connect to server: %s"),
245 if (enable_printer(http
, printer
))
249 case 'm' : /* Use the specified standard script/PPD file */
251 num_options
= cupsAddOption("ppd-name", argv
[i
] + 2, num_options
,
259 _cupsLangPuts(stderr
,
260 _("lpadmin: Expected model after \"-m\" "
265 num_options
= cupsAddOption("ppd-name", argv
[i
], num_options
,
270 case 'o' : /* Set option */
272 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
279 _cupsLangPuts(stderr
,
280 _("lpadmin: Expected name=value after \"-o\" "
285 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
289 case 'p' : /* Add/modify a printer */
291 printer
= argv
[i
] + 2;
298 _cupsLangPuts(stderr
,
299 _("lpadmin: Expected printer after \"-p\" "
307 if (!validate_name(printer
))
309 _cupsLangPuts(stderr
,
310 _("lpadmin: Printer name can only contain "
311 "printable characters."));
316 case 'r' : /* Remove printer from class */
319 http
= httpConnectEncrypt(cupsServer(), ippPort(),
324 _cupsLangPrintf(stderr
,
325 _("lpadmin: Unable to connect to server: %s"),
333 _cupsLangPuts(stderr
,
334 _("lpadmin: Unable to remove a printer from the "
336 " You must specify a printer name "
342 pclass
= argv
[i
] + 2;
349 _cupsLangPuts(stderr
,
350 _("lpadmin: Expected class after \"-r\" "
358 if (!validate_name(pclass
))
360 _cupsLangPuts(stderr
,
361 _("lpadmin: Class name can only contain printable "
366 if (delete_printer_from_class(http
, printer
, pclass
))
370 case 'R' : /* Remove option */
373 http
= httpConnectEncrypt(cupsServer(), ippPort(),
378 _cupsLangPrintf(stderr
,
379 _("lpadmin: Unable to connect to server: %s"),
387 _cupsLangPuts(stderr
,
388 _("lpadmin: Unable to delete option:\n"
389 " You must specify a printer name "
402 _cupsLangPuts(stderr
,
403 _("lpadmin: Expected name after \"-R\" "
411 if (delete_printer_option(http
, printer
, val
))
415 case 'U' : /* Username */
416 if (argv
[i
][2] != '\0')
417 cupsSetUser(argv
[i
] + 2);
423 _cupsLangPrintf(stderr
,
424 _("%s: Error - expected username after "
425 "\"-U\" option."), argv
[0]);
429 cupsSetUser(argv
[i
]);
433 case 'u' : /* Allow/deny users */
442 _cupsLangPuts(stderr
,
443 _("lpadmin: Expected allow/deny:userlist after "
451 if (!_cups_strncasecmp(val
, "allow:", 6))
452 num_options
= cupsAddOption("requesting-user-name-allowed",
453 val
+ 6, num_options
, &options
);
454 else if (!_cups_strncasecmp(val
, "deny:", 5))
455 num_options
= cupsAddOption("requesting-user-name-denied",
456 val
+ 5, num_options
, &options
);
459 _cupsLangPrintf(stderr
,
460 _("lpadmin: Unknown allow/deny option \"%s\"."),
466 case 'v' : /* Set the device-uri attribute */
468 num_options
= cupsAddOption("device-uri", argv
[i
] + 2,
469 num_options
, &options
);
476 _cupsLangPuts(stderr
,
477 _("lpadmin: Expected device URI after \"-v\" "
482 num_options
= cupsAddOption("device-uri", argv
[i
],
483 num_options
, &options
);
487 case 'x' : /* Delete a printer */
490 http
= httpConnectEncrypt(cupsServer(), ippPort(),
495 _cupsLangPrintf(stderr
,
496 _("lpadmin: Unable to connect to server: %s"),
503 printer
= argv
[i
] + 2;
510 _cupsLangPuts(stderr
,
511 _("lpadmin: Expected printer or class after "
519 if (!validate_name(printer
))
521 _cupsLangPuts(stderr
,
522 _("lpadmin: Printer name can only contain "
523 "printable characters."));
527 if (delete_printer(http
, printer
))
533 case 'D' : /* Set the printer-info attribute */
535 num_options
= cupsAddOption("printer-info", argv
[i
] + 2,
536 num_options
, &options
);
543 _cupsLangPuts(stderr
,
544 _("lpadmin: Expected description after "
549 num_options
= cupsAddOption("printer-info", argv
[i
],
550 num_options
, &options
);
554 case 'I' : /* Set the supported file types (ignored) */
559 _cupsLangPuts(stderr
,
560 _("lpadmin: Expected file type(s) after \"-I\" "
565 _cupsLangPuts(stderr
,
566 _("lpadmin: Warning - content type list ignored."));
569 case 'L' : /* Set the printer-location attribute */
571 num_options
= cupsAddOption("printer-location", argv
[i
] + 2,
572 num_options
, &options
);
579 _cupsLangPuts(stderr
,
580 _("lpadmin: Expected location after \"-L\" "
585 num_options
= cupsAddOption("printer-location", argv
[i
],
586 num_options
, &options
);
590 case 'P' : /* Use the specified PPD file */
599 _cupsLangPuts(stderr
,
600 _("lpadmin: Expected PPD after \"-P\" option."));
609 _cupsLangPrintf(stderr
,
610 _("lpadmin: Unknown option \"%c\"."), argv
[i
][1]);
615 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \"%s\"."),
621 * Set options as needed...
624 if (num_options
|| file
)
628 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
632 _cupsLangPrintf(stderr
,
633 _("lpadmin: Unable to connect to server: %s"),
641 _cupsLangPuts(stderr
,
642 _("lpadmin: Unable to set the printer options:\n"
643 " You must specify a printer name first."));
647 if (set_printer_options(http
, printer
, num_options
, options
, file
))
653 _cupsLangPuts(stdout
,
656 " lpadmin [-h server] -d destination\n"
657 " lpadmin [-h server] -x destination\n"
658 " lpadmin [-h server] -p printer [-c add-class] "
659 "[-i interface] [-m model]\n"
660 " [-r remove-class] [-v device] "
662 " [-P ppd-file] [-o name=value]\n"
663 " [-u allow:user,user] "
664 "[-u deny:user,user]"));
675 * 'add_printer_to_class()' - Add a printer to a class.
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 */
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 */
691 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
695 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
699 * attributes-natural-language
701 * requesting-user-name
704 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
706 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
707 "localhost", 0, "/classes/%s", pclass
);
708 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
709 "printer-uri", NULL
, uri
);
710 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
714 * Do the request and get back a response...
717 response
= cupsDoRequest(http
, request
, "/");
720 * Build a CUPS_ADD_MODIFY_CLASS request, which requires the following
724 * attributes-natural-language
726 * requesting-user-name
730 request
= ippNewRequest(CUPS_ADD_MODIFY_CLASS
);
732 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
733 "printer-uri", NULL
, uri
);
734 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
738 * See if the printer is already in the class...
741 if (response
!= NULL
&&
742 (members
= ippFindAttribute(response
, "member-names",
743 IPP_TAG_NAME
)) != NULL
)
744 for (i
= 0; i
< members
->num_values
; i
++)
745 if (_cups_strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
747 _cupsLangPrintf(stderr
,
748 _("lpadmin: Printer %s is already a member of class "
749 "%s."), printer
, pclass
);
756 * OK, the printer isn't part of the class, so add it...
759 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
760 "localhost", 0, "/printers/%s", printer
);
762 if (response
!= NULL
&&
763 (members
= ippFindAttribute(response
, "member-uris",
764 IPP_TAG_URI
)) != NULL
)
767 * Add the printer to the existing list...
770 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
771 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
772 for (i
= 0; i
< members
->num_values
; i
++)
773 attr
->values
[i
].string
.text
=
774 _cupsStrAlloc(members
->values
[i
].string
.text
);
776 attr
->values
[i
].string
.text
= _cupsStrAlloc(uri
);
779 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
,
783 * Then send the request...
788 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
789 if (cupsLastError() > IPP_OK_CONFLICT
)
791 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
801 * 'default_printer()' - Set the default printing destination.
804 static int /* O - 0 on success, 1 on fail */
805 default_printer(http_t
*http
, /* I - Server connection */
806 char *printer
) /* I - Printer name */
808 ipp_t
*request
; /* IPP Request */
809 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
812 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
815 * Build a CUPS_SET_DEFAULT request, which requires the following
819 * attributes-natural-language
821 * requesting-user-name
824 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
825 "localhost", 0, "/printers/%s", printer
);
827 request
= ippNewRequest(CUPS_SET_DEFAULT
);
829 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
830 "printer-uri", NULL
, uri
);
831 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
835 * Do the request and get back a response...
838 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
840 if (cupsLastError() > IPP_OK_CONFLICT
)
842 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
852 * 'delete_printer()' - Delete a printer from the system...
855 static int /* O - 0 on success, 1 on fail */
856 delete_printer(http_t
*http
, /* I - Server connection */
857 char *printer
) /* I - Printer to delete */
859 ipp_t
*request
; /* IPP Request */
860 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
863 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
866 * Build a CUPS_DELETE_PRINTER request, which requires the following
870 * attributes-natural-language
872 * requesting-user-name
875 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
877 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
878 "localhost", 0, "/printers/%s", printer
);
879 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
880 "printer-uri", NULL
, uri
);
881 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
885 * Do the request and get back a response...
888 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
890 if (cupsLastError() > IPP_OK_CONFLICT
)
892 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
902 * 'delete_printer_from_class()' - Delete a printer from a class.
905 static int /* O - 0 on success, 1 on fail */
906 delete_printer_from_class(
907 http_t
*http
, /* I - Server connection */
908 char *printer
, /* I - Printer to remove */
909 char *pclass
) /* I - Class to remove from */
911 int i
, j
, k
; /* Looping vars */
912 ipp_t
*request
, /* IPP Request */
913 *response
; /* IPP Response */
914 ipp_attribute_t
*attr
, /* Current attribute */
915 *members
; /* Members in class */
916 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
919 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
923 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
927 * attributes-natural-language
929 * requesting-user-name
932 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
934 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
935 "localhost", 0, "/classes/%s", pclass
);
936 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
937 "printer-uri", NULL
, uri
);
938 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
942 * Do the request and get back a response...
945 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
946 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
948 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
956 * See if the printer is already in the class...
959 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
961 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen."));
968 for (i
= 0; i
< members
->num_values
; i
++)
969 if (!_cups_strcasecmp(printer
, members
->values
[i
].string
.text
))
972 if (i
>= members
->num_values
)
974 _cupsLangPrintf(stderr
,
975 _("lpadmin: Printer %s is not a member of class %s."),
983 if (members
->num_values
== 1)
986 * Build a CUPS_DELETE_CLASS request, which requires the following
990 * attributes-natural-language
992 * requesting-user-name
995 request
= ippNewRequest(CUPS_DELETE_CLASS
);
997 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
998 "printer-uri", NULL
, uri
);
999 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1000 "requesting-user-name", NULL
, cupsUser());
1005 * Build a CUPS_ADD_MODIFY_CLASS request, which requires the following
1008 * attributes-charset
1009 * attributes-natural-language
1011 * requesting-user-name
1015 request
= ippNewRequest(CUPS_ADD_MODIFY_CLASS
);
1017 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1018 "printer-uri", NULL
, uri
);
1019 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1020 "requesting-user-name", NULL
, cupsUser());
1023 * Delete the printer from the class...
1026 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1027 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1028 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1030 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1032 attr
->values
[k
++].string
.text
=
1033 _cupsStrAlloc(members
->values
[j
].string
.text
);
1037 * Then send the request...
1040 ippDelete(response
);
1042 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1044 if (cupsLastError() > IPP_OK_CONFLICT
)
1046 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
1056 * 'delete_printer_option()' - Delete a printer option.
1059 static int /* O - 0 on success, 1 on fail */
1060 delete_printer_option(http_t
*http
, /* I - Server connection */
1061 char *printer
, /* I - Printer */
1062 char *option
) /* I - Option to delete */
1064 ipp_t
*request
; /* IPP request */
1065 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1069 * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
1070 * requires the following attributes:
1072 * attributes-charset
1073 * attributes-natural-language
1075 * requesting-user-name
1076 * option with deleteAttr tag
1079 if (get_printer_type(http
, printer
, uri
, sizeof(uri
)) & CUPS_PRINTER_CLASS
)
1080 request
= ippNewRequest(CUPS_ADD_MODIFY_CLASS
);
1082 request
= ippNewRequest(CUPS_ADD_MODIFY_PRINTER
);
1084 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1085 "printer-uri", NULL
, uri
);
1086 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1087 "requesting-user-name", NULL
, cupsUser());
1088 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_DELETEATTR
, option
, 0);
1091 * Do the request and get back a response...
1094 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1096 if (cupsLastError() > IPP_OK_CONFLICT
)
1098 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
1108 * 'enable_printer()' - Enable a printer...
1111 static int /* O - 0 on success, 1 on fail */
1112 enable_printer(http_t
*http
, /* I - Server connection */
1113 char *printer
) /* I - Printer to enable */
1115 ipp_t
*request
; /* IPP Request */
1116 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1119 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1122 * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
1123 * require the following attributes:
1125 * attributes-charset
1126 * attributes-natural-language
1128 * requesting-user-name
1130 * printer-is-accepting-jobs
1133 if (get_printer_type(http
, printer
, uri
, sizeof(uri
)) & CUPS_PRINTER_CLASS
)
1134 request
= ippNewRequest(CUPS_ADD_MODIFY_CLASS
);
1136 request
= ippNewRequest(CUPS_ADD_MODIFY_PRINTER
);
1138 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1139 "printer-uri", NULL
, uri
);
1140 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1141 "requesting-user-name", NULL
, cupsUser());
1142 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1144 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1147 * Do the request and get back a response...
1150 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1152 if (cupsLastError() > IPP_OK_CONFLICT
)
1154 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
1164 * 'get_printer_type()' - Determine the printer type and URI.
1167 static cups_ptype_t
/* O - printer-type value */
1168 get_printer_type(http_t
*http
, /* I - Server connection */
1169 char *printer
, /* I - Printer name */
1170 char *uri
, /* I - URI buffer */
1171 size_t urisize
) /* I - Size of URI buffer */
1173 ipp_t
*request
, /* IPP request */
1174 *response
; /* IPP response */
1175 ipp_attribute_t
*attr
; /* printer-type attribute */
1176 cups_ptype_t type
; /* printer-type value */
1180 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1183 * attributes-charset
1184 * attributes-natural-language
1186 * requested-attributes
1187 * requesting-user-name
1190 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, (int)urisize
, "ipp", NULL
, "localhost", ippPort(), "/printers/%s", printer
);
1192 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1193 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1194 "printer-uri", NULL
, uri
);
1195 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1196 "requested-attributes", NULL
, "printer-type");
1197 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1198 "requesting-user-name", NULL
, cupsUser());
1204 response
= cupsDoRequest(http
, request
, "/");
1205 if ((attr
= ippFindAttribute(response
, "printer-type",
1206 IPP_TAG_ENUM
)) != NULL
)
1208 type
= (cups_ptype_t
)attr
->values
[0].integer
;
1210 if (type
& CUPS_PRINTER_CLASS
)
1211 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, (int)urisize
, "ipp", NULL
, "localhost", ippPort(), "/classes/%s", printer
);
1214 type
= CUPS_PRINTER_LOCAL
;
1216 ippDelete(response
);
1223 * 'set_printer_options()' - Set the printer options.
1226 static int /* O - 0 on success, 1 on fail */
1227 set_printer_options(
1228 http_t
*http
, /* I - Server connection */
1229 char *printer
, /* I - Printer */
1230 int num_options
, /* I - Number of options */
1231 cups_option_t
*options
, /* I - Options */
1232 char *file
) /* I - PPD file/interface script */
1234 ipp_t
*request
; /* IPP Request */
1235 const char *ppdfile
; /* PPD filename */
1236 int ppdchanged
; /* PPD changed? */
1237 ppd_file_t
*ppd
; /* PPD file */
1238 ppd_choice_t
*choice
; /* Marked choice */
1239 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1240 line
[1024], /* Line from PPD file */
1241 keyword
[1024], /* Keyword from Default line */
1242 *keyptr
, /* Pointer into keyword... */
1243 tempfile
[1024]; /* Temporary filename */
1244 cups_file_t
*in
, /* PPD file */
1245 *out
; /* Temporary file */
1246 const char *protocol
, /* Old protocol option */
1247 *customval
, /* Custom option value */
1248 *boolval
; /* Boolean value */
1249 int wrote_ipp_supplies
= 0, /* Wrote cupsIPPSupplies keyword? */
1250 wrote_snmp_supplies
= 0;/* Wrote cupsSNMPSupplies keyword? */
1253 DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
1254 "options=%p, file=\"%s\")\n", http
, printer
, num_options
,
1258 * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
1259 * requires the following attributes:
1261 * attributes-charset
1262 * attributes-natural-language
1264 * requesting-user-name
1268 if (get_printer_type(http
, printer
, uri
, sizeof(uri
)) & CUPS_PRINTER_CLASS
)
1269 request
= ippNewRequest(CUPS_ADD_MODIFY_CLASS
);
1271 request
= ippNewRequest(CUPS_ADD_MODIFY_PRINTER
);
1273 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1274 "printer-uri", NULL
, uri
);
1275 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1276 "requesting-user-name", NULL
, cupsUser());
1279 * Add the options...
1282 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_OPERATION
);
1283 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1285 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1287 if (!_cups_strcasecmp(protocol
, "bcp"))
1288 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1290 else if (!_cups_strcasecmp(protocol
, "tbcp"))
1291 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1297 else if (request
->request
.op
.operation_id
== CUPS_ADD_MODIFY_PRINTER
)
1298 ppdfile
= cupsGetPPD(printer
);
1302 if (ppdfile
!= NULL
)
1305 * Set default options in the PPD file...
1308 ppd
= ppdOpenFile(ppdfile
);
1309 ppdMarkDefaults(ppd
);
1310 cupsMarkOptions(ppd
, num_options
, options
);
1312 if ((out
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
1314 _cupsLangPrintError(NULL
, _("lpadmin: Unable to create temporary file"));
1316 if (ppdfile
!= file
)
1321 if ((in
= cupsFileOpen(ppdfile
, "r")) == NULL
)
1323 _cupsLangPrintf(stderr
,
1324 _("lpadmin: Unable to open PPD file \"%s\" - %s"),
1325 ppdfile
, strerror(errno
));
1327 if (ppdfile
!= file
)
1336 while (cupsFileGets(in
, line
, sizeof(line
)))
1338 if (!strncmp(line
, "*cupsIPPSupplies:", 17) &&
1339 (boolval
= cupsGetOption("cupsIPPSupplies", num_options
,
1342 wrote_ipp_supplies
= 1;
1343 cupsFilePrintf(out
, "*cupsIPPSupplies: %s\n",
1344 (!_cups_strcasecmp(boolval
, "true") ||
1345 !_cups_strcasecmp(boolval
, "yes") ||
1346 !_cups_strcasecmp(boolval
, "on")) ? "True" : "False");
1348 else if (!strncmp(line
, "*cupsSNMPSupplies:", 18) &&
1349 (boolval
= cupsGetOption("cupsSNMPSupplies", num_options
,
1352 wrote_snmp_supplies
= 1;
1353 cupsFilePrintf(out
, "*cupsSNMPSupplies: %s\n",
1354 (!_cups_strcasecmp(boolval
, "true") ||
1355 !_cups_strcasecmp(boolval
, "yes") ||
1356 !_cups_strcasecmp(boolval
, "on")) ? "True" : "False");
1358 else if (strncmp(line
, "*Default", 8))
1359 cupsFilePrintf(out
, "%s\n", line
);
1363 * Get default option name...
1366 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1368 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1369 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1373 while (isspace(*keyptr
& 255))
1376 if (!strcmp(keyword
, "PageRegion") ||
1377 !strcmp(keyword
, "PageSize") ||
1378 !strcmp(keyword
, "PaperDimension") ||
1379 !strcmp(keyword
, "ImageableArea"))
1381 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1382 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1385 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1387 if (choice
&& strcmp(choice
->choice
, keyptr
))
1389 if (strcmp(choice
->choice
, "Custom"))
1391 cupsFilePrintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1394 else if ((customval
= cupsGetOption(keyword
, num_options
,
1397 cupsFilePrintf(out
, "*Default%s: %s\n", keyword
, customval
);
1401 cupsFilePrintf(out
, "%s\n", line
);
1404 cupsFilePrintf(out
, "%s\n", line
);
1408 if (!wrote_ipp_supplies
&&
1409 (boolval
= cupsGetOption("cupsIPPSupplies", num_options
,
1412 cupsFilePrintf(out
, "*cupsIPPSupplies: %s\n",
1413 (!_cups_strcasecmp(boolval
, "true") ||
1414 !_cups_strcasecmp(boolval
, "yes") ||
1415 !_cups_strcasecmp(boolval
, "on")) ? "True" : "False");
1418 if (!wrote_snmp_supplies
&&
1419 (boolval
= cupsGetOption("cupsSNMPSupplies", num_options
,
1422 cupsFilePrintf(out
, "*cupsSNMPSupplies: %s\n",
1423 (!_cups_strcasecmp(boolval
, "true") ||
1424 !_cups_strcasecmp(boolval
, "yes") ||
1425 !_cups_strcasecmp(boolval
, "on")) ? "True" : "False");
1436 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1437 ppdchanged
? tempfile
: file
));
1440 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1444 if (ppdfile
!= file
)
1451 * No PPD file - just set the options...
1454 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1458 * Check the response...
1461 if (cupsLastError() > IPP_OK_CONFLICT
)
1463 _cupsLangPrintf(stderr
, _("%s: %s"), "lpadmin", cupsLastErrorString());
1473 * 'validate_name()' - Make sure the printer name only contains valid chars.
1476 static int /* O - 0 if name is no good, 1 if name is good */
1477 validate_name(const char *name
) /* I - Name to check */
1479 const char *ptr
; /* Pointer into name */
1483 * Scan the whole name...
1486 for (ptr
= name
; *ptr
; ptr
++)
1489 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1494 * All the characters are good; validate the length, too...
1497 return ((ptr
- name
) < 128);
1502 * End of "$Id: lpadmin.c 11558 2014-02-06 18:33:34Z msweet $".