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