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