2 * "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $"
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 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_device() - Set the device-uri attribute.
24 * set_printer_file() - Set the interface script or PPD file.
25 * set_printer_info() - Set the printer description string.
26 * set_printer_location() - Set the printer location string.
27 * set_printer_model() - Set the driver model file.
28 * set_printer_options() - Set the printer options.
29 * validate_name() - Make sure the printer name only contains
34 * Include necessary headers...
41 #include <cups/string.h>
42 #include <cups/cups.h>
43 #include <cups/i18n.h>
44 #include <cups/debug.h>
47 #endif /* HAVE_LIBZ */
54 static int add_printer_to_class(http_t
*, char *, char *);
55 static int default_printer(http_t
*, char *);
56 static int delete_printer(http_t
*, char *);
57 static int delete_printer_from_class(http_t
*, char *, char *);
58 static int enable_printer(http_t
*, char *);
59 static char *get_line(char *, int, FILE *fp
);
60 static int set_printer_device(http_t
*, char *, char *);
61 static int set_printer_file(http_t
*, char *, char *);
62 static int set_printer_info(http_t
*, char *, char *);
63 static int set_printer_location(http_t
*, char *, char *);
64 static int set_printer_model(http_t
*, char *, char *);
65 static int set_printer_options(http_t
*, char *, int, cups_option_t
*);
66 static int validate_name(const char *);
70 * 'main()' - Parse options and configure the scheduler.
74 main(int argc
, /* I - Number of command-line arguments */
75 char *argv
[]) /* I - Command-line arguments */
77 int i
; /* Looping var */
78 http_t
*http
; /* Connection to server */
79 char *printer
, /* Destination printer */
80 *pclass
, /* Printer class name */
81 *val
; /* Pointer to allow/deny value */
82 int num_options
; /* Number of options */
83 cups_option_t
*options
; /* Options */
93 for (i
= 1; i
< argc
; i
++)
94 if (argv
[i
][0] == '-')
97 case 'c' : /* Add printer to class */
100 http
= httpConnectEncrypt(cupsServer(), ippPort(),
105 _cupsLangPrintf(stderr
,
106 _("lpadmin: Unable to connect to server: %s\n"),
114 _cupsLangPuts(stderr
,
115 _("lpadmin: Unable to add a printer to the class:\n"
116 " You must specify a printer name "
122 pclass
= argv
[i
] + 2;
129 _cupsLangPuts(stderr
,
130 _("lpadmin: Expected class name after \'-c\' "
138 if (!validate_name(pclass
))
140 _cupsLangPuts(stderr
,
141 _("lpadmin: Class name can only contain printable "
146 if (add_printer_to_class(http
, printer
, pclass
))
150 case 'd' : /* Set as default destination */
153 http
= httpConnectEncrypt(cupsServer(), ippPort(),
158 _cupsLangPrintf(stderr
,
159 _("lpadmin: Unable to connect to server: %s\n"),
166 printer
= argv
[i
] + 2;
173 _cupsLangPuts(stderr
,
174 _("lpadmin: Expected printer name after \'-d\' "
182 if (!validate_name(printer
))
184 _cupsLangPuts(stderr
,
185 _("lpadmin: Printer name can only contain "
186 "printable characters\n"));
190 if (default_printer(http
, printer
))
196 case 'h' : /* Connect to host */
203 if (argv
[i
][2] != '\0')
204 cupsSetServer(argv
[i
] + 2);
211 _cupsLangPuts(stderr
,
212 _("lpadmin: Expected hostname after \'-h\' "
217 cupsSetServer(argv
[i
]);
221 case 'i' : /* Use the specified interface script */
224 http
= httpConnectEncrypt(cupsServer(), ippPort(),
229 _cupsLangPrintf(stderr
,
230 _("lpadmin: Unable to connect to server: %s\n"),
238 _cupsLangPuts(stderr
,
239 _("lpadmin: Unable to set the interface script:\n"
240 " You must specify a printer name "
247 if (set_printer_file(http
, printer
, argv
[i
] + 2))
256 _cupsLangPuts(stderr
,
257 _("lpadmin: Expected interface after \'-i\' "
262 if (set_printer_file(http
, printer
, argv
[i
]))
267 case 'E' : /* Enable the printer */
271 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
274 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
276 _cupsLangPrintf(stderr
,
277 _("%s: Sorry, no encryption support compiled in\n"),
279 #endif /* HAVE_SSL */
285 http
= httpConnectEncrypt(cupsServer(), ippPort(),
290 _cupsLangPrintf(stderr
,
291 _("lpadmin: Unable to connect to server: %s\n"),
297 if (enable_printer(http
, printer
))
301 case 'm' : /* Use the specified standard script/PPD file */
304 http
= httpConnectEncrypt(cupsServer(), ippPort(),
309 _cupsLangPrintf(stderr
,
310 _("lpadmin: Unable to connect to server: %s\n"),
318 _cupsLangPuts(stderr
,
319 _("lpadmin: Unable to set the interface script or "
321 " You must specify a printer name "
328 if (set_printer_model(http
, printer
, argv
[i
] + 2))
337 _cupsLangPuts(stderr
,
338 _("lpadmin: Expected model after \'-m\' "
343 if (set_printer_model(http
, printer
, argv
[i
]))
348 case 'o' : /* Set option */
350 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
357 _cupsLangPuts(stderr
,
358 _("lpadmin: Expected name=value after \'-o\' "
363 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
367 case 'p' : /* Add/modify a printer */
370 http
= httpConnectEncrypt(cupsServer(), ippPort(),
375 _cupsLangPrintf(stderr
,
376 _("lpadmin: Unable to connect to server: %s\n"),
383 printer
= argv
[i
] + 2;
390 _cupsLangPuts(stderr
,
391 _("lpadmin: Expected printer after \'-p\' "
399 if (!validate_name(printer
))
401 _cupsLangPuts(stderr
,
402 _("lpadmin: Printer name can only contain "
403 "printable characters\n"));
408 case 'r' : /* Remove printer from class */
411 http
= httpConnectEncrypt(cupsServer(), ippPort(),
416 _cupsLangPrintf(stderr
,
417 _("lpadmin: Unable to connect to server: %s\n"),
425 _cupsLangPuts(stderr
,
426 _("lpadmin: Unable to remove a printer from the "
428 " You must specify a printer name "
434 pclass
= argv
[i
] + 2;
441 _cupsLangPuts(stderr
,
442 _("lpadmin: Expected class after \'-r\' "
450 if (!validate_name(pclass
))
452 _cupsLangPuts(stderr
,
453 _("lpadmin: Class name can only contain printable "
458 if (delete_printer_from_class(http
, printer
, pclass
))
462 case 'U' : /* Username */
463 if (argv
[i
][2] != '\0')
464 cupsSetUser(argv
[i
] + 2);
470 _cupsLangPrintf(stderr
,
471 _("%s: Error - expected username after "
477 cupsSetUser(argv
[i
]);
481 case 'u' : /* Allow/deny users */
490 _cupsLangPuts(stderr
,
491 _("lpadmin: Expected allow/deny:userlist after "
499 if (!strncasecmp(val
, "allow:", 6))
500 num_options
= cupsAddOption("requesting-user-name-allowed",
501 val
+ 6, num_options
, &options
);
502 else if (!strncasecmp(val
, "deny:", 5))
503 num_options
= cupsAddOption("requesting-user-name-denied",
504 val
+ 5, num_options
, &options
);
507 _cupsLangPrintf(stderr
,
508 _("lpadmin: Unknown allow/deny option \"%s\"\n"),
514 case 'v' : /* Set the device-uri attribute */
517 http
= httpConnectEncrypt(cupsServer(), ippPort(),
522 _cupsLangPrintf(stderr
,
523 _("lpadmin: Unable to connect to server: %s\n"),
531 _cupsLangPuts(stderr
,
532 _("lpadmin: Unable to set the device URI:\n"
533 " You must specify a printer name "
540 if (set_printer_device(http
, printer
, argv
[i
] + 2))
549 _cupsLangPuts(stderr
,
550 _("lpadmin: Expected device URI after \'-v\' "
555 if (set_printer_device(http
, printer
, argv
[i
]))
560 case 'x' : /* Delete a printer */
563 http
= httpConnectEncrypt(cupsServer(), ippPort(),
568 _cupsLangPrintf(stderr
,
569 _("lpadmin: Unable to connect to server: %s\n"),
576 printer
= argv
[i
] + 2;
583 _cupsLangPuts(stderr
,
584 _("lpadmin: Expected printer or class after "
592 if (!validate_name(printer
))
594 _cupsLangPuts(stderr
,
595 _("lpadmin: Printer name can only contain "
596 "printable characters\n"));
600 if (delete_printer(http
, printer
))
606 case 'D' : /* Set the printer-info attribute */
609 http
= httpConnectEncrypt(cupsServer(), ippPort(),
614 _cupsLangPrintf(stderr
,
615 _("lpadmin: Unable to connect to server: %s\n"),
623 _cupsLangPuts(stderr
,
624 _("lpadmin: Unable to set the printer "
626 " You must specify a printer name "
633 if (set_printer_info(http
, printer
, argv
[i
] + 2))
642 _cupsLangPuts(stderr
,
643 _("lpadmin: Expected description after "
648 if (set_printer_info(http
, printer
, argv
[i
]))
653 case 'I' : /* Set the supported file types (ignored) */
658 _cupsLangPuts(stderr
,
659 _("lpadmin: Expected file type(s) after \'-I\' "
664 _cupsLangPuts(stderr
,
665 _("lpadmin: Warning - content type list ignored\n"));
668 case 'L' : /* Set the printer-location attribute */
671 http
= httpConnectEncrypt(cupsServer(), ippPort(),
676 _cupsLangPrintf(stderr
,
677 _("lpadmin: Unable to connect to server: %s\n"),
685 _cupsLangPuts(stderr
,
686 _("lpadmin: Unable to set the printer location:\n"
687 " You must specify a printer name "
694 if (set_printer_location(http
, printer
, argv
[i
] + 2))
703 _cupsLangPuts(stderr
,
704 _("lpadmin: Expected location after \'-L\' "
709 if (set_printer_location(http
, printer
, argv
[i
]))
714 case 'P' : /* Use the specified PPD file */
717 http
= httpConnectEncrypt(cupsServer(), ippPort(),
722 _cupsLangPrintf(stderr
,
723 _("lpadmin: Unable to connect to server: %s\n"),
731 _cupsLangPuts(stderr
,
732 _("lpadmin: Unable to set the PPD file:\n"
733 " You must specify a printer name "
740 if (set_printer_file(http
, printer
, argv
[i
] + 2))
749 _cupsLangPuts(stderr
,
750 _("lpadmin: Expected PPD after \'-P\' option\n"));
754 if (set_printer_file(http
, printer
, argv
[i
]))
760 _cupsLangPrintf(stderr
,
761 _("lpadmin: Unknown option \'%c\'\n"), argv
[i
][1]);
766 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \'%s\'\n"),
772 * Set options as needed...
779 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
783 _cupsLangPrintf(stderr
,
784 _("lpadmin: Unable to connect to server: %s\n"),
792 _cupsLangPuts(stderr
,
793 _("lpadmin: Unable to set the printer options:\n"
794 " You must specify a printer name first\n"));
798 if (set_printer_options(http
, printer
, num_options
, options
))
804 _cupsLangPuts(stdout
,
807 " lpadmin [-h server] -d destination\n"
808 " lpadmin [-h server] -x destination\n"
809 " lpadmin [-h server] -p printer [-c add-class] "
810 "[-i interface] [-m model]\n"
811 " [-r remove-class] [-v device] "
813 " [-P ppd-file] [-o name=value]\n"
814 " [-u allow:user,user] "
815 "[-u deny:user,user]\n"
827 * 'add_printer_to_class()' - Add a printer to a class.
830 static int /* O - 0 on success, 1 on fail */
831 add_printer_to_class(http_t
*http
, /* I - Server connection */
832 char *printer
, /* I - Printer to add */
833 char *pclass
) /* I - Class to add to */
835 int i
; /* Looping var */
836 ipp_t
*request
, /* IPP Request */
837 *response
; /* IPP Response */
838 ipp_attribute_t
*attr
, /* Current attribute */
839 *members
; /* Members in class */
840 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
843 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
847 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
851 * attributes-natural-language
855 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
857 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
858 "localhost", 0, "/classes/%s", pclass
);
859 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
860 "printer-uri", NULL
, uri
);
863 * Do the request and get back a response...
866 response
= cupsDoRequest(http
, request
, "/");
869 * Build a CUPS_ADD_CLASS request, which requires the following
873 * attributes-natural-language
878 request
= ippNewRequest(CUPS_ADD_CLASS
);
880 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
881 "printer-uri", NULL
, uri
);
884 * See if the printer is already in the class...
887 if (response
!= NULL
&&
888 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
889 for (i
= 0; i
< members
->num_values
; i
++)
890 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
892 _cupsLangPrintf(stderr
,
893 _("lpadmin: Printer %s is already a member of class %s.\n"),
901 * OK, the printer isn't part of the class, so add it...
904 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
905 "localhost", 0, "/printers/%s", printer
);
907 if (response
!= NULL
&&
908 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
911 * Add the printer to the existing list...
914 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
915 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
916 for (i
= 0; i
< members
->num_values
; i
++)
917 attr
->values
[i
].string
.text
= _cupsStrAlloc(members
->values
[i
].string
.text
);
919 attr
->values
[i
].string
.text
= _cupsStrAlloc(uri
);
922 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
,
926 * Then send the request...
931 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
933 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
937 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
939 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
955 * 'default_printer()' - Set the default printing destination.
958 static int /* O - 0 on success, 1 on fail */
959 default_printer(http_t
*http
, /* I - Server connection */
960 char *printer
) /* I - Printer name */
962 ipp_t
*request
, /* IPP Request */
963 *response
; /* IPP Response */
964 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
967 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
970 * Build a CUPS_SET_DEFAULT request, which requires the following
974 * attributes-natural-language
978 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
979 "localhost", 0, "/printers/%s", printer
);
981 request
= ippNewRequest(CUPS_SET_DEFAULT
);
983 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
984 "printer-uri", NULL
, uri
);
987 * Do the request and get back a response...
990 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
992 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
996 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
998 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1000 ippDelete(response
);
1006 ippDelete(response
);
1014 * 'delete_printer()' - Delete a printer from the system...
1017 static int /* O - 0 on success, 1 on fail */
1018 delete_printer(http_t
*http
, /* I - Server connection */
1019 char *printer
) /* I - Printer to delete */
1021 ipp_t
*request
, /* IPP Request */
1022 *response
; /* IPP Response */
1023 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1026 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
1029 * Build a CUPS_DELETE_PRINTER request, which requires the following
1032 * attributes-charset
1033 * attributes-natural-language
1037 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
1039 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1040 "localhost", 0, "/printers/%s", printer
);
1041 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1042 "printer-uri", NULL
, uri
);
1045 * Do the request and get back a response...
1048 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1050 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1054 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1056 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1058 ippDelete(response
);
1064 ippDelete(response
);
1072 * 'delete_printer_from_class()' - Delete a printer from a class.
1075 static int /* O - 0 on success, 1 on fail */
1076 delete_printer_from_class(
1077 http_t
*http
, /* I - Server connection */
1078 char *printer
, /* I - Printer to remove */
1079 char *pclass
) /* I - Class to remove from */
1081 int i
, j
, k
; /* Looping vars */
1082 ipp_t
*request
, /* IPP Request */
1083 *response
; /* IPP Response */
1084 ipp_attribute_t
*attr
, /* Current attribute */
1085 *members
; /* Members in class */
1086 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1089 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
1093 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1096 * attributes-charset
1097 * attributes-natural-language
1101 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1103 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1104 "localhost", 0, "/classes/%s", pclass
);
1105 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1106 "printer-uri", NULL
, uri
);
1109 * Do the request and get back a response...
1112 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1113 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1115 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1117 ippDelete(response
);
1123 * See if the printer is already in the class...
1126 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1128 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen\n"));
1130 ippDelete(response
);
1135 for (i
= 0; i
< members
->num_values
; i
++)
1136 if (!strcasecmp(printer
, members
->values
[i
].string
.text
))
1139 if (i
>= members
->num_values
)
1141 _cupsLangPrintf(stderr
,
1142 _("lpadmin: Printer %s is not a member of class %s.\n"),
1145 ippDelete(response
);
1150 if (members
->num_values
== 1)
1153 * Build a CUPS_DELETE_CLASS request, which requires the following
1156 * attributes-charset
1157 * attributes-natural-language
1161 request
= ippNewRequest(CUPS_DELETE_CLASS
);
1163 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1164 "printer-uri", NULL
, uri
);
1169 * Build a CUPS_ADD_CLASS request, which requires the following
1172 * attributes-charset
1173 * attributes-natural-language
1178 request
= ippNewRequest(CUPS_ADD_CLASS
);
1180 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1181 "printer-uri", NULL
, uri
);
1184 * Delete the printer from the class...
1187 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1188 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1189 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1191 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1193 attr
->values
[k
++].string
.text
=
1194 _cupsStrAlloc(members
->values
[j
].string
.text
);
1198 * Then send the request...
1201 ippDelete(response
);
1203 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1205 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1209 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1211 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1213 ippDelete(response
);
1219 ippDelete(response
);
1227 * 'enable_printer()' - Enable a printer...
1230 static int /* O - 0 on success, 1 on fail */
1231 enable_printer(http_t
*http
, /* I - Server connection */
1232 char *printer
) /* I - Printer to enable */
1234 ipp_t
*request
, /* IPP Request */
1235 *response
; /* IPP Response */
1236 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1239 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1242 * Build a CUPS_ADD_PRINTER request, which requires the following
1245 * attributes-charset
1246 * attributes-natural-language
1249 * printer-is-accepting-jobs
1252 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1254 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1255 "localhost", 0, "/printers/%s", printer
);
1256 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1257 "printer-uri", NULL
, uri
);
1259 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1262 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1265 * Do the request and get back a response...
1268 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1270 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1274 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1276 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1278 ippDelete(response
);
1284 ippDelete(response
);
1292 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1295 static char * /* O - Pointer to buf or NULL on EOF */
1296 get_line(char *buf
, /* I - Line buffer */
1297 int length
, /* I - Length of buffer */
1298 FILE *fp
) /* I - File to read from */
1300 char *bufptr
; /* Pointer into buffer */
1301 int ch
; /* Character from file */
1307 while ((ch
= getc(fp
)) != EOF
)
1311 else if (ch
== '\r')
1318 if (ch
!= '\n' && ch
!= EOF
)
1340 * 'set_printer_device()' - Set the device-uri attribute.
1343 static int /* O - 0 on success, 1 on fail */
1344 set_printer_device(http_t
*http
, /* I - Server connection */
1345 char *printer
, /* I - Printer */
1346 char *device
) /* I - New device URI */
1348 ipp_t
*request
, /* IPP Request */
1349 *response
; /* IPP Response */
1350 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1353 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1357 * Build a CUPS_ADD_PRINTER request, which requires the following
1360 * attributes-charset
1361 * attributes-natural-language
1365 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1367 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1368 "localhost", 0, "/printers/%s", printer
);
1369 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1370 "printer-uri", NULL
, uri
);
1373 * Add the device URI...
1376 if (device
[0] == '/')
1379 * Convert filename to URI...
1382 snprintf(uri
, sizeof(uri
), "file://%s", device
);
1383 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1387 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1391 * Do the request and get back a response...
1394 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1396 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1400 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1402 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1404 ippDelete(response
);
1410 ippDelete(response
);
1418 * 'set_printer_file()' - Set the interface script or PPD file.
1421 static int /* O - 0 on success, 1 on fail */
1422 set_printer_file(http_t
*http
, /* I - Server connection */
1423 char *printer
, /* I - Printer */
1424 char *file
) /* I - PPD file or interface script */
1426 ipp_t
*request
, /* IPP Request */
1427 *response
; /* IPP Response */
1428 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1430 char tempfile
[1024]; /* Temporary filename */
1431 int fd
; /* Temporary file */
1432 gzFile
*gz
; /* GZIP'd file */
1433 char buffer
[8192]; /* Copy buffer */
1434 int bytes
; /* Bytes in buffer */
1437 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1441 * See if the file is gzip'd; if so, unzip it to a temporary file and
1442 * send the uncompressed file.
1445 if (!strcmp(file
+ strlen(file
) - 3, ".gz"))
1448 * Yes, the file is compressed; uncompress to a temp file...
1451 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1453 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
1457 if ((gz
= gzopen(file
, "rb")) == NULL
)
1459 _cupsLangPrintf(stderr
,
1460 _("lpadmin: Unable to open file \"%s\": %s\n"),
1461 file
, strerror(errno
));
1467 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1468 write(fd
, buffer
, bytes
);
1475 #endif /* HAVE_LIBZ */
1478 * Build a CUPS_ADD_PRINTER request, which requires the following
1481 * attributes-charset
1482 * attributes-natural-language
1486 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1488 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1489 "localhost", 0, "/printers/%s", printer
);
1490 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1491 "printer-uri", NULL
, uri
);
1494 * Do the request and get back a response...
1497 response
= cupsDoFileRequest(http
, request
, "/admin/", file
);
1498 ippDelete(response
);
1502 * Remove the temporary file as needed...
1505 if (file
== tempfile
)
1507 #endif /* HAVE_LIBZ */
1509 if (cupsLastError() > IPP_OK_CONFLICT
)
1511 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1521 * 'set_printer_info()' - Set the printer description string.
1524 static int /* O - 0 on success, 1 on fail */
1525 set_printer_info(http_t
*http
, /* I - Server connection */
1526 char *printer
, /* I - Printer */
1527 char *info
) /* I - New description string */
1529 ipp_t
*request
, /* IPP Request */
1530 *response
; /* IPP Response */
1531 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1534 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1538 * Build a CUPS_ADD_PRINTER request, which requires the following
1541 * attributes-charset
1542 * attributes-natural-language
1546 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1548 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1549 "localhost", 0, "/printers/%s", printer
);
1550 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1551 "printer-uri", NULL
, uri
);
1554 * Add the info string...
1557 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1561 * Do the request and get back a response...
1564 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1566 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1569 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1571 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1573 ippDelete(response
);
1579 ippDelete(response
);
1587 * 'set_printer_location()' - Set the printer location string.
1590 static int /* O - 0 on success, 1 on fail */
1591 set_printer_location(http_t
*http
, /* I - Server connection */
1592 char *printer
, /* I - Printer */
1593 char *location
) /* I - New location string */
1595 ipp_t
*request
, /* IPP Request */
1596 *response
; /* IPP Response */
1597 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1600 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1604 * Build a CUPS_ADD_PRINTER request, which requires the following
1607 * attributes-charset
1608 * attributes-natural-language
1612 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1614 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1615 "localhost", 0, "/printers/%s", printer
);
1616 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1617 "printer-uri", NULL
, uri
);
1620 * Add the location string...
1623 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1627 * Do the request and get back a response...
1630 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1632 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1636 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1638 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1640 ippDelete(response
);
1646 ippDelete(response
);
1654 * 'set_printer_model()' - Set the driver model file.
1657 static int /* O - 0 on success, 1 on fail */
1658 set_printer_model(http_t
*http
, /* I - Server connection */
1659 char *printer
, /* I - Printer */
1660 char *model
) /* I - Driver model file */
1662 ipp_t
*request
, /* IPP Request */
1663 *response
; /* IPP Response */
1664 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1668 * Build a CUPS_ADD_PRINTER request, which requires the following
1671 * attributes-charset
1672 * attributes-natural-language
1677 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1679 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1680 "localhost", 0, "/printers/%s", printer
);
1681 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1682 "printer-uri", NULL
, uri
);
1684 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1685 "ppd-name", NULL
, model
);
1688 * Do the request and get back a response...
1691 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1693 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1697 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1699 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1701 ippDelete(response
);
1707 ippDelete(response
);
1715 * 'set_printer_options()' - Set the printer options.
1718 static int /* O - 0 on success, 1 on fail */
1719 set_printer_options(
1720 http_t
*http
, /* I - Server connection */
1721 char *printer
, /* I - Printer */
1722 int num_options
, /* I - Number of options */
1723 cups_option_t
*options
) /* I - Options */
1725 ipp_t
*request
, /* IPP Request */
1726 *response
; /* IPP Response */
1727 ipp_attribute_t
*attr
; /* IPP attribute */
1728 ipp_op_t op
; /* Operation to perform */
1729 const char *ppdfile
; /* PPD filename */
1730 int ppdchanged
; /* PPD changed? */
1731 ppd_file_t
*ppd
; /* PPD file */
1732 ppd_choice_t
*choice
; /* Marked choice */
1733 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1734 line
[1024], /* Line from PPD file */
1735 keyword
[1024], /* Keyword from Default line */
1736 *keyptr
, /* Pointer into keyword... */
1737 tempfile
[1024]; /* Temporary filename */
1738 FILE *in
, /* PPD file */
1739 *out
; /* Temporary file */
1740 int outfd
; /* Temporary file descriptor */
1741 const char *protocol
; /* Old protocol option */
1744 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1745 num_options
, options
));
1747 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1748 "localhost", 0, "/printers/%s", printer
);
1751 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1754 * attributes-charset
1755 * attributes-natural-language
1757 * requested-attributes
1760 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1762 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1763 "printer-uri", NULL
, uri
);
1765 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1766 "requested-attributes", NULL
, "printer-type");
1772 op
= CUPS_ADD_PRINTER
;
1774 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1777 * See what kind of printer or class it is...
1780 if ((attr
= ippFindAttribute(response
, "printer-type",
1781 IPP_TAG_ENUM
)) != NULL
)
1783 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1785 op
= CUPS_ADD_CLASS
;
1786 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1787 "localhost", 0, "/classes/%s", printer
);
1791 ippDelete(response
);
1795 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1796 * the following attributes:
1798 * attributes-charset
1799 * attributes-natural-language
1804 request
= ippNewRequest(op
);
1806 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1807 "printer-uri", NULL
, uri
);
1810 * Add the options...
1813 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1815 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1817 if (!strcasecmp(protocol
, "bcp"))
1818 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1820 else if (!strcasecmp(protocol
, "tbcp"))
1821 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "port-monitor",
1825 if (op
== CUPS_ADD_PRINTER
)
1826 ppdfile
= cupsGetPPD(printer
);
1830 if (ppdfile
!= NULL
)
1833 * Set default options in the PPD file...
1836 ppd
= ppdOpenFile(ppdfile
);
1837 ppdMarkDefaults(ppd
);
1838 cupsMarkOptions(ppd
, num_options
, options
);
1840 if ((outfd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1842 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
1848 if ((in
= fopen(ppdfile
, "rb")) == NULL
)
1850 _cupsLangPrintf(stderr
,
1851 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1852 ppdfile
, strerror(errno
));
1860 out
= fdopen(outfd
, "wb");
1863 while (get_line(line
, sizeof(line
), in
) != NULL
)
1865 if (strncmp(line
, "*Default", 8))
1866 fprintf(out
, "%s\n", line
);
1870 * Get default option name...
1873 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1875 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1876 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1880 while (isspace(*keyptr
& 255))
1883 if (!strcmp(keyword
, "PageRegion") ||
1884 !strcmp(keyword
, "PageSize") ||
1885 !strcmp(keyword
, "PaperDimension") ||
1886 !strcmp(keyword
, "ImageableArea"))
1888 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1889 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1892 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1894 if (choice
&& strcmp(choice
->choice
, keyptr
))
1896 fprintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1900 fprintf(out
, "%s\n", line
);
1913 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1914 ppdchanged
? tempfile
: NULL
));
1917 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1927 * No PPD file - just set the options...
1930 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1934 * Check the response...
1937 if (cupsLastError() > IPP_OK_CONFLICT
)
1939 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1949 * 'validate_name()' - Make sure the printer name only contains valid chars.
1952 static int /* O - 0 if name is no good, 1 if name is good */
1953 validate_name(const char *name
) /* I - Name to check */
1955 const char *ptr
; /* Pointer into name */
1959 * Scan the whole name...
1962 for (ptr
= name
; *ptr
; ptr
++)
1965 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1970 * All the characters are good; validate the length, too...
1973 return ((ptr
- name
) < 128);
1978 * End of "$Id: lpadmin.c 7720 2008-07-11 22:46:21Z mike $".