]> git.ipfire.org Git - thirdparty/cups.git/blame - berkeley/lpr.c
Import CUPS trunk (1.4svn) r7116.
[thirdparty/cups.git] / berkeley / lpr.c
CommitLineData
ef416fc2 1/*
2e4ff8af 2 * "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $"
ef416fc2 3 *
4 * "lpr" command for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 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 *
17 * main() - Parse options and send files for printing.
18 * sighandler() - Signal catcher for when we print from stdin...
19 */
20
21/*
22 * Include necessary headers...
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <errno.h>
28
29#include <cups/string.h>
30#include <cups/cups.h>
31#include <cups/i18n.h>
32
33#ifndef WIN32
34# include <unistd.h>
35# include <signal.h>
36
37
38/*
39 * Local functions.
40 */
41
42void sighandler(int);
43#endif /* !WIN32 */
44
45
46/*
47 * Globals...
48 */
49
50char tempfile[1024]; /* Temporary file for printing from stdin */
51
52
53/*
54 * 'main()' - Parse options and send files for printing.
55 */
56
57int
fa73b229 58main(int argc, /* I - Number of command-line arguments */
59 char *argv[]) /* I - Command-line arguments */
ef416fc2 60{
fa73b229 61 int i, j; /* Looping var */
62 int job_id; /* Job ID */
63 char ch; /* Option character */
64 char *printer, /* Destination printer or class */
65 *instance; /* Instance */
66 const char *title, /* Job title */
67 *val; /* Environment variable name */
68 int num_copies; /* Number of copies per file */
69 int num_files; /* Number of files to print */
70 const char *files[1000]; /* Files to print */
71 int num_dests; /* Number of destinations */
72 cups_dest_t *dests, /* Destinations */
73 *dest; /* Selected destination */
74 int num_options; /* Number of options */
75 cups_option_t *options; /* Options */
76 int deletefile; /* Delete file after print? */
77 char buffer[8192]; /* Copy buffer */
78 ssize_t bytes; /* Bytes copied */
79 off_t filesize; /* Size of temp file */
80 int temp; /* Temporary file descriptor */
ef416fc2 81#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
fa73b229 82 struct sigaction action; /* Signal action */
83 struct sigaction oldaction; /* Old signal action */
ef416fc2 84#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
85
86
07725fee 87 _cupsSetLocale(argv);
d09495fa 88
ef416fc2 89 deletefile = 0;
90 printer = NULL;
91 num_dests = 0;
92 dests = NULL;
93 num_options = 0;
94 options = NULL;
95 num_files = 0;
96 title = NULL;
ef416fc2 97
98 for (i = 1; i < argc; i ++)
99 if (argv[i][0] == '-')
100 switch (ch = argv[i][1])
101 {
102 case 'E' : /* Encrypt */
103#ifdef HAVE_SSL
104 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
105#else
fa73b229 106 _cupsLangPrintf(stderr,
ef416fc2 107 _("%s: Sorry, no encryption support compiled in!\n"),
108 argv[0]);
109#endif /* HAVE_SSL */
110 break;
111
fa73b229 112 case 'U' : /* Username */
113 if (argv[i][2] != '\0')
114 cupsSetUser(argv[i] + 2);
115 else
116 {
117 i ++;
118 if (i >= argc)
119 {
120 _cupsLangPrintf(stderr,
121 _("%s: Error - expected username after "
122 "\'-U\' option!\n"),
123 argv[0]);
124 return (1);
125 }
126
127 cupsSetUser(argv[i]);
128 }
129 break;
130
131 case 'H' : /* Connect to host */
132 if (argv[i][2] != '\0')
133 cupsSetServer(argv[i] + 2);
134 else
135 {
136 i ++;
137
138 if (i >= argc)
139 {
140 _cupsLangPrintf(stderr,
141 _("%s: Error - expected hostname after "
142 "\'-H\' option!\n"),
143 argv[0]);
144 return (1);
145 }
146 else
147 cupsSetServer(argv[i]);
148 }
149 break;
150
ef416fc2 151 case '1' : /* TROFF font set 1 */
152 case '2' : /* TROFF font set 2 */
153 case '3' : /* TROFF font set 3 */
154 case '4' : /* TROFF font set 4 */
155 case 'i' : /* indent */
156 case 'w' : /* width */
157 if (argv[i][2] == '\0')
158 {
159 i ++;
160
161 if (i >= argc)
162 {
fa73b229 163 _cupsLangPrintf(stderr,
164 _("%s: Error - expected value after \'-%c\' "
165 "option!\n"), argv[0], ch);
ef416fc2 166 return (1);
167 }
168 }
169
170 case 'c' : /* CIFPLOT */
171 case 'd' : /* DVI */
172 case 'f' : /* FORTRAN */
173 case 'g' : /* plot */
174 case 'n' : /* Ditroff */
175 case 't' : /* Troff */
176 case 'v' : /* Raster image */
fa73b229 177 _cupsLangPrintf(stderr,
178 _("%s: Warning - \'%c\' format modifier not "
179 "supported - output may not be correct!\n"),
180 argv[0], ch);
ef416fc2 181 break;
182
183 case 'o' : /* Option */
184 if (argv[i][2] != '\0')
185 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
186 else
187 {
188 i ++;
189 if (i >= argc)
190 {
fa73b229 191 _cupsLangPrintf(stderr,
192 _("%s: error - expected option=value after "
193 "\'-o\' option!\n"),
194 argv[0]);
ef416fc2 195 return (1);
196 }
197
198 num_options = cupsParseOptions(argv[i], num_options, &options);
199 }
200 break;
201
202 case 'l' : /* Literal/raw */
2e4ff8af 203 num_options = cupsAddOption("raw", "true", num_options, &options);
ef416fc2 204 break;
205
206 case 'p' : /* Prettyprint */
2e4ff8af 207 num_options = cupsAddOption("prettyprint", "true", num_options,
fa73b229 208 &options);
ef416fc2 209 break;
210
211 case 'h' : /* Suppress burst page */
fa73b229 212 num_options = cupsAddOption("job-sheets", "none", num_options,
213 &options);
ef416fc2 214 break;
215
216 case 's' : /* Don't use symlinks */
217 break;
218
219 case 'm' : /* Mail on completion */
fa73b229 220 {
221 char email[1024]; /* EMail address */
222
223
224 snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(),
757d2cad 225 httpGetHostname(NULL, buffer, sizeof(buffer)));
7594b224 226 num_options = cupsAddOption("notify-recipient-uri", email,
fa73b229 227 num_options, &options);
228 }
ef416fc2 229 break;
230
231 case 'q' : /* Queue file but don't print */
232 num_options = cupsAddOption("job-hold-until", "indefinite",
233 num_options, &options);
234 break;
235
236 case 'r' : /* Remove file after printing */
237 deletefile = 1;
238 break;
239
240 case 'P' : /* Destination printer or class */
241 if (argv[i][2] != '\0')
242 printer = argv[i] + 2;
243 else
244 {
245 i ++;
246 if (i >= argc)
247 {
fa73b229 248 _cupsLangPrintf(stderr,
249 _("%s: Error - expected destination after "
250 "\'-P\' option!\n"),
251 argv[0]);
ef416fc2 252 return (1);
253 }
254
255 printer = argv[i];
256 }
257
258 if ((instance = strrchr(printer, '/')) != NULL)
259 *instance++ = '\0';
260
261 if (num_dests == 0)
262 num_dests = cupsGetDests(&dests);
263
264 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
265 {
266 for (j = 0; j < dest->num_options; j ++)
fa73b229 267 if (cupsGetOption(dest->options[j].name, num_options,
268 options) == NULL)
ef416fc2 269 num_options = cupsAddOption(dest->options[j].name,
270 dest->options[j].value,
271 num_options, &options);
272 }
273 break;
274
275 case '#' : /* Number of copies */
276 if (argv[i][2] != '\0')
277 num_copies = atoi(argv[i] + 2);
278 else
279 {
280 i ++;
281 if (i >= argc)
282 {
fa73b229 283 _cupsLangPrintf(stderr,
284 _("%s: Error - expected copy count after "
285 "\'-#\' option!\n"),
286 argv[0]);
ef416fc2 287 return (1);
288 }
289
290 num_copies = atoi(argv[i]);
291 }
292
293 sprintf(buffer, "%d", num_copies);
294 num_options = cupsAddOption("copies", buffer, num_options, &options);
295 break;
296
297 case 'C' : /* Class */
298 case 'J' : /* Job name */
299 case 'T' : /* Title */
300 if (argv[i][2] != '\0')
301 title = argv[i] + 2;
302 else
303 {
304 i ++;
305 if (i >= argc)
306 {
fa73b229 307 _cupsLangPrintf(stderr,
308 _("%s: Error - expected name after \'-%c\' "
309 "option!\n"), argv[0], ch);
ef416fc2 310 return (1);
311 }
312
313 title = argv[i];
314 }
315 break;
316
ef416fc2 317 default :
fa73b229 318 _cupsLangPrintf(stderr,
319 _("%s: Error - unknown option \'%c\'!\n"),
320 argv[0], argv[i][1]);
ef416fc2 321 return (1);
322 }
323 else if (num_files < 1000)
324 {
325 /*
326 * Print a file...
327 */
328
329 if (access(argv[i], R_OK) != 0)
330 {
fa73b229 331 _cupsLangPrintf(stderr,
332 _("%s: Error - unable to access \"%s\" - %s\n"),
333 argv[0], argv[i], strerror(errno));
ef416fc2 334 return (1);
335 }
336
337 files[num_files] = argv[i];
338 num_files ++;
339
340 if (title == NULL)
341 {
342 if ((title = strrchr(argv[i], '/')) != NULL)
343 title ++;
344 else
345 title = argv[i];
346 }
347 }
348 else
fa73b229 349 _cupsLangPrintf(stderr,
350 _("%s: Error - too many files - \"%s\"\n"),
351 argv[0], argv[i]);
ef416fc2 352 /*
353 * See if we have any files to print; if not, print from stdin...
354 */
355
356 if (printer == NULL)
357 {
358 if (num_dests == 0)
359 num_dests = cupsGetDests(&dests);
360
361 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
362 {
363 printer = dest->name;
364
365 for (j = 0; j < dest->num_options; j ++)
366 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
367 num_options = cupsAddOption(dest->options[j].name,
368 dest->options[j].value,
369 num_options, &options);
370 }
371 }
372
373 if (printer == NULL)
374 {
375 val = NULL;
376
377 if ((printer = getenv("LPDEST")) == NULL)
378 {
379 if ((printer = getenv("PRINTER")) != NULL)
380 {
381 if (!strcmp(printer, "lp"))
382 printer = NULL;
383 else
384 val = "PRINTER";
385 }
386 }
387 else
388 val = "LPDEST";
389
390 if (printer && !cupsGetDest(printer, NULL, num_dests, dests))
fa73b229 391 _cupsLangPrintf(stderr,
392 _("%s: Error - %s environment variable names "
ef416fc2 393 "non-existent destination \"%s\"!\n"),
fa73b229 394 argv[0], val, printer);
ef416fc2 395 else if (cupsLastError() == IPP_NOT_FOUND)
fa73b229 396 _cupsLangPrintf(stderr,
397 _("%s: Error - no default destination available.\n"),
398 argv[0]);
ef416fc2 399 else
fa73b229 400 _cupsLangPrintf(stderr,
401 _("%s: Error - scheduler not responding!\n"),
402 argv[0]);
ef416fc2 403
404 return (1);
405 }
406
407 if (num_files > 0)
408 {
409 job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
410
411 if (deletefile && job_id > 0)
412 {
413 /*
414 * Delete print files after printing...
415 */
416
417 for (i = 0; i < num_files; i ++)
418 unlink(files[i]);
419 }
420 }
421 else
422 {
423 num_files = 1;
424
425#ifndef WIN32
426# if defined(HAVE_SIGSET)
427 sigset(SIGHUP, sighandler);
428 if (sigset(SIGINT, sighandler) == SIG_IGN)
429 sigset(SIGINT, SIG_IGN);
430 sigset(SIGTERM, sighandler);
431# elif defined(HAVE_SIGACTION)
432 memset(&action, 0, sizeof(action));
433 action.sa_handler = sighandler;
434
435 sigaction(SIGHUP, &action, NULL);
436 sigaction(SIGINT, NULL, &oldaction);
437 if (oldaction.sa_handler != SIG_IGN)
438 sigaction(SIGINT, &action, NULL);
439 sigaction(SIGTERM, &action, NULL);
440# else
441 signal(SIGHUP, sighandler);
442 if (signal(SIGINT, sighandler) == SIG_IGN)
443 signal(SIGINT, SIG_IGN);
444 signal(SIGTERM, sighandler);
445# endif
446#endif /* !WIN32 */
447
448 if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
449 {
fa73b229 450 _cupsLangPrintf(stderr,
451 _("%s: Error - unable to create temporary file "
ef416fc2 452 "\"%s\" - %s\n"),
fa73b229 453 argv[0], tempfile, strerror(errno));
ef416fc2 454 return (1);
455 }
456
fa73b229 457 while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
458 if (write(temp, buffer, bytes) < 0)
ef416fc2 459 {
fa73b229 460 _cupsLangPrintf(stderr,
461 _("%s: Error - unable to write to temporary file "
ef416fc2 462 "\"%s\" - %s\n"),
fa73b229 463 argv[0], tempfile, strerror(errno));
ef416fc2 464 close(temp);
465 unlink(tempfile);
466 return (1);
467 }
468
fa73b229 469 filesize = lseek(temp, 0, SEEK_CUR);
ef416fc2 470 close(temp);
471
fa73b229 472 if (filesize <= 0)
ef416fc2 473 {
fa73b229 474 _cupsLangPrintf(stderr,
475 _("%s: Error - stdin is empty, so no job has been sent.\n"),
476 argv[0]);
ef416fc2 477 unlink(tempfile);
478 return (1);
479 }
480
481 if (title)
482 job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
483 else
484 job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
485
486 unlink(tempfile);
487 }
488
489 if (job_id < 1)
490 {
fa73b229 491 _cupsLangPrintf(stderr, "%s: %s\n", argv[0], cupsLastErrorString());
ef416fc2 492 return (1);
493 }
494
495 return (0);
496}
497
498
499#ifndef WIN32
500/*
501 * 'sighandler()' - Signal catcher for when we print from stdin...
502 */
503
504void
fa73b229 505sighandler(int s) /* I - Signal number */
ef416fc2 506{
507 /*
508 * Remove the temporary file we're using to print from stdin...
509 */
510
511 unlink(tempfile);
512
513 /*
514 * Exit...
515 */
516
517 exit(s);
518}
519#endif /* !WIN32 */
520
521
522/*
2e4ff8af 523 * End of "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $".
ef416fc2 524 */