]> git.ipfire.org Git - thirdparty/cups.git/blame - berkeley/lpr.c
Copyright update...
[thirdparty/cups.git] / berkeley / lpr.c
CommitLineData
bd0b97ff 1/*
efb2f309 2 * "$Id: lpr.c,v 1.23 2002/01/02 17:58:35 mike Exp $"
bd0b97ff 3 *
4 * "lpr" command for the Common UNIX Printing System (CUPS).
5 *
efb2f309 6 * Copyright 1997-2002 by Easy Software Products.
bd0b97ff 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-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
8dbf3e6a 26 * main() - Parse options and send files for printing.
27 * sighandler() - Signal catcher for when we print from stdin...
bd0b97ff 28 */
29
30/*
31 * Include necessary headers...
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
1c9e0181 36
37#include <config.h>
bd0b97ff 38#include <cups/cups.h>
39
40
8dbf3e6a 41#ifndef WIN32
42# include <signal.h>
43
44
45/*
46 * Local functions.
47 */
48
977acbd3 49void sighandler(int);
8dbf3e6a 50#endif /* !WIN32 */
51
52
53/*
54 * Globals...
55 */
56
57char tempfile[1024]; /* Temporary file for printing from stdin */
58
59
bd0b97ff 60/*
61 * 'main()' - Parse options and send files for printing.
62 */
63
64int
65main(int argc, /* I - Number of command-line arguments */
66 char *argv[]) /* I - Command-line arguments */
67{
caa7d083 68 int i, j; /* Looping var */
bd0b97ff 69 int job_id; /* Job ID */
1cb10d96 70 char ch; /* Option character */
caa7d083 71 char *printer, /* Destination printer or class */
72 *instance; /* Instance */
bf56a667 73 const char *title; /* Job title */
bd0b97ff 74 int num_copies; /* Number of copies per file */
caa7d083 75 int num_files; /* Number of files to print */
76 const char *files[1000]; /* Files to print */
77 int num_dests; /* Number of destinations */
78 cups_dest_t *dests, /* Destinations */
79 *dest; /* Selected destination */
bd0b97ff 80 int num_options; /* Number of options */
81 cups_option_t *options; /* Options */
8a2c2126 82 int deletefile; /* Delete file after print? */
bd0b97ff 83 char buffer[8192]; /* Copy buffer */
1b5bf964 84 int temp; /* Temporary file descriptor */
a5f8b9e7 85#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
977acbd3 86 struct sigaction action; /* Signal action */
a5f8b9e7 87#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
bd0b97ff 88
89
7dd958a9 90 deletefile = 0;
caa7d083 91 printer = NULL;
92 num_dests = 0;
93 dests = NULL;
bd0b97ff 94 num_options = 0;
95 options = NULL;
96 num_files = 0;
97 title = NULL;
98
99 for (i = 1; i < argc; i ++)
100 if (argv[i][0] == '-')
1cb10d96 101 switch (ch = argv[i][1])
bd0b97ff 102 {
1c9e0181 103 case 'E' : /* Encrypt */
104#ifdef HAVE_LIBSSL
105 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
106#else
107 fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
108 argv[0]);
109#endif /* HAVE_LIBSSL */
110 break;
111
a8131f99 112 case '1' : /* TROFF font set 1 */
113 case '2' : /* TROFF font set 2 */
114 case '3' : /* TROFF font set 3 */
115 case '4' : /* TROFF font set 4 */
bd0b97ff 116 case 'i' : /* indent */
117 case 'w' : /* width */
118 if (argv[i][2] == '\0')
1cb10d96 119 {
bd0b97ff 120 i ++;
1cb10d96 121
122 if (i >= argc)
123 {
124 fprintf(stderr, "lpr: Expected value after -%c option!\n", ch);
125 return (1);
126 }
127 }
128
bd0b97ff 129 case 'c' : /* CIFPLOT */
130 case 'd' : /* DVI */
131 case 'f' : /* FORTRAN */
132 case 'g' : /* plot */
133 case 'n' : /* Ditroff */
134 case 't' : /* Troff */
135 case 'v' : /* Raster image */
136 fprintf(stderr, "Warning: \'%c\' format modifier not supported - output may not be correct!\n",
1cb10d96 137 ch);
bd0b97ff 138 break;
139
5b187d9c 140 case 'o' : /* Option */
141 if (argv[i][2] != '\0')
142 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
143 else
144 {
145 i ++;
1cb10d96 146 if (i >= argc)
147 {
148 fputs("lpr: Expected option=value after -o option!\n", stderr);
149 return (1);
150 }
151
5b187d9c 152 num_options = cupsParseOptions(argv[i], num_options, &options);
153 }
154 break;
155
bd0b97ff 156 case 'l' : /* Literal/raw */
20178dbb 157 num_options = cupsAddOption("raw", "", num_options, &options);
bd0b97ff 158 break;
159
160 case 'p' : /* Prettyprint */
20178dbb 161 num_options = cupsAddOption("prettyprint", "", num_options, &options);
bd0b97ff 162 break;
163
164 case 'h' : /* Suppress burst page */
20178dbb 165 num_options = cupsAddOption("job-sheets", "none", num_options, &options);
166 break;
167
bd0b97ff 168 case 's' : /* Don't use symlinks */
169 break;
170
7dd958a9 171 case 'm' : /* Mail on completion */
bd0b97ff 172 fputs("Warning: email notification is not supported!\n", stderr);
173 break;
174
1cb10d96 175 case 'q' : /* Queue file but don't print */
176 num_options = cupsAddOption("job-hold-until", "indefinite",
177 num_options, &options);
178 break;
179
7dd958a9 180 case 'r' : /* Remove file after printing */
181 deletefile = 1;
182 break;
183
bd0b97ff 184 case 'P' : /* Destination printer or class */
185 if (argv[i][2] != '\0')
caa7d083 186 printer = argv[i] + 2;
bd0b97ff 187 else
188 {
189 i ++;
1cb10d96 190 if (i >= argc)
191 {
192 fputs("lpr: Expected destination after -P option!\n", stderr);
193 return (1);
194 }
195
caa7d083 196 printer = argv[i];
197 }
198
199 if ((instance = strrchr(printer, '/')) != NULL)
200 *instance++ = '\0';
201
202 if (num_dests == 0)
203 num_dests = cupsGetDests(&dests);
204
205 if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
206 {
207 for (j = 0; j < dest->num_options; j ++)
e8973392 208 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
209 num_options = cupsAddOption(dest->options[j].name,
210 dest->options[j].value,
211 num_options, &options);
bd0b97ff 212 }
213 break;
214
215 case '#' : /* Number of copies */
216 if (argv[i][2] != '\0')
217 num_copies = atoi(argv[i] + 2);
218 else
219 {
220 i ++;
1cb10d96 221 if (i >= argc)
222 {
223 fputs("lpr: Expected copy count after -# option!\n", stderr);
224 return (1);
225 }
226
bd0b97ff 227 num_copies = atoi(argv[i]);
228 }
229
230 if (num_copies < 1 || num_copies > 100)
231 {
232 fputs("lpr: Number copies must be between 1 and 100.\n", stderr);
233 return (1);
234 }
235
236 sprintf(buffer, "%d", num_copies);
237 num_options = cupsAddOption("copies", buffer, num_options, &options);
238 break;
239
240 case 'C' : /* Class */
241 case 'J' : /* Job name */
242 case 'T' : /* Title */
243 if (argv[i][2] != '\0')
244 title = argv[i] + 2;
245 else
246 {
247 i ++;
1cb10d96 248 if (i >= argc)
249 {
250 fprintf(stderr, "lpr: Expected name after -%c option!\n", ch);
251 return (1);
252 }
253
bd0b97ff 254 title = argv[i];
255 }
256 break;
257
1cb10d96 258 case 'U' : /* User */
259 if (argv[i][2] != '\0')
260 cupsSetUser(argv[i] + 2);
261 else
262 {
263 i ++;
264 if (i >= argc)
265 {
266 fputs("lpr: Expected username after -U option!\n", stderr);
267 return (1);
268 }
269
270 cupsSetUser(argv[i]);
271 }
272 break;
273
bd0b97ff 274 default :
275 fprintf(stderr, "lpr: Unknown option \'%c\'!\n", argv[i][1]);
276 return (1);
277 }
caa7d083 278 else if (num_files < 1000)
bd0b97ff 279 {
280 /*
281 * Print a file...
282 */
283
caa7d083 284 files[num_files] = argv[i];
bd0b97ff 285 num_files ++;
bd0b97ff 286
caa7d083 287 if (title == NULL)
288 {
289 if ((title = strrchr(argv[i], '/')) != NULL)
290 title ++;
bd0b97ff 291 else
caa7d083 292 title = argv[i];
bd0b97ff 293 }
caa7d083 294 }
295 else
296 fprintf(stderr, "lpr: Too many files - \"%s\"\n", argv[i]);
297 /*
298 * See if we have any files to print; if not, print from stdin...
299 */
300
301 if (printer == NULL)
302 {
303 if (num_dests == 0)
304 num_dests = cupsGetDests(&dests);
bd0b97ff 305
caa7d083 306 for (j = 0, dest = dests; j < num_dests; j ++, dest ++)
307 if (dest->is_default)
bd0b97ff 308 {
caa7d083 309 printer = dests[j].name;
310
311 for (j = 0; j < dest->num_options; j ++)
e8973392 312 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
313 num_options = cupsAddOption(dest->options[j].name,
314 dest->options[j].value,
315 num_options, &options);
caa7d083 316 break;
bd0b97ff 317 }
caa7d083 318 }
bd0b97ff 319
caa7d083 320 if (printer == NULL)
321 {
322 fputs("lpr: error - no default destination available.\n", stderr);
323 return (1);
324 }
bd0b97ff 325
caa7d083 326 if (num_files > 0)
bd0b97ff 327 {
caa7d083 328 job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
329
330 if (deletefile)
bd0b97ff 331 {
caa7d083 332 /*
333 * Delete print files after printing...
334 */
335
336 for (i = 0; i < num_files; i ++)
337 unlink(files[i]);
bd0b97ff 338 }
caa7d083 339 }
340 else
341 {
342 num_files = 1;
bd0b97ff 343
8dbf3e6a 344#ifndef WIN32
977acbd3 345# if defined(HAVE_SIGSET)
346 sigset(SIGHUP, sighandler);
347 sigset(SIGINT, sighandler);
348 sigset(SIGTERM, sighandler);
349# elif defined(HAVE_SIGACTION)
350 memset(&action, 0, sizeof(action));
351 action.sa_handler = sighandler;
352
353 sigaction(SIGHUP, &action, NULL);
354 sigaction(SIGINT, &action, NULL);
355 sigaction(SIGTERM, &action, NULL);
356# else
357 signal(SIGHUP, sighandler);
358 signal(SIGINT, sighandler);
8dbf3e6a 359 signal(SIGTERM, sighandler);
977acbd3 360# endif
8dbf3e6a 361#endif /* !WIN32 */
362
1b5bf964 363 if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
bd0b97ff 364 {
365 fputs("lpr: unable to create temporary file.\n", stderr);
366 return (1);
367 }
368
9fda7ee8 369 while ((i = read(0, buffer, sizeof(buffer))) > 0)
1b5bf964 370 write(temp, buffer, i);
bd0b97ff 371
1b5bf964 372 i = lseek(temp, 0, SEEK_CUR);
373 close(temp);
bd0b97ff 374
375 if (i == 0)
376 {
caa7d083 377 fputs("lpr: stdin is empty, so no job has been sent.\n", stderr);
bd0b97ff 378 return (1);
379 }
380
381 if (title)
caa7d083 382 job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
bd0b97ff 383 else
caa7d083 384 job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
bd0b97ff 385
68ea7095 386 unlink(tempfile);
caa7d083 387 }
68ea7095 388
caa7d083 389 if (job_id < 1)
390 {
391 fprintf(stderr, "lpr: unable to print file: %s\n",
392 ippErrorString(cupsLastError()));
393 return (1);
bd0b97ff 394 }
395
396 return (0);
397}
398
399
8dbf3e6a 400#ifndef WIN32
401/*
402 * 'sighandler()' - Signal catcher for when we print from stdin...
403 */
404
405void
977acbd3 406sighandler(int s) /* I - Signal number */
8dbf3e6a 407{
408 /*
409 * Remove the temporary file we're using to print from stdin...
410 */
411
412 unlink(tempfile);
977acbd3 413
414 /*
415 * Exit...
416 */
417
418 exit(s);
8dbf3e6a 419}
420#endif /* !WIN32 */
421
422
bd0b97ff 423/*
efb2f309 424 * End of "$Id: lpr.c,v 1.23 2002/01/02 17:58:35 mike Exp $".
bd0b97ff 425 */