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