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