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