4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Parse options and configure the scheduler.
27 * add_printer_to_class() - Add a printer to a class.
28 * default_printer() - Set the default printing destination.
29 * delete_printer() - Delete a printer from the system...
30 * delete_printer_from_class() - Delete a printer from a class.
31 * enable_printer() - Enable a printer...
32 * set_printer_device() - Set the device-uri attribute.
33 * set_printer_file() - Set the interface script or PPD file.
34 * set_printer_info() - Set the printer description string.
35 * set_printer_location() - Set the printer location string.
36 * set_printer_model() - Set the driver model file.
37 * set_printer_options() - Set the printer options.
38 * validate_name() - Make sure the printer name only contains
43 * Include necessary headers...
50 #include <cups/string.h>
51 #include <cups/cups.h>
52 #include <cups/i18n.h>
53 #include <cups/debug.h>
56 #endif /* HAVE_LIBZ */
63 static int add_printer_to_class(http_t
*, char *, char *);
64 static int default_printer(http_t
*, char *);
65 static int delete_printer(http_t
*, char *);
66 static int delete_printer_from_class(http_t
*, char *, char *);
67 static int enable_printer(http_t
*, char *);
68 static char *get_line(char *, int, FILE *fp
);
69 static int set_printer_device(http_t
*, char *, char *);
70 static int set_printer_file(http_t
*, char *, char *);
71 static int set_printer_info(http_t
*, char *, char *);
72 static int set_printer_location(http_t
*, char *, char *);
73 static int set_printer_model(http_t
*, char *, char *);
74 static int set_printer_options(http_t
*, char *, int, cups_option_t
*);
75 static int validate_name(const char *);
79 * 'main()' - Parse options and configure the scheduler.
83 main(int argc
, /* I - Number of command-line arguments */
84 char *argv
[]) /* I - Command-line arguments */
86 int i
; /* Looping var */
87 http_t
*http
; /* Connection to server */
88 char *printer
, /* Destination printer */
89 *pclass
, /* Printer class name */
90 *val
; /* Pointer to allow/deny value */
91 int num_options
; /* Number of options */
92 cups_option_t
*options
; /* Options */
102 for (i
= 1; i
< argc
; i
++)
103 if (argv
[i
][0] == '-')
106 case 'c' : /* Add printer to class */
109 http
= httpConnectEncrypt(cupsServer(), ippPort(),
114 _cupsLangPrintf(stderr
,
115 _("lpadmin: Unable to connect to server: %s\n"),
123 _cupsLangPuts(stderr
,
124 _("lpadmin: Unable to add a printer to the class:\n"
125 " You must specify a printer name "
131 pclass
= argv
[i
] + 2;
138 _cupsLangPuts(stderr
,
139 _("lpadmin: Expected class name after \'-c\' "
147 if (!validate_name(pclass
))
149 _cupsLangPuts(stderr
,
150 _("lpadmin: Class name can only contain printable "
155 if (add_printer_to_class(http
, printer
, pclass
))
159 case 'd' : /* Set as default destination */
162 http
= httpConnectEncrypt(cupsServer(), ippPort(),
167 _cupsLangPrintf(stderr
,
168 _("lpadmin: Unable to connect to server: %s\n"),
175 printer
= argv
[i
] + 2;
182 _cupsLangPuts(stderr
,
183 _("lpadmin: Expected printer name after \'-d\' "
191 if (!validate_name(printer
))
193 _cupsLangPuts(stderr
,
194 _("lpadmin: Printer name can only contain "
195 "printable characters!\n"));
199 if (default_printer(http
, printer
))
205 case 'h' : /* Connect to host */
212 if (argv
[i
][2] != '\0')
213 cupsSetServer(argv
[i
] + 2);
220 _cupsLangPuts(stderr
,
221 _("lpadmin: Expected hostname after \'-h\' "
226 cupsSetServer(argv
[i
]);
230 case 'i' : /* Use the specified interface script */
233 http
= httpConnectEncrypt(cupsServer(), ippPort(),
238 _cupsLangPrintf(stderr
,
239 _("lpadmin: Unable to connect to server: %s\n"),
247 _cupsLangPuts(stderr
,
248 _("lpadmin: Unable to set the interface script:\n"
249 " You must specify a printer name "
256 if (set_printer_file(http
, printer
, argv
[i
] + 2))
265 _cupsLangPuts(stderr
,
266 _("lpadmin: Expected interface after \'-i\' "
271 if (set_printer_file(http
, printer
, argv
[i
]))
276 case 'E' : /* Enable the printer */
280 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
283 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
285 _cupsLangPrintf(stderr
,
286 _("%s: Sorry, no encryption support compiled in!\n"),
288 #endif /* HAVE_SSL */
294 http
= httpConnectEncrypt(cupsServer(), ippPort(),
299 _cupsLangPrintf(stderr
,
300 _("lpadmin: Unable to connect to server: %s\n"),
306 if (enable_printer(http
, printer
))
310 case 'm' : /* Use the specified standard script/PPD file */
313 http
= httpConnectEncrypt(cupsServer(), ippPort(),
318 _cupsLangPrintf(stderr
,
319 _("lpadmin: Unable to connect to server: %s\n"),
327 _cupsLangPuts(stderr
,
328 _("lpadmin: Unable to set the interface script or "
330 " You must specify a printer name "
337 if (set_printer_model(http
, printer
, argv
[i
] + 2))
346 _cupsLangPuts(stderr
,
347 _("lpadmin: Expected model after \'-m\' "
352 if (set_printer_model(http
, printer
, argv
[i
]))
357 case 'o' : /* Set option */
359 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
366 _cupsLangPuts(stderr
,
367 _("lpadmin: Expected name=value after \'-o\' "
372 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
376 case 'p' : /* Add/modify a printer */
379 http
= httpConnectEncrypt(cupsServer(), ippPort(),
384 _cupsLangPrintf(stderr
,
385 _("lpadmin: Unable to connect to server: %s\n"),
392 printer
= argv
[i
] + 2;
399 _cupsLangPuts(stderr
,
400 _("lpadmin: Expected printer after \'-p\' "
408 if (!validate_name(printer
))
410 _cupsLangPuts(stderr
,
411 _("lpadmin: Printer name can only contain "
412 "printable characters!\n"));
417 case 'r' : /* Remove printer from class */
420 http
= httpConnectEncrypt(cupsServer(), ippPort(),
425 _cupsLangPrintf(stderr
,
426 _("lpadmin: Unable to connect to server: %s\n"),
434 _cupsLangPuts(stderr
,
435 _("lpadmin: Unable to remove a printer from the "
437 " You must specify a printer name "
443 pclass
= argv
[i
] + 2;
450 _cupsLangPuts(stderr
,
451 _("lpadmin: Expected class after \'-r\' "
459 if (!validate_name(pclass
))
461 _cupsLangPuts(stderr
,
462 _("lpadmin: Class name can only contain printable "
467 if (delete_printer_from_class(http
, printer
, pclass
))
471 case 'U' : /* Username */
472 if (argv
[i
][2] != '\0')
473 cupsSetUser(argv
[i
] + 2);
479 _cupsLangPrintf(stderr
,
480 _("%s: Error - expected username after "
486 cupsSetUser(argv
[i
]);
490 case 'u' : /* Allow/deny users */
499 _cupsLangPuts(stderr
,
500 _("lpadmin: Expected allow/deny:userlist after "
501 "\'-u\' option!\n"));
508 if (!strncasecmp(val
, "allow:", 6))
509 num_options
= cupsAddOption("requesting-user-name-allowed",
510 val
+ 6, num_options
, &options
);
511 else if (!strncasecmp(val
, "deny:", 5))
512 num_options
= cupsAddOption("requesting-user-name-denied",
513 val
+ 5, num_options
, &options
);
516 _cupsLangPrintf(stderr
,
517 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
523 case 'v' : /* Set the device-uri attribute */
526 http
= httpConnectEncrypt(cupsServer(), ippPort(),
531 _cupsLangPrintf(stderr
,
532 _("lpadmin: Unable to connect to server: %s\n"),
540 _cupsLangPuts(stderr
,
541 _("lpadmin: Unable to set the device URI:\n"
542 " You must specify a printer name "
549 if (set_printer_device(http
, printer
, argv
[i
] + 2))
558 _cupsLangPuts(stderr
,
559 _("lpadmin: Expected device URI after \'-v\' "
564 if (set_printer_device(http
, printer
, argv
[i
]))
569 case 'x' : /* Delete a printer */
572 http
= httpConnectEncrypt(cupsServer(), ippPort(),
577 _cupsLangPrintf(stderr
,
578 _("lpadmin: Unable to connect to server: %s\n"),
585 printer
= argv
[i
] + 2;
592 _cupsLangPuts(stderr
,
593 _("lpadmin: Expected printer or class after "
594 "\'-x\' option!\n"));
601 if (!validate_name(printer
))
603 _cupsLangPuts(stderr
,
604 _("lpadmin: Printer name can only contain "
605 "printable characters!\n"));
609 if (delete_printer(http
, printer
))
615 case 'D' : /* Set the printer-info attribute */
618 http
= httpConnectEncrypt(cupsServer(), ippPort(),
623 _cupsLangPrintf(stderr
,
624 _("lpadmin: Unable to connect to server: %s\n"),
632 _cupsLangPuts(stderr
,
633 _("lpadmin: Unable to set the printer "
635 " You must specify a printer name "
642 if (set_printer_info(http
, printer
, argv
[i
] + 2))
651 _cupsLangPuts(stderr
,
652 _("lpadmin: Expected description after "
653 "\'-D\' option!\n"));
657 if (set_printer_info(http
, printer
, argv
[i
]))
662 case 'I' : /* Set the supported file types (ignored) */
667 _cupsLangPuts(stderr
,
668 _("lpadmin: Expected file type(s) after \'-I\' "
673 _cupsLangPuts(stderr
,
674 _("lpadmin: Warning - content type list ignored!\n"));
677 case 'L' : /* Set the printer-location attribute */
680 http
= httpConnectEncrypt(cupsServer(), ippPort(),
685 _cupsLangPrintf(stderr
,
686 _("lpadmin: Unable to connect to server: %s\n"),
694 _cupsLangPuts(stderr
,
695 _("lpadmin: Unable to set the printer location:\n"
696 " You must specify a printer name "
703 if (set_printer_location(http
, printer
, argv
[i
] + 2))
712 _cupsLangPuts(stderr
,
713 _("lpadmin: Expected location after \'-L\' "
718 if (set_printer_location(http
, printer
, argv
[i
]))
723 case 'P' : /* Use the specified PPD file */
726 http
= httpConnectEncrypt(cupsServer(), ippPort(),
731 _cupsLangPrintf(stderr
,
732 _("lpadmin: Unable to connect to server: %s\n"),
740 _cupsLangPuts(stderr
,
741 _("lpadmin: Unable to set the PPD file:\n"
742 " You must specify a printer name "
749 if (set_printer_file(http
, printer
, argv
[i
] + 2))
758 _cupsLangPuts(stderr
,
759 _("lpadmin: Expected PPD after \'-P\' option!\n"));
763 if (set_printer_file(http
, printer
, argv
[i
]))
769 _cupsLangPrintf(stderr
,
770 _("lpadmin: Unknown option \'%c\'!\n"), argv
[i
][1]);
775 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \'%s\'!\n"),
781 * Set options as needed...
788 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
792 _cupsLangPrintf(stderr
,
793 _("lpadmin: Unable to connect to server: %s\n"),
801 _cupsLangPuts(stderr
,
802 _("lpadmin: Unable to set the printer options:\n"
803 " You must specify a printer name first!\n"));
807 if (set_printer_options(http
, printer
, num_options
, options
))
813 _cupsLangPuts(stdout
,
816 " lpadmin [-h server] -d destination\n"
817 " lpadmin [-h server] -x destination\n"
818 " lpadmin [-h server] -p printer [-c add-class] "
819 "[-i interface] [-m model]\n"
820 " [-r remove-class] [-v device] "
822 " [-P ppd-file] [-o name=value]\n"
823 " [-u allow:user,user] "
824 "[-u deny:user,user]\n"
836 * 'add_printer_to_class()' - Add a printer to a class.
839 static int /* O - 0 on success, 1 on fail */
840 add_printer_to_class(http_t
*http
, /* I - Server connection */
841 char *printer
, /* I - Printer to add */
842 char *pclass
) /* I - Class to add to */
844 int i
; /* Looping var */
845 ipp_t
*request
, /* IPP Request */
846 *response
; /* IPP Response */
847 ipp_attribute_t
*attr
, /* Current attribute */
848 *members
; /* Members in class */
849 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
852 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
856 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
860 * attributes-natural-language
864 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
866 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
867 "localhost", 0, "/classes/%s", pclass
);
868 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
869 "printer-uri", NULL
, uri
);
872 * Do the request and get back a response...
875 response
= cupsDoRequest(http
, request
, "/");
878 * Build a CUPS_ADD_CLASS request, which requires the following
882 * attributes-natural-language
887 request
= ippNewRequest(CUPS_ADD_CLASS
);
889 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
890 "printer-uri", NULL
, uri
);
893 * See if the printer is already in the class...
896 if (response
!= NULL
&&
897 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
898 for (i
= 0; i
< members
->num_values
; i
++)
899 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
901 _cupsLangPrintf(stderr
,
902 _("lpadmin: Printer %s is already a member of class %s.\n"),
910 * OK, the printer isn't part of the class, so add it...
913 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
914 "localhost", 0, "/printers/%s", printer
);
916 if (response
!= NULL
&&
917 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
920 * Add the printer to the existing list...
923 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
924 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
925 for (i
= 0; i
< members
->num_values
; i
++)
926 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
928 attr
->values
[i
].string
.text
= strdup(uri
);
931 attr
= ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
934 * Then send the request...
939 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
941 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
945 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
947 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
963 * 'default_printer()' - Set the default printing destination.
966 static int /* O - 0 on success, 1 on fail */
967 default_printer(http_t
*http
, /* I - Server connection */
968 char *printer
) /* I - Printer name */
970 ipp_t
*request
, /* IPP Request */
971 *response
; /* IPP Response */
972 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
975 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
978 * Build a CUPS_SET_DEFAULT request, which requires the following
982 * attributes-natural-language
986 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
987 "localhost", 0, "/printers/%s", printer
);
989 request
= ippNewRequest(CUPS_SET_DEFAULT
);
991 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
992 "printer-uri", NULL
, uri
);
995 * Do the request and get back a response...
998 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1000 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1004 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1006 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1008 ippDelete(response
);
1014 ippDelete(response
);
1022 * 'delete_printer()' - Delete a printer from the system...
1025 static int /* O - 0 on success, 1 on fail */
1026 delete_printer(http_t
*http
, /* I - Server connection */
1027 char *printer
) /* I - Printer to delete */
1029 ipp_t
*request
, /* IPP Request */
1030 *response
; /* IPP Response */
1031 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1034 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
1037 * Build a CUPS_DELETE_PRINTER request, which requires the following
1040 * attributes-charset
1041 * attributes-natural-language
1045 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
1047 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1048 "localhost", 0, "/printers/%s", printer
);
1049 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1050 "printer-uri", NULL
, uri
);
1053 * Do the request and get back a response...
1056 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1058 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1062 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1064 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1066 ippDelete(response
);
1072 ippDelete(response
);
1080 * 'delete_printer_from_class()' - Delete a printer from a class.
1083 static int /* O - 0 on success, 1 on fail */
1084 delete_printer_from_class(
1085 http_t
*http
, /* I - Server connection */
1086 char *printer
, /* I - Printer to remove */
1087 char *pclass
) /* I - Class to remove from */
1089 int i
, j
, k
; /* Looping vars */
1090 ipp_t
*request
, /* IPP Request */
1091 *response
; /* IPP Response */
1092 ipp_attribute_t
*attr
, /* Current attribute */
1093 *members
; /* Members in class */
1094 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1097 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
1101 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1104 * attributes-charset
1105 * attributes-natural-language
1109 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1111 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1112 "localhost", 0, "/classes/%s", pclass
);
1113 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1114 "printer-uri", NULL
, uri
);
1117 * Do the request and get back a response...
1120 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1121 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1123 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1125 ippDelete(response
);
1131 * See if the printer is already in the class...
1134 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1136 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen!\n"));
1138 ippDelete(response
);
1143 for (i
= 0; i
< members
->num_values
; i
++)
1144 if (!strcasecmp(printer
, members
->values
[i
].string
.text
))
1147 if (i
>= members
->num_values
)
1149 _cupsLangPrintf(stderr
,
1150 _("lpadmin: Printer %s is not a member of class %s.\n"),
1153 ippDelete(response
);
1158 if (members
->num_values
== 1)
1161 * Build a CUPS_DELETE_CLASS request, which requires the following
1164 * attributes-charset
1165 * attributes-natural-language
1169 request
= ippNewRequest(CUPS_DELETE_CLASS
);
1171 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1172 "printer-uri", NULL
, uri
);
1177 * Build a CUPS_ADD_CLASS request, which requires the following
1180 * attributes-charset
1181 * attributes-natural-language
1186 request
= ippNewRequest(CUPS_ADD_CLASS
);
1188 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1189 "printer-uri", NULL
, uri
);
1192 * Delete the printer from the class...
1195 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1196 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1197 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1199 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1201 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1205 * Then send the request...
1208 ippDelete(response
);
1210 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1212 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1216 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1218 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1220 ippDelete(response
);
1226 ippDelete(response
);
1234 * 'enable_printer()' - Enable a printer...
1237 static int /* O - 0 on success, 1 on fail */
1238 enable_printer(http_t
*http
, /* I - Server connection */
1239 char *printer
) /* I - Printer to enable */
1241 ipp_t
*request
, /* IPP Request */
1242 *response
; /* IPP Response */
1243 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1246 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1249 * Build a CUPS_ADD_PRINTER request, which requires the following
1252 * attributes-charset
1253 * attributes-natural-language
1256 * printer-is-accepting-jobs
1259 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1261 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1262 "localhost", 0, "/printers/%s", printer
);
1263 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1264 "printer-uri", NULL
, uri
);
1266 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1269 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1272 * Do the request and get back a response...
1275 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1277 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1281 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1283 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1285 ippDelete(response
);
1291 ippDelete(response
);
1299 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1302 static char * /* O - Pointer to buf or NULL on EOF */
1303 get_line(char *buf
, /* I - Line buffer */
1304 int length
, /* I - Length of buffer */
1305 FILE *fp
) /* I - File to read from */
1307 char *bufptr
; /* Pointer into buffer */
1308 int ch
; /* Character from file */
1314 while ((ch
= getc(fp
)) != EOF
)
1318 else if (ch
== '\r')
1325 if (ch
!= '\n' && ch
!= EOF
)
1347 * 'set_printer_device()' - Set the device-uri attribute.
1350 static int /* O - 0 on success, 1 on fail */
1351 set_printer_device(http_t
*http
, /* I - Server connection */
1352 char *printer
, /* I - Printer */
1353 char *device
) /* I - New device URI */
1355 ipp_t
*request
, /* IPP Request */
1356 *response
; /* IPP Response */
1357 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1360 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1364 * Build a CUPS_ADD_PRINTER request, which requires the following
1367 * attributes-charset
1368 * attributes-natural-language
1372 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1374 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1375 "localhost", 0, "/printers/%s", printer
);
1376 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1377 "printer-uri", NULL
, uri
);
1380 * Add the device URI...
1383 if (device
[0] == '/')
1386 * Convert filename to URI...
1389 snprintf(uri
, sizeof(uri
), "file://%s", device
);
1390 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1394 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1398 * Do the request and get back a response...
1401 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1403 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1407 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1409 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1411 ippDelete(response
);
1417 ippDelete(response
);
1425 * 'set_printer_file()' - Set the interface script or PPD file.
1428 static int /* O - 0 on success, 1 on fail */
1429 set_printer_file(http_t
*http
, /* I - Server connection */
1430 char *printer
, /* I - Printer */
1431 char *file
) /* I - PPD file or interface script */
1433 ipp_t
*request
, /* IPP Request */
1434 *response
; /* IPP Response */
1435 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1437 char tempfile
[1024]; /* Temporary filename */
1438 int fd
; /* Temporary file */
1439 gzFile
*gz
; /* GZIP'd file */
1440 char buffer
[8192]; /* Copy buffer */
1441 int bytes
; /* Bytes in buffer */
1444 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1448 * See if the file is gzip'd; if so, unzip it to a temporary file and
1449 * send the uncompressed file.
1452 if (!strcmp(file
+ strlen(file
) - 3, ".gz"))
1455 * Yes, the file is compressed; uncompress to a temp file...
1458 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1460 _cupsLangPrintf(stderr
,
1461 _("lpadmin: Unable to create temporary file: %s\n"),
1466 if ((gz
= gzopen(file
, "rb")) == NULL
)
1468 _cupsLangPrintf(stderr
,
1469 _("lpadmin: Unable to open file \"%s\": %s\n"),
1470 file
, strerror(errno
));
1476 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1477 write(fd
, buffer
, bytes
);
1484 #endif /* HAVE_LIBZ */
1487 * Build a CUPS_ADD_PRINTER request, which requires the following
1490 * attributes-charset
1491 * attributes-natural-language
1495 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1497 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1498 "localhost", 0, "/printers/%s", printer
);
1499 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1500 "printer-uri", NULL
, uri
);
1503 * Do the request and get back a response...
1506 response
= cupsDoFileRequest(http
, request
, "/admin/", file
);
1507 ippDelete(response
);
1511 * Remove the temporary file as needed...
1514 if (file
== tempfile
)
1516 #endif /* HAVE_LIBZ */
1518 if (cupsLastError() > IPP_OK_CONFLICT
)
1520 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1530 * 'set_printer_info()' - Set the printer description string.
1533 static int /* O - 0 on success, 1 on fail */
1534 set_printer_info(http_t
*http
, /* I - Server connection */
1535 char *printer
, /* I - Printer */
1536 char *info
) /* I - New description string */
1538 ipp_t
*request
, /* IPP Request */
1539 *response
; /* IPP Response */
1540 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1543 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1547 * Build a CUPS_ADD_PRINTER request, which requires the following
1550 * attributes-charset
1551 * attributes-natural-language
1555 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1557 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1558 "localhost", 0, "/printers/%s", printer
);
1559 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1560 "printer-uri", NULL
, uri
);
1563 * Add the info string...
1566 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1570 * Do the request and get back a response...
1573 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1575 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1578 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1580 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1582 ippDelete(response
);
1588 ippDelete(response
);
1596 * 'set_printer_location()' - Set the printer location string.
1599 static int /* O - 0 on success, 1 on fail */
1600 set_printer_location(http_t
*http
, /* I - Server connection */
1601 char *printer
, /* I - Printer */
1602 char *location
) /* I - New location string */
1604 ipp_t
*request
, /* IPP Request */
1605 *response
; /* IPP Response */
1606 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1609 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1613 * Build a CUPS_ADD_PRINTER request, which requires the following
1616 * attributes-charset
1617 * attributes-natural-language
1621 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1623 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1624 "localhost", 0, "/printers/%s", printer
);
1625 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1626 "printer-uri", NULL
, uri
);
1629 * Add the location string...
1632 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1636 * Do the request and get back a response...
1639 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1641 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1645 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1647 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1649 ippDelete(response
);
1655 ippDelete(response
);
1663 * 'set_printer_model()' - Set the driver model file.
1666 static int /* O - 0 on success, 1 on fail */
1667 set_printer_model(http_t
*http
, /* I - Server connection */
1668 char *printer
, /* I - Printer */
1669 char *model
) /* I - Driver model file */
1671 ipp_t
*request
, /* IPP Request */
1672 *response
; /* IPP Response */
1673 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1677 * Build a CUPS_ADD_PRINTER request, which requires the following
1680 * attributes-charset
1681 * attributes-natural-language
1686 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1688 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1689 "localhost", 0, "/printers/%s", printer
);
1690 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1691 "printer-uri", NULL
, uri
);
1693 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1694 "ppd-name", NULL
, model
);
1697 * Do the request and get back a response...
1700 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1702 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1706 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1708 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1710 ippDelete(response
);
1716 ippDelete(response
);
1724 * 'set_printer_options()' - Set the printer options.
1727 static int /* O - 0 on success, 1 on fail */
1728 set_printer_options(
1729 http_t
*http
, /* I - Server connection */
1730 char *printer
, /* I - Printer */
1731 int num_options
, /* I - Number of options */
1732 cups_option_t
*options
) /* I - Options */
1734 ipp_t
*request
, /* IPP Request */
1735 *response
; /* IPP Response */
1736 ipp_attribute_t
*attr
; /* IPP attribute */
1737 ipp_op_t op
; /* Operation to perform */
1738 const char *ppdfile
; /* PPD filename */
1739 int ppdchanged
; /* PPD changed? */
1740 ppd_file_t
*ppd
; /* PPD file */
1741 ppd_choice_t
*choice
; /* Marked choice */
1742 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1743 line
[1024], /* Line from PPD file */
1744 keyword
[1024], /* Keyword from Default line */
1745 *keyptr
, /* Pointer into keyword... */
1746 tempfile
[1024]; /* Temporary filename */
1747 FILE *in
, /* PPD file */
1748 *out
; /* Temporary file */
1749 int outfd
; /* Temporary file descriptor */
1750 const char *protocol
; /* Old protocol option */
1753 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1754 num_options
, options
));
1756 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1757 "localhost", 0, "/printers/%s", printer
);
1760 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1763 * attributes-charset
1764 * attributes-natural-language
1766 * requested-attributes
1769 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1771 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1772 "printer-uri", NULL
, uri
);
1774 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1775 "requested-attributes", NULL
, "printer-type");
1781 op
= CUPS_ADD_PRINTER
;
1783 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1786 * See what kind of printer or class it is...
1789 if ((attr
= ippFindAttribute(response
, "printer-type",
1790 IPP_TAG_ENUM
)) != NULL
)
1792 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1794 op
= CUPS_ADD_CLASS
;
1795 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1796 "localhost", 0, "/classes/%s", printer
);
1800 ippDelete(response
);
1804 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1805 * the following attributes:
1807 * attributes-charset
1808 * attributes-natural-language
1813 request
= ippNewRequest(op
);
1815 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1816 "printer-uri", NULL
, uri
);
1819 * Add the options...
1822 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1824 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1826 if (!strcasecmp(protocol
, "bcp"))
1827 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1829 else if (!strcasecmp(protocol
, "tbcp"))
1830 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1834 if (op
== CUPS_ADD_PRINTER
)
1835 ppdfile
= cupsGetPPD(printer
);
1839 if (ppdfile
!= NULL
)
1842 * Set default options in the PPD file...
1845 ppd
= ppdOpenFile(ppdfile
);
1846 ppdMarkDefaults(ppd
);
1847 cupsMarkOptions(ppd
, num_options
, options
);
1849 if ((outfd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1851 _cupsLangPrintf(stderr
,
1852 _("lpadmin: Unable to create temporary file - %s\n"),
1859 if ((in
= fopen(ppdfile
, "rb")) == NULL
)
1861 _cupsLangPrintf(stderr
,
1862 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1863 ppdfile
, strerror(errno
));
1871 out
= fdopen(outfd
, "wb");
1874 while (get_line(line
, sizeof(line
), in
) != NULL
)
1876 if (strncmp(line
, "*Default", 8))
1877 fprintf(out
, "%s\n", line
);
1881 * Get default option name...
1884 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1886 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1887 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1891 while (isspace(*keyptr
& 255))
1894 if (!strcmp(keyword
, "PageRegion") ||
1895 !strcmp(keyword
, "PageSize") ||
1896 !strcmp(keyword
, "PaperDimension") ||
1897 !strcmp(keyword
, "ImageableArea"))
1899 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1900 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1903 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1905 if (choice
&& strcmp(choice
->choice
, keyptr
))
1907 fprintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1911 fprintf(out
, "%s\n", line
);
1924 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1925 ppdchanged
? tempfile
: NULL
));
1928 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1938 * No PPD file - just set the options...
1941 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1945 * Check the response...
1948 if (cupsLastError() > IPP_OK_CONFLICT
)
1950 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1960 * 'validate_name()' - Make sure the printer name only contains valid chars.
1963 static int /* O - 0 if name is no good, 1 if name is good */
1964 validate_name(const char *name
) /* I - Name to check */
1966 const char *ptr
; /* Pointer into name */
1970 * Scan the whole name...
1973 for (ptr
= name
; *ptr
; ptr
++)
1976 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1981 * All the characters are good; validate the length, too...
1984 return ((ptr
- name
) < 128);