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