]> git.ipfire.org Git - thirdparty/cups.git/blame - berkeley/lpr.c
Merge changes from CUPS 1.4svn-r7961.
[thirdparty/cups.git] / berkeley / lpr.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: lpr.c 7720 2008-07-11 22:46:21Z mike $"
ef416fc2 3 *
4 * "lpr" command for the Common UNIX Printing System (CUPS).
5 *
1f0275e3 6 * Copyright 2007-2008 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 *
3d052e43 17 * main() - Parse options and send files for printing.
ef416fc2 18 */
19
20/*
21 * Include necessary headers...
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
27
28#include <cups/string.h>
29#include <cups/cups.h>
30#include <cups/i18n.h>
31
ef416fc2 32
33/*
34 * 'main()' - Parse options and send files for printing.
35 */
36
37int
fa73b229 38main(int argc, /* I - Number of command-line arguments */
39 char *argv[]) /* I - Command-line arguments */
ef416fc2 40{
fa73b229 41 int i, j; /* Looping var */
42 int job_id; /* Job ID */
43 char ch; /* Option character */
44 char *printer, /* Destination printer or class */
45 *instance; /* Instance */
46 const char *title, /* Job title */
47 *val; /* Environment variable name */
48 int num_copies; /* Number of copies per file */
49 int num_files; /* Number of files to print */
50 const char *files[1000]; /* Files to print */
a4924f6c 51 cups_dest_t *dest; /* Selected destination */
fa73b229 52 int num_options; /* Number of options */
53 cups_option_t *options; /* Options */
54 int deletefile; /* Delete file after print? */
55 char buffer[8192]; /* Copy buffer */
ef416fc2 56
57
07725fee 58 _cupsSetLocale(argv);
d09495fa 59
ef416fc2 60 deletefile = 0;
61 printer = NULL;
a4924f6c 62 dest = NULL;
ef416fc2 63 num_options = 0;
64 options = NULL;
65 num_files = 0;
66 title = NULL;
ef416fc2 67
68 for (i = 1; i < argc; i ++)
69 if (argv[i][0] == '-')
70 switch (ch = argv[i][1])
71 {
72 case 'E' : /* Encrypt */
73#ifdef HAVE_SSL
74 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
75#else
fa73b229 76 _cupsLangPrintf(stderr,
ef416fc2 77 _("%s: Sorry, no encryption support compiled in!\n"),
78 argv[0]);
79#endif /* HAVE_SSL */
80 break;
81
fa73b229 82 case 'U' : /* Username */
83 if (argv[i][2] != '\0')
84 cupsSetUser(argv[i] + 2);
85 else
86 {
87 i ++;
88 if (i >= argc)
89 {
90 _cupsLangPrintf(stderr,
91 _("%s: Error - expected username after "
92 "\'-U\' option!\n"),
93 argv[0]);
94 return (1);
95 }
96
97 cupsSetUser(argv[i]);
98 }
99 break;
100
101 case 'H' : /* Connect to host */
102 if (argv[i][2] != '\0')
103 cupsSetServer(argv[i] + 2);
104 else
105 {
106 i ++;
107
108 if (i >= argc)
109 {
110 _cupsLangPrintf(stderr,
111 _("%s: Error - expected hostname after "
112 "\'-H\' option!\n"),
113 argv[0]);
114 return (1);
115 }
116 else
117 cupsSetServer(argv[i]);
118 }
119 break;
120
ef416fc2 121 case '1' : /* TROFF font set 1 */
122 case '2' : /* TROFF font set 2 */
123 case '3' : /* TROFF font set 3 */
124 case '4' : /* TROFF font set 4 */
125 case 'i' : /* indent */
126 case 'w' : /* width */
127 if (argv[i][2] == '\0')
128 {
129 i ++;
130
131 if (i >= argc)
132 {
fa73b229 133 _cupsLangPrintf(stderr,
134 _("%s: Error - expected value after \'-%c\' "
135 "option!\n"), argv[0], ch);
ef416fc2 136 return (1);
137 }
138 }
139
140 case 'c' : /* CIFPLOT */
141 case 'd' : /* DVI */
142 case 'f' : /* FORTRAN */
143 case 'g' : /* plot */
144 case 'n' : /* Ditroff */
145 case 't' : /* Troff */
146 case 'v' : /* Raster image */
fa73b229 147 _cupsLangPrintf(stderr,
148 _("%s: Warning - \'%c\' format modifier not "
149 "supported - output may not be correct!\n"),
150 argv[0], ch);
ef416fc2 151 break;
152
153 case 'o' : /* Option */
154 if (argv[i][2] != '\0')
155 num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
156 else
157 {
158 i ++;
159 if (i >= argc)
160 {
fa73b229 161 _cupsLangPrintf(stderr,
162 _("%s: error - expected option=value after "
163 "\'-o\' option!\n"),
164 argv[0]);
ef416fc2 165 return (1);
166 }
167
168 num_options = cupsParseOptions(argv[i], num_options, &options);
169 }
170 break;
171
172 case 'l' : /* Literal/raw */
2e4ff8af 173 num_options = cupsAddOption("raw", "true", num_options, &options);
ef416fc2 174 break;
175
176 case 'p' : /* Prettyprint */
2e4ff8af 177 num_options = cupsAddOption("prettyprint", "true", num_options,
fa73b229 178 &options);
ef416fc2 179 break;
180
181 case 'h' : /* Suppress burst page */
fa73b229 182 num_options = cupsAddOption("job-sheets", "none", num_options,
183 &options);
ef416fc2 184 break;
185
186 case 's' : /* Don't use symlinks */
187 break;
188
189 case 'm' : /* Mail on completion */
fa73b229 190 {
191 char email[1024]; /* EMail address */
192
193
194 snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(),
757d2cad 195 httpGetHostname(NULL, buffer, sizeof(buffer)));
7594b224 196 num_options = cupsAddOption("notify-recipient-uri", email,
fa73b229 197 num_options, &options);
198 }
ef416fc2 199 break;
200
201 case 'q' : /* Queue file but don't print */
202 num_options = cupsAddOption("job-hold-until", "indefinite",
203 num_options, &options);
204 break;
205
206 case 'r' : /* Remove file after printing */
207 deletefile = 1;
208 break;
209
210 case 'P' : /* Destination printer or class */
211 if (argv[i][2] != '\0')
212 printer = argv[i] + 2;
213 else
214 {
215 i ++;
216 if (i >= argc)
217 {
fa73b229 218 _cupsLangPrintf(stderr,
219 _("%s: Error - expected destination after "
220 "\'-P\' option!\n"),
221 argv[0]);
ef416fc2 222 return (1);
223 }
224
225 printer = argv[i];
226 }
227
228 if ((instance = strrchr(printer, '/')) != NULL)
229 *instance++ = '\0';
230
a4924f6c 231 if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL)
ef416fc2 232 {
233 for (j = 0; j < dest->num_options; j ++)
fa73b229 234 if (cupsGetOption(dest->options[j].name, num_options,
235 options) == NULL)
ef416fc2 236 num_options = cupsAddOption(dest->options[j].name,
237 dest->options[j].value,
238 num_options, &options);
239 }
240 break;
241
242 case '#' : /* Number of copies */
243 if (argv[i][2] != '\0')
244 num_copies = atoi(argv[i] + 2);
245 else
246 {
247 i ++;
248 if (i >= argc)
249 {
fa73b229 250 _cupsLangPrintf(stderr,
251 _("%s: Error - expected copy count after "
252 "\'-#\' option!\n"),
253 argv[0]);
ef416fc2 254 return (1);
255 }
256
257 num_copies = atoi(argv[i]);
258 }
259
260 sprintf(buffer, "%d", num_copies);
261 num_options = cupsAddOption("copies", buffer, num_options, &options);
262 break;
263
264 case 'C' : /* Class */
265 case 'J' : /* Job name */
266 case 'T' : /* Title */
267 if (argv[i][2] != '\0')
268 title = argv[i] + 2;
269 else
270 {
271 i ++;
272 if (i >= argc)
273 {
fa73b229 274 _cupsLangPrintf(stderr,
275 _("%s: Error - expected name after \'-%c\' "
276 "option!\n"), argv[0], ch);
ef416fc2 277 return (1);
278 }
279
280 title = argv[i];
281 }
282 break;
283
ef416fc2 284 default :
fa73b229 285 _cupsLangPrintf(stderr,
286 _("%s: Error - unknown option \'%c\'!\n"),
287 argv[0], argv[i][1]);
ef416fc2 288 return (1);
289 }
290 else if (num_files < 1000)
291 {
292 /*
293 * Print a file...
294 */
295
296 if (access(argv[i], R_OK) != 0)
297 {
fa73b229 298 _cupsLangPrintf(stderr,
299 _("%s: Error - unable to access \"%s\" - %s\n"),
300 argv[0], argv[i], strerror(errno));
ef416fc2 301 return (1);
302 }
303
304 files[num_files] = argv[i];
305 num_files ++;
306
307 if (title == NULL)
308 {
309 if ((title = strrchr(argv[i], '/')) != NULL)
310 title ++;
311 else
312 title = argv[i];
313 }
314 }
315 else
fa73b229 316 _cupsLangPrintf(stderr,
317 _("%s: Error - too many files - \"%s\"\n"),
318 argv[0], argv[i]);
ef416fc2 319 /*
320 * See if we have any files to print; if not, print from stdin...
321 */
322
323 if (printer == NULL)
324 {
a4924f6c 325 if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL)
ef416fc2 326 {
327 printer = dest->name;
328
329 for (j = 0; j < dest->num_options; j ++)
330 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
331 num_options = cupsAddOption(dest->options[j].name,
332 dest->options[j].value,
333 num_options, &options);
334 }
335 }
336
337 if (printer == NULL)
338 {
339 val = NULL;
340
341 if ((printer = getenv("LPDEST")) == NULL)
342 {
343 if ((printer = getenv("PRINTER")) != NULL)
344 {
345 if (!strcmp(printer, "lp"))
346 printer = NULL;
347 else
348 val = "PRINTER";
349 }
350 }
351 else
352 val = "LPDEST";
353
a4924f6c 354 if (printer && !cupsGetNamedDest(NULL, printer, NULL))
fa73b229 355 _cupsLangPrintf(stderr,
356 _("%s: Error - %s environment variable names "
ef416fc2 357 "non-existent destination \"%s\"!\n"),
fa73b229 358 argv[0], val, printer);
ef416fc2 359 else if (cupsLastError() == IPP_NOT_FOUND)
fa73b229 360 _cupsLangPrintf(stderr,
361 _("%s: Error - no default destination available.\n"),
362 argv[0]);
ef416fc2 363 else
fa73b229 364 _cupsLangPrintf(stderr,
365 _("%s: Error - scheduler not responding!\n"),
366 argv[0]);
ef416fc2 367
368 return (1);
369 }
370
371 if (num_files > 0)
372 {
373 job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
374
375 if (deletefile && job_id > 0)
376 {
377 /*
378 * Delete print files after printing...
379 */
380
381 for (i = 0; i < num_files; i ++)
382 unlink(files[i]);
383 }
384 }
3d052e43
MS
385 else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
386 title ? title : "(stdin)",
387 num_options, options)) > 0)
ef416fc2 388 {
3d052e43
MS
389 http_status_t status; /* Write status */
390 const char *format; /* Document format */
391 ssize_t bytes; /* Bytes read */
ef416fc2 392
ef416fc2 393
3d052e43
MS
394 if (cupsGetOption("raw", num_options, options))
395 format = CUPS_FORMAT_RAW;
396 else if ((format = cupsGetOption("document-format", num_options,
397 options)) == NULL)
398 format = CUPS_FORMAT_AUTO;
399
400 status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
401 format, 1);
ef416fc2 402
3d052e43
MS
403 while (status == HTTP_CONTINUE &&
404 (bytes = read(0, buffer, sizeof(buffer))) > 0)
405 status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
406
407 if (status != HTTP_CONTINUE)
ef416fc2 408 {
fa73b229 409 _cupsLangPrintf(stderr,
3d052e43
MS
410 _("%s: Error - unable to queue from stdin - %s\n"),
411 argv[0], httpStatus(status));
ef416fc2 412 return (1);
413 }
414
3d052e43
MS
415 if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
416 job_id = 0;
ef416fc2 417 }
418
419 if (job_id < 1)
420 {
fa73b229 421 _cupsLangPrintf(stderr, "%s: %s\n", argv[0], cupsLastErrorString());
ef416fc2 422 return (1);
423 }
424
425 return (0);
426}
427
428
ef416fc2 429/*
b19ccc9e 430 * End of "$Id: lpr.c 7720 2008-07-11 22:46:21Z mike $".
ef416fc2 431 */