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