Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/berkeley/lpr.c
1090 views
1
/*
2
* "lpr" command for CUPS.
3
*
4
* Copyright © 2021-2022 by OpenPrinting.
5
* Copyright © 2007-2019 by Apple Inc.
6
* Copyright © 1997-2007 by Easy Software Products.
7
*
8
* Licensed under Apache License v2.0. See the file "LICENSE" for more
9
* information.
10
*/
11
12
/*
13
* Include necessary headers...
14
*/
15
16
#include <cups/cups-private.h>
17
18
19
/*
20
* Local functions...
21
*/
22
23
static void usage(void) _CUPS_NORETURN;
24
25
26
/*
27
* 'main()' - Parse options and send files for printing.
28
*/
29
30
int
31
main(int argc, /* I - Number of command-line arguments */
32
char *argv[]) /* I - Command-line arguments */
33
{
34
int i, j; /* Looping var */
35
int job_id; /* Job ID */
36
char ch; /* Option character */
37
char *printer, /* Destination printer or class */
38
*instance, /* Instance */
39
*opt; /* Option pointer */
40
const char *title; /* Job title */
41
int num_copies; /* Number of copies per file */
42
int num_files; /* Number of files to print */
43
const char *files[1000]; /* Files to print */
44
cups_dest_t *dest; /* Selected destination */
45
int num_options; /* Number of options */
46
cups_option_t *options; /* Options */
47
int deletefile; /* Delete file after print? */
48
char buffer[8192]; /* Copy buffer */
49
50
51
_cupsSetLocale(argv);
52
53
deletefile = 0;
54
printer = NULL;
55
dest = NULL;
56
num_options = 0;
57
options = NULL;
58
num_files = 0;
59
title = NULL;
60
61
for (i = 1; i < argc; i ++)
62
{
63
if (!strcmp(argv[i], "--help"))
64
usage();
65
else if (argv[i][0] == '-')
66
{
67
for (opt = argv[i] + 1; *opt; opt ++)
68
{
69
switch (ch = *opt)
70
{
71
case 'E' : /* Encrypt */
72
#ifdef HAVE_TLS
73
cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
74
#else
75
_cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
76
#endif /* HAVE_TLS */
77
break;
78
79
case 'U' : /* Username */
80
if (opt[1] != '\0')
81
{
82
cupsSetUser(opt + 1);
83
opt += strlen(opt) - 1;
84
}
85
else
86
{
87
i ++;
88
if (i >= argc)
89
{
90
_cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]);
91
usage();
92
}
93
94
cupsSetUser(argv[i]);
95
}
96
break;
97
98
case 'H' : /* Connect to host */
99
if (opt[1] != '\0')
100
{
101
cupsSetServer(opt + 1);
102
opt += strlen(opt) - 1;
103
}
104
else
105
{
106
i ++;
107
108
if (i >= argc)
109
{
110
_cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-H\" option."), argv[0]);
111
usage();
112
}
113
else
114
cupsSetServer(argv[i]);
115
}
116
break;
117
118
case '1' : /* TROFF font set 1 */
119
case '2' : /* TROFF font set 2 */
120
case '3' : /* TROFF font set 3 */
121
case '4' : /* TROFF font set 4 */
122
case 'i' : /* indent */
123
case 'w' : /* width */
124
if (opt[1] != '\0')
125
{
126
opt += strlen(opt) - 1;
127
}
128
else
129
{
130
i ++;
131
132
if (i >= argc)
133
{
134
_cupsLangPrintf(stderr,
135
_("%s: Error - expected value after \"-%c\" "
136
"option."), argv[0], ch);
137
usage();
138
}
139
}
140
141
case 'c' : /* CIFPLOT */
142
case 'd' : /* DVI */
143
case 'f' : /* FORTRAN */
144
case 'g' : /* plot */
145
case 'n' : /* Ditroff */
146
case 't' : /* Troff */
147
case 'v' : /* Raster image */
148
_cupsLangPrintf(stderr, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv[0], ch);
149
break;
150
151
case 'o' : /* Option */
152
if (opt[1] != '\0')
153
{
154
num_options = cupsParseOptions(opt + 1, num_options, &options);
155
opt += strlen(opt) - 1;
156
}
157
else
158
{
159
i ++;
160
if (i >= argc)
161
{
162
_cupsLangPrintf(stderr, _("%s: Error - expected option=value after \"-o\" option."), argv[0]);
163
usage();
164
}
165
166
num_options = cupsParseOptions(argv[i], num_options, &options);
167
}
168
break;
169
170
case 'l' : /* Literal/raw */
171
num_options = cupsAddOption("raw", "true", num_options, &options);
172
break;
173
174
case 'p' : /* Prettyprint */
175
num_options = cupsAddOption("prettyprint", "true", num_options, &options);
176
break;
177
178
case 'h' : /* Suppress burst page */
179
num_options = cupsAddOption("job-sheets", "none", num_options, &options);
180
break;
181
182
case 's' : /* Don't use symlinks */
183
break;
184
185
case 'm' : /* Mail on completion */
186
{
187
char email[1024]; /* EMail address */
188
189
snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL, buffer, sizeof(buffer)));
190
num_options = cupsAddOption("notify-recipient-uri", email, num_options, &options);
191
}
192
break;
193
194
case 'q' : /* Queue file but don't print */
195
num_options = cupsAddOption("job-hold-until", "indefinite", num_options, &options);
196
break;
197
198
case 'r' : /* Remove file after printing */
199
deletefile = 1;
200
break;
201
202
case 'P' : /* Destination printer or class */
203
if (opt[1] != '\0')
204
{
205
printer = opt + 1;
206
opt += strlen(opt) - 1;
207
}
208
else
209
{
210
i ++;
211
if (i >= argc)
212
{
213
_cupsLangPrintf(stderr, _("%s: Error - expected destination after \"-P\" option."), argv[0]);
214
usage();
215
}
216
217
printer = argv[i];
218
}
219
220
if ((instance = strrchr(printer, '/')) != NULL)
221
*instance++ = '\0';
222
223
if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL)
224
{
225
for (j = 0; j < dest->num_options; j ++)
226
if (cupsGetOption(dest->options[j].name, num_options,
227
options) == NULL)
228
num_options = cupsAddOption(dest->options[j].name,
229
dest->options[j].value,
230
num_options, &options);
231
}
232
else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
233
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
234
{
235
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
236
return (1);
237
}
238
else if (cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND)
239
{
240
_cupsLangPrintf(stderr,
241
_("%s: Error - The printer or class does not exist."), argv[0]);
242
return (1);
243
}
244
break;
245
246
case '#' : /* Number of copies */
247
if (opt[1] != '\0')
248
{
249
num_copies = atoi(opt + 1);
250
opt += strlen(opt) - 1;
251
}
252
else
253
{
254
i ++;
255
if (i >= argc)
256
{
257
_cupsLangPrintf(stderr, _("%s: Error - expected copies after \"-#\" option."), argv[0]);
258
usage();
259
}
260
261
num_copies = atoi(argv[i]);
262
}
263
264
if (num_copies < 1)
265
{
266
_cupsLangPrintf(stderr, _("%s: Error - copies must be 1 or more."), argv[0]);
267
return (1);
268
}
269
270
num_options = cupsAddIntegerOption("copies", num_copies, num_options, &options);
271
break;
272
273
case 'C' : /* Class */
274
case 'J' : /* Job name */
275
case 'T' : /* Title */
276
if (opt[1] != '\0')
277
{
278
title = opt + 1;
279
opt += strlen(opt) - 1;
280
}
281
else
282
{
283
i ++;
284
if (i >= argc)
285
{
286
_cupsLangPrintf(stderr, _("%s: Error - expected name after \"-%c\" option."), argv[0], ch);
287
usage();
288
}
289
290
title = argv[i];
291
}
292
break;
293
294
default :
295
_cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], *opt);
296
return (1);
297
}
298
}
299
}
300
else if (num_files < 1000)
301
{
302
/*
303
* Print a file...
304
*/
305
306
if (access(argv[i], R_OK) != 0)
307
{
308
_cupsLangPrintf(stderr,
309
_("%s: Error - unable to access \"%s\" - %s"),
310
argv[0], argv[i], strerror(errno));
311
return (1);
312
}
313
314
files[num_files] = argv[i];
315
num_files ++;
316
317
if (title == NULL)
318
{
319
if ((title = strrchr(argv[i], '/')) != NULL)
320
title ++;
321
else
322
title = argv[i];
323
}
324
}
325
else
326
{
327
_cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."), argv[0], argv[i]);
328
}
329
}
330
331
/*
332
* See if we have any files to print; if not, print from stdin...
333
*/
334
335
if (printer == NULL)
336
{
337
if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL)
338
{
339
printer = dest->name;
340
341
for (j = 0; j < dest->num_options; j ++)
342
if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
343
num_options = cupsAddOption(dest->options[j].name,
344
dest->options[j].value,
345
num_options, &options);
346
}
347
else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
348
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
349
{
350
_cupsLangPrintf(stderr,
351
_("%s: Error - add '/version=1.1' to server "
352
"name."), argv[0]);
353
return (1);
354
}
355
}
356
357
if (printer == NULL)
358
{
359
if (!cupsGetNamedDest(NULL, NULL, NULL) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND)
360
_cupsLangPrintf(stderr, _("%s: Error - %s"), argv[0], cupsLastErrorString());
361
else
362
_cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]);
363
364
return (1);
365
}
366
367
if (num_files > 0)
368
{
369
job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
370
371
if (deletefile && job_id > 0)
372
{
373
/*
374
* Delete print files after printing...
375
*/
376
377
for (i = 0; i < num_files; i ++)
378
unlink(files[i]);
379
}
380
}
381
else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
382
title ? title : "(stdin)",
383
num_options, options)) > 0)
384
{
385
http_status_t status; /* Write status */
386
const char *format; /* Document format */
387
ssize_t bytes; /* Bytes read */
388
389
if (cupsGetOption("raw", num_options, options))
390
format = CUPS_FORMAT_RAW;
391
else if ((format = cupsGetOption("document-format", num_options,
392
options)) == NULL)
393
format = CUPS_FORMAT_AUTO;
394
395
status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
396
format, 1);
397
398
while (status == HTTP_CONTINUE &&
399
(bytes = read(0, buffer, sizeof(buffer))) > 0)
400
status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes);
401
402
if (status != HTTP_CONTINUE)
403
{
404
_cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."),
405
argv[0], httpStatus(status));
406
cupsFinishDocument(CUPS_HTTP_DEFAULT, printer);
407
cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
408
return (1);
409
}
410
411
if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
412
{
413
_cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
414
cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
415
return (1);
416
}
417
}
418
419
if (job_id < 1)
420
{
421
_cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
422
return (1);
423
}
424
425
return (0);
426
}
427
428
429
/*
430
* 'usage()' - Show program usage and exit.
431
*/
432
433
static void
434
usage(void)
435
{
436
_cupsLangPuts(stdout, _("Usage: lpr [options] [file(s)]"));
437
_cupsLangPuts(stdout, _("Options:"));
438
_cupsLangPuts(stdout, _("-# num-copies Specify the number of copies to print"));
439
_cupsLangPuts(stdout, _("-E Encrypt the connection to the server"));
440
_cupsLangPuts(stdout, _("-H server[:port] Connect to the named server and port"));
441
_cupsLangPuts(stdout, _("-m Send an email notification when the job completes"));
442
_cupsLangPuts(stdout, _("-o option[=value] Specify a printer-specific option"));
443
_cupsLangPuts(stdout, _("-o job-sheets=standard Print a banner page with the job"));
444
_cupsLangPuts(stdout, _("-o media=size Specify the media size to use"));
445
_cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)"));
446
_cupsLangPuts(stdout, _("-o orientation-requested=N\n"
447
" Specify portrait (3) or landscape (4) orientation"));
448
_cupsLangPuts(stdout, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)"));
449
_cupsLangPuts(stdout, _("-o sides=one-sided Specify 1-sided printing"));
450
_cupsLangPuts(stdout, _("-o sides=two-sided-long-edge\n"
451
" Specify 2-sided portrait printing"));
452
_cupsLangPuts(stdout, _("-o sides=two-sided-short-edge\n"
453
" Specify 2-sided landscape printing"));
454
_cupsLangPuts(stdout, _("-P destination Specify the destination"));
455
_cupsLangPuts(stdout, _("-q Specify the job should be held for printing"));
456
_cupsLangPuts(stdout, _("-r Remove the file(s) after submission"));
457
_cupsLangPuts(stdout, _("-T title Specify the job title"));
458
_cupsLangPuts(stdout, _("-U username Specify the username to use for authentication"));
459
460
exit(1);
461
}
462
463