]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
503b54c9 | 2 | * "cancel" command for CUPS. |
ef416fc2 | 3 | * |
bdbfacc7 | 4 | * Copyright 2007-2016 by Apple Inc. |
503b54c9 | 5 | * Copyright 1997-2006 by Easy Software Products. |
ef416fc2 | 6 | * |
503b54c9 MS |
7 | * These coded instructions, statements, and computer programs are the |
8 | * property of Apple Inc. and are protected by Federal copyright | |
9 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
10 | * which should have been included with this file. If this file is | |
57b7b66b | 11 | * missing or damaged, see the license at "http://www.cups.org/". |
ef416fc2 | 12 | */ |
13 | ||
14 | /* | |
15 | * Include necessary headers... | |
16 | */ | |
17 | ||
71e16022 | 18 | #include <cups/cups-private.h> |
ef416fc2 | 19 | |
20 | ||
21 | /* | |
22 | * 'main()' - Parse options and cancel jobs. | |
23 | */ | |
24 | ||
25 | int /* O - Exit status */ | |
26 | main(int argc, /* I - Number of command-line arguments */ | |
27 | char *argv[]) /* I - Command-line arguments */ | |
28 | { | |
29 | http_t *http; /* HTTP connection to server */ | |
30 | int i; /* Looping var */ | |
31 | int job_id; /* Job ID */ | |
32 | int num_dests; /* Number of destinations */ | |
33 | cups_dest_t *dests; /* Destinations */ | |
bdbfacc7 MS |
34 | char *opt, /* Option pointer */ |
35 | *dest, /* Destination printer */ | |
ef416fc2 | 36 | *job, /* Job ID pointer */ |
37 | *user; /* Cancel jobs for a user */ | |
38 | int purge; /* Purge or cancel jobs? */ | |
39 | char uri[1024]; /* Printer or job URI */ | |
40 | ipp_t *request; /* IPP request */ | |
41 | ipp_t *response; /* IPP response */ | |
42 | ipp_op_t op; /* Operation */ | |
ef416fc2 | 43 | |
44 | ||
07725fee | 45 | _cupsSetLocale(argv); |
d09495fa | 46 | |
ef416fc2 | 47 | /* |
48 | * Setup to cancel individual print jobs... | |
49 | */ | |
50 | ||
fa73b229 | 51 | op = IPP_CANCEL_JOB; |
52 | purge = 0; | |
fa73b229 | 53 | dest = NULL; |
54 | user = NULL; | |
55 | http = NULL; | |
56 | num_dests = 0; | |
57 | dests = NULL; | |
ef416fc2 | 58 | |
59 | ||
60 | /* | |
61 | * Process command-line arguments... | |
62 | */ | |
63 | ||
64 | for (i = 1; i < argc; i ++) | |
bdbfacc7 | 65 | { |
ef416fc2 | 66 | if (argv[i][0] == '-' && argv[i][1]) |
db8b865d | 67 | { |
bdbfacc7 | 68 | for (opt = argv[i] + 1; *opt; opt ++) |
ef416fc2 | 69 | { |
bdbfacc7 MS |
70 | switch (*opt) |
71 | { | |
72 | case 'E' : /* Encrypt */ | |
ef416fc2 | 73 | #ifdef HAVE_SSL |
bdbfacc7 | 74 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); |
ef416fc2 | 75 | |
bdbfacc7 MS |
76 | if (http) |
77 | httpEncryption(http, HTTP_ENCRYPT_REQUIRED); | |
ef416fc2 | 78 | #else |
bdbfacc7 | 79 | _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); |
ef416fc2 | 80 | #endif /* HAVE_SSL */ |
bdbfacc7 MS |
81 | break; |
82 | ||
83 | case 'U' : /* Username */ | |
84 | if (opt[1] != '\0') | |
85 | { | |
86 | cupsSetUser(opt + 1); | |
87 | opt += strlen(opt) - 1; | |
88 | } | |
89 | else | |
fa73b229 | 90 | { |
bdbfacc7 MS |
91 | i ++; |
92 | if (i >= argc) | |
93 | { | |
94 | _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]); | |
95 | return (1); | |
96 | } | |
97 | ||
98 | cupsSetUser(argv[i]); | |
fa73b229 | 99 | } |
bdbfacc7 | 100 | break; |
fa73b229 | 101 | |
bdbfacc7 MS |
102 | case 'a' : /* Cancel all jobs */ |
103 | op = purge ? IPP_PURGE_JOBS : IPP_CANCEL_JOBS; | |
104 | break; | |
88f9aafc | 105 | |
bdbfacc7 MS |
106 | case 'h' : /* Connect to host */ |
107 | if (http != NULL) | |
108 | { | |
109 | httpClose(http); | |
110 | http = NULL; | |
111 | } | |
ef416fc2 | 112 | |
bdbfacc7 MS |
113 | if (opt[1] != '\0') |
114 | { | |
115 | cupsSetServer(opt + 1); | |
116 | opt += strlen(opt) - 1; | |
117 | } | |
118 | else | |
119 | { | |
120 | i ++; | |
121 | ||
122 | if (i >= argc) | |
123 | { | |
124 | _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), argv[0]); | |
125 | return (1); | |
126 | } | |
127 | else | |
128 | cupsSetServer(argv[i]); | |
129 | } | |
130 | break; | |
ef416fc2 | 131 | |
bdbfacc7 MS |
132 | case 'u' : /* Username */ |
133 | op = IPP_CANCEL_MY_JOBS; | |
ef416fc2 | 134 | |
bdbfacc7 | 135 | if (opt[1] != '\0') |
ef416fc2 | 136 | { |
bdbfacc7 MS |
137 | user = opt + 1; |
138 | opt += strlen(opt) - 1; | |
139 | } | |
ef416fc2 | 140 | else |
bdbfacc7 MS |
141 | { |
142 | i ++; | |
143 | ||
144 | if (i >= argc) | |
145 | { | |
146 | _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-u\" option."), argv[0]); | |
147 | return (1); | |
148 | } | |
149 | else | |
150 | user = argv[i]; | |
151 | } | |
152 | break; | |
ef416fc2 | 153 | |
bdbfacc7 MS |
154 | case 'x' : /* Purge job(s) */ |
155 | purge = 1; | |
ef416fc2 | 156 | |
bdbfacc7 MS |
157 | if (op == IPP_CANCEL_JOBS) |
158 | op = IPP_PURGE_JOBS; | |
159 | break; | |
ef416fc2 | 160 | |
bdbfacc7 MS |
161 | default : |
162 | _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], *opt); | |
163 | return (1); | |
164 | } | |
ef416fc2 | 165 | } |
db8b865d | 166 | } |
ef416fc2 | 167 | else |
168 | { | |
169 | /* | |
170 | * Cancel a job or printer... | |
171 | */ | |
172 | ||
173 | if (num_dests == 0) | |
174 | num_dests = cupsGetDests(&dests); | |
175 | ||
bd7854cb | 176 | if (!strcmp(argv[i], "-")) |
ef416fc2 | 177 | { |
178 | /* | |
179 | * Delete the current job... | |
180 | */ | |
181 | ||
182 | dest = ""; | |
183 | job_id = 0; | |
184 | } | |
185 | else if (cupsGetDest(argv[i], NULL, num_dests, dests) != NULL) | |
186 | { | |
187 | /* | |
188 | * Delete the current job on the named destination... | |
189 | */ | |
190 | ||
191 | dest = argv[i]; | |
192 | job_id = 0; | |
193 | } | |
194 | else if ((job = strrchr(argv[i], '-')) != NULL && isdigit(job[1] & 255)) | |
195 | { | |
196 | /* | |
197 | * Delete the specified job ID. | |
198 | */ | |
199 | ||
200 | dest = NULL; | |
201 | op = IPP_CANCEL_JOB; | |
202 | job_id = atoi(job + 1); | |
203 | } | |
204 | else if (isdigit(argv[i][0] & 255)) | |
205 | { | |
206 | /* | |
207 | * Delete the specified job ID. | |
208 | */ | |
209 | ||
210 | dest = NULL; | |
211 | op = IPP_CANCEL_JOB; | |
212 | job_id = atoi(argv[i]); | |
213 | } | |
214 | else | |
215 | { | |
216 | /* | |
217 | * Bad printer name! | |
218 | */ | |
219 | ||
fa73b229 | 220 | _cupsLangPrintf(stderr, |
0837b7e8 | 221 | _("%s: Error - unknown destination \"%s\"."), |
fa73b229 | 222 | argv[0], argv[i]); |
ef416fc2 | 223 | return (1); |
224 | } | |
225 | ||
226 | /* | |
227 | * For Solaris LP compatibility, ignore a destination name after | |
228 | * cancelling a specific job ID... | |
229 | */ | |
230 | ||
231 | if (job_id && (i + 1) < argc && | |
232 | cupsGetDest(argv[i + 1], NULL, num_dests, dests) != NULL) | |
233 | i ++; | |
234 | ||
235 | /* | |
236 | * Open a connection to the server... | |
237 | */ | |
238 | ||
239 | if (http == NULL) | |
240 | if ((http = httpConnectEncrypt(cupsServer(), ippPort(), | |
241 | cupsEncryption())) == NULL) | |
242 | { | |
fa73b229 | 243 | _cupsLangPrintf(stderr, |
84315f46 | 244 | _("%s: Unable to connect to server."), argv[0]); |
ef416fc2 | 245 | return (1); |
246 | } | |
247 | ||
248 | /* | |
249 | * Build an IPP request, which requires the following | |
250 | * attributes: | |
251 | * | |
252 | * attributes-charset | |
253 | * attributes-natural-language | |
254 | * printer-uri + job-id *or* job-uri | |
255 | * [requesting-user-name] | |
256 | */ | |
257 | ||
fa73b229 | 258 | request = ippNewRequest(op); |
ef416fc2 | 259 | |
260 | if (dest) | |
261 | { | |
a4d04587 | 262 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
263 | "localhost", 0, "/printers/%s", dest); | |
ef416fc2 | 264 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, |
265 | "printer-uri", NULL, uri); | |
266 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", | |
267 | job_id); | |
268 | } | |
269 | else | |
270 | { | |
271 | sprintf(uri, "ipp://localhost/jobs/%d", job_id); | |
272 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, | |
273 | uri); | |
274 | } | |
275 | ||
276 | if (user) | |
277 | { | |
278 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
279 | "requesting-user-name", NULL, user); | |
280 | ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); | |
db8b865d MS |
281 | |
282 | if (op == IPP_CANCEL_JOBS) | |
283 | op = IPP_CANCEL_MY_JOBS; | |
ef416fc2 | 284 | } |
285 | else | |
286 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
287 | "requesting-user-name", NULL, cupsUser()); | |
288 | ||
db8b865d | 289 | if (purge) |
68c4690a | 290 | ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", (char)purge); |
ef416fc2 | 291 | |
292 | /* | |
293 | * Do the request and get back a response... | |
294 | */ | |
295 | ||
db8b865d | 296 | if (op == IPP_CANCEL_JOBS && (!user || _cups_strcasecmp(user, cupsUser()))) |
ef416fc2 | 297 | response = cupsDoRequest(http, request, "/admin/"); |
298 | else | |
299 | response = cupsDoRequest(http, request, "/jobs/"); | |
300 | ||
301 | if (response == NULL || | |
302 | response->request.status.status_code > IPP_OK_CONFLICT) | |
303 | { | |
0837b7e8 | 304 | _cupsLangPrintf(stderr, _("%s: %s failed: %s"), argv[0], |
ef416fc2 | 305 | op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", |
bd7854cb | 306 | cupsLastErrorString()); |
ef416fc2 | 307 | |
308 | if (response) | |
309 | ippDelete(response); | |
310 | ||
311 | return (1); | |
312 | } | |
313 | ||
314 | ippDelete(response); | |
315 | } | |
bdbfacc7 | 316 | } |
ef416fc2 | 317 | |
242b936a | 318 | if (num_dests == 0 && op != IPP_CANCEL_JOB) |
ef416fc2 | 319 | { |
320 | /* | |
321 | * Open a connection to the server... | |
322 | */ | |
323 | ||
324 | if (http == NULL) | |
325 | if ((http = httpConnectEncrypt(cupsServer(), ippPort(), | |
326 | cupsEncryption())) == NULL) | |
327 | { | |
0837b7e8 | 328 | _cupsLangPrintf(stderr, _("%s: Unable to contact server."), argv[0]); |
ef416fc2 | 329 | return (1); |
330 | } | |
331 | ||
332 | /* | |
333 | * Build an IPP request, which requires the following | |
334 | * attributes: | |
335 | * | |
336 | * attributes-charset | |
337 | * attributes-natural-language | |
338 | * printer-uri + job-id *or* job-uri | |
339 | * [requesting-user-name] | |
340 | */ | |
341 | ||
fa73b229 | 342 | request = ippNewRequest(op); |
ef416fc2 | 343 | |
344 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
345 | "printer-uri", NULL, "ipp://localhost/printers/"); | |
346 | ||
347 | if (user) | |
348 | { | |
349 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
350 | "requesting-user-name", NULL, user); | |
351 | ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); | |
352 | } | |
353 | else | |
354 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
355 | "requesting-user-name", NULL, cupsUser()); | |
356 | ||
68c4690a | 357 | ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", (char)purge); |
ef416fc2 | 358 | |
359 | /* | |
360 | * Do the request and get back a response... | |
361 | */ | |
362 | ||
363 | response = cupsDoRequest(http, request, "/admin/"); | |
364 | ||
365 | if (response == NULL || | |
366 | response->request.status.status_code > IPP_OK_CONFLICT) | |
367 | { | |
0837b7e8 | 368 | _cupsLangPrintf(stderr, _("%s: %s failed: %s"), argv[0], |
ef416fc2 | 369 | op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", |
fa73b229 | 370 | cupsLastErrorString()); |
ef416fc2 | 371 | |
372 | if (response) | |
373 | ippDelete(response); | |
374 | ||
375 | return (1); | |
376 | } | |
377 | ||
378 | ippDelete(response); | |
379 | } | |
380 | ||
381 | return (0); | |
382 | } |