2 * "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $"
4 * "lpadmin" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2001 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_options() - Set the printer options.
37 * validate_name() - Make sure the printer name only contains
38 * letters, numbers, and the underscore...
42 * Include necessary headers...
48 #include <cups/cups.h>
49 #include <cups/language.h>
50 #include <cups/debug.h>
54 #endif /* HAVE_LIBZ */
61 static void add_printer_to_class(http_t
*, char *, char *);
62 static void default_printer(http_t
*, char *);
63 static void delete_printer(http_t
*, char *);
64 static void delete_printer_from_class(http_t
*, char *, char *);
65 static void enable_printer(http_t
*, char *);
66 static char *get_line(char *, int, FILE *fp
);
67 static void set_printer_device(http_t
*, char *, char *);
68 static void set_printer_file(http_t
*, char *, char *);
69 static void set_printer_info(http_t
*, char *, char *);
70 static void set_printer_location(http_t
*, char *, char *);
71 static void set_printer_options(http_t
*, char *, int, cups_option_t
*);
72 static int validate_name(const char *);
76 * 'main()' - Parse options and configure the scheduler.
80 main(int argc
, /* I - Number of command-line arguments */
81 char *argv
[]) /* I - Command-line arguments */
83 int i
; /* Looping var */
84 http_t
*http
; /* Connection to server */
85 char *printer
, /* Destination printer */
86 *pclass
, /* Printer class name */
87 *host
, /* Pointer to hostname */
88 *val
, /* Pointer to allow/deny value */
89 filename
[1024]; /* Model filename */
90 const char *datadir
; /* CUPS_DATADIR env variable */
91 int num_options
; /* Number of options */
92 cups_option_t
*options
; /* Options */
93 http_encryption_t encryption
; /* Encryption? */
100 encryption
= cupsEncryption();
102 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
103 datadir
= CUPS_DATADIR
;
105 for (i
= 1; i
< argc
; i
++)
106 if (argv
[i
][0] == '-')
109 case 'c' : /* Add printer to class */
112 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
116 perror("lpadmin: Unable to connect to server");
123 fputs("lpadmin: Unable to add a printer to the class:\n", stderr
);
124 fputs(" You must specify a printer name first!\n", stderr
);
129 pclass
= argv
[i
] + 2;
136 fputs("lpadmin: Expected class name after \'-c\' option!\n", stderr
);
143 if (!validate_name(pclass
))
145 fputs("lpadmin: Class name can only contain letters, numbers, and the underscore!\n", stderr
);
149 add_printer_to_class(http
, printer
, pclass
);
152 case 'd' : /* Set as default destination */
155 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
159 perror("lpadmin: Unable to connect to server");
165 printer
= argv
[i
] + 2;
172 fputs("lpadmin: Expected printer name after \'-d\' option!\n", stderr
);
179 if (!validate_name(printer
))
181 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
185 default_printer(http
, printer
);
189 case 'h' : /* Connect to host */
193 if (argv
[i
][2] != '\0')
194 http
= httpConnectEncrypt(argv
[i
] + 2, ippPort(), encryption
);
201 fputs("lpadmin: Expected hostname after \'-h\' option!\n", stderr
);
205 http
= httpConnectEncrypt(argv
[i
], ippPort(), encryption
);
210 perror("lpadmin: Unable to connect to server");
214 cupsSetServer(http
->hostname
);
217 case 'i' : /* Use the specified interface script */
220 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
224 perror("lpadmin: Unable to connect to server");
231 fputs("lpadmin: Unable to set the interface script:\n", stderr
);
232 fputs(" You must specify a printer name first!\n", stderr
);
237 set_printer_file(http
, printer
, argv
[i
] + 2);
244 fputs("lpadmin: Expected interface after \'-i\' option!\n", stderr
);
248 set_printer_file(http
, printer
, argv
[i
]);
252 case 'E' : /* Enable the printer */
256 cupsSetEncryption(encryption
= HTTP_ENCRYPT_REQUIRED
);
259 httpEncryption(http
, encryption
);
261 fprintf(stderr
, "%s: Sorry, no encryption support compiled in!\n",
263 #endif /* HAVE_LIBSSL */
269 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
273 perror("lpadmin: Unable to connect to server");
278 enable_printer(http
, printer
);
281 case 'm' : /* Use the specified standard script/PPD file */
284 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
288 perror("lpadmin: Unable to connect to server");
295 fputs("lpadmin: Unable to set the interface script or PPD file:\n", stderr
);
296 fputs(" You must specify a printer name first!\n", stderr
);
301 snprintf(filename
, sizeof(filename
), "%s/model/%s", datadir
,
309 fputs("lpadmin: Expected model after \'-m\' option!\n", stderr
);
313 snprintf(filename
, sizeof(filename
), "%s/model/%s", datadir
,
317 set_printer_file(http
, printer
, filename
);
320 case 'o' : /* Set option */
322 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
329 fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr
);
333 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
337 case 'p' : /* Add/modify a printer */
340 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
344 perror("lpadmin: Unable to connect to server");
350 printer
= argv
[i
] + 2;
357 fputs("lpadmin: Expected printer after \'-p\' option!\n", stderr
);
364 if (!validate_name(printer
))
366 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
370 if ((host
= strchr(printer
, '@')) != NULL
)
373 * printer@host - reconnect to the named host...
379 if ((http
= httpConnectEncrypt(host
, ippPort(), encryption
)) == NULL
)
381 perror("lpadmin: Unable to connect to server");
387 case 'r' : /* Remove printer from class */
390 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
394 perror("lpadmin: Unable to connect to server");
401 fputs("lpadmin: Unable to remove a printer from the class:\n", stderr
);
402 fputs(" You must specify a printer name first!\n", stderr
);
407 pclass
= argv
[i
] + 2;
414 fputs("lpadmin: Expected class after \'-r\' option!\n", stderr
);
421 if (!validate_name(pclass
))
423 fputs("lpadmin: Class name can only contain letters, numbers, and the underscore!\n", stderr
);
427 delete_printer_from_class(http
, printer
, pclass
);
430 case 'u' : /* Allow/deny users */
439 fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr
);
446 if (strncasecmp(val
, "allow:", 6) == 0)
447 num_options
= cupsAddOption("requesting-user-name-allowed",
448 val
+ 6, num_options
, &options
);
449 else if (strncasecmp(val
, "deny:", 5) == 0)
450 num_options
= cupsAddOption("requesting-user-name-denied",
451 val
+ 5, num_options
, &options
);
454 fprintf(stderr
, "lpadmin: Unknown allow/deny option \"%s\"!\n",
460 case 'v' : /* Set the device-uri attribute */
463 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
467 perror("lpadmin: Unable to connect to server");
474 fputs("lpadmin: Unable to set the device URI:\n", stderr
);
475 fputs(" You must specify a printer name first!\n", stderr
);
480 set_printer_device(http
, printer
, argv
[i
] + 2);
487 fputs("lpadmin: Expected device URI after \'-v\' option!\n", stderr
);
491 set_printer_device(http
, printer
, argv
[i
]);
495 case 'x' : /* Delete a printer */
498 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
502 perror("lpadmin: Unable to connect to server");
508 printer
= argv
[i
] + 2;
515 fputs("lpadmin: Expected printer or class after \'-x\' option!\n", stderr
);
522 if (!validate_name(printer
))
524 fputs("lpadmin: Printer name can only contain letters, numbers, and the underscore!\n", stderr
);
528 if ((host
= strchr(printer
, '@')) != NULL
)
531 * printer@host - reconnect to the named host...
537 if ((http
= httpConnectEncrypt(host
, ippPort(), encryption
)) == NULL
)
539 perror("lpadmin: Unable to connect to server");
544 delete_printer(http
, printer
);
548 case 'D' : /* Set the printer-info attribute */
551 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
555 perror("lpadmin: Unable to connect to server");
562 fputs("lpadmin: Unable to set the printer description:\n", stderr
);
563 fputs(" You must specify a printer name first!\n", stderr
);
568 set_printer_info(http
, printer
, argv
[i
] + 2);
575 fputs("lpadmin: Expected description after \'-D\' option!\n", stderr
);
579 set_printer_info(http
, printer
, argv
[i
]);
583 case 'L' : /* Set the printer-location attribute */
586 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
590 perror("lpadmin: Unable to connect to server");
597 fputs("lpadmin: Unable to set the printer location:\n", stderr
);
598 fputs(" You must specify a printer name first!\n", stderr
);
603 set_printer_location(http
, printer
, argv
[i
] + 2);
610 fputs("lpadmin: Expected location after \'-L\' option!\n", stderr
);
614 set_printer_location(http
, printer
, argv
[i
]);
618 case 'P' : /* Use the specified PPD file */
621 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
625 perror("lpadmin: Unable to connect to server");
632 fputs("lpadmin: Unable to set the PPD file:\n", stderr
);
633 fputs(" You must specify a printer name first!\n", stderr
);
638 set_printer_file(http
, printer
, argv
[i
] + 2);
645 fputs("lpadmin: Expected PPD after \'-P\' option!\n", stderr
);
649 set_printer_file(http
, printer
, argv
[i
]);
654 fprintf(stderr
, "lpadmin: Unknown option \'%c\'!\n", argv
[i
][1]);
659 fprintf(stderr
, "lpadmin: Unknown argument \'%s\'!\n", argv
[i
]);
664 * Set options as needed...
671 http
= httpConnectEncrypt(cupsServer(), ippPort(), encryption
);
675 perror("lpadmin: Unable to connect to server");
682 fputs("lpadmin: Unable to set the printer options:\n", stderr
);
683 fputs(" You must specify a printer name first!\n", stderr
);
687 set_printer_options(http
, printer
, num_options
, options
);
694 puts(" lpadmin [-h server] -d destination");
695 puts(" lpadmin [-h server] -x destination");
696 puts(" lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]");
697 puts(" [-r remove-class] [-v device] [-D description]");
698 puts(" [-P ppd-file] [-o name=value]");
699 puts(" [-u allow:user,user] [-u deny:user,user]");
711 * 'add_printer_to_class()' - Add a printer to a class.
715 add_printer_to_class(http_t
*http
, /* I - Server connection */
716 char *printer
, /* I - Printer to add */
717 char *pclass
) /* I - Class to add to */
719 int i
; /* Looping var */
720 ipp_t
*request
, /* IPP Request */
721 *response
; /* IPP Response */
722 ipp_attribute_t
*attr
, /* Current attribute */
723 *members
; /* Members in class */
724 cups_lang_t
*language
; /* Default language */
725 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
728 DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http
,
732 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
736 * attributes-natural-language
740 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
744 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
745 request
->request
.op
.request_id
= 1;
747 language
= cupsLangDefault();
749 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
750 "attributes-charset", NULL
, cupsLangEncoding(language
));
752 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
753 "attributes-natural-language", NULL
, language
->language
);
755 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
756 "printer-uri", NULL
, uri
);
759 * Do the request and get back a response...
762 response
= cupsDoRequest(http
, request
, "/");
765 * Build a CUPS_ADD_CLASS request, which requires the following
769 * attributes-natural-language
776 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
777 request
->request
.op
.request_id
= 1;
779 language
= cupsLangDefault();
781 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
782 "attributes-charset", NULL
, cupsLangEncoding(language
));
784 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
785 "attributes-natural-language", NULL
, language
->language
);
787 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
788 "printer-uri", NULL
, uri
);
791 * See if the printer is already in the class...
794 if (response
!= NULL
&&
795 (members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) != NULL
)
796 for (i
= 0; i
< members
->num_values
; i
++)
797 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
799 fprintf(stderr
, "lpadmin: Printer %s is already a member of class %s.\n",
807 * OK, the printer isn't part of the class, so add it...
810 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
812 if (response
!= NULL
&&
813 (members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
)) != NULL
)
816 * Add the printer to the existing list...
819 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
820 "member-uris", members
->num_values
+ 1, NULL
, NULL
);
821 for (i
= 0; i
< members
->num_values
; i
++)
822 attr
->values
[i
].string
.text
= strdup(members
->values
[i
].string
.text
);
824 attr
->values
[i
].string
.text
= strdup(uri
);
827 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "member-uris", NULL
, uri
);
830 * Then send the request...
835 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
836 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
837 ippErrorString(cupsLastError()));
840 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
841 fprintf(stderr
, "lpadmin: add-class failed: %s\n",
842 ippErrorString(response
->request
.status
.status_code
));
850 * 'default_printer()' - Set the default printing destination.
854 default_printer(http_t
*http
, /* I - Server connection */
855 char *printer
) /* I - Printer name */
857 ipp_t
*request
, /* IPP Request */
858 *response
; /* IPP Response */
859 cups_lang_t
*language
; /* Default language */
860 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
863 DEBUG_printf(("default_printer(%p, \"%s\")\n", http
, printer
));
866 * Build a CUPS_SET_DEFAULT request, which requires the following
870 * attributes-natural-language
874 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
878 request
->request
.op
.operation_id
= CUPS_SET_DEFAULT
;
879 request
->request
.op
.request_id
= 1;
881 language
= cupsLangDefault();
883 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
884 "attributes-charset", NULL
, cupsLangEncoding(language
));
886 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
887 "attributes-natural-language", NULL
, language
->language
);
889 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
890 "printer-uri", NULL
, uri
);
893 * Do the request and get back a response...
896 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
897 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
898 ippErrorString(cupsLastError()));
901 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
902 fprintf(stderr
, "lpadmin: set-default failed: %s\n",
903 ippErrorString(response
->request
.status
.status_code
));
911 * 'delete_printer()' - Delete a printer from the system...
915 delete_printer(http_t
*http
, /* I - Server connection */
916 char *printer
) /* I - Printer to delete */
918 ipp_t
*request
, /* IPP Request */
919 *response
; /* IPP Response */
920 cups_lang_t
*language
; /* Default language */
921 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
924 DEBUG_printf(("delete_printer(%p, \"%s\")\n", http
, printer
));
927 * Build a CUPS_DELETE_PRINTER request, which requires the following
931 * attributes-natural-language
935 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
939 request
->request
.op
.operation_id
= CUPS_DELETE_PRINTER
;
940 request
->request
.op
.request_id
= 1;
942 language
= cupsLangDefault();
944 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
945 "attributes-charset", NULL
, cupsLangEncoding(language
));
947 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
948 "attributes-natural-language", NULL
, language
->language
);
950 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
951 "printer-uri", NULL
, uri
);
954 * Do the request and get back a response...
957 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
958 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
959 ippErrorString(cupsLastError()));
962 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
963 fprintf(stderr
, "lpadmin: delete-printer failed: %s\n",
964 ippErrorString(response
->request
.status
.status_code
));
972 * 'delete_printer_from_class()' - Delete a printer from a class.
976 delete_printer_from_class(http_t
*http
, /* I - Server connection */
977 char *printer
, /* I - Printer to remove */
978 char *pclass
) /* I - Class to remove from */
980 int i
, j
, k
; /* Looping vars */
981 ipp_t
*request
, /* IPP Request */
982 *response
; /* IPP Response */
983 ipp_attribute_t
*attr
, /* Current attribute */
984 *members
; /* Members in class */
985 cups_lang_t
*language
; /* Default language */
986 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
989 DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http
,
993 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
997 * attributes-natural-language
1001 snprintf(uri
, sizeof(uri
), "ipp://localhost/classes/%s", pclass
);
1005 request
->request
.op
.operation_id
= IPP_GET_PRINTER_ATTRIBUTES
;
1006 request
->request
.op
.request_id
= 1;
1008 language
= cupsLangDefault();
1010 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1011 "attributes-charset", NULL
, cupsLangEncoding(language
));
1013 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1014 "attributes-natural-language", NULL
, language
->language
);
1016 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1017 "printer-uri", NULL
, uri
);
1020 * Do the request and get back a response...
1023 if ((response
= cupsDoRequest(http
, request
, "/classes/")) == NULL
||
1024 response
->request
.status
.status_code
== IPP_NOT_FOUND
)
1026 ippDelete(response
);
1027 fprintf(stderr
, "lpadmin: Class %s does not exist!\n", pclass
);
1032 * See if the printer is already in the class...
1035 if ((members
= ippFindAttribute(response
, "member-names", IPP_TAG_NAME
)) == NULL
)
1037 ippDelete(response
);
1038 fputs("lpadmin: No member names were seen!\n", stderr
);
1042 for (i
= 0; i
< members
->num_values
; i
++)
1043 if (strcasecmp(printer
, members
->values
[i
].string
.text
) == 0)
1046 if (i
>= members
->num_values
)
1048 fprintf(stderr
, "lpadmin: Printer %s is not a member of class %s.\n",
1050 ippDelete(response
);
1054 if (members
->num_values
== 1)
1057 * Build a CUPS_DELETE_CLASS request, which requires the following
1060 * attributes-charset
1061 * attributes-natural-language
1067 request
->request
.op
.operation_id
= CUPS_DELETE_CLASS
;
1068 request
->request
.op
.request_id
= 1;
1070 language
= cupsLangDefault();
1072 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1073 "attributes-charset", NULL
, cupsLangEncoding(language
));
1075 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1076 "attributes-natural-language", NULL
, language
->language
);
1078 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1079 "printer-uri", NULL
, uri
);
1084 * Build a CUPS_ADD_CLASS request, which requires the following
1087 * attributes-charset
1088 * attributes-natural-language
1095 request
->request
.op
.operation_id
= CUPS_ADD_CLASS
;
1096 request
->request
.op
.request_id
= 1;
1098 language
= cupsLangDefault();
1100 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1101 "attributes-charset", NULL
, cupsLangEncoding(language
));
1103 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1104 "attributes-natural-language", NULL
, language
->language
);
1106 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1107 "printer-uri", NULL
, uri
);
1110 * Delete the printer from the class...
1113 members
= ippFindAttribute(response
, "member-uris", IPP_TAG_URI
);
1114 attr
= ippAddStrings(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1115 "member-uris", members
->num_values
- 1, NULL
, NULL
);
1117 for (j
= 0, k
= 0; j
< members
->num_values
; j
++)
1119 attr
->values
[k
++].string
.text
= strdup(members
->values
[j
].string
.text
);
1123 * Then send the request...
1126 ippDelete(response
);
1128 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1129 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1130 ippErrorString(cupsLastError()));
1133 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1134 fprintf(stderr
, "lpadmin: add/delete-class failed: %s\n",
1135 ippErrorString(response
->request
.status
.status_code
));
1137 ippDelete(response
);
1143 * 'enable_printer()' - Enable a printer...
1147 enable_printer(http_t
*http
, /* I - Server connection */
1148 char *printer
) /* I - Printer to enable */
1150 ipp_t
*request
, /* IPP Request */
1151 *response
; /* IPP Response */
1152 cups_lang_t
*language
; /* Default language */
1153 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1156 DEBUG_printf(("enable_printer(%p, \"%s\")\n", http
, printer
));
1159 * Build a CUPS_ADD_PRINTER request, which requires the following
1162 * attributes-charset
1163 * attributes-natural-language
1166 * printer-is-accepting-jobs
1169 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1173 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1174 request
->request
.op
.request_id
= 1;
1176 language
= cupsLangDefault();
1178 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1179 "attributes-charset", NULL
, cupsLangEncoding(language
));
1181 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1182 "attributes-natural-language", NULL
, language
->language
);
1184 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1185 "printer-uri", NULL
, uri
);
1187 ippAddInteger(request
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
1190 ippAddBoolean(request
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs", 1);
1193 * Do the request and get back a response...
1196 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1197 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1198 ippErrorString(cupsLastError()));
1201 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1202 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1203 ippErrorString(response
->request
.status
.status_code
));
1205 ippDelete(response
);
1211 * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
1214 static char * /* O - Pointer to buf or NULL on EOF */
1215 get_line(char *buf
, /* I - Line buffer */
1216 int length
, /* I - Length of buffer */
1217 FILE *fp
) /* I - File to read from */
1219 char *bufptr
; /* Pointer into buffer */
1220 int ch
; /* Character from file */
1226 while ((ch
= getc(fp
)) != EOF
)
1230 else if (ch
== '\r')
1237 if (ch
!= '\n' && ch
!= EOF
)
1259 * 'set_printer_device()' - Set the device-uri attribute.
1263 set_printer_device(http_t
*http
, /* I - Server connection */
1264 char *printer
, /* I - Printer */
1265 char *device
) /* I - New device URI */
1267 ipp_t
*request
, /* IPP Request */
1268 *response
; /* IPP Response */
1269 cups_lang_t
*language
; /* Default language */
1270 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1273 DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http
, printer
,
1277 * Build a CUPS_ADD_PRINTER request, which requires the following
1280 * attributes-charset
1281 * attributes-natural-language
1285 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1289 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1290 request
->request
.op
.request_id
= 1;
1292 language
= cupsLangDefault();
1294 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1295 "attributes-charset", NULL
, cupsLangEncoding(language
));
1297 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1298 "attributes-natural-language", NULL
, language
->language
);
1300 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1301 "printer-uri", NULL
, uri
);
1304 * Add the device URI...
1307 if (device
[0] == '/')
1310 * Convert filename to URI...
1313 snprintf(uri
, sizeof(uri
), "file:%s", device
);
1314 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1318 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1322 * Do the request and get back a response...
1325 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1326 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1327 ippErrorString(cupsLastError()));
1330 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1331 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1332 ippErrorString(response
->request
.status
.status_code
));
1334 ippDelete(response
);
1340 * 'set_printer_file()' - Set the interface script or PPD file.
1344 set_printer_file(http_t
*http
, /* I - Server connection */
1345 char *printer
, /* I - Printer */
1346 char *file
) /* I - PPD file or interface script */
1348 ipp_t
*request
, /* IPP Request */
1349 *response
; /* IPP Response */
1350 cups_lang_t
*language
; /* Default language */
1351 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1353 char tempfile
[1024]; /* Temporary filename */
1354 int fd
; /* Temporary file */
1355 gzFile
*gz
; /* GZIP'd file */
1356 char buffer
[8192]; /* Copy buffer */
1357 int bytes
; /* Bytes in buffer */
1360 DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http
, printer
,
1364 * See if the file is gzip'd; if so, unzip it to a temporary file and
1365 * send the uncompressed file.
1368 if (strcmp(file
+ strlen(file
) - 3, ".gz") == 0)
1371 * Yes, the file is compressed; uncompress to a temp file...
1374 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
1376 perror("lpadmin: Unable to create temporary file");
1380 if ((gz
= gzopen(file
, "rb")) == NULL
)
1382 perror("lpadmin: Unable to open file");
1388 while ((bytes
= gzread(gz
, buffer
, sizeof(buffer
))) > 0)
1389 write(fd
, buffer
, bytes
);
1396 #endif /* HAVE_LIBZ */
1399 * Build a CUPS_ADD_PRINTER request, which requires the following
1402 * attributes-charset
1403 * attributes-natural-language
1407 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1411 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1412 request
->request
.op
.request_id
= 1;
1414 language
= cupsLangDefault();
1416 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1417 "attributes-charset", NULL
, cupsLangEncoding(language
));
1419 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1420 "attributes-natural-language", NULL
, language
->language
);
1422 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1423 "printer-uri", NULL
, uri
);
1426 * Do the request and get back a response...
1429 if ((response
= cupsDoFileRequest(http
, request
, "/admin/", file
)) == NULL
)
1430 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1431 ippErrorString(cupsLastError()));
1434 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1435 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1436 ippErrorString(response
->request
.status
.status_code
));
1438 ippDelete(response
);
1443 * Remove the temporary file as needed...
1446 if (file
== tempfile
)
1448 #endif /* HAVE_LIBZ */
1453 * 'set_printer_info()' - Set the printer description string.
1457 set_printer_info(http_t
*http
, /* I - Server connection */
1458 char *printer
, /* I - Printer */
1459 char *info
) /* I - New description string */
1461 ipp_t
*request
, /* IPP Request */
1462 *response
; /* IPP Response */
1463 cups_lang_t
*language
; /* Default language */
1464 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1467 DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http
, printer
,
1471 * Build a CUPS_ADD_PRINTER request, which requires the following
1474 * attributes-charset
1475 * attributes-natural-language
1479 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1483 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1484 request
->request
.op
.request_id
= 1;
1486 language
= cupsLangDefault();
1488 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1489 "attributes-charset", NULL
, cupsLangEncoding(language
));
1491 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1492 "attributes-natural-language", NULL
, language
->language
);
1494 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1495 "printer-uri", NULL
, uri
);
1498 * Add the info string...
1501 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info", NULL
,
1505 * Do the request and get back a response...
1508 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1509 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1510 ippErrorString(cupsLastError()));
1513 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1514 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1515 ippErrorString(response
->request
.status
.status_code
));
1517 ippDelete(response
);
1523 * 'set_printer_location()' - Set the printer location string.
1527 set_printer_location(http_t
*http
, /* I - Server connection */
1528 char *printer
, /* I - Printer */
1529 char *location
) /* I - New location string */
1531 ipp_t
*request
, /* IPP Request */
1532 *response
; /* IPP Response */
1533 cups_lang_t
*language
; /* Default language */
1534 char uri
[HTTP_MAX_URI
]; /* URI for printer/class */
1537 DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http
, printer
,
1541 * Build a CUPS_ADD_PRINTER request, which requires the following
1544 * attributes-charset
1545 * attributes-natural-language
1549 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1553 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1554 request
->request
.op
.request_id
= 1;
1556 language
= cupsLangDefault();
1558 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1559 "attributes-charset", NULL
, cupsLangEncoding(language
));
1561 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1562 "attributes-natural-language", NULL
, language
->language
);
1564 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1565 "printer-uri", NULL
, uri
);
1568 * Add the location string...
1571 ippAddString(request
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location", NULL
,
1575 * Do the request and get back a response...
1578 if ((response
= cupsDoRequest(http
, request
, "/admin/")) == NULL
)
1579 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1580 ippErrorString(cupsLastError()));
1583 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1584 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1585 ippErrorString(response
->request
.status
.status_code
));
1587 ippDelete(response
);
1593 * 'set_printer_options()' - Set the printer options.
1597 set_printer_options(http_t
*http
, /* I - Server connection */
1598 char *printer
, /* I - Printer */
1599 int num_options
, /* I - Number of options */
1600 cups_option_t
*options
) /* I - Options */
1602 ipp_t
*request
, /* IPP Request */
1603 *response
; /* IPP Response */
1604 cups_lang_t
*language
; /* Default language */
1605 const char *val
, /* Option value */
1606 *ppdfile
; /* PPD filename */
1607 char uri
[HTTP_MAX_URI
], /* URI for printer/class */
1608 line
[1024], /* Line from PPD file */
1609 keyword
[1024], /* Keyword from Default line */
1610 *keyptr
, /* Pointer into keyword... */
1611 tempfile
[1024]; /* Temporary filename */
1612 FILE *in
, /* PPD file */
1613 *out
; /* Temporary file */
1614 int outfd
; /* Temporary file descriptor */
1617 DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http
, printer
,
1618 num_options
, options
));
1621 * Build a CUPS_ADD_PRINTER request, which requires the following
1624 * attributes-charset
1625 * attributes-natural-language
1630 snprintf(uri
, sizeof(uri
), "ipp://localhost/printers/%s", printer
);
1634 request
->request
.op
.operation_id
= CUPS_ADD_PRINTER
;
1635 request
->request
.op
.request_id
= 1;
1637 language
= cupsLangDefault();
1639 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
1640 "attributes-charset", NULL
, cupsLangEncoding(language
));
1642 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
1643 "attributes-natural-language", NULL
, language
->language
);
1645 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
1646 "printer-uri", NULL
, uri
);
1649 * Add the options...
1652 cupsEncodeOptions(request
, num_options
, options
);
1654 if ((ppdfile
= cupsGetPPD(printer
)) != NULL
)
1657 * Set default options in the PPD file...
1660 outfd
= cupsTempFd(tempfile
, sizeof(tempfile
));
1662 in
= fopen(ppdfile
, "rb");
1663 out
= fdopen(outfd
, "wb");
1665 while (get_line(line
, sizeof(line
), in
) != NULL
)
1667 if (strncmp(line
, "*Default", 8) != 0)
1668 fprintf(out
, "%s\n", line
);
1672 * Get default option name...
1675 strncpy(keyword
, line
+ 8, sizeof(keyword
) - 1);
1676 keyword
[sizeof(keyword
) - 1] = '\0';
1678 for (keyptr
= keyword
; *keyptr
; keyptr
++)
1679 if (*keyptr
== ':' || isspace(*keyptr
))
1684 if (strcmp(keyword
, "PageRegion") == 0)
1685 val
= cupsGetOption("PageSize", num_options
, options
);
1687 val
= cupsGetOption(keyword
, num_options
, options
);
1690 fprintf(out
, "*Default%s: %s\n", keyword
, val
);
1692 fprintf(out
, "%s\n", line
);
1704 response
= cupsDoFileRequest(http
, request
, "/admin/", tempfile
);
1707 * Clean up temp files... (TODO: catch signals in case we CTRL-C during
1717 * No PPD file - just set the options...
1720 response
= cupsDoRequest(http
, request
, "/admin/");
1724 * Do the request and get back a response...
1727 if (response
== NULL
)
1728 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1729 ippErrorString(cupsLastError()));
1732 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
1733 fprintf(stderr
, "lpadmin: add-printer failed: %s\n",
1734 ippErrorString(response
->request
.status
.status_code
));
1736 ippDelete(response
);
1742 * 'validate_name()' - Make sure the printer name only contains letters,
1743 * numbers, and the underscore...
1746 static int /* O - 0 if name is no good, 1 if name is good */
1747 validate_name(const char *name
) /* I - Name to check */
1750 * Don't allow names to start with a digit...
1757 * Scan the whole name...
1763 else if (!isalnum(*name
) && *name
!= '_')
1773 * End of "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $".