2 * "lpr" command for CUPS.
4 * Copyright © 2007-2018 by Apple Inc.
5 * Copyright © 1997-2007 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers...
15 #include <cups/cups-private.h>
22 static void usage(void) _CUPS_NORETURN
;
26 * 'main()' - Parse options and send files for printing.
30 main(int argc
, /* I - Number of command-line arguments */
31 char *argv
[]) /* I - Command-line arguments */
33 int i
, j
; /* Looping var */
34 int job_id
; /* Job ID */
35 char ch
; /* Option character */
36 char *printer
, /* Destination printer or class */
37 *instance
, /* Instance */
38 *opt
; /* Option pointer */
39 const char *title
; /* Job title */
40 int num_copies
; /* Number of copies per file */
41 int num_files
; /* Number of files to print */
42 const char *files
[1000]; /* Files to print */
43 cups_dest_t
*dest
; /* Selected destination */
44 int num_options
; /* Number of options */
45 cups_option_t
*options
; /* Options */
46 int deletefile
; /* Delete file after print? */
47 char buffer
[8192]; /* Copy buffer */
60 for (i
= 1; i
< argc
; i
++)
62 if (!strcmp(argv
[i
], "--help"))
64 else if (argv
[i
][0] == '-')
66 for (opt
= argv
[i
] + 1; *opt
; opt
++)
70 case 'E' : /* Encrypt */
72 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
74 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."), argv
[0]);
78 case 'U' : /* Username */
82 opt
+= strlen(opt
) - 1;
89 _cupsLangPrintf(stderr
, _("%s: Error - expected username after \"-U\" option."), argv
[0]);
97 case 'H' : /* Connect to host */
100 cupsSetServer(opt
+ 1);
101 opt
+= strlen(opt
) - 1;
109 _cupsLangPrintf(stderr
, _("%s: Error - expected hostname after \"-H\" option."), argv
[0]);
113 cupsSetServer(argv
[i
]);
117 case '1' : /* TROFF font set 1 */
118 case '2' : /* TROFF font set 2 */
119 case '3' : /* TROFF font set 3 */
120 case '4' : /* TROFF font set 4 */
121 case 'i' : /* indent */
122 case 'w' : /* width */
125 opt
+= strlen(opt
) - 1;
133 _cupsLangPrintf(stderr
,
134 _("%s: Error - expected value after \"-%c\" "
135 "option."), argv
[0], ch
);
140 case 'c' : /* CIFPLOT */
142 case 'f' : /* FORTRAN */
143 case 'g' : /* plot */
144 case 'n' : /* Ditroff */
145 case 't' : /* Troff */
146 case 'v' : /* Raster image */
147 _cupsLangPrintf(stderr
, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv
[0], ch
);
150 case 'o' : /* Option */
153 num_options
= cupsParseOptions(opt
+ 1, num_options
, &options
);
154 opt
+= strlen(opt
) - 1;
161 _cupsLangPrintf(stderr
, _("%s: Error - expected option=value after \"-o\" option."), argv
[0]);
165 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
169 case 'l' : /* Literal/raw */
170 num_options
= cupsAddOption("raw", "true", num_options
, &options
);
173 case 'p' : /* Prettyprint */
174 num_options
= cupsAddOption("prettyprint", "true", num_options
, &options
);
177 case 'h' : /* Suppress burst page */
178 num_options
= cupsAddOption("job-sheets", "none", num_options
, &options
);
181 case 's' : /* Don't use symlinks */
184 case 'm' : /* Mail on completion */
186 char email
[1024]; /* EMail address */
188 snprintf(email
, sizeof(email
), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL
, buffer
, sizeof(buffer
)));
189 num_options
= cupsAddOption("notify-recipient-uri", email
, num_options
, &options
);
193 case 'q' : /* Queue file but don't print */
194 num_options
= cupsAddOption("job-hold-until", "indefinite", num_options
, &options
);
197 case 'r' : /* Remove file after printing */
201 case 'P' : /* Destination printer or class */
205 opt
+= strlen(opt
) - 1;
212 _cupsLangPrintf(stderr
, _("%s: Error - expected destination after \"-P\" option."), argv
[0]);
219 if ((instance
= strrchr(printer
, '/')) != NULL
)
222 if ((dest
= cupsGetNamedDest(NULL
, printer
, instance
)) != NULL
)
224 for (j
= 0; j
< dest
->num_options
; j
++)
225 if (cupsGetOption(dest
->options
[j
].name
, num_options
,
227 num_options
= cupsAddOption(dest
->options
[j
].name
,
228 dest
->options
[j
].value
,
229 num_options
, &options
);
231 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
232 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
234 _cupsLangPrintf(stderr
, _("%s: Error - add '/version=1.1' to server name."), argv
[0]);
239 case '#' : /* Number of copies */
242 num_copies
= atoi(opt
+ 1);
243 opt
+= strlen(opt
) - 1;
250 _cupsLangPrintf(stderr
, _("%s: Error - expected copies after \"-#\" option."), argv
[0]);
254 num_copies
= atoi(argv
[i
]);
259 _cupsLangPrintf(stderr
, _("%s: Error - copies must be 1 or more."), argv
[0]);
263 sprintf(buffer
, "%d", num_copies
);
264 num_options
= cupsAddOption("copies", buffer
, num_options
, &options
);
267 case 'C' : /* Class */
268 case 'J' : /* Job name */
269 case 'T' : /* Title */
273 opt
+= strlen(opt
) - 1;
280 _cupsLangPrintf(stderr
, _("%s: Error - expected name after \"-%c\" option."), argv
[0], ch
);
289 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \"%c\"."), argv
[0], *opt
);
294 else if (num_files
< 1000)
300 if (access(argv
[i
], R_OK
) != 0)
302 _cupsLangPrintf(stderr
,
303 _("%s: Error - unable to access \"%s\" - %s"),
304 argv
[0], argv
[i
], strerror(errno
));
308 files
[num_files
] = argv
[i
];
313 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
321 _cupsLangPrintf(stderr
, _("%s: Error - too many files - \"%s\"."), argv
[0], argv
[i
]);
326 * See if we have any files to print; if not, print from stdin...
331 if ((dest
= cupsGetNamedDest(NULL
, NULL
, NULL
)) != NULL
)
333 printer
= dest
->name
;
335 for (j
= 0; j
< dest
->num_options
; j
++)
336 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
337 num_options
= cupsAddOption(dest
->options
[j
].name
,
338 dest
->options
[j
].value
,
339 num_options
, &options
);
341 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
342 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
344 _cupsLangPrintf(stderr
,
345 _("%s: Error - add '/version=1.1' to server "
353 if (!cupsGetNamedDest(NULL
, NULL
, NULL
) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND
)
354 _cupsLangPrintf(stderr
, _("%s: Error - %s"), argv
[0], cupsLastErrorString());
356 _cupsLangPrintf(stderr
, _("%s: Error - scheduler not responding."), argv
[0]);
363 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
365 if (deletefile
&& job_id
> 0)
368 * Delete print files after printing...
371 for (i
= 0; i
< num_files
; i
++)
375 else if ((job_id
= cupsCreateJob(CUPS_HTTP_DEFAULT
, printer
,
376 title
? title
: "(stdin)",
377 num_options
, options
)) > 0)
379 http_status_t status
; /* Write status */
380 const char *format
; /* Document format */
381 ssize_t bytes
; /* Bytes read */
383 if (cupsGetOption("raw", num_options
, options
))
384 format
= CUPS_FORMAT_RAW
;
385 else if ((format
= cupsGetOption("document-format", num_options
,
387 format
= CUPS_FORMAT_AUTO
;
389 status
= cupsStartDocument(CUPS_HTTP_DEFAULT
, printer
, job_id
, NULL
,
392 while (status
== HTTP_CONTINUE
&&
393 (bytes
= read(0, buffer
, sizeof(buffer
))) > 0)
394 status
= cupsWriteRequestData(CUPS_HTTP_DEFAULT
, buffer
, (size_t)bytes
);
396 if (status
!= HTTP_CONTINUE
)
398 _cupsLangPrintf(stderr
, _("%s: Error - unable to queue from stdin - %s."),
399 argv
[0], httpStatus(status
));
400 cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
);
401 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
405 if (cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
) != IPP_OK
)
407 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
408 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
415 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
424 * 'usage()' - Show program usage and exit.
430 _cupsLangPuts(stdout
, _("Usage: lpr [options] [file(s)]"));
431 _cupsLangPuts(stdout
, _("Options:"));
432 _cupsLangPuts(stdout
, _("-# num-copies Specify the number of copies to print"));
433 _cupsLangPuts(stdout
, _("-E Encrypt the connection to the server"));
434 _cupsLangPuts(stdout
, _("-H server[:port] Connect to the named server and port"));
435 _cupsLangPuts(stdout
, _("-m Send an email notification when the job completes"));
436 _cupsLangPuts(stdout
, _("-o option[=value] Specify a printer-specific option"));
437 _cupsLangPuts(stdout
, _("-o job-sheets=standard Print a banner page with the job"));
438 _cupsLangPuts(stdout
, _("-o media=size Specify the media size to use"));
439 _cupsLangPuts(stdout
, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)"));
440 _cupsLangPuts(stdout
, _("-o orientation-requested=N\n"
441 " Specify portrait (3) or landscape (4) orientation"));
442 _cupsLangPuts(stdout
, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)"));
443 _cupsLangPuts(stdout
, _("-o sides=one-sided Specify 1-sided printing"));
444 _cupsLangPuts(stdout
, _("-o sides=two-sided-long-edge\n"
445 " Specify 2-sided portrait printing"));
446 _cupsLangPuts(stdout
, _("-o sides=two-sided-short-edge\n"
447 " Specify 2-sided landscape printing"));
448 _cupsLangPuts(stdout
, _("-q Specify the job should be held for printing"));
449 _cupsLangPuts(stdout
, _("-r Remove the file(s) after submission"));
450 _cupsLangPuts(stdout
, _("-P destination Specify the destination"));
451 _cupsLangPuts(stdout
, _("-T title Specify the job title"));
452 _cupsLangPuts(stdout
, _("-U username Specify the username to use for authentication"));