2 * "lpr" command for CUPS.
4 * Copyright 2007-2017 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products.
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
11 * missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
18 #include <cups/cups-private.h>
22 * 'main()' - Parse options and send files for printing.
26 main(int argc
, /* I - Number of command-line arguments */
27 char *argv
[]) /* I - Command-line arguments */
29 int i
, j
; /* Looping var */
30 int job_id
; /* Job ID */
31 char ch
; /* Option character */
32 char *printer
, /* Destination printer or class */
33 *instance
, /* Instance */
34 *opt
; /* Option pointer */
35 const char *title
; /* Job title */
36 int num_copies
; /* Number of copies per file */
37 int num_files
; /* Number of files to print */
38 const char *files
[1000]; /* Files to print */
39 cups_dest_t
*dest
; /* Selected destination */
40 int num_options
; /* Number of options */
41 cups_option_t
*options
; /* Options */
42 int deletefile
; /* Delete file after print? */
43 char buffer
[8192]; /* Copy buffer */
56 for (i
= 1; i
< argc
; i
++)
58 if (argv
[i
][0] == '-')
60 for (opt
= argv
[i
] + 1; *opt
; opt
++)
64 case 'E' : /* Encrypt */
66 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
68 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."), argv
[0]);
72 case 'U' : /* Username */
76 opt
+= strlen(opt
) - 1;
83 _cupsLangPrintf(stderr
, _("%s: Error - expected username after \"-U\" option."), argv
[0]);
91 case 'H' : /* Connect to host */
94 cupsSetServer(opt
+ 1);
95 opt
+= strlen(opt
) - 1;
103 _cupsLangPrintf(stderr
, _("%s: Error - expected hostname after \"-H\" option."), argv
[0]);
107 cupsSetServer(argv
[i
]);
111 case '1' : /* TROFF font set 1 */
112 case '2' : /* TROFF font set 2 */
113 case '3' : /* TROFF font set 3 */
114 case '4' : /* TROFF font set 4 */
115 case 'i' : /* indent */
116 case 'w' : /* width */
119 opt
+= strlen(opt
) - 1;
127 _cupsLangPrintf(stderr
,
128 _("%s: Error - expected value after \"-%c\" "
129 "option."), argv
[0], ch
);
134 case 'c' : /* CIFPLOT */
136 case 'f' : /* FORTRAN */
137 case 'g' : /* plot */
138 case 'n' : /* Ditroff */
139 case 't' : /* Troff */
140 case 'v' : /* Raster image */
141 _cupsLangPrintf(stderr
, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv
[0], ch
);
144 case 'o' : /* Option */
147 num_options
= cupsParseOptions(opt
+ 1, num_options
, &options
);
148 opt
+= strlen(opt
) - 1;
155 _cupsLangPrintf(stderr
, _("%s: Error - expected option=value after \"-o\" option."), argv
[0]);
159 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
163 case 'l' : /* Literal/raw */
164 num_options
= cupsAddOption("raw", "true", num_options
, &options
);
167 case 'p' : /* Prettyprint */
168 num_options
= cupsAddOption("prettyprint", "true", num_options
, &options
);
171 case 'h' : /* Suppress burst page */
172 num_options
= cupsAddOption("job-sheets", "none", num_options
, &options
);
175 case 's' : /* Don't use symlinks */
178 case 'm' : /* Mail on completion */
180 char email
[1024]; /* EMail address */
182 snprintf(email
, sizeof(email
), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL
, buffer
, sizeof(buffer
)));
183 num_options
= cupsAddOption("notify-recipient-uri", email
, num_options
, &options
);
187 case 'q' : /* Queue file but don't print */
188 num_options
= cupsAddOption("job-hold-until", "indefinite", num_options
, &options
);
191 case 'r' : /* Remove file after printing */
195 case 'P' : /* Destination printer or class */
199 opt
+= strlen(opt
) - 1;
206 _cupsLangPrintf(stderr
, _("%s: Error - expected destination after \"-P\" option."), argv
[0]);
213 if ((instance
= strrchr(printer
, '/')) != NULL
)
216 if ((dest
= cupsGetNamedDest(NULL
, printer
, instance
)) != NULL
)
218 for (j
= 0; j
< dest
->num_options
; j
++)
219 if (cupsGetOption(dest
->options
[j
].name
, num_options
,
221 num_options
= cupsAddOption(dest
->options
[j
].name
,
222 dest
->options
[j
].value
,
223 num_options
, &options
);
225 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
226 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
228 _cupsLangPrintf(stderr
, _("%s: Error - add '/version=1.1' to server name."), argv
[0]);
233 case '#' : /* Number of copies */
236 num_copies
= atoi(opt
+ 1);
237 opt
+= strlen(opt
) - 1;
244 _cupsLangPrintf(stderr
, _("%s: Error - expected copies after \"-#\" option."), argv
[0]);
248 num_copies
= atoi(argv
[i
]);
253 _cupsLangPrintf(stderr
, _("%s: Error - copies must be 1 or more."), argv
[0]);
257 sprintf(buffer
, "%d", num_copies
);
258 num_options
= cupsAddOption("copies", buffer
, num_options
, &options
);
261 case 'C' : /* Class */
262 case 'J' : /* Job name */
263 case 'T' : /* Title */
267 opt
+= strlen(opt
) - 1;
274 _cupsLangPrintf(stderr
, _("%s: Error - expected name after \"-%c\" option."), argv
[0], ch
);
283 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \"%c\"."), argv
[0], *opt
);
288 else if (num_files
< 1000)
294 if (access(argv
[i
], R_OK
) != 0)
296 _cupsLangPrintf(stderr
,
297 _("%s: Error - unable to access \"%s\" - %s"),
298 argv
[0], argv
[i
], strerror(errno
));
302 files
[num_files
] = argv
[i
];
307 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
315 _cupsLangPrintf(stderr
, _("%s: Error - too many files - \"%s\"."), argv
[0], argv
[i
]);
320 * See if we have any files to print; if not, print from stdin...
325 if ((dest
= cupsGetNamedDest(NULL
, NULL
, NULL
)) != NULL
)
327 printer
= dest
->name
;
329 for (j
= 0; j
< dest
->num_options
; j
++)
330 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
331 num_options
= cupsAddOption(dest
->options
[j
].name
,
332 dest
->options
[j
].value
,
333 num_options
, &options
);
335 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
336 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
338 _cupsLangPrintf(stderr
,
339 _("%s: Error - add '/version=1.1' to server "
347 if (!cupsGetNamedDest(NULL
, NULL
, NULL
) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND
)
348 _cupsLangPrintf(stderr
, _("%s: Error - %s"), argv
[0], cupsLastErrorString());
350 _cupsLangPrintf(stderr
, _("%s: Error - scheduler not responding."), argv
[0]);
357 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
359 if (deletefile
&& job_id
> 0)
362 * Delete print files after printing...
365 for (i
= 0; i
< num_files
; i
++)
369 else if ((job_id
= cupsCreateJob(CUPS_HTTP_DEFAULT
, printer
,
370 title
? title
: "(stdin)",
371 num_options
, options
)) > 0)
373 http_status_t status
; /* Write status */
374 const char *format
; /* Document format */
375 ssize_t bytes
; /* Bytes read */
377 if (cupsGetOption("raw", num_options
, options
))
378 format
= CUPS_FORMAT_RAW
;
379 else if ((format
= cupsGetOption("document-format", num_options
,
381 format
= CUPS_FORMAT_AUTO
;
383 status
= cupsStartDocument(CUPS_HTTP_DEFAULT
, printer
, job_id
, NULL
,
386 while (status
== HTTP_CONTINUE
&&
387 (bytes
= read(0, buffer
, sizeof(buffer
))) > 0)
388 status
= cupsWriteRequestData(CUPS_HTTP_DEFAULT
, buffer
, (size_t)bytes
);
390 if (status
!= HTTP_CONTINUE
)
392 _cupsLangPrintf(stderr
, _("%s: Error - unable to queue from stdin - %s."),
393 argv
[0], httpStatus(status
));
394 cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
);
395 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
399 if (cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
) != IPP_OK
)
401 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
402 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
409 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());