2 * "lpr" command for CUPS.
4 * Copyright 2007-2017 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 * Include necessary headers...
14 #include <cups/cups-private.h>
18 * 'main()' - Parse options and send files for printing.
22 main(int argc
, /* I - Number of command-line arguments */
23 char *argv
[]) /* I - Command-line arguments */
25 int i
, j
; /* Looping var */
26 int job_id
; /* Job ID */
27 char ch
; /* Option character */
28 char *printer
, /* Destination printer or class */
29 *instance
, /* Instance */
30 *opt
; /* Option pointer */
31 const char *title
; /* Job title */
32 int num_copies
; /* Number of copies per file */
33 int num_files
; /* Number of files to print */
34 const char *files
[1000]; /* Files to print */
35 cups_dest_t
*dest
; /* Selected destination */
36 int num_options
; /* Number of options */
37 cups_option_t
*options
; /* Options */
38 int deletefile
; /* Delete file after print? */
39 char buffer
[8192]; /* Copy buffer */
52 for (i
= 1; i
< argc
; i
++)
54 if (argv
[i
][0] == '-')
56 for (opt
= argv
[i
] + 1; *opt
; opt
++)
60 case 'E' : /* Encrypt */
62 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
64 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."), argv
[0]);
68 case 'U' : /* Username */
72 opt
+= strlen(opt
) - 1;
79 _cupsLangPrintf(stderr
, _("%s: Error - expected username after \"-U\" option."), argv
[0]);
87 case 'H' : /* Connect to host */
90 cupsSetServer(opt
+ 1);
91 opt
+= strlen(opt
) - 1;
99 _cupsLangPrintf(stderr
, _("%s: Error - expected hostname after \"-H\" option."), argv
[0]);
103 cupsSetServer(argv
[i
]);
107 case '1' : /* TROFF font set 1 */
108 case '2' : /* TROFF font set 2 */
109 case '3' : /* TROFF font set 3 */
110 case '4' : /* TROFF font set 4 */
111 case 'i' : /* indent */
112 case 'w' : /* width */
115 opt
+= strlen(opt
) - 1;
123 _cupsLangPrintf(stderr
,
124 _("%s: Error - expected value after \"-%c\" "
125 "option."), argv
[0], ch
);
130 case 'c' : /* CIFPLOT */
132 case 'f' : /* FORTRAN */
133 case 'g' : /* plot */
134 case 'n' : /* Ditroff */
135 case 't' : /* Troff */
136 case 'v' : /* Raster image */
137 _cupsLangPrintf(stderr
, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv
[0], ch
);
140 case 'o' : /* Option */
143 num_options
= cupsParseOptions(opt
+ 1, num_options
, &options
);
144 opt
+= strlen(opt
) - 1;
151 _cupsLangPrintf(stderr
, _("%s: Error - expected option=value after \"-o\" option."), argv
[0]);
155 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
159 case 'l' : /* Literal/raw */
160 num_options
= cupsAddOption("raw", "true", num_options
, &options
);
163 case 'p' : /* Prettyprint */
164 num_options
= cupsAddOption("prettyprint", "true", num_options
, &options
);
167 case 'h' : /* Suppress burst page */
168 num_options
= cupsAddOption("job-sheets", "none", num_options
, &options
);
171 case 's' : /* Don't use symlinks */
174 case 'm' : /* Mail on completion */
176 char email
[1024]; /* EMail address */
178 snprintf(email
, sizeof(email
), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL
, buffer
, sizeof(buffer
)));
179 num_options
= cupsAddOption("notify-recipient-uri", email
, num_options
, &options
);
183 case 'q' : /* Queue file but don't print */
184 num_options
= cupsAddOption("job-hold-until", "indefinite", num_options
, &options
);
187 case 'r' : /* Remove file after printing */
191 case 'P' : /* Destination printer or class */
195 opt
+= strlen(opt
) - 1;
202 _cupsLangPrintf(stderr
, _("%s: Error - expected destination after \"-P\" option."), argv
[0]);
209 if ((instance
= strrchr(printer
, '/')) != NULL
)
212 if ((dest
= cupsGetNamedDest(NULL
, printer
, instance
)) != NULL
)
214 for (j
= 0; j
< dest
->num_options
; j
++)
215 if (cupsGetOption(dest
->options
[j
].name
, num_options
,
217 num_options
= cupsAddOption(dest
->options
[j
].name
,
218 dest
->options
[j
].value
,
219 num_options
, &options
);
221 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
222 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
224 _cupsLangPrintf(stderr
, _("%s: Error - add '/version=1.1' to server name."), argv
[0]);
229 case '#' : /* Number of copies */
232 num_copies
= atoi(opt
+ 1);
233 opt
+= strlen(opt
) - 1;
240 _cupsLangPrintf(stderr
, _("%s: Error - expected copies after \"-#\" option."), argv
[0]);
244 num_copies
= atoi(argv
[i
]);
249 _cupsLangPrintf(stderr
, _("%s: Error - copies must be 1 or more."), argv
[0]);
253 sprintf(buffer
, "%d", num_copies
);
254 num_options
= cupsAddOption("copies", buffer
, num_options
, &options
);
257 case 'C' : /* Class */
258 case 'J' : /* Job name */
259 case 'T' : /* Title */
263 opt
+= strlen(opt
) - 1;
270 _cupsLangPrintf(stderr
, _("%s: Error - expected name after \"-%c\" option."), argv
[0], ch
);
279 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \"%c\"."), argv
[0], *opt
);
284 else if (num_files
< 1000)
290 if (access(argv
[i
], R_OK
) != 0)
292 _cupsLangPrintf(stderr
,
293 _("%s: Error - unable to access \"%s\" - %s"),
294 argv
[0], argv
[i
], strerror(errno
));
298 files
[num_files
] = argv
[i
];
303 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
311 _cupsLangPrintf(stderr
, _("%s: Error - too many files - \"%s\"."), argv
[0], argv
[i
]);
316 * See if we have any files to print; if not, print from stdin...
321 if ((dest
= cupsGetNamedDest(NULL
, NULL
, NULL
)) != NULL
)
323 printer
= dest
->name
;
325 for (j
= 0; j
< dest
->num_options
; j
++)
326 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
327 num_options
= cupsAddOption(dest
->options
[j
].name
,
328 dest
->options
[j
].value
,
329 num_options
, &options
);
331 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST
||
332 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED
)
334 _cupsLangPrintf(stderr
,
335 _("%s: Error - add '/version=1.1' to server "
343 if (!cupsGetNamedDest(NULL
, NULL
, NULL
) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND
)
344 _cupsLangPrintf(stderr
, _("%s: Error - %s"), argv
[0], cupsLastErrorString());
346 _cupsLangPrintf(stderr
, _("%s: Error - scheduler not responding."), argv
[0]);
353 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
355 if (deletefile
&& job_id
> 0)
358 * Delete print files after printing...
361 for (i
= 0; i
< num_files
; i
++)
365 else if ((job_id
= cupsCreateJob(CUPS_HTTP_DEFAULT
, printer
,
366 title
? title
: "(stdin)",
367 num_options
, options
)) > 0)
369 http_status_t status
; /* Write status */
370 const char *format
; /* Document format */
371 ssize_t bytes
; /* Bytes read */
373 if (cupsGetOption("raw", num_options
, options
))
374 format
= CUPS_FORMAT_RAW
;
375 else if ((format
= cupsGetOption("document-format", num_options
,
377 format
= CUPS_FORMAT_AUTO
;
379 status
= cupsStartDocument(CUPS_HTTP_DEFAULT
, printer
, job_id
, NULL
,
382 while (status
== HTTP_CONTINUE
&&
383 (bytes
= read(0, buffer
, sizeof(buffer
))) > 0)
384 status
= cupsWriteRequestData(CUPS_HTTP_DEFAULT
, buffer
, (size_t)bytes
);
386 if (status
!= HTTP_CONTINUE
)
388 _cupsLangPrintf(stderr
, _("%s: Error - unable to queue from stdin - %s."),
389 argv
[0], httpStatus(status
));
390 cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
);
391 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
395 if (cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
) != IPP_OK
)
397 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
398 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
405 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());