1 /*
2 * "cupsaccept", "cupsdisable", "cupsenable", and "cupsreject" commands for
3 * CUPS.
4 *
5 * Copyright © 2020-2024 by OpenPrinting.
6 * Copyright © 2007-2018 by Apple Inc.
7 * Copyright © 1997-2006 by Easy Software Products.
8 *
9 * Licensed under Apache License v2.0. See the file "LICENSE" for more
10 * information.
11 */
12
13 /*
14 * Include necessary headers...
15 */
16
17 #include <cups/cups-private.h>
18
19
20 /*
21 * Local functions...
22 */
23
24 static void usage(const char *command) _CUPS_NORETURN;
25
26
27 /*
28 * 'main()' - Parse options and accept/reject jobs or disable/enable printers.
29 */
30
31 int /* O - Exit status */
main(int argc,char * argv[])32 main(int argc, /* I - Number of command-line arguments */
33 char *argv[]) /* I - Command-line arguments */
34 {
35 int i; /* Looping var */
36 char *command, /* Command to do */
37 *opt, /* Option pointer */
38 uri[1024], /* Printer URI */
39 *reason; /* Reason for reject/disable */
40 ipp_t *request; /* IPP request */
41 ipp_op_t op; /* Operation */
42 int cancel; /* Cancel jobs? */
43
44
45 _cupsSetLocale(argv);
46
47 /*
48 * See what operation we're supposed to do...
49 */
50
51 if ((command = strrchr(argv[0], '/')) != NULL)
52 command ++;
53 else
54 command = argv[0];
55
56 cancel = 0;
57
58 if (!strcmp(command, "cupsaccept"))
59 op = CUPS_ACCEPT_JOBS;
60 else if (!strcmp(command, "cupsreject"))
61 op = CUPS_REJECT_JOBS;
62 else if (!strcmp(command, "cupsdisable"))
63 op = IPP_PAUSE_PRINTER;
64 else if (!strcmp(command, "cupsenable"))
65 op = IPP_RESUME_PRINTER;
66 else
67 {
68 _cupsLangPrintf(stderr, _("%s: Don't know what to do."), command);
69 return (1);
70 }
71
72 reason = NULL;
73
74 /*
75 * Process command-line arguments...
76 */
77
78 for (i = 1; i < argc; i ++)
79 {
80 if (!strcmp(argv[i], "--help"))
81 usage(command);
82 else if (!strcmp(argv[i], "--hold"))
83 op = IPP_HOLD_NEW_JOBS;
84 else if (!strcmp(argv[i], "--release"))
85 op = IPP_RELEASE_HELD_NEW_JOBS;
86 else if (argv[i][0] == '-')
87 {
88 for (opt = argv[i] + 1; *opt; opt ++)
89 {
90 switch (*opt)
91 {
92 case 'E' : /* Encrypt */
93 #ifdef HAVE_TLS
94 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
95 #else
96 _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), command);
97 #endif /* HAVE_TLS */
98 break;
99
100 case 'U' : /* Username */
101 if (opt[1] != '\0')
102 {
103 cupsSetUser(opt + 1);
104 opt += strlen(opt) - 1;
105 }
106 else
107 {
108 i ++;
109 if (i >= argc)
110 {
111 _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), command);
112 usage(command);
113 }
114
115 cupsSetUser(argv[i]);
116 }
117 break;
118
119 case 'c' : /* Cancel jobs */
120 cancel = 1;
121 break;
122
123 case 'h' : /* Connect to host */
124 if (opt[1] != '\0')
125 {
126 cupsSetServer(opt + 1);
127 opt += strlen(opt) - 1;
128 }
129 else
130 {
131 i ++;
132 if (i >= argc)
133 {
134 _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), command);
135 usage(command);
136 }
137
138 cupsSetServer(argv[i]);
139 }
140 break;
141
142 case 'r' : /* Reason for cancellation */
143 if (opt[1] != '\0')
144 {
145 reason = opt + 1;
146 opt += strlen(opt) - 1;
147 }
148 else
149 {
150 i ++;
151 if (i >= argc)
152 {
153 _cupsLangPrintf(stderr, _("%s: Error - expected reason text after \"-r\" option."), command);
154 usage(command);
155 }
156
157 reason = argv[i];
158 }
159 break;
160
161 default :
162 _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), command, *opt);
163 usage(command);
164 }
165 }
166 }
167 else
168 {
169 /*
170 * Accept/disable/enable/reject a destination...
171 */
172
173 request = ippNewRequest(op);
174
175 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
176 "localhost", 0, "/printers/%s", argv[i]);
177 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
178 "printer-uri", NULL, uri);
179
180 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
181 "requesting-user-name", NULL, cupsUser());
182
183 if (reason != NULL)
184 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
185 "printer-state-message", NULL, reason);
186
187 /*
188 * Do the request and get back a response...
189 */
190
191 ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/"));
192
193 if (cupsLastError() > IPP_OK_CONFLICT)
194 {
195 _cupsLangPrintf(stderr,
196 _("%s: Operation failed: %s"),
197 command, ippErrorString(cupsLastError()));
198 return (1);
199 }
200
201 /*
202 * Cancel all jobs if requested...
203 */
204
205 if (cancel)
206 {
207 /*
208 * Build an IPP_PURGE_JOBS request, which requires the following
209 * attributes:
210 *
211 * attributes-charset
212 * attributes-natural-language
213 * printer-uri
214 */
215
216 request = ippNewRequest(IPP_PURGE_JOBS);
217
218 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
219 "printer-uri", NULL, uri);
220
221 ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/"));
222
223 if (cupsLastError() > IPP_OK_CONFLICT)
224 {
225 _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
226 return (1);
227 }
228 }
229 }
230 }
231
232 return (0);
233 }
234
235
236 /*
237 * 'usage()' - Show program usage and exit.
238 */
239
240 static void
usage(const char * command)241 usage(const char *command) /* I - Command name */
242 {
243 _cupsLangPrintf(stdout, _("Usage: %s [options] destination(s)"), command);
244 _cupsLangPuts(stdout, _("Options:"));
245 _cupsLangPuts(stdout, _("-E Encrypt the connection to the server"));
246 _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port"));
247 _cupsLangPuts(stdout, _("-r reason Specify a reason message that others can see"));
248 _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication"));
249 if (!strcmp(command, "cupsdisable"))
250 _cupsLangPuts(stdout, _("--hold Hold new jobs"));
251 if (!strcmp(command, "cupsenable"))
252 _cupsLangPuts(stdout, _("--release Release previously held jobs"));
253
254 exit(1);
255 }
256