]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
7e86f2f6 | 2 | * "lp" command for CUPS. |
ef416fc2 | 3 | * |
fca9a981 | 4 | * Copyright © 2007-2019 by Apple Inc. |
8e52928c | 5 | * Copyright © 1997-2007 by Easy Software Products. |
ef416fc2 | 6 | * |
8e52928c MS |
7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more |
8 | * information. | |
ef416fc2 | 9 | */ |
10 | ||
11 | /* | |
12 | * Include necessary headers... | |
13 | */ | |
14 | ||
71e16022 | 15 | #include <cups/cups-private.h> |
ef416fc2 | 16 | |
17 | ||
ef416fc2 | 18 | /* |
19 | * Local functions. | |
20 | */ | |
21 | ||
8e52928c MS |
22 | static int restart_job(const char *command, int job_id); |
23 | static int set_job_attrs(const char *command, int job_id, int num_options, cups_option_t *options); | |
24 | static void usage(void) _CUPS_NORETURN; | |
ef416fc2 | 25 | |
26 | ||
ef416fc2 | 27 | /* |
28 | * 'main()' - Parse options and send files for printing. | |
29 | */ | |
30 | ||
31 | int | |
32 | main(int argc, /* I - Number of command-line arguments */ | |
33 | char *argv[]) /* I - Command-line arguments */ | |
34 | { | |
35 | int i, j; /* Looping vars */ | |
36 | int job_id; /* Job ID */ | |
37 | char *printer, /* Printer name */ | |
a29fd7dd | 38 | *instance, /* Instance name */ |
bdbfacc7 | 39 | *opt, /* Option pointer */ |
ef416fc2 | 40 | *val, /* Option value */ |
41 | *title; /* Job title */ | |
42 | int priority; /* Job priority (1-100) */ | |
43 | int num_copies; /* Number of copies per file */ | |
44 | int num_files; /* Number of files to print */ | |
45 | const char *files[1000]; /* Files to print */ | |
a4924f6c | 46 | cups_dest_t *dest; /* Selected destination */ |
ef416fc2 | 47 | int num_options; /* Number of options */ |
48 | cups_option_t *options; /* Options */ | |
fa73b229 | 49 | int end_options; /* No more options? */ |
ef416fc2 | 50 | int silent; /* Silent or verbose output? */ |
51 | char buffer[8192]; /* Copy buffer */ | |
ef416fc2 | 52 | |
53 | ||
54 | #ifdef __sun | |
55 | /* | |
56 | * Solaris does some rather strange things to re-queue remote print | |
57 | * jobs. On bootup, the "lp" command is run as "printd" to re-spool | |
58 | * any remote jobs in /var/spool/print. Since CUPS doesn't need this | |
59 | * nonsense, we just need to add the necessary check here to prevent | |
60 | * lp from causing boot problems... | |
61 | */ | |
62 | ||
63 | if ((val = strrchr(argv[0], '/')) != NULL) | |
64 | val ++; | |
65 | else | |
66 | val = argv[0]; | |
67 | ||
68 | if (!strcmp(val, "printd")) | |
69 | return (0); | |
70 | #endif /* __sun */ | |
71 | ||
07725fee | 72 | _cupsSetLocale(argv); |
d09495fa | 73 | |
ef416fc2 | 74 | silent = 0; |
75 | printer = NULL; | |
a4924f6c | 76 | dest = NULL; |
ef416fc2 | 77 | num_options = 0; |
78 | options = NULL; | |
79 | num_files = 0; | |
80 | title = NULL; | |
81 | job_id = 0; | |
fa73b229 | 82 | end_options = 0; |
ef416fc2 | 83 | |
84 | for (i = 1; i < argc; i ++) | |
bdbfacc7 | 85 | { |
8e52928c MS |
86 | if (!strcmp(argv[i], "--help")) |
87 | usage(); | |
88 | else if (argv[i][0] == '-' && argv[i][1] && !end_options) | |
bdbfacc7 MS |
89 | { |
90 | for (opt = argv[i] + 1; *opt; opt ++) | |
ef416fc2 | 91 | { |
bdbfacc7 MS |
92 | switch (*opt) |
93 | { | |
94 | case 'E' : /* Encrypt */ | |
ef416fc2 | 95 | #ifdef HAVE_SSL |
bdbfacc7 | 96 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); |
ef416fc2 | 97 | #else |
bdbfacc7 | 98 | _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); |
ef416fc2 | 99 | #endif /* HAVE_SSL */ |
bdbfacc7 | 100 | break; |
ef416fc2 | 101 | |
bdbfacc7 MS |
102 | case 'U' : /* Username */ |
103 | if (opt[1] != '\0') | |
104 | { | |
105 | cupsSetUser(opt + 1); | |
106 | opt += strlen(opt) - 1; | |
107 | } | |
108 | else | |
fa73b229 | 109 | { |
bdbfacc7 MS |
110 | i ++; |
111 | if (i >= argc) | |
112 | { | |
113 | _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]); | |
8e52928c | 114 | usage(); |
bdbfacc7 MS |
115 | } |
116 | ||
117 | cupsSetUser(argv[i]); | |
fa73b229 | 118 | } |
bdbfacc7 | 119 | break; |
fa73b229 | 120 | |
bdbfacc7 MS |
121 | case 'c' : /* Copy to spool dir (always enabled) */ |
122 | break; | |
a29fd7dd | 123 | |
bdbfacc7 MS |
124 | case 'd' : /* Destination printer or class */ |
125 | if (opt[1] != '\0') | |
126 | { | |
127 | printer = opt + 1; | |
128 | opt += strlen(opt) - 1; | |
129 | } | |
130 | else | |
131 | { | |
132 | i ++; | |
ef416fc2 | 133 | |
bdbfacc7 MS |
134 | if (i >= argc) |
135 | { | |
136 | _cupsLangPrintf(stderr, _("%s: Error - expected destination after \"-d\" option."), argv[0]); | |
8e52928c | 137 | usage(); |
bdbfacc7 | 138 | } |
ef416fc2 | 139 | |
bdbfacc7 MS |
140 | printer = argv[i]; |
141 | } | |
ef416fc2 | 142 | |
bdbfacc7 MS |
143 | if ((instance = strrchr(printer, '/')) != NULL) |
144 | *instance++ = '\0'; | |
ef416fc2 | 145 | |
bdbfacc7 MS |
146 | if ((dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, |
147 | instance)) != NULL) | |
ef416fc2 | 148 | { |
bdbfacc7 MS |
149 | for (j = 0; j < dest->num_options; j ++) |
150 | if (cupsGetOption(dest->options[j].name, num_options, | |
151 | options) == NULL) | |
152 | num_options = cupsAddOption(dest->options[j].name, | |
153 | dest->options[j].value, | |
154 | num_options, &options); | |
155 | } | |
156 | else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || | |
157 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
158 | { | |
159 | _cupsLangPrintf(stderr, | |
160 | _("%s: Error - add '/version=1.1' to server " | |
161 | "name."), argv[0]); | |
ef416fc2 | 162 | return (1); |
bdbfacc7 MS |
163 | } |
164 | break; | |
165 | ||
166 | case 'f' : /* Form */ | |
167 | if (opt[1] != '\0') | |
168 | { | |
169 | opt += strlen(opt) - 1; | |
170 | } | |
171 | else | |
172 | { | |
173 | i ++; | |
ef416fc2 | 174 | |
bdbfacc7 MS |
175 | if (i >= argc) |
176 | { | |
177 | _cupsLangPrintf(stderr, _("%s: Error - expected form after \"-f\" option."), argv[0]); | |
8e52928c | 178 | usage(); |
bdbfacc7 MS |
179 | } |
180 | } | |
ef416fc2 | 181 | |
bdbfacc7 MS |
182 | _cupsLangPrintf(stderr, _("%s: Warning - form option ignored."), argv[0]); |
183 | break; | |
ef416fc2 | 184 | |
bdbfacc7 MS |
185 | case 'h' : /* Destination host */ |
186 | if (opt[1] != '\0') | |
ef416fc2 | 187 | { |
bdbfacc7 MS |
188 | cupsSetServer(opt + 1); |
189 | opt += strlen(opt) - 1; | |
190 | } | |
191 | else | |
192 | { | |
193 | i ++; | |
ef416fc2 | 194 | |
bdbfacc7 MS |
195 | if (i >= argc) |
196 | { | |
197 | _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), argv[0]); | |
8e52928c | 198 | usage(); |
bdbfacc7 | 199 | } |
ef416fc2 | 200 | |
bdbfacc7 MS |
201 | cupsSetServer(argv[i]); |
202 | } | |
203 | break; | |
ef416fc2 | 204 | |
bdbfacc7 MS |
205 | case 'i' : /* Change job */ |
206 | if (opt[1] != '\0') | |
ef416fc2 | 207 | { |
bdbfacc7 MS |
208 | val = opt + 1; |
209 | opt += strlen(opt) - 1; | |
210 | } | |
211 | else | |
212 | { | |
213 | i ++; | |
ef416fc2 | 214 | |
bdbfacc7 MS |
215 | if (i >= argc) |
216 | { | |
217 | _cupsLangPrintf(stderr, _("%s: Expected job ID after \"-i\" option."), argv[0]); | |
8e52928c | 218 | usage(); |
bdbfacc7 | 219 | } |
ef416fc2 | 220 | |
bdbfacc7 MS |
221 | val = argv[i]; |
222 | } | |
ef416fc2 | 223 | |
bdbfacc7 MS |
224 | if (num_files > 0) |
225 | { | |
226 | _cupsLangPrintf(stderr, _("%s: Error - cannot print files and alter jobs simultaneously."), argv[0]); | |
227 | return (1); | |
228 | } | |
ef416fc2 | 229 | |
bdbfacc7 MS |
230 | if (strrchr(val, '-') != NULL) |
231 | job_id = atoi(strrchr(val, '-') + 1); | |
232 | else | |
233 | job_id = atoi(val); | |
234 | ||
235 | if (job_id < 0) | |
236 | { | |
237 | _cupsLangPrintf(stderr, _("%s: Error - bad job ID."), argv[0]); | |
238 | break; | |
239 | } | |
ef416fc2 | 240 | break; |
ef416fc2 | 241 | |
bdbfacc7 | 242 | case 'm' : /* Send email when job is done */ |
ef416fc2 | 243 | #ifdef __sun |
bdbfacc7 | 244 | case 'p' : /* Notify on completion */ |
ef416fc2 | 245 | #endif /* __sun */ |
bdbfacc7 MS |
246 | case 'w' : /* Write to console or email */ |
247 | { | |
248 | char email[1024]; /* EMail address */ | |
fa73b229 | 249 | |
fa73b229 | 250 | |
bdbfacc7 MS |
251 | snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL, buffer, sizeof(buffer))); |
252 | num_options = cupsAddOption("notify-recipient-uri", email, num_options, &options); | |
253 | } | |
ef416fc2 | 254 | |
bdbfacc7 MS |
255 | silent = 1; |
256 | break; | |
ef416fc2 | 257 | |
bdbfacc7 MS |
258 | case 'n' : /* Number of copies */ |
259 | if (opt[1] != '\0') | |
ef416fc2 | 260 | { |
bdbfacc7 MS |
261 | num_copies = atoi(opt + 1); |
262 | opt += strlen(opt) - 1; | |
263 | } | |
264 | else | |
265 | { | |
266 | i ++; | |
ef416fc2 | 267 | |
bdbfacc7 MS |
268 | if (i >= argc) |
269 | { | |
270 | _cupsLangPrintf(stderr, _("%s: Error - expected copies after \"-n\" option."), argv[0]); | |
8e52928c | 271 | usage(); |
bdbfacc7 | 272 | } |
ef416fc2 | 273 | |
bdbfacc7 MS |
274 | num_copies = atoi(argv[i]); |
275 | } | |
ef416fc2 | 276 | |
bdbfacc7 | 277 | if (num_copies < 1) |
ef416fc2 | 278 | { |
bdbfacc7 | 279 | _cupsLangPrintf(stderr, _("%s: Error - copies must be 1 or more."), argv[0]); |
ef416fc2 | 280 | return (1); |
bdbfacc7 MS |
281 | } |
282 | ||
283 | sprintf(buffer, "%d", num_copies); | |
284 | num_options = cupsAddOption("copies", buffer, num_options, | |
285 | &options); | |
286 | break; | |
ef416fc2 | 287 | |
bdbfacc7 MS |
288 | case 'o' : /* Option */ |
289 | if (opt[1] != '\0') | |
290 | { | |
291 | num_options = cupsParseOptions(opt + 1, num_options, &options); | |
292 | opt += strlen(opt) - 1; | |
293 | } | |
294 | else | |
295 | { | |
296 | i ++; | |
297 | ||
298 | if (i >= argc) | |
299 | { | |
300 | _cupsLangPrintf(stderr, _("%s: Error - expected option=value after \"-o\" option."), argv[0]); | |
8e52928c | 301 | usage(); |
bdbfacc7 MS |
302 | } |
303 | ||
304 | num_options = cupsParseOptions(argv[i], num_options, &options); | |
305 | } | |
306 | break; | |
ef416fc2 | 307 | |
308 | #ifndef __sun | |
bdbfacc7 | 309 | case 'p' : /* Queue priority */ |
ef416fc2 | 310 | #endif /* !__sun */ |
bdbfacc7 MS |
311 | case 'q' : /* Queue priority */ |
312 | if (opt[1] != '\0') | |
313 | { | |
314 | priority = atoi(opt + 1); | |
315 | opt += strlen(opt) - 1; | |
316 | } | |
317 | else | |
318 | { | |
319 | if ((i + 1) >= argc) | |
320 | { | |
321 | _cupsLangPrintf(stderr, _("%s: Error - expected priority after \"-%c\" option."), argv[0], *opt); | |
8e52928c | 322 | usage(); |
bdbfacc7 | 323 | } |
ef416fc2 | 324 | |
bdbfacc7 | 325 | i ++; |
ef416fc2 | 326 | |
bdbfacc7 MS |
327 | priority = atoi(argv[i]); |
328 | } | |
ef416fc2 | 329 | |
bdbfacc7 MS |
330 | /* |
331 | * For 100% Solaris compatibility, need to add: | |
332 | * | |
333 | * priority = 99 * (39 - priority) / 39 + 1; | |
334 | * | |
335 | * However, to keep CUPS lp the same across all platforms | |
336 | * we will break compatibility this far... | |
337 | */ | |
ef416fc2 | 338 | |
bdbfacc7 | 339 | if (priority < 1 || priority > 100) |
ef416fc2 | 340 | { |
bdbfacc7 | 341 | _cupsLangPrintf(stderr, _("%s: Error - priority must be between 1 and 100."), argv[0]); |
ef416fc2 | 342 | return (1); |
bdbfacc7 | 343 | } |
ef416fc2 | 344 | |
bdbfacc7 MS |
345 | sprintf(buffer, "%d", priority); |
346 | num_options = cupsAddOption("job-priority", buffer, num_options, | |
347 | &options); | |
348 | break; | |
ef416fc2 | 349 | |
bdbfacc7 MS |
350 | case 's' : /* Silent */ |
351 | silent = 1; | |
352 | break; | |
ef416fc2 | 353 | |
bdbfacc7 MS |
354 | case 't' : /* Title */ |
355 | if (opt[1] != '\0') | |
ef416fc2 | 356 | { |
bdbfacc7 MS |
357 | title = opt + 1; |
358 | opt += strlen(opt) - 1; | |
359 | } | |
360 | else | |
361 | { | |
362 | i ++; | |
ef416fc2 | 363 | |
bdbfacc7 MS |
364 | if (i >= argc) |
365 | { | |
366 | _cupsLangPrintf(stderr, _("%s: Error - expected title after \"-t\" option."), argv[0]); | |
8e52928c | 367 | usage(); |
bdbfacc7 | 368 | } |
ef416fc2 | 369 | |
bdbfacc7 MS |
370 | title = argv[i]; |
371 | } | |
372 | break; | |
ef416fc2 | 373 | |
bdbfacc7 MS |
374 | case 'y' : /* mode-list */ |
375 | if (opt[1] != '\0') | |
ef416fc2 | 376 | { |
bdbfacc7 | 377 | opt += strlen(opt) - 1; |
ef416fc2 | 378 | } |
bdbfacc7 MS |
379 | else |
380 | { | |
381 | i ++; | |
ef416fc2 | 382 | |
bdbfacc7 MS |
383 | if (i >= argc) |
384 | { | |
385 | _cupsLangPrintf(stderr, _("%s: Error - expected mode list after \"-y\" option."), argv[0]); | |
8e52928c | 386 | usage(); |
bdbfacc7 MS |
387 | } |
388 | } | |
ef416fc2 | 389 | |
bdbfacc7 MS |
390 | _cupsLangPrintf(stderr, _("%s: Warning - mode option ignored."), argv[0]); |
391 | break; | |
ef416fc2 | 392 | |
bdbfacc7 MS |
393 | case 'H' : /* Hold job */ |
394 | if (opt[1] != '\0') | |
ef416fc2 | 395 | { |
bdbfacc7 MS |
396 | val = opt + 1; |
397 | opt += strlen(opt) - 1; | |
398 | } | |
399 | else | |
400 | { | |
401 | i ++; | |
402 | ||
403 | if (i >= argc) | |
404 | { | |
405 | _cupsLangPrintf(stderr, _("%s: Error - expected hold name after \"-H\" option."), argv[0]); | |
8e52928c | 406 | usage(); |
bdbfacc7 MS |
407 | } |
408 | ||
409 | val = argv[i]; | |
410 | } | |
411 | ||
412 | if (!strcmp(val, "hold")) | |
413 | num_options = cupsAddOption("job-hold-until", "indefinite", num_options, &options); | |
414 | else if (!strcmp(val, "resume") || !strcmp(val, "release")) | |
415 | num_options = cupsAddOption("job-hold-until", "no-hold", num_options, &options); | |
416 | else if (!strcmp(val, "immediate")) | |
417 | { | |
418 | num_options = cupsAddOption("job-hold-until", "no-hold", num_options, &options); | |
419 | num_options = cupsAddOption("job-priority", "100", num_options, &options); | |
420 | } | |
421 | else if (!strcmp(val, "restart")) | |
422 | { | |
423 | if (job_id < 1) | |
424 | { | |
425 | _cupsLangPrintf(stderr, _("%s: Need job ID (\"-i jobid\") before \"-H restart\"."), argv[0]); | |
426 | return (1); | |
427 | } | |
428 | ||
429 | if (restart_job(argv[0], job_id)) | |
430 | return (1); | |
431 | } | |
432 | else | |
433 | num_options = cupsAddOption("job-hold-until", val, num_options, &options); | |
434 | break; | |
ef416fc2 | 435 | |
bdbfacc7 MS |
436 | case 'P' : /* Page list */ |
437 | if (opt[1] != '\0') | |
438 | { | |
439 | val = opt + 1; | |
440 | opt += strlen(opt) - 1; | |
441 | } | |
442 | else | |
443 | { | |
444 | i ++; | |
ef416fc2 | 445 | |
bdbfacc7 MS |
446 | if (i >= argc) |
447 | { | |
448 | _cupsLangPrintf(stderr, _("%s: Error - expected page list after \"-P\" option."), argv[0]); | |
8e52928c | 449 | usage(); |
bdbfacc7 | 450 | } |
ef416fc2 | 451 | |
bdbfacc7 MS |
452 | val = argv[i]; |
453 | } | |
ef416fc2 | 454 | |
bdbfacc7 MS |
455 | num_options = cupsAddOption("page-ranges", val, num_options, &options); |
456 | break; | |
457 | ||
458 | case 'S' : /* character set */ | |
459 | if (opt[1] != '\0') | |
ef416fc2 | 460 | { |
bdbfacc7 MS |
461 | opt += strlen(opt) - 1; |
462 | } | |
463 | else | |
464 | { | |
465 | i ++; | |
ef416fc2 | 466 | |
bdbfacc7 MS |
467 | if (i >= argc) |
468 | { | |
469 | _cupsLangPrintf(stderr, _("%s: Error - expected character set after \"-S\" option."), argv[0]); | |
8e52928c | 470 | usage(); |
bdbfacc7 MS |
471 | } |
472 | } | |
ef416fc2 | 473 | |
bdbfacc7 MS |
474 | _cupsLangPrintf(stderr, _("%s: Warning - character set option ignored."), argv[0]); |
475 | break; | |
ef416fc2 | 476 | |
bdbfacc7 MS |
477 | case 'T' : /* Content-Type */ |
478 | if (opt[1] != '\0') | |
ef416fc2 | 479 | { |
bdbfacc7 MS |
480 | opt += strlen(opt) - 1; |
481 | } | |
482 | else | |
483 | { | |
484 | i ++; | |
485 | ||
486 | if (i >= argc) | |
487 | { | |
488 | _cupsLangPrintf(stderr, _("%s: Error - expected content type after \"-T\" option."), argv[0]); | |
8e52928c | 489 | usage(); |
bdbfacc7 MS |
490 | } |
491 | } | |
492 | ||
493 | _cupsLangPrintf(stderr, _("%s: Warning - content type option ignored."), argv[0]); | |
494 | break; | |
495 | ||
496 | case '-' : /* Stop processing options */ | |
497 | if (opt[1] != '\0') | |
498 | { | |
499 | _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%s\"."), argv[0], argv[i]); | |
8e52928c | 500 | usage(); |
bdbfacc7 | 501 | } |
db8b865d | 502 | |
bdbfacc7 MS |
503 | end_options = 1; |
504 | break; | |
ef416fc2 | 505 | |
bdbfacc7 MS |
506 | default : |
507 | _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], *opt); | |
8e52928c | 508 | usage(); |
bdbfacc7 | 509 | } |
ef416fc2 | 510 | } |
bdbfacc7 | 511 | } |
ef416fc2 | 512 | else if (!strcmp(argv[i], "-")) |
513 | { | |
514 | if (num_files || job_id) | |
515 | { | |
fa73b229 | 516 | _cupsLangPrintf(stderr, |
517 | _("%s: Error - cannot print from stdin if files or a " | |
0837b7e8 | 518 | "job ID are provided."), argv[0]); |
ef416fc2 | 519 | return (1); |
520 | } | |
521 | ||
522 | break; | |
523 | } | |
524 | else if (num_files < 1000 && job_id == 0) | |
525 | { | |
526 | /* | |
527 | * Print a file... | |
528 | */ | |
529 | ||
530 | if (access(argv[i], R_OK) != 0) | |
531 | { | |
bdbfacc7 | 532 | _cupsLangPrintf(stderr, _("%s: Error - unable to access \"%s\" - %s"), argv[0], argv[i], strerror(errno)); |
ef416fc2 | 533 | return (1); |
534 | } | |
535 | ||
536 | files[num_files] = argv[i]; | |
537 | num_files ++; | |
538 | ||
539 | if (title == NULL) | |
540 | { | |
541 | if ((title = strrchr(argv[i], '/')) != NULL) | |
542 | title ++; | |
543 | else | |
544 | title = argv[i]; | |
545 | } | |
546 | } | |
547 | else | |
bdbfacc7 MS |
548 | { |
549 | _cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."), argv[0], argv[i]); | |
550 | } | |
551 | } | |
ef416fc2 | 552 | |
553 | /* | |
554 | * See if we are altering an existing job... | |
555 | */ | |
556 | ||
557 | if (job_id) | |
fa73b229 | 558 | return (set_job_attrs(argv[0], job_id, num_options, options)); |
ef416fc2 | 559 | |
560 | /* | |
561 | * See if we have any files to print; if not, print from stdin... | |
562 | */ | |
563 | ||
564 | if (printer == NULL) | |
565 | { | |
a4924f6c | 566 | if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) |
ef416fc2 | 567 | { |
568 | printer = dest->name; | |
569 | ||
570 | for (j = 0; j < dest->num_options; j ++) | |
571 | if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) | |
572 | num_options = cupsAddOption(dest->options[j].name, | |
573 | dest->options[j].value, | |
574 | num_options, &options); | |
575 | } | |
c606bcae MS |
576 | else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || |
577 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
578 | { | |
579 | _cupsLangPrintf(stderr, | |
580 | _("%s: Error - add '/version=1.1' to server " | |
581 | "name."), argv[0]); | |
582 | return (1); | |
583 | } | |
ef416fc2 | 584 | } |
585 | ||
586 | if (printer == NULL) | |
587 | { | |
d6db9ea1 MS |
588 | if (!cupsGetNamedDest(NULL, NULL, NULL) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND) |
589 | _cupsLangPrintf(stderr, _("%s: Error - %s"), argv[0], cupsLastErrorString()); | |
ef416fc2 | 590 | else |
d6db9ea1 | 591 | _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]); |
ef416fc2 | 592 | |
593 | return (1); | |
594 | } | |
595 | ||
596 | if (num_files > 0) | |
597 | job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options); | |
3d052e43 MS |
598 | else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, |
599 | title ? title : "(stdin)", | |
600 | num_options, options)) > 0) | |
ef416fc2 | 601 | { |
3d052e43 MS |
602 | http_status_t status; /* Write status */ |
603 | const char *format; /* Document format */ | |
604 | ssize_t bytes; /* Bytes read */ | |
ef416fc2 | 605 | |
3d052e43 MS |
606 | if (cupsGetOption("raw", num_options, options)) |
607 | format = CUPS_FORMAT_RAW; | |
608 | else if ((format = cupsGetOption("document-format", num_options, | |
609 | options)) == NULL) | |
610 | format = CUPS_FORMAT_AUTO; | |
611 | ||
612 | status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL, | |
613 | format, 1); | |
ef416fc2 | 614 | |
3d052e43 MS |
615 | while (status == HTTP_CONTINUE && |
616 | (bytes = read(0, buffer, sizeof(buffer))) > 0) | |
7e86f2f6 | 617 | status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes); |
3d052e43 MS |
618 | |
619 | if (status != HTTP_CONTINUE) | |
ef416fc2 | 620 | { |
0837b7e8 | 621 | _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."), |
3d052e43 | 622 | argv[0], httpStatus(status)); |
12f89d24 MS |
623 | cupsFinishDocument(CUPS_HTTP_DEFAULT, printer); |
624 | cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); | |
ef416fc2 | 625 | return (1); |
626 | } | |
627 | ||
3d052e43 | 628 | if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK) |
12f89d24 | 629 | { |
a29fd7dd | 630 | _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); |
12f89d24 | 631 | cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); |
a29fd7dd | 632 | return (1); |
12f89d24 | 633 | } |
ef416fc2 | 634 | } |
635 | ||
636 | if (job_id < 1) | |
637 | { | |
0837b7e8 | 638 | _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); |
ef416fc2 | 639 | return (1); |
640 | } | |
641 | else if (!silent) | |
0837b7e8 | 642 | _cupsLangPrintf(stdout, _("request id is %s-%d (%d file(s))"), |
ef416fc2 | 643 | printer, job_id, num_files); |
644 | ||
645 | return (0); | |
646 | } | |
647 | ||
648 | ||
649 | /* | |
650 | * 'restart_job()' - Restart a job. | |
651 | */ | |
652 | ||
8e52928c | 653 | static int /* O - Exit status */ |
fa73b229 | 654 | restart_job(const char *command, /* I - Command name */ |
655 | int job_id) /* I - Job ID */ | |
ef416fc2 | 656 | { |
fa73b229 | 657 | ipp_t *request; /* IPP request */ |
ef416fc2 | 658 | char uri[HTTP_MAX_URI]; /* URI for job */ |
659 | ||
660 | ||
fa73b229 | 661 | request = ippNewRequest(IPP_RESTART_JOB); |
ef416fc2 | 662 | |
663 | sprintf(uri, "ipp://localhost/jobs/%d", job_id); | |
664 | ||
665 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
666 | "job-uri", NULL, uri); | |
667 | ||
668 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
669 | "requesting-user-name", NULL, cupsUser()); | |
670 | ||
3d052e43 | 671 | ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs")); |
ef416fc2 | 672 | |
c606bcae MS |
673 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || |
674 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
675 | { | |
676 | _cupsLangPrintf(stderr, | |
677 | _("%s: Error - add '/version=1.1' to server " | |
678 | "name."), command); | |
679 | return (1); | |
680 | } | |
681 | else if (cupsLastError() > IPP_OK_CONFLICT) | |
ef416fc2 | 682 | { |
0837b7e8 | 683 | _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); |
ef416fc2 | 684 | return (1); |
685 | } | |
686 | ||
687 | return (0); | |
688 | } | |
689 | ||
690 | ||
691 | /* | |
692 | * 'set_job_attrs()' - Set job attributes. | |
693 | */ | |
694 | ||
8e52928c MS |
695 | static int /* O - Exit status */ |
696 | set_job_attrs( | |
697 | const char *command, /* I - Command name */ | |
698 | int job_id, /* I - Job ID */ | |
699 | int num_options, /* I - Number of options */ | |
700 | cups_option_t *options) /* I - Options */ | |
ef416fc2 | 701 | { |
fa73b229 | 702 | ipp_t *request; /* IPP request */ |
ef416fc2 | 703 | char uri[HTTP_MAX_URI]; /* URI for job */ |
704 | ||
705 | ||
706 | if (num_options == 0) | |
707 | return (0); | |
708 | ||
fa73b229 | 709 | request = ippNewRequest(IPP_SET_JOB_ATTRIBUTES); |
ef416fc2 | 710 | |
711 | sprintf(uri, "ipp://localhost/jobs/%d", job_id); | |
712 | ||
713 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, | |
714 | "job-uri", NULL, uri); | |
715 | ||
716 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
717 | "requesting-user-name", NULL, cupsUser()); | |
718 | ||
719 | cupsEncodeOptions(request, num_options, options); | |
720 | ||
3d052e43 | 721 | ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs")); |
ef416fc2 | 722 | |
c606bcae MS |
723 | if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || |
724 | cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) | |
725 | { | |
726 | _cupsLangPrintf(stderr, | |
727 | _("%s: Error - add '/version=1.1' to server " | |
728 | "name."), command); | |
729 | return (1); | |
730 | } | |
731 | else if (cupsLastError() > IPP_OK_CONFLICT) | |
ef416fc2 | 732 | { |
0837b7e8 | 733 | _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); |
ef416fc2 | 734 | return (1); |
735 | } | |
736 | ||
737 | return (0); | |
738 | } | |
8e52928c MS |
739 | |
740 | ||
741 | /* | |
742 | * 'usage()' - Show program usage and exit. | |
743 | */ | |
744 | ||
745 | static void | |
746 | usage(void) | |
747 | { | |
748 | _cupsLangPuts(stdout, _("Usage: lp [options] [--] [file(s)]\n" | |
749 | " lp [options] -i id")); | |
750 | _cupsLangPuts(stdout, _("Options:")); | |
751 | _cupsLangPuts(stdout, _("-c Make a copy of the print file(s)")); | |
13e6d13e | 752 | _cupsLangPuts(stdout, _("-d destination Specify the destination")); |
8e52928c MS |
753 | _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); |
754 | _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); | |
755 | _cupsLangPuts(stdout, _("-H HH:MM Hold the job until the specified UTC time")); | |
756 | _cupsLangPuts(stdout, _("-H hold Hold the job until released/resumed")); | |
757 | _cupsLangPuts(stdout, _("-H immediate Print the job as soon as possible")); | |
758 | _cupsLangPuts(stdout, _("-H restart Reprint the job")); | |
759 | _cupsLangPuts(stdout, _("-H resume Resume a held job")); | |
760 | _cupsLangPuts(stdout, _("-i id Specify an existing job ID to modify")); | |
761 | _cupsLangPuts(stdout, _("-m Send an email notification when the job completes")); | |
762 | _cupsLangPuts(stdout, _("-n num-copies Specify the number of copies to print")); | |
763 | _cupsLangPuts(stdout, _("-o option[=value] Specify a printer-specific option")); | |
764 | _cupsLangPuts(stdout, _("-o job-sheets=standard Print a banner page with the job")); | |
765 | _cupsLangPuts(stdout, _("-o media=size Specify the media size to use")); | |
766 | _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)")); | |
767 | _cupsLangPuts(stdout, _("-o orientation-requested=N\n" | |
768 | " Specify portrait (3) or landscape (4) orientation")); | |
769 | _cupsLangPuts(stdout, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)")); | |
770 | _cupsLangPuts(stdout, _("-o sides=one-sided Specify 1-sided printing")); | |
771 | _cupsLangPuts(stdout, _("-o sides=two-sided-long-edge\n" | |
772 | " Specify 2-sided portrait printing")); | |
773 | _cupsLangPuts(stdout, _("-o sides=two-sided-short-edge\n" | |
774 | " Specify 2-sided landscape printing")); | |
775 | _cupsLangPuts(stdout, _("-P page-list Specify a list of pages to print")); | |
776 | _cupsLangPuts(stdout, _("-q priority Specify the priority from low (1) to high (100)")); | |
777 | _cupsLangPuts(stdout, _("-s Be silent")); | |
778 | _cupsLangPuts(stdout, _("-t title Specify the job title")); | |
779 | _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication")); | |
780 | ||
781 | ||
782 | exit(1); | |
783 | } |