2 * "$Id: lpadmin.c 5545 2006-05-18 21:00:56Z 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' : /* Username */
470 if (argv
[i
][2] != '\0')
471 cupsSetUser(argv
[i
] + 2);
477 _cupsLangPrintf(stderr
,
478 _("%s: Error - expected username after "
484 cupsSetUser(argv
[i
]);
488 case 'u' : /* Allow/deny users */
497 _cupsLangPuts(stderr
,
498 _("lpadmin: Expected allow/deny:userlist after "
499 "\'-u\' option!\n"));
506 if (!strncasecmp(val
, "allow:", 6))
507 num_options
= cupsAddOption("requesting-user-name-allowed",
508 val
+ 6, num_options
, &options
);
509 else if (!strncasecmp(val
, "deny:", 5))
510 num_options
= cupsAddOption("requesting-user-name-denied",
511 val
+ 5, num_options
, &options
);
514 _cupsLangPrintf(stderr
,
515 _("lpadmin: Unknown allow/deny option \"%s\"!\n"),
521 case 'v' : /* Set the device-uri attribute */
524 http
= httpConnectEncrypt(cupsServer(), ippPort(),
529 _cupsLangPrintf(stderr
,
530 _("lpadmin: Unable to connect to server: %s\n"),
538 _cupsLangPuts(stderr
,
539 _("lpadmin: Unable to set the device URI:\n"
540 " You must specify a printer name "
547 if (set_printer_device(http
, printer
, argv
[i
] + 2))
556 _cupsLangPuts(stderr
,
557 _("lpadmin: Expected device URI after \'-v\' "
562 if (set_printer_device(http
, printer
, argv
[i
]))
567 case 'x' : /* Delete a printer */
570 http
= httpConnectEncrypt(cupsServer(), ippPort(),
575 _cupsLangPrintf(stderr
,
576 _("lpadmin: Unable to connect to server: %s\n"),
583 printer
= argv
[i
] + 2;
590 _cupsLangPuts(stderr
,
591 _("lpadmin: Expected printer or class after "
592 "\'-x\' option!\n"));
599 if (!validate_name(printer
))
601 _cupsLangPuts(stderr
,
602 _("lpadmin: Printer name can only contain "
603 "printable characters!\n"));
607 if (delete_printer(http
, printer
))
613 case 'D' : /* Set the printer-info attribute */
616 http
= httpConnectEncrypt(cupsServer(), ippPort(),
621 _cupsLangPrintf(stderr
,
622 _("lpadmin: Unable to connect to server: %s\n"),
630 _cupsLangPuts(stderr
,
631 _("lpadmin: Unable to set the printer "
633 " You must specify a printer name "
640 if (set_printer_info(http
, printer
, argv
[i
] + 2))
649 _cupsLangPuts(stderr
,
650 _("lpadmin: Expected description after "
651 "\'-D\' option!\n"));
655 if (set_printer_info(http
, printer
, argv
[i
]))
660 case 'I' : /* Set the supported file types (ignored) */
665 _cupsLangPuts(stderr
,
666 _("lpadmin: Expected file type(s) after \'-I\' "
671 _cupsLangPuts(stderr
,
672 _("lpadmin: Warning - content type list ignored!\n"));
675 case 'L' : /* Set the printer-location attribute */
678 http
= httpConnectEncrypt(cupsServer(), ippPort(),
683 _cupsLangPrintf(stderr
,
684 _("lpadmin: Unable to connect to server: %s\n"),
692 _cupsLangPuts(stderr
,
693 _("lpadmin: Unable to set the printer location:\n"
694 " You must specify a printer name "
701 if (set_printer_location(http
, printer
, argv
[i
] + 2))
710 _cupsLangPuts(stderr
,
711 _("lpadmin: Expected location after \'-L\' "
716 if (set_printer_location(http
, printer
, argv
[i
]))
721 case 'P' : /* Use the specified PPD file */
724 http
= httpConnectEncrypt(cupsServer(), ippPort(),
729 _cupsLangPrintf(stderr
,
730 _("lpadmin: Unable to connect to server: %s\n"),
738 _cupsLangPuts(stderr
,
739 _("lpadmin: Unable to set the PPD file:\n"
740 " You must specify a printer name "
747 if (set_printer_file(http
, printer
, argv
[i
] + 2))
756 _cupsLangPuts(stderr
,
757 _("lpadmin: Expected PPD after \'-P\' option!\n"));
761 if (set_printer_file(http
, printer
, argv
[i
]))
767 _cupsLangPrintf(stderr
,
768 _("lpadmin: Unknown option \'%c\'!\n"), argv
[i
][1]);
773 _cupsLangPrintf(stderr
, _("lpadmin: Unknown argument \'%s\'!\n"),
779 * Set options as needed...
786 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
790 _cupsLangPrintf(stderr
,
791 _("lpadmin: Unable to connect to server: %s\n"),
799 _cupsLangPuts(stderr
,
800 _("lpadmin: Unable to set the printer options:\n"
801 " You must specify a printer name first!\n"));
805 if (set_printer_options(http
, printer
, num_options
, options
))
811 _cupsLangPuts(stdout
,
814 " lpadmin [-h server] -d destination\n"
815 " lpadmin [-h server] -x destination\n"
816 " lpadmin [-h server] -p printer [-c add-class] "
817 "[-i interface] [-m model]\n"
818 " [-r remove-class] [-v device] "
820 " [-P ppd-file] [-o name=value]\n"
821 " [-u allow:user,user] "
822 "[-u deny:user,user]\n"
834 * 'add_printer_to_class()' - Add a printer to a class.
837 static int /* O - 0 on success, 1 on fail */
838 add_printer_to_class(http_t
*http
, /* I - Server connection */
839 char *printer
, /* I - Printer to add */
840 char *pclass
) /* I - Class to add to */
842 int i
; /* Looping var */
843 ipp_t
*request
, /* IPP Request */
844 *response
; /* IPP Response */
845 ipp_attribute_t
*attr
, /* Current attribute */
846 *members
; /* Members in class */
847 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
850 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
854 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
858 * attributes-natural-language
862 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
864 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
865 "localhost", 0, "/classes/%s", pclass
);
866 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
867 "printer-uri", NULL
, uri
);
870 * Do the request and get back a response...
873 response
= cupsDoRequest(http
, request
, "/");
876 * Build a CUPS_ADD_CLASS request, which requires the following
880 * attributes-natural-language
885 request
= ippNewRequest(CUPS_ADD_CLASS
);
887 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
888 "printer-uri", NULL
, uri
);
891 * See if the printer is already in the class...
894 if (response
!= NULL
&&
895 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
896 for (i
= 0; i
< members
->num_values
; i
++)
897 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
899 _cupsLangPrintf(stderr
,
900 _("lpadmin: Printer %s is already a member of class %s.\n"),
908 * OK, the printer isn't part of the class, so add it...
911 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
912 "localhost", 0, "/printers/%s", printer
);
914 if (response
!= NULL
&&
915 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
918 * Add the printer to the existing list...
921 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
922 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
923 for (i
= 0; i
< members
->num_values
; i
++)
924 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
926 attr
->values
[i
].string
.text
= strdup(uri
);
929 attr
= ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
932 * Then send the request...
937 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
939 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
943 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
945 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
961 * 'default_printer()' - Set the default printing destination.
964 static int /* O - 0 on success, 1 on fail */
965 default_printer(http_t
*http
, /* I - Server connection */
966 char *printer
) /* I - Printer name */
968 ipp_t
*request
, /* IPP Request */
969 *response
; /* IPP Response */
970 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
973 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
976 * Build a CUPS_SET_DEFAULT request, which requires the following
980 * attributes-natural-language
984 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
985 "localhost", 0, "/printers/%s", printer
);
987 request
= ippNewRequest(CUPS_SET_DEFAULT
);
989 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
990 "printer-uri", NULL
, uri
);
993 * Do the request and get back a response...
996 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
998 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1002 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1004 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1006 ippDelete(response
);
1012 ippDelete(response
);
1020 * 'delete_printer()' - Delete a printer from the system...
1023 static int /* O - 0 on success, 1 on fail */
1024 delete_printer(http_t
*http
, /* I - Server connection */
1025 char *printer
) /* I - Printer to delete */
1027 ipp_t
*request
, /* IPP Request */
1028 *response
; /* IPP Response */
1029 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1032 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
1035 * Build a CUPS_DELETE_PRINTER request, which requires the following
1038 * attributes-charset
1039 * attributes-natural-language
1043 request
= ippNewRequest(CUPS_DELETE_PRINTER
);
1045 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1046 "localhost", 0, "/printers/%s", printer
);
1047 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1048 "printer-uri", NULL
, uri
);
1051 * Do the request and get back a response...
1054 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1056 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1060 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1062 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1064 ippDelete(response
);
1070 ippDelete(response
);
1078 * 'delete_printer_from_class()' - Delete a printer from a class.
1081 static int /* O - 0 on success, 1 on fail */
1082 delete_printer_from_class(
1083 http_t
*http
, /* I - Server connection */
1084 char *printer
, /* I - Printer to remove */
1085 char *pclass
) /* I - Class to remove from */
1087 int i
, j
, k
; /* Looping vars */
1088 ipp_t
*request
, /* IPP Request */
1089 *response
; /* IPP Response */
1090 ipp_attribute_t
*attr
, /* Current attribute */
1091 *members
; /* Members in class */
1092 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1095 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
1099 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1102 * attributes-charset
1103 * attributes-natural-language
1107 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1109 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1110 "localhost", 0, "/classes/%s", pclass
);
1111 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1112 "printer-uri", NULL
, uri
);
1115 * Do the request and get back a response...
1118 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1119 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1121 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1123 ippDelete(response
);
1129 * See if the printer is already in the class...
1132 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1134 _cupsLangPuts(stderr
, _("lpadmin: No member names were seen!\n"));
1136 ippDelete(response
);
1141 for (i
= 0; i
< members
->num_values
; i
++)
1142 if (!strcasecmp(printer
, members
->values
[i
].string
.text
))
1145 if (i
>= members
->num_values
)
1147 _cupsLangPrintf(stderr
,
1148 _("lpadmin: Printer %s is not a member of class %s.\n"),
1151 ippDelete(response
);
1156 if (members
->num_values
== 1)
1159 * Build a CUPS_DELETE_CLASS request, which requires the following
1162 * attributes-charset
1163 * attributes-natural-language
1167 request
= ippNewRequest(CUPS_DELETE_CLASS
);
1169 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1170 "printer-uri", NULL
, uri
);
1175 * Build a CUPS_ADD_CLASS request, which requires the following
1178 * attributes-charset
1179 * attributes-natural-language
1184 request
= ippNewRequest(CUPS_ADD_CLASS
);
1186 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1187 "printer-uri", NULL
, uri
);
1190 * Delete the printer from the class...
1193 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1194 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1195 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1197 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1199 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1203 * Then send the request...
1206 ippDelete(response
);
1208 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1210 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1214 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1216 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1218 ippDelete(response
);
1224 ippDelete(response
);
1232 * 'enable_printer()' - Enable a printer...
1235 static int /* O - 0 on success, 1 on fail */
1236 enable_printer(http_t
*http
, /* I - Server connection */
1237 char *printer
) /* I - Printer to enable */
1239 ipp_t
*request
, /* IPP Request */
1240 *response
; /* IPP Response */
1241 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1244 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1247 * Build a CUPS_ADD_PRINTER request, which requires the following
1250 * attributes-charset
1251 * attributes-natural-language
1254 * printer-is-accepting-jobs
1257 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1259 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1260 "localhost", 0, "/printers/%s", printer
);
1261 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1262 "printer-uri", NULL
, uri
);
1264 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1267 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1270 * Do the request and get back a response...
1273 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1275 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1279 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1281 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1283 ippDelete(response
);
1289 ippDelete(response
);
1297 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1300 static char * /* O - Pointer to buf or NULL on EOF */
1301 get_line(char *buf
, /* I - Line buffer */
1302 int length
, /* I - Length of buffer */
1303 FILE *fp
) /* I - File to read from */
1305 char *bufptr
; /* Pointer into buffer */
1306 int ch
; /* Character from file */
1312 while ((ch
= getc(fp
)) != EOF
)
1316 else if (ch
== '\r')
1323 if (ch
!= '\n' && ch
!= EOF
)
1345 * 'set_printer_device()' - Set the device-uri attribute.
1348 static int /* O - 0 on success, 1 on fail */
1349 set_printer_device(http_t
*http
, /* I - Server connection */
1350 char *printer
, /* I - Printer */
1351 char *device
) /* I - New device URI */
1353 ipp_t
*request
, /* IPP Request */
1354 *response
; /* IPP Response */
1355 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1358 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1362 * Build a CUPS_ADD_PRINTER request, which requires the following
1365 * attributes-charset
1366 * attributes-natural-language
1370 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1372 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1373 "localhost", 0, "/printers/%s", printer
);
1374 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1375 "printer-uri", NULL
, uri
);
1378 * Add the device URI...
1381 if (device
[0] == '/')
1384 * Convert filename to URI...
1387 snprintf(uri
, sizeof(uri
), "file://%s", device
);
1388 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1392 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1396 * Do the request and get back a response...
1399 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1401 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1405 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1407 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1409 ippDelete(response
);
1415 ippDelete(response
);
1423 * 'set_printer_file()' - Set the interface script or PPD file.
1426 static int /* O - 0 on success, 1 on fail */
1427 set_printer_file(http_t
*http
, /* I - Server connection */
1428 char *printer
, /* I - Printer */
1429 char *file
) /* I - PPD file or interface script */
1431 ipp_t
*request
, /* IPP Request */
1432 *response
; /* IPP Response */
1433 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1435 char tempfile
[1024]; /* Temporary filename */
1436 int fd
; /* Temporary file */
1437 gzFile
*gz
; /* GZIP'd file */
1438 char buffer
[8192]; /* Copy buffer */
1439 int bytes
; /* Bytes in buffer */
1442 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1446 * See if the file is gzip'd; if so, unzip it to a temporary file and
1447 * send the uncompressed file.
1450 if (!strcmp(file
+ strlen(file
) - 3, ".gz"))
1453 * Yes, the file is compressed; uncompress to a temp file...
1456 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1458 _cupsLangPrintf(stderr
,
1459 _("lpadmin: Unable to create temporary file: %s\n"),
1464 if ((gz
= gzopen(file
, "rb")) == NULL
)
1466 _cupsLangPrintf(stderr
,
1467 _("lpadmin: Unable to open file \"%s\": %s\n"),
1468 file
, strerror(errno
));
1474 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1475 write(fd
, buffer
, bytes
);
1482 #endif /* HAVE_LIBZ */
1485 * Build a CUPS_ADD_PRINTER request, which requires the following
1488 * attributes-charset
1489 * attributes-natural-language
1493 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1495 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1496 "localhost", 0, "/printers/%s", printer
);
1497 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1498 "printer-uri", NULL
, uri
);
1501 * Do the request and get back a response...
1504 response
= cupsDoFileRequest(http
, request
, "/admin/", file
);
1505 ippDelete(response
);
1509 * Remove the temporary file as needed...
1512 if (file
== tempfile
)
1514 #endif /* HAVE_LIBZ */
1516 if (cupsLastError() > IPP_OK_CONFLICT
)
1518 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1528 * 'set_printer_info()' - Set the printer description string.
1531 static int /* O - 0 on success, 1 on fail */
1532 set_printer_info(http_t
*http
, /* I - Server connection */
1533 char *printer
, /* I - Printer */
1534 char *info
) /* I - New description string */
1536 ipp_t
*request
, /* IPP Request */
1537 *response
; /* IPP Response */
1538 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1541 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1545 * Build a CUPS_ADD_PRINTER request, which requires the following
1548 * attributes-charset
1549 * attributes-natural-language
1553 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1555 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1556 "localhost", 0, "/printers/%s", printer
);
1557 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1558 "printer-uri", NULL
, uri
);
1561 * Add the info string...
1564 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1568 * Do the request and get back a response...
1571 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1573 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1576 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1578 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1580 ippDelete(response
);
1586 ippDelete(response
);
1594 * 'set_printer_location()' - Set the printer location string.
1597 static int /* O - 0 on success, 1 on fail */
1598 set_printer_location(http_t
*http
, /* I - Server connection */
1599 char *printer
, /* I - Printer */
1600 char *location
) /* I - New location string */
1602 ipp_t
*request
, /* IPP Request */
1603 *response
; /* IPP Response */
1604 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1607 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1611 * Build a CUPS_ADD_PRINTER request, which requires the following
1614 * attributes-charset
1615 * attributes-natural-language
1619 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1621 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1622 "localhost", 0, "/printers/%s", printer
);
1623 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1624 "printer-uri", NULL
, uri
);
1627 * Add the location string...
1630 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1634 * Do the request and get back a response...
1637 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1639 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1643 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1645 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1647 ippDelete(response
);
1653 ippDelete(response
);
1661 * 'set_printer_model()' - Set the driver model file.
1664 static int /* O - 0 on success, 1 on fail */
1665 set_printer_model(http_t
*http
, /* I - Server connection */
1666 char *printer
, /* I - Printer */
1667 char *model
) /* I - Driver model file */
1669 ipp_t
*request
, /* IPP Request */
1670 *response
; /* IPP Response */
1671 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1675 * Build a CUPS_ADD_PRINTER request, which requires the following
1678 * attributes-charset
1679 * attributes-natural-language
1684 request
= ippNewRequest(CUPS_ADD_PRINTER
);
1686 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1687 "localhost", 0, "/printers/%s", printer
);
1688 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1689 "printer-uri", NULL
, uri
);
1691 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1692 "ppd-name", NULL
, model
);
1695 * Do the request and get back a response...
1698 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1700 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1704 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1706 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1708 ippDelete(response
);
1714 ippDelete(response
);
1722 * 'set_printer_options()' - Set the printer options.
1725 static int /* O - 0 on success, 1 on fail */
1726 set_printer_options(
1727 http_t
*http
, /* I - Server connection */
1728 char *printer
, /* I - Printer */
1729 int num_options
, /* I - Number of options */
1730 cups_option_t
*options
) /* I - Options */
1732 ipp_t
*request
, /* IPP Request */
1733 *response
; /* IPP Response */
1734 ipp_attribute_t
*attr
; /* IPP attribute */
1735 ipp_op_t op
; /* Operation to perform */
1736 const char *ppdfile
; /* PPD filename */
1737 int ppdchanged
; /* PPD changed? */
1738 ppd_file_t
*ppd
; /* PPD file */
1739 ppd_choice_t
*choice
; /* Marked choice */
1740 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1741 line
[1024], /* Line from PPD file */
1742 keyword
[1024], /* Keyword from Default line */
1743 *keyptr
, /* Pointer into keyword... */
1744 tempfile
[1024]; /* Temporary filename */
1745 FILE *in
, /* PPD file */
1746 *out
; /* Temporary file */
1747 int outfd
; /* Temporary file descriptor */
1748 const char *protocol
; /* Old protocol option */
1751 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1752 num_options
, options
));
1754 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1755 "localhost", 0, "/printers/%s", printer
);
1758 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1761 * attributes-charset
1762 * attributes-natural-language
1764 * requested-attributes
1767 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
1769 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1770 "printer-uri", NULL
, uri
);
1772 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1773 "requested-attributes", NULL
, "printer-type");
1779 op
= CUPS_ADD_PRINTER
;
1781 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1784 * See what kind of printer or class it is...
1787 if ((attr
= ippFindAttribute(response
, "printer-type",
1788 IPP_TAG_ENUM
)) != NULL
)
1790 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1792 op
= CUPS_ADD_CLASS
;
1793 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
1794 "localhost", 0, "/classes/%s", printer
);
1798 ippDelete(response
);
1802 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1803 * the following attributes:
1805 * attributes-charset
1806 * attributes-natural-language
1811 request
= ippNewRequest(op
);
1813 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1814 "printer-uri", NULL
, uri
);
1817 * Add the options...
1820 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_PRINTER
);
1822 if ((protocol
= cupsGetOption("protocol", num_options
, options
)) != NULL
)
1824 if (!strcasecmp(protocol
, "bcp"))
1825 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1827 else if (!strcasecmp(protocol
, "tbcp"))
1828 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "port-monitor",
1832 if (op
== CUPS_ADD_PRINTER
)
1833 ppdfile
= cupsGetPPD(printer
);
1837 if (ppdfile
!= NULL
)
1840 * Set default options in the PPD file...
1843 ppd
= ppdOpenFile(ppdfile
);
1844 ppdMarkDefaults(ppd
);
1845 cupsMarkOptions(ppd
, num_options
, options
);
1847 if ((outfd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1849 _cupsLangPrintf(stderr
,
1850 _("lpadmin: Unable to create temporary file - %s\n"),
1857 if ((in
= fopen(ppdfile
, "rb")) == NULL
)
1859 _cupsLangPrintf(stderr
,
1860 _("lpadmin: Unable to open PPD file \"%s\" - %s\n"),
1861 ppdfile
, strerror(errno
));
1869 out
= fdopen(outfd
, "wb");
1872 while (get_line(line
, sizeof(line
), in
) != NULL
)
1874 if (strncmp(line
, "*Default", 8))
1875 fprintf(out
, "%s\n", line
);
1879 * Get default option name...
1882 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1884 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1885 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1889 while (isspace(*keyptr
& 255))
1892 if (!strcmp(keyword
, "PageRegion") ||
1893 !strcmp(keyword
, "PageSize") ||
1894 !strcmp(keyword
, "PaperDimension") ||
1895 !strcmp(keyword
, "ImageableArea"))
1897 if ((choice
= ppdFindMarkedChoice(ppd
, "PageSize")) == NULL
)
1898 choice
= ppdFindMarkedChoice(ppd
, "PageRegion");
1901 choice
= ppdFindMarkedChoice(ppd
, keyword
);
1903 if (choice
&& strcmp(choice
->choice
, keyptr
))
1905 fprintf(out
, "*Default%s: %s\n", keyword
, choice
->choice
);
1909 fprintf(out
, "%s\n", line
);
1922 ippDelete(cupsDoFileRequest(http
, request
, "/admin/",
1923 ppdchanged
? tempfile
: NULL
));
1926 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1936 * No PPD file - just set the options...
1939 ippDelete(cupsDoRequest(http
, request
, "/admin/"));
1943 * Check the response...
1946 if (cupsLastError() > IPP_OK_CONFLICT
)
1948 _cupsLangPrintf(stderr
, "lpadmin: %s\n", cupsLastErrorString());
1958 * 'validate_name()' - Make sure the printer name only contains valid chars.
1961 static int /* O - 0 if name is no good, 1 if name is good */
1962 validate_name(const char *name
) /* I - Name to check */
1964 const char *ptr
; /* Pointer into name */
1968 * Scan the whole name...
1971 for (ptr
= name
; *ptr
; ptr
++)
1974 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/' ||
1979 * All the characters are good; validate the length, too...
1982 return ((ptr
- name
) < 128);
1987 * End of "$Id: lpadmin.c 5545 2006-05-18 21:00:56Z mike $".