2 * "$Id: lpadmin.c,v 1.28 2002/01/02 17:59:19 mike Exp $"
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2002 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
39 * letters, numbers, and the underscore...
43 * Include necessary headers...
49 #include <cups/cups.h>
50 #include <cups/string.h>
51 #include <cups/language.h>
52 #include <cups/debug.h>
56 #endif /* HAVE_LIBZ */
63 static void add_printer_to_class(http_t
*, char *, char *);
64 static void default_printer(http_t
*, char *);
65 static void delete_printer(http_t
*, char *);
66 static void delete_printer_from_class(http_t
*, char *, char *);
67 static void enable_printer(http_t
*, char *);
68 static char *get_line(char *, int, FILE *fp
);
69 static void set_printer_device(http_t
*, char *, char *);
70 static void set_printer_file(http_t
*, char *, char *);
71 static void set_printer_info(http_t
*, char *, char *);
72 static void set_printer_location(http_t
*, char *, char *);
73 static void set_printer_model(http_t
*, char *, char *);
74 static void 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 */
93 http_encryption_t encryption
; /* Encryption? */
100 encryption
= cupsEncryption();
102 for (i
= 1; i
< argc
; i
++)
103 if (argv
[i
][0] == '-')
106 case 'c' : /* Add printer to class */
109 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
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 letters, numbers, and the underscore!\n", stderr
);
146 add_printer_to_class(http
, printer
, pclass
);
149 case 'd' : /* Set as default destination */
152 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
156 perror("lpadmin: Unable to connect to server");
162 printer
= argv
[i
] + 2;
169 fputs("lpadmin: Expected printer name after \'-d\' option!\n", stderr
);
176 if (!validate_name(printer
))
178 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
182 default_printer(http
, printer
);
186 case 'h' : /* Connect to host */
190 if (argv
[i
][2] != '\0')
191 http
= httpConnectEncrypt(argv
[i
] + 2, ippPort(), encryption
);
198 fputs("lpadmin: Expected hostname after \'-h\' option!\n", stderr
);
202 http
= httpConnectEncrypt(argv
[i
], ippPort(), encryption
);
207 perror("lpadmin: Unable to connect to server");
211 cupsSetServer(http
->hostname
);
214 case 'i' : /* Use the specified interface script */
217 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
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
);
234 set_printer_file(http
, printer
, argv
[i
] + 2);
241 fputs("lpadmin: Expected interface after \'-i\' option!\n", stderr
);
245 set_printer_file(http
, printer
, argv
[i
]);
249 case 'E' : /* Enable the printer */
253 cupsSetEncryption(encryption
= HTTP_ENCRYPT_REQUIRED
);
256 httpEncryption(http
, encryption
);
258 fprintf(stderr
, "%s: Sorry, no encryption support compiled in!\n",
260 #endif /* HAVE_LIBSSL */
266 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
270 perror("lpadmin: Unable to connect to server");
275 enable_printer(http
, printer
);
278 case 'm' : /* Use the specified standard script/PPD file */
281 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
285 perror("lpadmin: Unable to connect to server");
292 fputs("lpadmin: Unable to set the interface script or PPD file:\n", stderr
);
293 fputs(" You must specify a printer name first!\n", stderr
);
298 set_printer_model(http
, printer
, argv
[i
] + 2);
305 fputs("lpadmin: Expected model after \'-m\' option!\n", stderr
);
309 set_printer_model(http
, printer
, argv
[i
]);
313 case 'o' : /* Set option */
315 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
322 fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr
);
326 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
330 case 'p' : /* Add/modify a printer */
333 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
337 perror("lpadmin: Unable to connect to server");
343 printer
= argv
[i
] + 2;
350 fputs("lpadmin: Expected printer after \'-p\' option!\n", stderr
);
357 if (!validate_name(printer
))
359 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
364 case 'r' : /* Remove printer from class */
367 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
371 perror("lpadmin: Unable to connect to server");
378 fputs("lpadmin: Unable to remove a printer from the class:\n", stderr
);
379 fputs(" You must specify a printer name first!\n", stderr
);
384 pclass
= argv
[i
] + 2;
391 fputs("lpadmin: Expected class after \'-r\' option!\n", stderr
);
398 if (!validate_name(pclass
))
400 fputs("lpadmin: Class name can only contain letters, numbers, and the underscore!\n", stderr
);
404 delete_printer_from_class(http
, printer
, pclass
);
407 case 'u' : /* Allow/deny users */
416 fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr
);
423 if (strncasecmp(val
, "allow:", 6) == 0)
424 num_options
= cupsAddOption("requesting-user-name-allowed",
425 val
+ 6, num_options
, &options
);
426 else if (strncasecmp(val
, "deny:", 5) == 0)
427 num_options
= cupsAddOption("requesting-user-name-denied",
428 val
+ 5, num_options
, &options
);
431 fprintf(stderr
, "lpadmin: Unknown allow/deny option \"%s\"!\n",
437 case 'v' : /* Set the device-uri attribute */
440 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
444 perror("lpadmin: Unable to connect to server");
451 fputs("lpadmin: Unable to set the device URI:\n", stderr
);
452 fputs(" You must specify a printer name first!\n", stderr
);
457 set_printer_device(http
, printer
, argv
[i
] + 2);
464 fputs("lpadmin: Expected device URI after \'-v\' option!\n", stderr
);
468 set_printer_device(http
, printer
, argv
[i
]);
472 case 'x' : /* Delete a printer */
475 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
479 perror("lpadmin: Unable to connect to server");
485 printer
= argv
[i
] + 2;
492 fputs("lpadmin: Expected printer or class after \'-x\' option!\n", stderr
);
499 if (!validate_name(printer
))
501 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
505 delete_printer(http
, printer
);
509 case 'D' : /* Set the printer-info attribute */
512 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
516 perror("lpadmin: Unable to connect to server");
523 fputs("lpadmin: Unable to set the printer description:\n", stderr
);
524 fputs(" You must specify a printer name first!\n", stderr
);
529 set_printer_info(http
, printer
, argv
[i
] + 2);
536 fputs("lpadmin: Expected description after \'-D\' option!\n", stderr
);
540 set_printer_info(http
, printer
, argv
[i
]);
544 case 'L' : /* Set the printer-location attribute */
547 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
551 perror("lpadmin: Unable to connect to server");
558 fputs("lpadmin: Unable to set the printer location:\n", stderr
);
559 fputs(" You must specify a printer name first!\n", stderr
);
564 set_printer_location(http
, printer
, argv
[i
] + 2);
571 fputs("lpadmin: Expected location after \'-L\' option!\n", stderr
);
575 set_printer_location(http
, printer
, argv
[i
]);
579 case 'P' : /* Use the specified PPD file */
582 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
586 perror("lpadmin: Unable to connect to server");
593 fputs("lpadmin: Unable to set the PPD file:\n", stderr
);
594 fputs(" You must specify a printer name first!\n", stderr
);
599 set_printer_file(http
, printer
, argv
[i
] + 2);
606 fputs("lpadmin: Expected PPD after \'-P\' option!\n", stderr
);
610 set_printer_file(http
, printer
, argv
[i
]);
615 fprintf(stderr
, "lpadmin: Unknown option \'%c\'!\n", argv
[i
][1]);
620 fprintf(stderr
, "lpadmin: Unknown argument \'%s\'!\n", argv
[i
]);
625 * Set options as needed...
632 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
636 perror("lpadmin: Unable to connect to server");
643 fputs("lpadmin: Unable to set the printer options:\n", stderr
);
644 fputs(" You must specify a printer name first!\n", stderr
);
648 set_printer_options(http
, printer
, num_options
, options
);
655 puts(" lpadmin [-h server] -d destination");
656 puts(" lpadmin [-h server] -x destination");
657 puts(" lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]");
658 puts(" [-r remove-class] [-v device] [-D description]");
659 puts(" [-P ppd-file] [-o name=value]");
660 puts(" [-u allow:user,user] [-u deny:user,user]");
672 * 'add_printer_to_class()' - Add a printer to a class.
676 add_printer_to_class(http_t
*http
, /* I - Server connection */
677 char *printer
, /* I - Printer to add */
678 char *pclass
) /* I - Class to add to */
680 int i
; /* Looping var */
681 ipp_t
*request
, /* IPP Request */
682 *response
; /* IPP Response */
683 ipp_attribute_t
*attr
, /* Current attribute */
684 *members
; /* Members in class */
685 cups_lang_t
*language
; /* Default language */
686 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
689 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
693 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
697 * attributes-natural-language
701 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
705 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
706 request
->request
.op
.request_id
= 1;
708 language
= cupsLangDefault();
710 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
711 "attributes-charset", NULL
, cupsLangEncoding(language
));
713 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
714 "attributes-natural-language", NULL
, language
->language
);
716 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
717 "printer-uri", NULL
, uri
);
720 * Do the request and get back a response...
723 response
= cupsDoRequest(http
, request
, "/");
726 * Build a CUPS_ADD_CLASS request, which requires the following
730 * attributes-natural-language
737 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
738 request
->request
.op
.request_id
= 1;
740 language
= cupsLangDefault();
742 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
743 "attributes-charset", NULL
, cupsLangEncoding(language
));
745 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
746 "attributes-natural-language", NULL
, language
->language
);
748 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
749 "printer-uri", NULL
, uri
);
752 * See if the printer is already in the class...
755 if (response
!= NULL
&&
756 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
757 for (i
= 0; i
< members
->num_values
; i
++)
758 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
760 fprintf(stderr
, "lpadmin: Printer %s is already a member of class %s.\n",
768 * OK, the printer isn't part of the class, so add it...
771 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
773 if (response
!= NULL
&&
774 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
777 * Add the printer to the existing list...
780 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
781 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
782 for (i
= 0; i
< members
->num_values
; i
++)
783 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
785 attr
->values
[i
].string
.text
= strdup(uri
);
788 attr
= ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
791 * Then send the request...
796 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
797 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
798 ippErrorString(cupsLastError()));
801 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
802 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
803 ippErrorString(response
->request
.status
.status_code
));
811 * 'default_printer()' - Set the default printing destination.
815 default_printer(http_t
*http
, /* I - Server connection */
816 char *printer
) /* I - Printer name */
818 ipp_t
*request
, /* IPP Request */
819 *response
; /* IPP Response */
820 cups_lang_t
*language
; /* Default language */
821 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
824 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
827 * Build a CUPS_SET_DEFAULT request, which requires the following
831 * attributes-natural-language
835 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
839 request
->request
.op
.operation_id
= CUPS_SET_DEFAULT
;
840 request
->request
.op
.request_id
= 1;
842 language
= cupsLangDefault();
844 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
845 "attributes-charset", NULL
, cupsLangEncoding(language
));
847 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
848 "attributes-natural-language", NULL
, language
->language
);
850 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
851 "printer-uri", NULL
, uri
);
854 * Do the request and get back a response...
857 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
858 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
859 ippErrorString(cupsLastError()));
862 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
863 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
864 ippErrorString(response
->request
.status
.status_code
));
872 * 'delete_printer()' - Delete a printer from the system...
876 delete_printer(http_t
*http
, /* I - Server connection */
877 char *printer
) /* I - Printer to delete */
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(("delete_printer(%p, \"%s\")\n", http
, printer
));
888 * Build a CUPS_DELETE_PRINTER 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_DELETE_PRINTER
;
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
)
919 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
920 ippErrorString(cupsLastError()));
923 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
924 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
925 ippErrorString(response
->request
.status
.status_code
));
933 * 'delete_printer_from_class()' - Delete a printer from a class.
937 delete_printer_from_class(http_t
*http
, /* I - Server connection */
938 char *printer
, /* I - Printer to remove */
939 char *pclass
) /* I - Class to remove from */
941 int i
, j
, k
; /* Looping vars */
942 ipp_t
*request
, /* IPP Request */
943 *response
; /* IPP Response */
944 ipp_attribute_t
*attr
, /* Current attribute */
945 *members
; /* Members in class */
946 cups_lang_t
*language
; /* Default language */
947 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
950 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
954 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
958 * attributes-natural-language
962 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
966 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
967 request
->request
.op
.request_id
= 1;
969 language
= cupsLangDefault();
971 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
972 "attributes-charset", NULL
, cupsLangEncoding(language
));
974 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
975 "attributes-natural-language", NULL
, language
->language
);
977 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
978 "printer-uri", NULL
, uri
);
981 * Do the request and get back a response...
984 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
985 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
988 fprintf(stderr
, "lpadmin: Class %s does not exist!\n", pclass
);
993 * See if the printer is already in the class...
996 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
999 fputs("lpadmin: No member names were seen!\n", stderr
);
1003 for (i
= 0; i
< members
->num_values
; i
++)
1004 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
1007 if (i
>= members
->num_values
)
1009 fprintf(stderr
, "lpadmin: Printer %s is not a member of class %s.\n",
1011 ippDelete(response
);
1015 if (members
->num_values
== 1)
1018 * Build a CUPS_DELETE_CLASS request, which requires the following
1021 * attributes-charset
1022 * attributes-natural-language
1028 request
->request
.op
.operation_id
= CUPS_DELETE_CLASS
;
1029 request
->request
.op
.request_id
= 1;
1031 language
= cupsLangDefault();
1033 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1034 "attributes-charset", NULL
, cupsLangEncoding(language
));
1036 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1037 "attributes-natural-language", NULL
, language
->language
);
1039 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1040 "printer-uri", NULL
, uri
);
1045 * Build a CUPS_ADD_CLASS request, which requires the following
1048 * attributes-charset
1049 * attributes-natural-language
1056 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
1057 request
->request
.op
.request_id
= 1;
1059 language
= cupsLangDefault();
1061 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1062 "attributes-charset", NULL
, cupsLangEncoding(language
));
1064 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1065 "attributes-natural-language", NULL
, language
->language
);
1067 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1068 "printer-uri", NULL
, uri
);
1071 * Delete the printer from the class...
1074 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1075 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1076 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1078 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1080 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1084 * Then send the request...
1087 ippDelete(response
);
1089 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1090 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1091 ippErrorString(cupsLastError()));
1094 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1095 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1096 ippErrorString(response
->request
.status
.status_code
));
1098 ippDelete(response
);
1104 * 'enable_printer()' - Enable a printer...
1108 enable_printer(http_t
*http
, /* I - Server connection */
1109 char *printer
) /* I - Printer to enable */
1111 ipp_t
*request
, /* IPP Request */
1112 *response
; /* IPP Response */
1113 cups_lang_t
*language
; /* Default language */
1114 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1117 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1120 * Build a CUPS_ADD_PRINTER request, which requires the following
1123 * attributes-charset
1124 * attributes-natural-language
1127 * printer-is-accepting-jobs
1130 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1134 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1135 request
->request
.op
.request_id
= 1;
1137 language
= cupsLangDefault();
1139 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1140 "attributes-charset", NULL
, cupsLangEncoding(language
));
1142 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1143 "attributes-natural-language", NULL
, language
->language
);
1145 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1146 "printer-uri", NULL
, uri
);
1148 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1151 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1154 * Do the request and get back a response...
1157 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1158 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1159 ippErrorString(cupsLastError()));
1162 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1163 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1164 ippErrorString(response
->request
.status
.status_code
));
1166 ippDelete(response
);
1172 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1175 static char * /* O - Pointer to buf or NULL on EOF */
1176 get_line(char *buf
, /* I - Line buffer */
1177 int length
, /* I - Length of buffer */
1178 FILE *fp
) /* I - File to read from */
1180 char *bufptr
; /* Pointer into buffer */
1181 int ch
; /* Character from file */
1187 while ((ch
= getc(fp
)) != EOF
)
1191 else if (ch
== '\r')
1198 if (ch
!= '\n' && ch
!= EOF
)
1220 * 'set_printer_device()' - Set the device-uri attribute.
1224 set_printer_device(http_t
*http
, /* I - Server connection */
1225 char *printer
, /* I - Printer */
1226 char *device
) /* I - New device URI */
1228 ipp_t
*request
, /* IPP Request */
1229 *response
; /* IPP Response */
1230 cups_lang_t
*language
; /* Default language */
1231 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1234 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1238 * Build a CUPS_ADD_PRINTER request, which requires the following
1241 * attributes-charset
1242 * attributes-natural-language
1246 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1250 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1251 request
->request
.op
.request_id
= 1;
1253 language
= cupsLangDefault();
1255 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1256 "attributes-charset", NULL
, cupsLangEncoding(language
));
1258 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1259 "attributes-natural-language", NULL
, language
->language
);
1261 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1262 "printer-uri", NULL
, uri
);
1265 * Add the device URI...
1268 if (device
[0] == '/')
1271 * Convert filename to URI...
1274 snprintf(uri
, sizeof(uri
), "file:%s", device
);
1275 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1279 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1283 * Do the request and get back a response...
1286 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1287 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1288 ippErrorString(cupsLastError()));
1291 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1292 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1293 ippErrorString(response
->request
.status
.status_code
));
1295 ippDelete(response
);
1301 * 'set_printer_file()' - Set the interface script or PPD file.
1305 set_printer_file(http_t
*http
, /* I - Server connection */
1306 char *printer
, /* I - Printer */
1307 char *file
) /* I - PPD file or interface script */
1309 ipp_t
*request
, /* IPP Request */
1310 *response
; /* IPP Response */
1311 cups_lang_t
*language
; /* Default language */
1312 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1314 char tempfile
[1024]; /* Temporary filename */
1315 int fd
; /* Temporary file */
1316 gzFile
*gz
; /* GZIP'd file */
1317 char buffer
[8192]; /* Copy buffer */
1318 int bytes
; /* Bytes in buffer */
1321 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1325 * See if the file is gzip'd; if so, unzip it to a temporary file and
1326 * send the uncompressed file.
1329 if (strcmp(file
+ strlen(file
) - 3, ".gz") == 0)
1332 * Yes, the file is compressed; uncompress to a temp file...
1335 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1337 perror("lpadmin: Unable to create temporary file");
1341 if ((gz
= gzopen(file
, "rb")) == NULL
)
1343 perror("lpadmin: Unable to open file");
1349 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1350 write(fd
, buffer
, bytes
);
1357 #endif /* HAVE_LIBZ */
1360 * Build a CUPS_ADD_PRINTER request, which requires the following
1363 * attributes-charset
1364 * attributes-natural-language
1368 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1372 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1373 request
->request
.op
.request_id
= 1;
1375 language
= cupsLangDefault();
1377 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1378 "attributes-charset", NULL
, cupsLangEncoding(language
));
1380 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1381 "attributes-natural-language", NULL
, language
->language
);
1383 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1384 "printer-uri", NULL
, uri
);
1387 * Do the request and get back a response...
1390 if ((response
= cupsDoFileRequest(http
, request
, "/admin/", file
)) == NULL
)
1391 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1392 ippErrorString(cupsLastError()));
1395 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1396 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1397 ippErrorString(response
->request
.status
.status_code
));
1399 ippDelete(response
);
1404 * Remove the temporary file as needed...
1407 if (file
== tempfile
)
1409 #endif /* HAVE_LIBZ */
1414 * 'set_printer_info()' - Set the printer description string.
1418 set_printer_info(http_t
*http
, /* I - Server connection */
1419 char *printer
, /* I - Printer */
1420 char *info
) /* I - New description string */
1422 ipp_t
*request
, /* IPP Request */
1423 *response
; /* IPP Response */
1424 cups_lang_t
*language
; /* Default language */
1425 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1428 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1432 * Build a CUPS_ADD_PRINTER request, which requires the following
1435 * attributes-charset
1436 * attributes-natural-language
1440 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1444 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1445 request
->request
.op
.request_id
= 1;
1447 language
= cupsLangDefault();
1449 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1450 "attributes-charset", NULL
, cupsLangEncoding(language
));
1452 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1453 "attributes-natural-language", NULL
, language
->language
);
1455 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1456 "printer-uri", NULL
, uri
);
1459 * Add the info string...
1462 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1466 * Do the request and get back a response...
1469 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1470 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1471 ippErrorString(cupsLastError()));
1474 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1475 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1476 ippErrorString(response
->request
.status
.status_code
));
1478 ippDelete(response
);
1484 * 'set_printer_location()' - Set the printer location string.
1488 set_printer_location(http_t
*http
, /* I - Server connection */
1489 char *printer
, /* I - Printer */
1490 char *location
) /* I - New location string */
1492 ipp_t
*request
, /* IPP Request */
1493 *response
; /* IPP Response */
1494 cups_lang_t
*language
; /* Default language */
1495 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1498 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1502 * Build a CUPS_ADD_PRINTER request, which requires the following
1505 * attributes-charset
1506 * attributes-natural-language
1510 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1514 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1515 request
->request
.op
.request_id
= 1;
1517 language
= cupsLangDefault();
1519 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1520 "attributes-charset", NULL
, cupsLangEncoding(language
));
1522 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1523 "attributes-natural-language", NULL
, language
->language
);
1525 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1526 "printer-uri", NULL
, uri
);
1529 * Add the location string...
1532 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1536 * Do the request and get back a response...
1539 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1540 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1541 ippErrorString(cupsLastError()));
1544 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1545 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1546 ippErrorString(response
->request
.status
.status_code
));
1548 ippDelete(response
);
1554 * 'set_printer_model()' - Set the driver model file.
1558 set_printer_model(http_t
*http
, /* I - Server connection */
1559 char *printer
, /* I - Printer */
1560 char *model
) /* I - Driver model file */
1562 ipp_t
*request
, /* IPP Request */
1563 *response
; /* IPP Response */
1564 cups_lang_t
*language
; /* Default language */
1565 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1569 * Build a CUPS_ADD_PRINTER request, which requires the following
1572 * attributes-charset
1573 * attributes-natural-language
1578 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1582 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1583 request
->request
.op
.request_id
= 1;
1585 language
= cupsLangDefault();
1587 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1588 "attributes-charset", NULL
, cupsLangEncoding(language
));
1590 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1591 "attributes-natural-language", NULL
, language
->language
);
1593 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1594 "printer-uri", NULL
, uri
);
1596 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
1597 "ppd-name", NULL
, model
);
1600 * Do the request and get back a response...
1603 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1604 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1605 ippErrorString(cupsLastError()));
1608 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1609 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1610 ippErrorString(response
->request
.status
.status_code
));
1612 ippDelete(response
);
1618 * 'set_printer_options()' - Set the printer options.
1622 set_printer_options(http_t
*http
, /* I - Server connection */
1623 char *printer
, /* I - Printer */
1624 int num_options
, /* I - Number of options */
1625 cups_option_t
*options
) /* I - Options */
1627 ipp_t
*request
, /* IPP Request */
1628 *response
; /* IPP Response */
1629 ipp_attribute_t
*attr
; /* IPP attribute */
1630 cups_lang_t
*language
; /* Default language */
1631 ipp_op_t op
; /* Operation to perform */
1632 const char *val
, /* Option value */
1633 *ppdfile
; /* PPD filename */
1634 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1635 line
[1024], /* Line from PPD file */
1636 keyword
[1024], /* Keyword from Default line */
1637 *keyptr
, /* Pointer into keyword... */
1638 tempfile
[1024]; /* Temporary filename */
1639 FILE *in
, /* PPD file */
1640 *out
; /* Temporary file */
1641 int outfd
; /* Temporary file descriptor */
1644 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1645 num_options
, options
));
1647 language
= cupsLangDefault();
1649 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1652 * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
1655 * attributes-charset
1656 * attributes-natural-language
1658 * requested-attributes
1663 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
1664 request
->request
.op
.request_id
= 1;
1666 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1667 "attributes-charset", NULL
, cupsLangEncoding(language
));
1669 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1670 "attributes-natural-language", NULL
, language
->language
);
1672 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1673 "printer-uri", NULL
, uri
);
1675 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
1676 "requested-attributes", NULL
, "printer-type");
1682 op
= CUPS_ADD_PRINTER
;
1684 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1687 * See what kind of printer or class it is...
1690 if ((attr
= ippFindAttribute(response
, "printer-type", IPP_TAG_ENUM
)) != NULL
)
1692 if (attr
->values
[0].integer
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1693 op
= CUPS_ADD_CLASS
;
1696 ippDelete(response
);
1700 * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
1701 * the following attributes:
1703 * attributes-charset
1704 * attributes-natural-language
1711 request
->request
.op
.operation_id
= op
;
1712 request
->request
.op
.request_id
= 1;
1714 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1715 "attributes-charset", NULL
, cupsLangEncoding(language
));
1717 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1718 "attributes-natural-language", NULL
, language
->language
);
1720 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1721 "printer-uri", NULL
, uri
);
1724 * Add the options...
1727 cupsEncodeOptions(request
, num_options
, options
);
1729 if (op
== CUPS_ADD_PRINTER
)
1730 ppdfile
= cupsGetPPD(printer
);
1734 if (ppdfile
!= NULL
)
1737 * Set default options in the PPD file...
1740 outfd
= cupsTempFd(tempfile
, sizeof(tempfile
));
1742 in
= fopen(ppdfile
, "rb");
1743 out
= fdopen(outfd
, "wb");
1745 while (get_line(line
, sizeof(line
), in
) != NULL
)
1747 if (strncmp(line
, "*Default", 8) != 0)
1748 fprintf(out
, "%s\n", line
);
1752 * Get default option name...
1755 strncpy(keyword
, line
+ 8, sizeof(keyword
) - 1);
1756 keyword
[sizeof(keyword
) - 1] = '\0';
1758 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1759 if (*keyptr
== ':' || isspace(*keyptr
))
1764 if (strcmp(keyword
, "PageRegion") == 0)
1765 val
= cupsGetOption("PageSize", num_options
, options
);
1767 val
= cupsGetOption(keyword
, num_options
, options
);
1770 fprintf(out
, "*Default%s: %s\n", keyword
, val
);
1772 fprintf(out
, "%s\n", line
);
1784 response
= cupsDoFileRequest(http
, request
, "/admin/", tempfile
);
1787 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1797 * No PPD file - just set the options...
1800 response
= cupsDoRequest(http
, request
, "/admin/");
1804 * Check the response...
1807 if (response
== NULL
)
1808 fprintf(stderr
, "lpadmin: %s failed: %s\n",
1809 op
== CUPS_ADD_PRINTER
? "add-printer" : "add-class",
1810 ippErrorString(cupsLastError()));
1813 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1814 fprintf(stderr
, "lpadmin: %s failed: %s\n",
1815 op
== CUPS_ADD_PRINTER
? "add-printer" : "add-class",
1816 ippErrorString(response
->request
.status
.status_code
));
1818 ippDelete(response
);
1824 * 'validate_name()' - Make sure the printer name only contains letters,
1825 * numbers, and the underscore...
1828 static int /* O - 0 if name is no good, 1 if name is good */
1829 validate_name(const char *name
) /* I - Name to check */
1832 * Don't allow names to start with a digit...
1839 * Scan the whole name...
1845 else if (!isalnum(*name
) && *name
!= '_')
1855 * End of "$Id: lpadmin.c,v 1.28 2002/01/02 17:59:19 mike Exp $".