]> git.ipfire.org Git - thirdparty/cups.git/blame - berkeley/lpr.c
Fix source file header text duplication text duplication.
[thirdparty/cups.git] / berkeley / lpr.c
CommitLineData
ef416fc2 1/*
7e86f2f6 2 * "lpr" command for CUPS.
ef416fc2 3 *
bdbfacc7 4 * Copyright 2007-2016 by Apple Inc.
7e86f2f6 5 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 6 *
7e86f2f6
MS
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
57b7b66b 11 * missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 12 */
13
14/*
15 * Include necessary headers...
16 */
17
71e16022 18#include <cups/cups-private.h>
ef416fc2 19
ef416fc2 20
21/*
22 * 'main()' - Parse options and send files for printing.
23 */
24
25int
fa73b229 26main(int argc, /* I - Number of command-line arguments */
27 char *argv[]) /* I - Command-line arguments */
ef416fc2 28{
fa73b229 29 int i, j; /* Looping var */
30 int job_id; /* Job ID */
31 char ch; /* Option character */
32 char *printer, /* Destination printer or class */
bdbfacc7
MS
33 *instance, /* Instance */
34 *opt; /* Option pointer */
fa73b229 35 const char *title, /* Job title */
36 *val; /* Environment variable name */
37 int num_copies; /* Number of copies per file */
38 int num_files; /* Number of files to print */
39 const char *files[1000]; /* Files to print */
a4924f6c 40 cups_dest_t *dest; /* Selected destination */
fa73b229 41 int num_options; /* Number of options */
42 cups_option_t *options; /* Options */
43 int deletefile; /* Delete file after print? */
44 char buffer[8192]; /* Copy buffer */
ef416fc2 45
46
07725fee 47 _cupsSetLocale(argv);
d09495fa 48
ef416fc2 49 deletefile = 0;
50 printer = NULL;
a4924f6c 51 dest = NULL;
ef416fc2 52 num_options = 0;
53 options = NULL;
54 num_files = 0;
55 title = NULL;
ef416fc2 56
57 for (i = 1; i < argc; i ++)
bdbfacc7 58 {
ef416fc2 59 if (argv[i][0] == '-')
c606bcae 60 {
bdbfacc7 61 for (opt = argv[i] + 1; *opt; opt ++)
ef416fc2 62 {
bdbfacc7
MS
63 switch (ch = *opt)
64 {
65 case 'E' : /* Encrypt */
ef416fc2 66#ifdef HAVE_SSL
bdbfacc7 67 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
ef416fc2 68#else
bdbfacc7 69 _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
ef416fc2 70#endif /* HAVE_SSL */
bdbfacc7
MS
71 break;
72
73 case 'U' : /* Username */
74 if (opt[1] != '\0')
fa73b229 75 {
bdbfacc7
MS
76 cupsSetUser(opt + 1);
77 opt += strlen(opt) - 1;
fa73b229 78 }
bdbfacc7
MS
79 else
80 {
81 i ++;
82 if (i >= argc)
83 {
84 _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]);
85 return (1);
86 }
87
88 cupsSetUser(argv[i]);
89 }
90 break;
fa73b229 91
bdbfacc7
MS
92 case 'H' : /* Connect to host */
93 if (opt[1] != '\0')
94 {
95 cupsSetServer(opt + 1);
96 opt += strlen(opt) - 1;
97 }
98 else
99 {
100 i ++;
101
102 if (i >= argc)
103 {
104 _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-H\" option."), argv[0]);
105 return (1);
106 }
107 else
108 cupsSetServer(argv[i]);
109 }
110 break;
111
112 case '1' : /* TROFF font set 1 */
113 case '2' : /* TROFF font set 2 */
114 case '3' : /* TROFF font set 3 */
115 case '4' : /* TROFF font set 4 */
116 case 'i' : /* indent */
117 case 'w' : /* width */
118 if (opt[1] != '\0')
119 {
120 opt += strlen(opt) - 1;
121 }
122 else
123 {
124 i ++;
125
126 if (i >= argc)
127 {
128 _cupsLangPrintf(stderr,
129 _("%s: Error - expected value after \"-%c\" "
130 "option."), argv[0], ch);
131 return (1);
132 }
133 }
fa73b229 134
bdbfacc7
MS
135 case 'c' : /* CIFPLOT */
136 case 'd' : /* DVI */
137 case 'f' : /* FORTRAN */
138 case 'g' : /* plot */
139 case 'n' : /* Ditroff */
140 case 't' : /* Troff */
141 case 'v' : /* Raster image */
142 _cupsLangPrintf(stderr, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv[0], ch);
143 break;
144
145 case 'o' : /* Option */
146 if (opt[1] != '\0')
fa73b229 147 {
bdbfacc7
MS
148 num_options = cupsParseOptions(opt + 1, num_options, &options);
149 opt += strlen(opt) - 1;
150 }
fa73b229 151 else
ef416fc2 152 {
bdbfacc7
MS
153 i ++;
154 if (i >= argc)
155 {
156 _cupsLangPrintf(stderr, _("%s: Error - expected option=value after \"-o\" option."), argv[0]);
157 return (1);
158 }
159
160 num_options = cupsParseOptions(argv[i], num_options, &options);
ef416fc2 161 }
bdbfacc7
MS
162 break;
163
164 case 'l' : /* Literal/raw */
165 num_options = cupsAddOption("raw", "true", num_options, &options);
166 break;
167
168 case 'p' : /* Prettyprint */
169 num_options = cupsAddOption("prettyprint", "true", num_options, &options);
170 break;
171
172 case 'h' : /* Suppress burst page */
173 num_options = cupsAddOption("job-sheets", "none", num_options, &options);
174 break;
175
176 case 's' : /* Don't use symlinks */
177 break;
178
179 case 'm' : /* Mail on completion */
ef416fc2 180 {
bdbfacc7
MS
181 char email[1024]; /* EMail address */
182
183 snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL, buffer, sizeof(buffer)));
184 num_options = cupsAddOption("notify-recipient-uri", email, num_options, &options);
ef416fc2 185 }
bdbfacc7 186 break;
ef416fc2 187
bdbfacc7
MS
188 case 'q' : /* Queue file but don't print */
189 num_options = cupsAddOption("job-hold-until", "indefinite", num_options, &options);
190 break;
191
192 case 'r' : /* Remove file after printing */
193 deletefile = 1;
194 break;
195
196 case 'P' : /* Destination printer or class */
197 if (opt[1] != '\0')
ef416fc2 198 {
bdbfacc7
MS
199 printer = opt + 1;
200 opt += strlen(opt) - 1;
201 }
202 else
203 {
204 i ++;
205 if (i >= argc)
206 {
207 _cupsLangPrintf(stderr, _("%s: Error - expected destination after \"-P\" option."), argv[0]);
208 return (1);
209 }
210
211 printer = argv[i];
ef416fc2 212 }
213
bdbfacc7
MS
214 if ((instance = strrchr(printer, '/')) != NULL)
215 *instance++ = '\0';
216
217 if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL)
218 {
219 for (j = 0; j < dest->num_options; j ++)
220 if (cupsGetOption(dest->options[j].name, num_options,
221 options) == NULL)
222 num_options = cupsAddOption(dest->options[j].name,
223 dest->options[j].value,
224 num_options, &options);
225 }
226 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
227 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
ef416fc2 228 {
bdbfacc7 229 _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
ef416fc2 230 return (1);
231 }
bdbfacc7
MS
232 break;
233
234 case '#' : /* Number of copies */
235 if (opt[1] != '\0')
236 {
237 num_copies = atoi(opt + 1);
238 opt += strlen(opt) - 1;
239 }
240 else
241 {
242 i ++;
243 if (i >= argc)
244 {
245 _cupsLangPrintf(stderr, _("%s: Error - expected copies after \"-#\" option."), argv[0]);
246 return (1);
247 }
248
249 num_copies = atoi(argv[i]);
250 }
ef416fc2 251
bdbfacc7 252 if (num_copies < 1)
ef416fc2 253 {
bdbfacc7 254 _cupsLangPrintf(stderr, _("%s: Error - copies must be 1 or more."), argv[0]);
ef416fc2 255 return (1);
256 }
257
bdbfacc7
MS
258 sprintf(buffer, "%d", num_copies);
259 num_options = cupsAddOption("copies", buffer, num_options, &options);
260 break;
ef416fc2 261
bdbfacc7
MS
262 case 'C' : /* Class */
263 case 'J' : /* Job name */
264 case 'T' : /* Title */
265 if (opt[1] != '\0')
266 {
267 title = opt + 1;
268 opt += strlen(opt) - 1;
269 }
270 else
271 {
272 i ++;
273 if (i >= argc)
274 {
275 _cupsLangPrintf(stderr, _("%s: Error - expected name after \"-%c\" option."), argv[0], ch);
276 return (1);
277 }
278
279 title = argv[i];
280 }
281 break;
282
283 default :
284 _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], *opt);
285 return (1);
286 }
ef416fc2 287 }
c606bcae 288 }
ef416fc2 289 else if (num_files < 1000)
290 {
291 /*
292 * Print a file...
293 */
294
295 if (access(argv[i], R_OK) != 0)
296 {
fa73b229 297 _cupsLangPrintf(stderr,
84315f46 298 _("%s: Error - unable to access \"%s\" - %s"),
fa73b229 299 argv[0], argv[i], strerror(errno));
ef416fc2 300 return (1);
301 }
302
303 files[num_files] = argv[i];
304 num_files ++;
305
306 if (title == NULL)
307 {
308 if ((title = strrchr(argv[i], '/')) != NULL)
309 title ++;
310 else
311 title = argv[i];
312 }
313 }
314 else
bdbfacc7
MS
315 {
316 _cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."), argv[0], argv[i]);
317 }
318 }
319
ef416fc2 320 /*
321 * See if we have any files to print; if not, print from stdin...
322 */
323
324 if (printer == NULL)
325 {
a4924f6c 326 if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL)
ef416fc2 327 {
328 printer = dest->name;
329
330 for (j = 0; j < dest->num_options; j ++)
331 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
332 num_options = cupsAddOption(dest->options[j].name,
333 dest->options[j].value,
334 num_options, &options);
335 }
c606bcae
MS
336 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
337 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
338 {
339 _cupsLangPrintf(stderr,
340 _("%s: Error - add '/version=1.1' to server "
341 "name."), argv[0]);
342 return (1);
343 }
ef416fc2 344 }
345
346 if (printer == NULL)
347 {
348 val = NULL;
349
350 if ((printer = getenv("LPDEST")) == NULL)
351 {
352 if ((printer = getenv("PRINTER")) != NULL)
353 {
354 if (!strcmp(printer, "lp"))
355 printer = NULL;
356 else
357 val = "PRINTER";
358 }
359 }
360 else
361 val = "LPDEST";
362
a4924f6c 363 if (printer && !cupsGetNamedDest(NULL, printer, NULL))
fa73b229 364 _cupsLangPrintf(stderr,
365 _("%s: Error - %s environment variable names "
0837b7e8
MS
366 "non-existent destination \"%s\"."), argv[0], val,
367 printer);
ef416fc2 368 else if (cupsLastError() == IPP_NOT_FOUND)
fa73b229 369 _cupsLangPrintf(stderr,
0837b7e8 370 _("%s: Error - no default destination available."),
fa73b229 371 argv[0]);
ef416fc2 372 else
0837b7e8 373 _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."),
fa73b229 374 argv[0]);
ef416fc2 375
376 return (1);
377 }
378
379 if (num_files > 0)
380 {
381 job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
382
383 if (deletefile && job_id > 0)
384 {
385 /*
386 * Delete print files after printing...
387 */
388
389 for (i = 0; i < num_files; i ++)
390 unlink(files[i]);
391 }
392 }
3d052e43
MS
393 else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
394 title ? title : "(stdin)",
395 num_options, options)) > 0)
ef416fc2 396 {
3d052e43
MS
397 http_status_t status; /* Write status */
398 const char *format; /* Document format */
399 ssize_t bytes; /* Bytes read */
ef416fc2 400
3d052e43
MS
401 if (cupsGetOption("raw", num_options, options))
402 format = CUPS_FORMAT_RAW;
403 else if ((format = cupsGetOption("document-format", num_options,
404 options)) == NULL)
405 format = CUPS_FORMAT_AUTO;
406
407 status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
408 format, 1);
ef416fc2 409
3d052e43
MS
410 while (status == HTTP_CONTINUE &&
411 (bytes = read(0, buffer, sizeof(buffer))) > 0)
7e86f2f6 412 status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes);
3d052e43
MS
413
414 if (status != HTTP_CONTINUE)
ef416fc2 415 {
0837b7e8 416 _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."),
3d052e43 417 argv[0], httpStatus(status));
12f89d24
MS
418 cupsFinishDocument(CUPS_HTTP_DEFAULT, printer);
419 cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
ef416fc2 420 return (1);
421 }
422
3d052e43 423 if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
12f89d24 424 {
a29fd7dd 425 _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
12f89d24 426 cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
a29fd7dd 427 return (1);
12f89d24 428 }
ef416fc2 429 }
430
431 if (job_id < 1)
432 {
0837b7e8 433 _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
ef416fc2 434 return (1);
435 }
436
437 return (0);
438}