2 * "$Id: lpadmin.c,v 1.44 2004/02/25 20:14:54 mike Exp $"
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2004 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-3111 USA
20 * Voice: (301) 373-9603
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/cups.h>
51 #include <cups/string.h>
52 #include <cups/language.h>
53 #include <cups/debug.h>
57 #endif /* HAVE_LIBZ */
64 static int add_printer_to_class(http_t
*, char *, char *);
65 static int default_printer(http_t
*, char *);
66 static int delete_printer(http_t
*, char *);
67 static int delete_printer_from_class(http_t
*, char *, char *);
68 static int enable_printer(http_t
*, char *);
69 static char *get_line(char *, int, FILE *fp
);
70 static int set_printer_device(http_t
*, char *, char *);
71 static int set_printer_file(http_t
*, char *, char *);
72 static int set_printer_info(http_t
*, char *, char *);
73 static int set_printer_location(http_t
*, char *, char *);
74 static int set_printer_model(http_t
*, char *, char *);
75 static int set_printer_options(http_t
*, char *, int, cups_option_t
*);
76 static int validate_name(const char *);
80 * 'main()' - Parse options and configure the scheduler.
84 main(int argc
, /* I - Number of command-line arguments */
85 char *argv
[]) /* I - Command-line arguments */
87 int i
; /* Looping var */
88 http_t
*http
; /* Connection to server */
89 char *printer
, /* Destination printer */
90 *pclass
, /* Printer class name */
91 *val
; /* Pointer to allow/deny value */
92 int num_options
; /* Number of options */
93 cups_option_t
*options
; /* Options */
101 for (i
= 1; i
< argc
; i
++)
102 if (argv
[i
][0] == '-')
105 case 'c' : /* Add printer to class */
108 http
= httpConnectEncrypt(cupsServer(), ippPort(),
113 perror("lpadmin: Unable to connect to server");
120 fputs("lpadmin: Unable to add a printer to the class:\n", stderr
);
121 fputs(" You must specify a printer name first!\n", stderr
);
126 pclass
= argv
[i
] + 2;
133 fputs("lpadmin: Expected class name after \'-c\' option!\n", stderr
);
140 if (!validate_name(pclass
))
142 fputs("lpadmin: Class name can only contain printable characters!\n", stderr
);
146 if (add_printer_to_class(http
, printer
, pclass
))
150 case 'd' : /* Set as default destination */
153 http
= httpConnectEncrypt(cupsServer(), ippPort(),
158 perror("lpadmin: Unable to connect to server");
164 printer
= argv
[i
] + 2;
171 fputs("lpadmin: Expected printer name after \'-d\' option!\n", stderr
);
178 if (!validate_name(printer
))
180 fputs("lpadmin: Printer name can only contain printable characters!\n", stderr
);
184 if (default_printer(http
, printer
))
190 case 'h' : /* Connect to host */
197 if (argv
[i
][2] != '\0')
198 cupsSetServer(argv
[i
] + 2);
205 fputs("lpadmin: Expected hostname after \'-h\' option!\n", stderr
);
209 cupsSetServer(argv
[i
]);
213 case 'i' : /* Use the specified interface script */
216 http
= httpConnectEncrypt(cupsServer(), ippPort(),
221 perror("lpadmin: Unable to connect to server");
228 fputs("lpadmin: Unable to set the interface script:\n", stderr
);
229 fputs(" You must specify a printer name first!\n", stderr
);
235 if (set_printer_file(http
, printer
, argv
[i
] + 2))
244 fputs("lpadmin: Expected interface after \'-i\' option!\n", stderr
);
248 if (set_printer_file(http
, printer
, argv
[i
]))
253 case 'E' : /* Enable the printer */
257 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
260 httpEncryption(http
, HTTP_ENCRYPT_REQUIRED
);
262 fprintf(stderr
, "%s: Sorry, no encryption support compiled in!\n",
264 #endif /* HAVE_SSL */
270 http
= httpConnectEncrypt(cupsServer(), ippPort(),
275 perror("lpadmin: Unable to connect to server");
280 if (enable_printer(http
, printer
))
284 case 'm' : /* Use the specified standard script/PPD file */
287 http
= httpConnectEncrypt(cupsServer(), ippPort(),
292 perror("lpadmin: Unable to connect to server");
299 fputs("lpadmin: Unable to set the interface script or PPD file:\n", stderr
);
300 fputs(" You must specify a printer name first!\n", stderr
);
306 if (set_printer_model(http
, printer
, argv
[i
] + 2))
315 fputs("lpadmin: Expected model after \'-m\' option!\n", stderr
);
319 if (set_printer_model(http
, printer
, argv
[i
]))
324 case 'o' : /* Set option */
326 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
333 fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr
);
337 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
341 case 'p' : /* Add/modify a printer */
344 http
= httpConnectEncrypt(cupsServer(), ippPort(),
349 perror("lpadmin: Unable to connect to server");
355 printer
= argv
[i
] + 2;
362 fputs("lpadmin: Expected printer after \'-p\' option!\n", stderr
);
369 if (!validate_name(printer
))
371 fputs("lpadmin: Printer name can only contain printable characters!\n", stderr
);
376 case 'r' : /* Remove printer from class */
379 http
= httpConnectEncrypt(cupsServer(), ippPort(),
384 perror("lpadmin: Unable to connect to server");
391 fputs("lpadmin: Unable to remove a printer from the class:\n", stderr
);
392 fputs(" You must specify a printer name first!\n", stderr
);
397 pclass
= argv
[i
] + 2;
404 fputs("lpadmin: Expected class after \'-r\' option!\n", stderr
);
411 if (!validate_name(pclass
))
413 fputs("lpadmin: Class name can only contain printable characters!\n", stderr
);
417 if (delete_printer_from_class(http
, printer
, pclass
))
421 case 'u' : /* Allow/deny users */
430 fputs("lpadmin: Expected allow/deny:userlist after \'-u\' option!\n", stderr
);
437 if (strncasecmp(val
, "allow:", 6) == 0)
438 num_options
= cupsAddOption("requesting-user-name-allowed",
439 val
+ 6, num_options
, &options
);
440 else if (strncasecmp(val
, "deny:", 5) == 0)
441 num_options
= cupsAddOption("requesting-user-name-denied",
442 val
+ 5, num_options
, &options
);
445 fprintf(stderr
, "lpadmin: Unknown allow/deny option \"%s\"!\n",
451 case 'v' : /* Set the device-uri attribute */
454 http
= httpConnectEncrypt(cupsServer(), ippPort(),
459 perror("lpadmin: Unable to connect to server");
466 fputs("lpadmin: Unable to set the device URI:\n", stderr
);
467 fputs(" You must specify a printer name first!\n", stderr
);
473 if (set_printer_device(http
, printer
, argv
[i
] + 2))
482 fputs("lpadmin: Expected device URI after \'-v\' option!\n", stderr
);
486 if (set_printer_device(http
, printer
, argv
[i
]))
491 case 'x' : /* Delete a printer */
494 http
= httpConnectEncrypt(cupsServer(), ippPort(),
499 perror("lpadmin: Unable to connect to server");
505 printer
= argv
[i
] + 2;
512 fputs("lpadmin: Expected printer or class after \'-x\' option!\n", stderr
);
519 if (!validate_name(printer
))
521 fputs("lpadmin: Printer name can only contain printable characters!\n", stderr
);
525 if (delete_printer(http
, printer
))
531 case 'D' : /* Set the printer-info attribute */
534 http
= httpConnectEncrypt(cupsServer(), ippPort(),
539 perror("lpadmin: Unable to connect to server");
546 fputs("lpadmin: Unable to set the printer description:\n", stderr
);
547 fputs(" You must specify a printer name first!\n", stderr
);
553 if (set_printer_info(http
, printer
, argv
[i
] + 2))
562 fputs("lpadmin: Expected description after \'-D\' option!\n", stderr
);
566 if (set_printer_info(http
, printer
, argv
[i
]))
571 case 'I' : /* Set the supported file types (ignored) */
576 fputs("lpadmin: Expected file type(s) after \'-I\' option!\n", stderr
);
580 fputs("lpadmin: Warning - content type list ignored!\n", stderr
);
583 case 'L' : /* Set the printer-location attribute */
586 http
= httpConnectEncrypt(cupsServer(), ippPort(),
591 perror("lpadmin: Unable to connect to server");
598 fputs("lpadmin: Unable to set the printer location:\n", stderr
);
599 fputs(" You must specify a printer name first!\n", stderr
);
605 if (set_printer_location(http
, printer
, argv
[i
] + 2))
614 fputs("lpadmin: Expected location after \'-L\' option!\n", stderr
);
618 if (set_printer_location(http
, printer
, argv
[i
]))
623 case 'P' : /* Use the specified PPD file */
626 http
= httpConnectEncrypt(cupsServer(), ippPort(),
631 perror("lpadmin: Unable to connect to server");
638 fputs("lpadmin: Unable to set the PPD file:\n", stderr
);
639 fputs(" You must specify a printer name first!\n", stderr
);
645 if (set_printer_file(http
, printer
, argv
[i
] + 2))
654 fputs("lpadmin: Expected PPD after \'-P\' option!\n", stderr
);
658 if (set_printer_file(http
, printer
, argv
[i
]))
664 fprintf(stderr
, "lpadmin: Unknown option \'%c\'!\n", argv
[i
][1]);
669 fprintf(stderr
, "lpadmin: Unknown argument \'%s\'!\n", argv
[i
]);
674 * Set options as needed...
681 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
685 perror("lpadmin: Unable to connect to server");
692 fputs("lpadmin: Unable to set the printer options:\n", stderr
);
693 fputs(" You must specify a printer name first!\n", stderr
);
697 if (set_printer_options(http
, printer
, num_options
, options
))
705 puts(" lpadmin [-h server] -d destination");
706 puts(" lpadmin [-h server] -x destination");
707 puts(" lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]");
708 puts(" [-r remove-class] [-v device] [-D description]");
709 puts(" [-P ppd-file] [-o name=value]");
710 puts(" [-u allow:user,user] [-u deny:user,user]");
722 * 'add_printer_to_class()' - Add a printer to a class.
725 static int /* O - 0 on success, 1 on fail */
726 add_printer_to_class(http_t
*http
, /* I - Server connection */
727 char *printer
, /* I - Printer to add */
728 char *pclass
) /* I - Class to add to */
730 int i
; /* Looping var */
731 ipp_t
*request
, /* IPP Request */
732 *response
; /* IPP Response */
733 ipp_attribute_t
*attr
, /* Current attribute */
734 *members
; /* Members in class */
735 cups_lang_t
*language
; /* Default language */
736 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
739 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
743 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
747 * attributes-natural-language
751 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
755 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
756 request
->request
.op
.request_id
= 1;
758 language
= cupsLangDefault();
760 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
761 "attributes-charset", NULL
, cupsLangEncoding(language
));
763 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
764 "attributes-natural-language", NULL
, language
->language
);
766 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
767 "printer-uri", NULL
, uri
);
770 * Do the request and get back a response...
773 response
= cupsDoRequest(http
, request
, "/");
776 * Build a CUPS_ADD_CLASS request, which requires the following
780 * attributes-natural-language
787 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
788 request
->request
.op
.request_id
= 1;
790 language
= cupsLangDefault();
792 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
793 "attributes-charset", NULL
, cupsLangEncoding(language
));
795 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
796 "attributes-natural-language", NULL
, language
->language
);
798 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
799 "printer-uri", NULL
, uri
);
802 * See if the printer is already in the class...
805 if (response
!= NULL
&&
806 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
807 for (i
= 0; i
< members
->num_values
; i
++)
808 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
810 fprintf(stderr
, "lpadmin: Printer %s is already a member of class %s.\n",
818 * OK, the printer isn't part of the class, so add it...
821 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
823 if (response
!= NULL
&&
824 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
827 * Add the printer to the existing list...
830 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
831 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
832 for (i
= 0; i
< members
->num_values
; i
++)
833 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
835 attr
->values
[i
].string
.text
= strdup(uri
);
838 attr
= ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
841 * Then send the request...
846 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
848 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
849 ippErrorString(cupsLastError()));
853 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
855 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
856 ippErrorString(response
->request
.status
.status_code
));
872 * 'default_printer()' - Set the default printing destination.
875 static int /* O - 0 on success, 1 on fail */
876 default_printer(http_t
*http
, /* I - Server connection */
877 char *printer
) /* I - Printer name */
879 ipp_t
*request
, /* IPP Request */
880 *response
; /* IPP Response */
881 cups_lang_t
*language
; /* Default language */
882 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
885 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
888 * Build a CUPS_SET_DEFAULT request, which requires the following
892 * attributes-natural-language
896 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
900 request
->request
.op
.operation_id
= CUPS_SET_DEFAULT
;
901 request
->request
.op
.request_id
= 1;
903 language
= cupsLangDefault();
905 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
906 "attributes-charset", NULL
, cupsLangEncoding(language
));
908 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
909 "attributes-natural-language", NULL
, language
->language
);
911 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
912 "printer-uri", NULL
, uri
);
915 * Do the request and get back a response...
918 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
920 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
921 ippErrorString(cupsLastError()));
925 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
927 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
928 ippErrorString(response
->request
.status
.status_code
));
944 * 'delete_printer()' - Delete a printer from the system...
947 static int /* O - 0 on success, 1 on fail */
948 delete_printer(http_t
*http
, /* I - Server connection */
949 char *printer
) /* I - Printer to delete */
951 ipp_t
*request
, /* IPP Request */
952 *response
; /* IPP Response */
953 cups_lang_t
*language
; /* Default language */
954 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
957 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
960 * Build a CUPS_DELETE_PRINTER request, which requires the following
964 * attributes-natural-language
968 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
972 request
->request
.op
.operation_id
= CUPS_DELETE_PRINTER
;
973 request
->request
.op
.request_id
= 1;
975 language
= cupsLangDefault();
977 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
978 "attributes-charset", NULL
, cupsLangEncoding(language
));
980 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
981 "attributes-natural-language", NULL
, language
->language
);
983 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
984 "printer-uri", NULL
, uri
);
987 * Do the request and get back a response...
990 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
992 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
993 ippErrorString(cupsLastError()));
997 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
999 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
1000 ippErrorString(response
->request
.status
.status_code
));
1002 ippDelete(response
);
1008 ippDelete(response
);
1016 * 'delete_printer_from_class()' - Delete a printer from a class.
1019 static int /* O - 0 on success, 1 on fail */
1020 delete_printer_from_class(http_t
*http
, /* I - Server connection */
1022 /* I - Printer to remove */
1024 /* I - Class to remove from */
1026 int i
, j
, k
; /* Looping vars */
1027 ipp_t
*request
, /* IPP Request */
1028 *response
; /* IPP Response */
1029 ipp_attribute_t
*attr
, /* Current attribute */
1030 *members
; /* Members in class */
1031 cups_lang_t
*language
; /* Default language */
1032 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1035 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
1039 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1042 * attributes-charset
1043 * attributes-natural-language
1047 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
1051 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
1052 request
->request
.op
.request_id
= 1;
1054 language
= cupsLangDefault();
1056 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1057 "attributes-charset", NULL
, cupsLangEncoding(language
));
1059 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1060 "attributes-natural-language", NULL
, language
->language
);
1062 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1063 "printer-uri", NULL
, uri
);
1066 * Do the request and get back a response...
1069 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1070 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1072 ippDelete(response
);
1073 fprintf(stderr
, "lpadmin: Class %s does not exist!\n", pclass
);
1078 * See if the printer is already in the class...
1081 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1083 ippDelete(response
);
1084 fputs("lpadmin: No member names were seen!\n", stderr
);
1088 for (i
= 0; i
< members
->num_values
; i
++)
1089 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
1092 if (i
>= members
->num_values
)
1094 fprintf(stderr
, "lpadmin: Printer %s is not a member of class %s.\n",
1096 ippDelete(response
);
1100 if (members
->num_values
== 1)
1103 * Build a CUPS_DELETE_CLASS request, which requires the following
1106 * attributes-charset
1107 * attributes-natural-language
1113 request
->request
.op
.operation_id
= CUPS_DELETE_CLASS
;
1114 request
->request
.op
.request_id
= 1;
1116 language
= cupsLangDefault();
1118 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1119 "attributes-charset", NULL
, cupsLangEncoding(language
));
1121 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1122 "attributes-natural-language", NULL
, language
->language
);
1124 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1125 "printer-uri", NULL
, uri
);
1130 * Build a CUPS_ADD_CLASS request, which requires the following
1133 * attributes-charset
1134 * attributes-natural-language
1141 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
1142 request
->request
.op
.request_id
= 1;
1144 language
= cupsLangDefault();
1146 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1147 "attributes-charset", NULL
, cupsLangEncoding(language
));
1149 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1150 "attributes-natural-language", NULL
, language
->language
);
1152 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1153 "printer-uri", NULL
, uri
);
1156 * Delete the printer from the class...
1159 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1160 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1161 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1163 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1165 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1169 * Then send the request...
1172 ippDelete(response
);
1174 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1176 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1177 ippErrorString(cupsLastError()));
1180 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1182 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1183 ippErrorString(response
->request
.status
.status_code
));
1185 ippDelete(response
);
1191 ippDelete(response
);
1199 * 'enable_printer()' - Enable a printer...
1202 static int /* O - 0 on success, 1 on fail */
1203 enable_printer(http_t
*http
, /* I - Server connection */
1204 char *printer
) /* I - Printer to enable */
1206 ipp_t
*request
, /* IPP Request */
1207 *response
; /* IPP Response */
1208 cups_lang_t
*language
; /* Default language */
1209 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1212 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1215 * Build a CUPS_ADD_PRINTER request, which requires the following
1218 * attributes-charset
1219 * attributes-natural-language
1222 * printer-is-accepting-jobs
1225 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1229 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1230 request
->request
.op
.request_id
= 1;
1232 language
= cupsLangDefault();
1234 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1235 "attributes-charset", NULL
, cupsLangEncoding(language
));
1237 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1238 "attributes-natural-language", NULL
, language
->language
);
1240 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1241 "printer-uri", NULL
, uri
);
1243 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1246 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1249 * Do the request and get back a response...
1252 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1254 fprintf(stderr
, "lpadmin: add-printer (enable) failed: %s\n",
1255 ippErrorString(cupsLastError()));
1258 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1260 fprintf(stderr
, "lpadmin: add-printer (enable) failed: %s\n",
1261 ippErrorString(response
->request
.status
.status_code
));
1263 ippDelete(response
);
1269 ippDelete(response
);
1277 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1280 static char * /* O - Pointer to buf or NULL on EOF */
1281 get_line(char *buf
, /* I - Line buffer */
1282 int length
, /* I - Length of buffer */
1283 FILE *fp
) /* I - File to read from */
1285 char *bufptr
; /* Pointer into buffer */
1286 int ch
; /* Character from file */
1292 while ((ch
= getc(fp
)) != EOF
)
1296 else if (ch
== '\r')
1303 if (ch
!= '\n' && ch
!= EOF
)
1325 * 'set_printer_device()' - Set the device-uri attribute.
1328 static int /* O - 0 on success, 1 on fail */
1329 set_printer_device(http_t
*http
, /* I - Server connection */
1330 char *printer
, /* I - Printer */
1331 char *device
) /* I - New device URI */
1333 ipp_t
*request
, /* IPP Request */
1334 *response
; /* IPP Response */
1335 cups_lang_t
*language
; /* Default language */
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 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1355 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1356 request
->request
.op
.request_id
= 1;
1358 language
= cupsLangDefault();
1360 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1361 "attributes-charset", NULL
, cupsLangEncoding(language
));
1363 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1364 "attributes-natural-language", NULL
, language
->language
);
1366 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1367 "printer-uri", NULL
, uri
);
1370 * Add the device URI...
1373 if (device
[0] == '/')
1376 * Convert filename to URI...
1379 snprintf(uri
, sizeof(uri
), "file:%s", device
);
1380 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1384 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1388 * Do the request and get back a response...
1391 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1393 fprintf(stderr
, "lpadmin: add-printer (set device) failed: %s\n",
1394 ippErrorString(cupsLastError()));
1397 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1399 fprintf(stderr
, "lpadmin: add-printer (set device) failed: %s\n",
1400 ippErrorString(response
->request
.status
.status_code
));
1402 ippDelete(response
);
1408 ippDelete(response
);
1416 * 'set_printer_file()' - Set the interface script or PPD file.
1419 static int /* O - 0 on success, 1 on fail */
1420 set_printer_file(http_t
*http
, /* I - Server connection */
1421 char *printer
, /* I - Printer */
1422 char *file
) /* I - PPD file or interface script */
1424 ipp_status_t status
; /* IPP status code */
1425 ipp_t
*request
, /* IPP Request */
1426 *response
; /* IPP Response */
1427 cups_lang_t
*language
; /* Default language */
1428 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1430 char tempfile
[1024]; /* Temporary filename */
1431 int fd
; /* Temporary file */
1432 gzFile
*gz
; /* GZIP'd file */
1433 char buffer
[8192]; /* Copy buffer */
1434 int bytes
; /* Bytes in buffer */
1437 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1441 * See if the file is gzip'd; if so, unzip it to a temporary file and
1442 * send the uncompressed file.
1445 if (strcmp(file
+ strlen(file
) - 3, ".gz") == 0)
1448 * Yes, the file is compressed; uncompress to a temp file...
1451 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1453 perror("lpadmin: Unable to create temporary file");
1457 if ((gz
= gzopen(file
, "rb")) == NULL
)
1459 perror("lpadmin: Unable to open file");
1465 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1466 write(fd
, buffer
, bytes
);
1473 #endif /* HAVE_LIBZ */
1476 * Build a CUPS_ADD_PRINTER request, which requires the following
1479 * attributes-charset
1480 * attributes-natural-language
1484 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1488 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1489 request
->request
.op
.request_id
= 1;
1491 language
= cupsLangDefault();
1493 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1494 "attributes-charset", NULL
, cupsLangEncoding(language
));
1496 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1497 "attributes-natural-language", NULL
, language
->language
);
1499 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1500 "printer-uri", NULL
, uri
);
1503 * Do the request and get back a response...
1506 if ((response
= cupsDoFileRequest(http
, request
, "/admin/", file
)) == NULL
)
1507 status
= cupsLastError();
1510 status
= response
->request
.status
.status_code
;
1511 ippDelete(response
);
1516 * Remove the temporary file as needed...
1519 if (file
== tempfile
)
1521 #endif /* HAVE_LIBZ */
1523 if (status
> IPP_OK_CONFLICT
)
1525 fprintf(stderr
, "lpadmin: add-printer (set model) failed: %s\n",
1526 ippErrorString(status
));
1536 * 'set_printer_info()' - Set the printer description string.
1539 static int /* O - 0 on success, 1 on fail */
1540 set_printer_info(http_t
*http
, /* I - Server connection */
1541 char *printer
, /* I - Printer */
1542 char *info
) /* I - New description string */
1544 ipp_t
*request
, /* IPP Request */
1545 *response
; /* IPP Response */
1546 cups_lang_t
*language
; /* Default language */
1547 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1550 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1554 * Build a CUPS_ADD_PRINTER request, which requires the following
1557 * attributes-charset
1558 * attributes-natural-language
1562 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1566 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1567 request
->request
.op
.request_id
= 1;
1569 language
= cupsLangDefault();
1571 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1572 "attributes-charset", NULL
, cupsLangEncoding(language
));
1574 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1575 "attributes-natural-language", NULL
, language
->language
);
1577 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1578 "printer-uri", NULL
, uri
);
1581 * Add the info string...
1584 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1588 * Do the request and get back a response...
1591 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1593 fprintf(stderr
, "lpadmin: add-printer (set description) failed: %s\n",
1594 ippErrorString(cupsLastError()));
1597 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1599 fprintf(stderr
, "lpadmin: add-printer (set description) failed: %s\n",
1600 ippErrorString(response
->request
.status
.status_code
));
1602 ippDelete(response
);
1608 ippDelete(response
);
1616 * 'set_printer_location()' - Set the printer location string.
1619 static int /* O - 0 on success, 1 on fail */
1620 set_printer_location(http_t
*http
, /* I - Server connection */
1621 char *printer
, /* I - Printer */
1622 char *location
) /* I - New location string */
1624 ipp_t
*request
, /* IPP Request */
1625 *response
; /* IPP Response */
1626 cups_lang_t
*language
; /* Default language */
1627 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1630 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1634 * Build a CUPS_ADD_PRINTER request, which requires the following
1637 * attributes-charset
1638 * attributes-natural-language
1642 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1646 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1647 request
->request
.op
.request_id
= 1;
1649 language
= cupsLangDefault();
1651 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1652 "attributes-charset", NULL
, cupsLangEncoding(language
));
1654 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1655 "attributes-natural-language", NULL
, language
->language
);
1657 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1658 "printer-uri", NULL
, uri
);
1661 * Add the location string...
1664 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1668 * Do the request and get back a response...
1671 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1673 fprintf(stderr
, "lpadmin: add-printer (set location) failed: %s\n",
1674 ippErrorString(cupsLastError()));
1678 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1680 fprintf(stderr
, "lpadmin: add-printer (set location) failed: %s\n",
1681 ippErrorString(response
->request
.status
.status_code
));
1683 ippDelete(response
);
1689 ippDelete(response
);
1697 * 'set_printer_model()' - Set the driver model file.
1700 static int /* O - 0 on success, 1 on fail */
1701 set_printer_model(http_t
*http
, /* I - Server connection */
1702 char *printer
, /* I - Printer */
1703 char *model
) /* I - Driver model file */
1705 ipp_t
*request
, /* IPP Request */
1706 *response
; /* IPP Response */
1707 cups_lang_t
*language
; /* Default language */
1708 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1712 * Build a CUPS_ADD_PRINTER request, which requires the following
1715 * attributes-charset
1716 * attributes-natural-language
1721 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1725 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1726 request
->request
.op
.request_id
= 1;
1728 language
= cupsLangDefault();
1730 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1731 "attributes-charset", NULL
, cupsLangEncoding(language
));
1733 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1734 "attributes-natural-language", NULL
, language
->language
);
1736 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1737 "printer-uri", NULL
, uri
);
1739 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1740 "ppd-name", NULL
, model
);
1743 * Do the request and get back a response...
1746 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1748 fprintf(stderr
, "lpadmin: add-printer (set model) failed: %s\n",
1749 ippErrorString(cupsLastError()));
1753 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1755 fprintf(stderr
, "lpadmin: add-printer (set model) failed: %s\n",
1756 ippErrorString(response
->request
.status
.status_code
));
1758 ippDelete(response
);
1764 ippDelete(response
);
1772 * 'set_printer_options()' - Set the printer options.
1775 static int /* O - 0 on success, 1 on fail */
1776 set_printer_options(http_t
*http
,/* I - Server connection */
1780 /* I - Number of options */
1781 cups_option_t
*options
)
1784 ipp_t
*request
, /* IPP Request */
1785 *response
; /* IPP Response */
1786 ipp_attribute_t
*attr
; /* IPP attribute */
1787 cups_lang_t
*language
; /* Default language */
1788 ipp_op_t op
; /* Operation to perform */
1789 const char *val
, /* Option value */
1790 *ppdfile
; /* PPD filename */
1791 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1792 line
[1024], /* Line from PPD file */
1793 keyword
[1024], /* Keyword from Default line */
1794 *keyptr
, /* Pointer into keyword... */
1795 tempfile
[1024]; /* Temporary filename */
1796 FILE *in
, /* PPD file */
1797 *out
; /* Temporary file */
1798 int outfd
; /* Temporary file descriptor */
1799 const char *protocol
; /* Protocol */
1802 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1803 num_options
, options
));
1805 language
= cupsLangDefault();
1807 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1810 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1813 * attributes-charset
1814 * attributes-natural-language
1816 * requested-attributes
1821 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
1822 request
->request
.op
.request_id
= 1;
1824 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1825 "attributes-charset", NULL
, cupsLangEncoding(language
));
1827 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1828 "attributes-natural-language", NULL
, language
->language
);
1830 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1831 "printer-uri", NULL
, uri
);
1833 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1834 "requested-attributes", NULL
, "printer-type");
1840 op
= CUPS_ADD_PRINTER
;
1842 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1845 * See what kind of printer or class it is...
1848 if ((attr
= ippFindAttribute(response
, "printer-type", IPP_TAG_ENUM
)) != NULL
)
1850 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1852 op
= CUPS_ADD_CLASS
;
1853 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", printer
);
1857 ippDelete(response
);
1861 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1862 * the following attributes:
1864 * attributes-charset
1865 * attributes-natural-language
1872 request
->request
.op
.operation_id
= op
;
1873 request
->request
.op
.request_id
= 1;
1875 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1876 "attributes-charset", NULL
, cupsLangEncoding(language
));
1878 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1879 "attributes-natural-language", NULL
, language
->language
);
1881 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1882 "printer-uri", NULL
, uri
);
1885 * Add the options...
1888 cupsEncodeOptions(request
, num_options
, options
);
1890 if (op
== CUPS_ADD_PRINTER
)
1891 ppdfile
= cupsGetPPD(printer
);
1895 if (ppdfile
!= NULL
)
1898 * Set default options in the PPD file...
1901 if ((outfd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1903 fprintf(stderr
, "lpadmin: Unable to create temporary file - %s\n",
1910 if ((in
= fopen(ppdfile
, "rb")) == NULL
)
1912 fprintf(stderr
, "lpadmin: Unable to open PPD file \"%s\" - %s\n",
1913 ppdfile
, strerror(errno
));
1921 out
= fdopen(outfd
, "wb");
1922 protocol
= cupsGetOption("protocol", num_options
, options
);
1924 while (get_line(line
, sizeof(line
), in
) != NULL
)
1926 if (!strncmp(line
, "*cupsProtocol:", 14) && protocol
)
1929 * Set a new output protocol (BCP or TBCP) below...
1934 else if (strncmp(line
, "*Default", 8))
1935 fprintf(out
, "%s\n", line
);
1939 * Get default option name...
1942 strlcpy(keyword
, line
+ 8, sizeof(keyword
));
1944 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1945 if (*keyptr
== ':' || isspace(*keyptr
& 255))
1950 if (strcmp(keyword
, "PageRegion") == 0)
1951 val
= cupsGetOption("PageSize", num_options
, options
);
1953 val
= cupsGetOption(keyword
, num_options
, options
);
1956 fprintf(out
, "*Default%s: %s\n", keyword
, val
);
1958 fprintf(out
, "%s\n", line
);
1963 fprintf(out
, "*cupsProtocol: \"%s\"\n", protocol
);
1973 response
= cupsDoFileRequest(http
, request
, "/admin/", tempfile
);
1976 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1986 * No PPD file - just set the options...
1989 response
= cupsDoRequest(http
, request
, "/admin/");
1993 * Check the response...
1996 if (response
== NULL
)
1998 fprintf(stderr
, "lpadmin: %s failed: %s\n",
1999 op
== CUPS_ADD_PRINTER
? "add-printer" : "add-class",
2000 ippErrorString(cupsLastError()));
2004 else if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
2006 fprintf(stderr
, "lpadmin: %s failed: %s\n",
2007 op
== CUPS_ADD_PRINTER
? "add-printer" : "add-class",
2008 ippErrorString(response
->request
.status
.status_code
));
2010 ippDelete(response
);
2016 ippDelete(response
);
2024 * 'validate_name()' - Make sure the printer name only contains valid chars.
2027 static int /* O - 0 if name is no good, 1 if name is good */
2028 validate_name(const char *name
) /* I - Name to check */
2030 const char *ptr
; /* Pointer into name */
2034 * Scan the whole name...
2037 for (ptr
= name
; *ptr
; ptr
++)
2040 else if ((*ptr
>= 0 && *ptr
<= ' ') || *ptr
== 127 || *ptr
== '/')
2044 * All the characters are good; validate the length, too...
2047 return ((ptr
- name
) < 128);
2052 * End of "$Id: lpadmin.c,v 1.44 2004/02/25 20:14:54 mike Exp $".