2 * "$Id: lpadmin.c 5154 2006-02-23 01:36:15Z mike $"
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 */
100 for (i
= 1; i
< argc
; i
++)
101 if (argv
[i
][0] == '-')
104 case 'c' : /* Add printer to class */
107 http
= httpConnectEncrypt(cupsServer(), ippPort(),
112 _cupsLangPrintf(stderr
,
113 _("lpadmin: Unable to connect to server: %s\n"),
121 _cupsLangPuts(stderr
,
122 _("lpadmin: Unable to add a printer to the class:\n"
123 " You must specify a printer name "
129 pclass
= argv
[i
] + 2;
136 _cupsLangPuts(stderr
,
137 _("lpadmin: Expected class name after \'-c\' "
145 if (!validate_name(pclass
))
147 _cupsLangPuts(stderr
,
148 _("lpadmin: Class name can only contain printable "
153 if (add_printer_to_class(http
, printer
, pclass
))
157 case 'd' : /* Set as default destination */
160 http
= httpConnectEncrypt(cupsServer(), ippPort(),
165 _cupsLangPrintf(stderr
,
166 _("lpadmin: Unable to connect to server: %s\n"),
173 printer
= argv
[i
] + 2;
180 _cupsLangPuts(stderr
,
181 _("lpadmin: Expected printer name after \'-d\' "
189 if (!validate_name(printer
))
191 _cupsLangPuts(stderr
,
192 _("lpadmin: Printer name can only contain "
193 "printable characters!\n"));
197 if (default_printer(http
, printer
))
203 case 'h' : /* Connect to host */
210 if (argv
[i
][2] != '\0')
211 cupsSetServer(argv
[i
] + 2);
218 _cupsLangPuts(stderr
,
219 _("lpadmin: Expected hostname after \'-h\' "
224 cupsSetServer(argv
[i
]);
228 case 'i' : /* Use the specified interface script */
231 http
= httpConnectEncrypt(cupsServer(), ippPort(),
236 _cupsLangPrintf(stderr
,
237 _("lpadmin: Unable to connect to server: %s\n"),
245 _cupsLangPuts(stderr
,
246 _("lpadmin: Unable to set the interface script:\n"
247 " You must specify a printer name "
254 if (set_printer_file(http
, printer
, argv
[i
] + 2))
263 _cupsLangPuts(stderr
,
264 _("lpadmin: Expected interface after \'-i\' "
269 if (set_printer_file(http
, printer
, argv
[i
]))
274 case 'E' : /* Enable the printer */
278 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
281 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
283 _cupsLangPrintf(stderr
,
284 _("%s: Sorry, no encryption support compiled in!\n"),
286 #endif /* HAVE_SSL */
292 http
= httpConnectEncrypt(cupsServer(), ippPort(),
297 _cupsLangPrintf(stderr
,
298 _("lpadmin: Unable to connect to server: %s\n"),
304 if (enable_printer(http
, printer
))
308 case 'm' : /* Use the specified standard script/PPD file */
311 http
= httpConnectEncrypt(cupsServer(), ippPort(),
316 _cupsLangPrintf(stderr
,
317 _("lpadmin: Unable to connect to server: %s\n"),
325 _cupsLangPuts(stderr
,
326 _("lpadmin: Unable to set the interface script or "
328 " You must specify a printer name "
335 if (set_printer_model(http
, printer
, argv
[i
] + 2))
344 _cupsLangPuts(stderr
,
345 _("lpadmin: Expected model after \'-m\' "
350 if (set_printer_model(http
, printer
, argv
[i
]))
355 case 'o' : /* Set option */
357 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
364 _cupsLangPuts(stderr
,
365 _("lpadmin: Expected name=value after \'-o\' "
370 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
374 case 'p' : /* Add/modify a printer */
377 http
= httpConnectEncrypt(cupsServer(), ippPort(),
382 _cupsLangPrintf(stderr
,
383 _("lpadmin: Unable to connect to server: %s\n"),
390 printer
= argv
[i
] + 2;
397 _cupsLangPuts(stderr
,
398 _("lpadmin: Expected printer after \'-p\' "
406 if (!validate_name(printer
))
408 _cupsLangPuts(stderr
,
409 _("lpadmin: Printer name can only contain "
410 "printable characters!\n"));
415 case 'r' : /* Remove printer from class */
418 http
= httpConnectEncrypt(cupsServer(), ippPort(),
423 _cupsLangPrintf(stderr
,
424 _("lpadmin: Unable to connect to server: %s\n"),
432 _cupsLangPuts(stderr
,
433 _("lpadmin: Unable to remove a printer from the "
435 " You must specify a printer name "
441 pclass
= argv
[i
] + 2;
448 _cupsLangPuts(stderr
,
449 _("lpadmin: Expected class after \'-r\' "
457 if (!validate_name(pclass
))
459 _cupsLangPuts(stderr
,
460 _("lpadmin: Class name can only contain printable "
465 if (delete_printer_from_class(http
, printer
, pclass
))
469 case 'u' : /* Allow/deny users */
478 _cupsLangPuts(stderr
,
479 _("lpadmin: Expected allow/deny:userlist after "
480 "\'-u\' option!\n"));
487 if (!strncasecmp(val
, "allow:", 6))
488 num_options
= cupsAddOption("requesting-user-name-allowed",
489 val
+ 6, num_options
, &options
);
490 else if (!strncasecmp(val
, "deny:", 5))
491 num_options
= cupsAddOption("requesting-user-name-denied",
492 val
+ 5, num_options
, &options
);
495 _cupsLangPrintf(stderr
,
496 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
502 case 'v' : /* Set the device-uri attribute */
505 http
= httpConnectEncrypt(cupsServer(), ippPort(),
510 _cupsLangPrintf(stderr
,
511 _("lpadmin: Unable to connect to server: %s\n"),
519 _cupsLangPuts(stderr
,
520 _("lpadmin: Unable to set the device URI:\n"
521 " You must specify a printer name "
528 if (set_printer_device(http
, printer
, argv
[i
] + 2))
537 _cupsLangPuts(stderr
,
538 _("lpadmin: Expected device URI after \'-v\' "
543 if (set_printer_device(http
, printer
, argv
[i
]))
548 case 'x' : /* Delete a printer */
551 http
= httpConnectEncrypt(cupsServer(), ippPort(),
556 _cupsLangPrintf(stderr
,
557 _("lpadmin: Unable to connect to server: %s\n"),
564 printer
= argv
[i
] + 2;
571 _cupsLangPuts(stderr
,
572 _("lpadmin: Expected printer or class after "
573 "\'-x\' option!\n"));
580 if (!validate_name(printer
))
582 _cupsLangPuts(stderr
,
583 _("lpadmin: Printer name can only contain "
584 "printable characters!\n"));
588 if (delete_printer(http
, printer
))
594 case 'D' : /* Set the printer-info attribute */
597 http
= httpConnectEncrypt(cupsServer(), ippPort(),
602 _cupsLangPrintf(stderr
,
603 _("lpadmin: Unable to connect to server: %s\n"),
611 _cupsLangPuts(stderr
,
612 _("lpadmin: Unable to set the printer "
614 " You must specify a printer name "
621 if (set_printer_info(http
, printer
, argv
[i
] + 2))
630 _cupsLangPuts(stderr
,
631 _("lpadmin: Expected description after "
632 "\'-D\' option!\n"));
636 if (set_printer_info(http
, printer
, argv
[i
]))
641 case 'I' : /* Set the supported file types (ignored) */
646 _cupsLangPuts(stderr
,
647 _("lpadmin: Expected file type(s) after \'-I\' "
652 _cupsLangPuts(stderr
,
653 _("lpadmin: Warning - content type list ignored!\n"));
656 case 'L' : /* Set the printer-location attribute */
659 http
= httpConnectEncrypt(cupsServer(), ippPort(),
664 _cupsLangPrintf(stderr
,
665 _("lpadmin: Unable to connect to server: %s\n"),
673 _cupsLangPuts(stderr
,
674 _("lpadmin: Unable to set the printer location:\n"
675 " You must specify a printer name "
682 if (set_printer_location(http
, printer
, argv
[i
] + 2))
691 _cupsLangPuts(stderr
,
692 _("lpadmin: Expected location after \'-L\' "
697 if (set_printer_location(http
, printer
, argv
[i
]))
702 case 'P' : /* Use the specified PPD file */
705 http
= httpConnectEncrypt(cupsServer(), ippPort(),
710 _cupsLangPrintf(stderr
,
711 _("lpadmin: Unable to connect to server: %s\n"),
719 _cupsLangPuts(stderr
,
720 _("lpadmin: Unable to set the PPD file:\n"
721 " You must specify a printer name "
728 if (set_printer_file(http
, printer
, argv
[i
] + 2))
737 _cupsLangPuts(stderr
,
738 _("lpadmin: Expected PPD after \'-P\' option!\n"));
742 if (set_printer_file(http
, printer
, argv
[i
]))
748 _cupsLangPrintf(stderr
,
749 _("lpadmin: Unknown option \'%c\'!\n"), argv
[i
][1]);
754 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \'%s\'!\n"),
760 * Set options as needed...
767 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
771 _cupsLangPrintf(stderr
,
772 _("lpadmin: Unable to connect to server: %s\n"),
780 _cupsLangPuts(stderr
,
781 _("lpadmin: Unable to set the printer options:\n"
782 " You must specify a printer name first!\n"));
786 if (set_printer_options(http
, printer
, num_options
, options
))
792 _cupsLangPuts(stdout
,
795 " lpadmin [-h server] -d destination\n"
796 " lpadmin [-h server] -x destination\n"
797 " lpadmin [-h server] -p printer [-c add-class] "
798 "[-i interface] [-m model]\n"
799 " [-r remove-class] [-v device] "
801 " [-P ppd-file] [-o name=value]\n"
802 " [-u allow:user,user] "
803 "[-u deny:user,user]\n"
815 * 'add_printer_to_class()' - Add a printer to a class.
818 static int /* O - 0 on success, 1 on fail */
819 add_printer_to_class(http_t
*http
, /* I - Server connection */
820 char *printer
, /* I - Printer to add */
821 char *pclass
) /* I - Class to add to */
823 int i
; /* Looping var */
824 ipp_t
*request
, /* IPP Request */
825 *response
; /* IPP Response */
826 ipp_attribute_t
*attr
, /* Current attribute */
827 *members
; /* Members in class */
828 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
831 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
835 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
839 * attributes-natural-language
843 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
845 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
846 "localhost", 0, "/classes/%s", pclass
);
847 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
848 "printer-uri", NULL
, uri
);
851 * Do the request and get back a response...
854 response
= cupsDoRequest(http
, request
, "/");
857 * Build a CUPS_ADD_CLASS request, which requires the following
861 * attributes-natural-language
866 request
= ippNewRequest(CUPS_ADD_CLASS
);
868 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
869 "printer-uri", NULL
, uri
);
872 * See if the printer is already in the class...
875 if (response
!= NULL
&&
876 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
877 for (i
= 0; i
< members
->num_values
; i
++)
878 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
880 _cupsLangPrintf(stderr
,
881 _("lpadmin: Printer %s is already a member of class %s.\n"),
889 * OK, the printer isn't part of the class, so add it...
892 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
893 "localhost", 0, "/printers/%s", printer
);
895 if (response
!= NULL
&&
896 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
899 * Add the printer to the existing list...
902 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
903 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
904 for (i
= 0; i
< members
->num_values
; i
++)
905 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
907 attr
->values
[i
].string
.text
= strdup(uri
);
910 attr
= ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
913 * Then send the request...
918 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
920 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
924 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
926 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
942 * 'default_printer()' - Set the default printing destination.
945 static int /* O - 0 on success, 1 on fail */
946 default_printer(http_t
*http
, /* I - Server connection */
947 char *printer
) /* I - Printer name */
949 ipp_t
*request
, /* IPP Request */
950 *response
; /* IPP Response */
951 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
954 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
957 * Build a CUPS_SET_DEFAULT request, which requires the following
961 * attributes-natural-language
965 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
966 "localhost", 0, "/printers/%s", printer
);
968 request
= ippNewRequest(CUPS_SET_DEFAULT
);
970 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
971 "printer-uri", NULL
, uri
);
974 * Do the request and get back a response...
977 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
979 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
983 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
985 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1001 * 'delete_printer()' - Delete a printer from the system...
1004 static int /* O - 0 on success, 1 on fail */
1005 delete_printer(http_t
*http
, /* I - Server connection */
1006 char *printer
) /* I - Printer to delete */
1008 ipp_t
*request
, /* IPP Request */
1009 *response
; /* IPP Response */
1010 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1013 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
1016 * Build a CUPS_DELETE_PRINTER request, which requires the following
1019 * attributes-charset
1020 * attributes-natural-language
1024 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
1026 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1027 "localhost", 0, "/printers/%s", printer
);
1028 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1029 "printer-uri", NULL
, uri
);
1032 * Do the request and get back a response...
1035 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1037 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1041 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1043 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1045 ippDelete(response
);
1051 ippDelete(response
);
1059 * 'delete_printer_from_class()' - Delete a printer from a class.
1062 static int /* O - 0 on success, 1 on fail */
1063 delete_printer_from_class(
1064 http_t
*http
, /* I - Server connection */
1065 char *printer
, /* I - Printer to remove */
1066 char *pclass
) /* I - Class to remove from */
1068 int i
, j
, k
; /* Looping vars */
1069 ipp_t
*request
, /* IPP Request */
1070 *response
; /* IPP Response */
1071 ipp_attribute_t
*attr
, /* Current attribute */
1072 *members
; /* Members in class */
1073 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1076 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
1080 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1083 * attributes-charset
1084 * attributes-natural-language
1088 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1090 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1091 "localhost", 0, "/classes/%s", pclass
);
1092 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1093 "printer-uri", NULL
, uri
);
1096 * Do the request and get back a response...
1099 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1100 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1102 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1104 ippDelete(response
);
1110 * See if the printer is already in the class...
1113 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1115 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen!\n"));
1117 ippDelete(response
);
1122 for (i
= 0; i
< members
->num_values
; i
++)
1123 if (!strcasecmp(printer
, members
->values
[i
].string
.text
))
1126 if (i
>= members
->num_values
)
1128 _cupsLangPrintf(stderr
,
1129 _("lpadmin: Printer %s is not a member of class %s.\n"),
1132 ippDelete(response
);
1137 if (members
->num_values
== 1)
1140 * Build a CUPS_DELETE_CLASS request, which requires the following
1143 * attributes-charset
1144 * attributes-natural-language
1148 request
= ippNewRequest(CUPS_DELETE_CLASS
);
1150 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1151 "printer-uri", NULL
, uri
);
1156 * Build a CUPS_ADD_CLASS request, which requires the following
1159 * attributes-charset
1160 * attributes-natural-language
1165 request
= ippNewRequest(CUPS_ADD_CLASS
);
1167 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1168 "printer-uri", NULL
, uri
);
1171 * Delete the printer from the class...
1174 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1175 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1176 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1178 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1180 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1184 * Then send the request...
1187 ippDelete(response
);
1189 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1191 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1195 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1197 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1199 ippDelete(response
);
1205 ippDelete(response
);
1213 * 'enable_printer()' - Enable a printer...
1216 static int /* O - 0 on success, 1 on fail */
1217 enable_printer(http_t
*http
, /* I - Server connection */
1218 char *printer
) /* I - Printer to enable */
1220 ipp_t
*request
, /* IPP Request */
1221 *response
; /* IPP Response */
1222 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1225 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1228 * Build a CUPS_ADD_PRINTER request, which requires the following
1231 * attributes-charset
1232 * attributes-natural-language
1235 * printer-is-accepting-jobs
1238 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1240 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1241 "localhost", 0, "/printers/%s", printer
);
1242 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1243 "printer-uri", NULL
, uri
);
1245 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1248 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1251 * Do the request and get back a response...
1254 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1256 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1260 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1262 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1264 ippDelete(response
);
1270 ippDelete(response
);
1278 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1281 static char * /* O - Pointer to buf or NULL on EOF */
1282 get_line(char *buf
, /* I - Line buffer */
1283 int length
, /* I - Length of buffer */
1284 FILE *fp
) /* I - File to read from */
1286 char *bufptr
; /* Pointer into buffer */
1287 int ch
; /* Character from file */
1293 while ((ch
= getc(fp
)) != EOF
)
1297 else if (ch
== '\r')
1304 if (ch
!= '\n' && ch
!= EOF
)
1326 * 'set_printer_device()' - Set the device-uri attribute.
1329 static int /* O - 0 on success, 1 on fail */
1330 set_printer_device(http_t
*http
, /* I - Server connection */
1331 char *printer
, /* I - Printer */
1332 char *device
) /* I - New device URI */
1334 ipp_t
*request
, /* IPP Request */
1335 *response
; /* IPP Response */
1336 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1339 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1343 * Build a CUPS_ADD_PRINTER request, which requires the following
1346 * attributes-charset
1347 * attributes-natural-language
1351 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1353 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1354 "localhost", 0, "/printers/%s", printer
);
1355 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1356 "printer-uri", NULL
, uri
);
1359 * Add the device URI...
1362 if (device
[0] == '/')
1365 * Convert filename to URI...
1368 snprintf(uri
, sizeof(uri
), "file://%s", device
);
1369 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1373 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1377 * Do the request and get back a response...
1380 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1382 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1386 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1388 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1390 ippDelete(response
);
1396 ippDelete(response
);
1404 * 'set_printer_file()' - Set the interface script or PPD file.
1407 static int /* O - 0 on success, 1 on fail */
1408 set_printer_file(http_t
*http
, /* I - Server connection */
1409 char *printer
, /* I - Printer */
1410 char *file
) /* I - PPD file or interface script */
1412 ipp_t
*request
, /* IPP Request */
1413 *response
; /* IPP Response */
1414 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1416 char tempfile
[1024]; /* Temporary filename */
1417 int fd
; /* Temporary file */
1418 gzFile
*gz
; /* GZIP'd file */
1419 char buffer
[8192]; /* Copy buffer */
1420 int bytes
; /* Bytes in buffer */
1423 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1427 * See if the file is gzip'd; if so, unzip it to a temporary file and
1428 * send the uncompressed file.
1431 if (!strcmp(file
+ strlen(file
) - 3, ".gz"))
1434 * Yes, the file is compressed; uncompress to a temp file...
1437 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1439 _cupsLangPrintf(stderr
,
1440 _("lpadmin: Unable to create temporary file: %s\n"),
1445 if ((gz
= gzopen(file
, "rb")) == NULL
)
1447 _cupsLangPrintf(stderr
,
1448 _("lpadmin: Unable to open file \"%s\": %s\n"),
1449 file
, strerror(errno
));
1455 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1456 write(fd
, buffer
, bytes
);
1463 #endif /* HAVE_LIBZ */
1466 * Build a CUPS_ADD_PRINTER request, which requires the following
1469 * attributes-charset
1470 * attributes-natural-language
1474 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1476 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1477 "localhost", 0, "/printers/%s", printer
);
1478 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1479 "printer-uri", NULL
, uri
);
1482 * Do the request and get back a response...
1485 response
= cupsDoFileRequest(http
, request
, "/admin/", file
);
1486 ippDelete(response
);
1490 * Remove the temporary file as needed...
1493 if (file
== tempfile
)
1495 #endif /* HAVE_LIBZ */
1497 if (cupsLastError() > IPP_OK_CONFLICT
)
1499 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1509 * 'set_printer_info()' - Set the printer description string.
1512 static int /* O - 0 on success, 1 on fail */
1513 set_printer_info(http_t
*http
, /* I - Server connection */
1514 char *printer
, /* I - Printer */
1515 char *info
) /* I - New description string */
1517 ipp_t
*request
, /* IPP Request */
1518 *response
; /* IPP Response */
1519 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1522 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1526 * Build a CUPS_ADD_PRINTER request, which requires the following
1529 * attributes-charset
1530 * attributes-natural-language
1534 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1536 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1537 "localhost", 0, "/printers/%s", printer
);
1538 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1539 "printer-uri", NULL
, uri
);
1542 * Add the info string...
1545 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1549 * Do the request and get back a response...
1552 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1554 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1557 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1559 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1561 ippDelete(response
);
1567 ippDelete(response
);
1575 * 'set_printer_location()' - Set the printer location string.
1578 static int /* O - 0 on success, 1 on fail */
1579 set_printer_location(http_t
*http
, /* I - Server connection */
1580 char *printer
, /* I - Printer */
1581 char *location
) /* I - New location string */
1583 ipp_t
*request
, /* IPP Request */
1584 *response
; /* IPP Response */
1585 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1588 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1592 * Build a CUPS_ADD_PRINTER request, which requires the following
1595 * attributes-charset
1596 * attributes-natural-language
1600 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1602 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1603 "localhost", 0, "/printers/%s", printer
);
1604 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1605 "printer-uri", NULL
, uri
);
1608 * Add the location string...
1611 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1615 * Do the request and get back a response...
1618 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1620 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1624 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1626 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1628 ippDelete(response
);
1634 ippDelete(response
);
1642 * 'set_printer_model()' - Set the driver model file.
1645 static int /* O - 0 on success, 1 on fail */
1646 set_printer_model(http_t
*http
, /* I - Server connection */
1647 char *printer
, /* I - Printer */
1648 char *model
) /* I - Driver model file */
1650 ipp_t
*request
, /* IPP Request */
1651 *response
; /* IPP Response */
1652 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1656 * Build a CUPS_ADD_PRINTER request, which requires the following
1659 * attributes-charset
1660 * attributes-natural-language
1665 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1667 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1668 "localhost", 0, "/printers/%s", printer
);
1669 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1670 "printer-uri", NULL
, uri
);
1672 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1673 "ppd-name", NULL
, model
);
1676 * Do the request and get back a response...
1679 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1681 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1685 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1687 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1689 ippDelete(response
);
1695 ippDelete(response
);
1703 * 'set_printer_options()' - Set the printer options.
1706 static int /* O - 0 on success, 1 on fail */
1707 set_printer_options(
1708 http_t
*http
, /* I - Server connection */
1709 char *printer
, /* I - Printer */
1710 int num_options
, /* I - Number of options */
1711 cups_option_t
*options
) /* I - Options */
1713 ipp_t
*request
, /* IPP Request */
1714 *response
; /* IPP Response */
1715 ipp_attribute_t
*attr
; /* IPP attribute */
1716 ipp_op_t op
; /* Operation to perform */
1717 const char *ppdfile
; /* PPD filename */
1718 int ppdchanged
; /* PPD changed? */
1719 ppd_file_t
*ppd
; /* PPD file */
1720 ppd_choice_t
*choice
; /* Marked choice */
1721 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1722 line
[1024], /* Line from PPD file */
1723 keyword
[1024], /* Keyword from Default line */
1724 *keyptr
, /* Pointer into keyword... */
1725 tempfile
[1024]; /* Temporary filename */
1726 FILE *in
, /* PPD file */
1727 *out
; /* Temporary file */
1728 int outfd
; /* Temporary file descriptor */
1729 const char *protocol
; /* Old protocol option */
1732 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1733 num_options
, options
));
1735 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1736 "localhost", 0, "/printers/%s", printer
);
1739 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1742 * attributes-charset
1743 * attributes-natural-language
1745 * requested-attributes
1748 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1750 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1751 "printer-uri", NULL
, uri
);
1753 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1754 "requested-attributes", NULL
, "printer-type");
1760 op
= CUPS_ADD_PRINTER
;
1762 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1765 * See what kind of printer or class it is...
1768 if ((attr
= ippFindAttribute(response
, "printer-type",
1769 IPP_TAG_ENUM
)) != NULL
)
1771 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1773 op
= CUPS_ADD_CLASS
;
1774 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1775 "localhost", 0, "/classes/%s", printer
);
1779 ippDelete(response
);
1783 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1784 * the following attributes:
1786 * attributes-charset
1787 * attributes-natural-language
1792 request
= ippNewRequest(op
);
1794 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1795 "printer-uri", NULL
, uri
);
1798 * Add the options...
1801 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1803 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1805 if (!strcasecmp(protocol
, "bcp"))
1806 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1808 else if (!strcasecmp(protocol
, "tbcp"))
1809 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1813 if (op
== CUPS_ADD_PRINTER
)
1814 ppdfile
= cupsGetPPD(printer
);
1818 if (ppdfile
!= NULL
)
1821 * Set default options in the PPD file...
1824 ppd
= ppdOpenFile(ppdfile
);
1825 ppdMarkDefaults(ppd
);
1826 cupsMarkOptions(ppd
, num_options
, options
);
1828 if ((outfd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1830 _cupsLangPrintf(stderr
,
1831 _("lpadmin: Unable to create temporary file - %s\n"),
1838 if ((in
= fopen(ppdfile
, "rb")) == NULL
)
1840 _cupsLangPrintf(stderr
,
1841 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1842 ppdfile
, strerror(errno
));
1850 out
= fdopen(outfd
, "wb");
1853 while (get_line(line
, sizeof(line
), in
) != NULL
)
1855 if (strncmp(line
, "*Default", 8))
1856 fprintf(out
, "%s\n", line
);
1860 * Get default option name...
1863 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1865 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1866 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1870 while (isspace(*keyptr
& 255))
1873 if (!strcmp(keyword
, "PageRegion") ||
1874 !strcmp(keyword
, "PageSize") ||
1875 !strcmp(keyword
, "PaperDimension") ||
1876 !strcmp(keyword
, "ImageableArea"))
1878 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1879 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1882 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1884 if (choice
&& strcmp(choice
->choice
, keyptr
))
1886 fprintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1890 fprintf(out
, "%s\n", line
);
1903 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1904 ppdchanged
? tempfile
: NULL
));
1907 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1917 * No PPD file - just set the options...
1920 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1924 * Check the response...
1927 if (cupsLastError() > IPP_OK_CONFLICT
)
1929 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1939 * 'validate_name()' - Make sure the printer name only contains valid chars.
1942 static int /* O - 0 if name is no good, 1 if name is good */
1943 validate_name(const char *name
) /* I - Name to check */
1945 const char *ptr
; /* Pointer into name */
1949 * Scan the whole name...
1952 for (ptr
= name
; *ptr
; ptr
++)
1955 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1960 * All the characters are good; validate the length, too...
1963 return ((ptr
- name
) < 128);
1968 * End of "$Id: lpadmin.c 5154 2006-02-23 01:36:15Z mike $".