]>
git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lp.c
2 * "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $"
4 * "lp" command for CUPS.
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
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/".
17 * main() - Parse options and send files for printing.
18 * restart_job() - Restart a job.
19 * set_job_attrs() - Set job attributes.
23 * Include necessary headers...
26 #include <cups/cups-private.h>
33 int restart_job(const char *command
, int job_id
);
34 int set_job_attrs(const char *command
, int job_id
, int num_options
,
35 cups_option_t
*options
);
39 * 'main()' - Parse options and send files for printing.
43 main(int argc
, /* I - Number of command-line arguments */
44 char *argv
[]) /* I - Command-line arguments */
46 int i
, j
; /* Looping vars */
47 int job_id
; /* Job ID */
48 char *printer
, /* Printer name */
49 *instance
, /* Instance name */
50 *val
, /* Option value */
51 *title
; /* Job title */
52 int priority
; /* Job priority (1-100) */
53 int num_copies
; /* Number of copies per file */
54 int num_files
; /* Number of files to print */
55 const char *files
[1000]; /* Files to print */
56 cups_dest_t
*dest
; /* Selected destination */
57 int num_options
; /* Number of options */
58 cups_option_t
*options
; /* Options */
59 int end_options
; /* No more options? */
60 int silent
; /* Silent or verbose output? */
61 char buffer
[8192]; /* Copy buffer */
66 * Solaris does some rather strange things to re-queue remote print
67 * jobs. On bootup, the "lp" command is run as "printd" to re-spool
68 * any remote jobs in /var/spool/print. Since CUPS doesn't need this
69 * nonsense, we just need to add the necessary check here to prevent
70 * lp from causing boot problems...
73 if ((val
= strrchr(argv
[0], '/')) != NULL
)
78 if (!strcmp(val
, "printd"))
94 for (i
= 1; i
< argc
; i
++)
95 if (argv
[i
][0] == '-' && argv
[i
][1] && !end_options
)
98 case 'E' : /* Encrypt */
100 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
102 _cupsLangPrintf(stderr
, _("%s: Sorry, no encryption support."),
104 #endif /* HAVE_SSL */
107 case 'U' : /* Username */
108 if (argv
[i
][2] != '\0')
109 cupsSetUser(argv
[i
] + 2);
115 _cupsLangPrintf(stderr
,
116 _("%s: Error - expected username after \"-U\" "
117 "option."), argv
[0]);
121 cupsSetUser(argv
[i
]);
125 case 'c' : /* Copy to spool dir (always enabled) */
128 case 'd' : /* Destination printer or class */
129 if (argv
[i
][2] != '\0')
130 printer
= argv
[i
] + 2;
137 _cupsLangPrintf(stderr
,
138 _("%s: Error - expected destination after "
139 "\"-d\" option."), argv
[0]);
146 if ((instance
= strrchr(printer
, '/')) != NULL
)
149 if ((dest
= cupsGetNamedDest(NULL
, printer
, instance
)) != NULL
)
151 for (j
= 0; j
< dest
->num_options
; j
++)
152 if (cupsGetOption(dest
->options
[j
].name
, num_options
,
154 num_options
= cupsAddOption(dest
->options
[j
].name
,
155 dest
->options
[j
].value
,
156 num_options
, &options
);
160 case 'f' : /* Form */
167 _cupsLangPrintf(stderr
,
168 _("%s: Error - expected form after \"-f\" "
175 _cupsLangPrintf(stderr
, _("%s: Warning - form option ignored."),
179 case 'h' : /* Destination host */
180 if (argv
[i
][2] != '\0')
181 cupsSetServer(argv
[i
] + 2);
188 _cupsLangPrintf(stderr
,
189 _("%s: Error - expected hostname after "
190 "\"-h\" option."), argv
[0]);
194 cupsSetServer(argv
[i
]);
198 case 'i' : /* Change job */
207 _cupsLangPrintf(stderr
,
208 _("%s: Expected job ID after \"-i\" option."),
218 _cupsLangPrintf(stderr
,
219 _("%s: Error - cannot print files and alter "
220 "jobs simultaneously."), argv
[0]);
224 if (strrchr(val
, '-') != NULL
)
225 job_id
= atoi(strrchr(val
, '-') + 1);
231 _cupsLangPrintf(stderr
, _("%s: Error - bad job ID."), argv
[0]);
236 case 'm' : /* Send email when job is done */
238 case 'p' : /* Notify on completion */
240 case 'w' : /* Write to console or email */
242 char email
[1024]; /* EMail address */
245 snprintf(email
, sizeof(email
), "mailto:%s@%s", cupsUser(),
246 httpGetHostname(NULL
, buffer
, sizeof(buffer
)));
247 num_options
= cupsAddOption("notify-recipient-uri", email
,
248 num_options
, &options
);
254 case 'n' : /* Number of copies */
255 if (argv
[i
][2] != '\0')
256 num_copies
= atoi(argv
[i
] + 2);
263 _cupsLangPrintf(stderr
,
264 _("%s: Error - expected copies after "
265 "\"-n\" option."), argv
[0]);
269 num_copies
= atoi(argv
[i
]);
272 sprintf(buffer
, "%d", num_copies
);
273 num_options
= cupsAddOption("copies", buffer
, num_options
,
277 case 'o' : /* Option */
278 if (argv
[i
][2] != '\0')
279 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
,
287 _cupsLangPrintf(stderr
,
288 _("%s: Error - expected option=value after "
289 "\"-o\" option."), argv
[0]);
293 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
298 case 'p' : /* Queue priority */
300 case 'q' : /* Queue priority */
301 if (argv
[i
][2] != '\0')
302 priority
= atoi(argv
[i
] + 2);
307 _cupsLangPrintf(stderr
,
308 _("%s: Error - expected priority after "
309 "\"-%c\" option."), argv
[0], argv
[i
][1]);
315 priority
= atoi(argv
[i
]);
319 * For 100% Solaris compatibility, need to add:
321 * priority = 99 * (39 - priority) / 39 + 1;
323 * However, to keep CUPS lp the same across all platforms
324 * we will break compatibility this far...
327 if (priority
< 1 || priority
> 100)
329 _cupsLangPrintf(stderr
,
330 _("%s: Error - priority must be between 1 and "
335 sprintf(buffer
, "%d", priority
);
336 num_options
= cupsAddOption("job-priority", buffer
, num_options
,
340 case 's' : /* Silent */
344 case 't' : /* Title */
345 if (argv
[i
][2] != '\0')
353 _cupsLangPrintf(stderr
,
354 _("%s: Error - expected title after "
355 "\"-t\" option."), argv
[0]);
363 case 'y' : /* mode-list */
370 _cupsLangPrintf(stderr
,
371 _("%s: Error - expected mode list after "
372 "\"-y\" option."), argv
[0]);
377 _cupsLangPrintf(stderr
,
378 _("%s: Warning - mode option ignored."), argv
[0]);
381 case 'H' : /* Hold job */
390 _cupsLangPrintf(stderr
,
391 _("%s: Error - expected hold name after "
392 "\"-H\" option."), argv
[0]);
399 if (!strcmp(val
, "hold"))
400 num_options
= cupsAddOption("job-hold-until", "indefinite",
401 num_options
, &options
);
402 else if (!strcmp(val
, "resume") ||
403 !strcmp(val
, "release"))
404 num_options
= cupsAddOption("job-hold-until", "no-hold",
405 num_options
, &options
);
406 else if (!strcmp(val
, "immediate"))
408 num_options
= cupsAddOption("job-hold-until", "no-hold",
409 num_options
, &options
);
410 num_options
= cupsAddOption("job-priority", "100",
411 num_options
, &options
);
413 else if (!strcmp(val
, "restart"))
417 _cupsLangPrintf(stderr
,
418 _("%s: Need job ID (\"-i jobid\") before "
419 "\"-H restart\"."), argv
[0]);
423 if (restart_job(argv
[0], job_id
))
427 num_options
= cupsAddOption("job-hold-until", val
,
428 num_options
, &options
);
431 case 'P' : /* Page list */
440 _cupsLangPrintf(stderr
,
441 _("%s: Error - expected page list after "
442 "\"-P\" option."), argv
[0]);
449 num_options
= cupsAddOption("page-ranges", val
, num_options
,
453 case 'S' : /* character set */
460 _cupsLangPrintf(stderr
,
461 _("%s: Error - expected character set after "
462 "\"-S\" option."), argv
[0]);
467 _cupsLangPrintf(stderr
,
468 _("%s: Warning - character set option ignored."),
472 case 'T' : /* Content-Type */
479 _cupsLangPrintf(stderr
,
480 _("%s: Error - expected content type after "
481 "\"-T\" option."), argv
[0]);
486 _cupsLangPrintf(stderr
,
487 _("%s: Warning - content type option ignored."),
491 case '-' : /* Stop processing options */
494 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \"%s\"."),
503 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \"%c\"."),
504 argv
[0], argv
[i
][1]);
507 else if (!strcmp(argv
[i
], "-"))
509 if (num_files
|| job_id
)
511 _cupsLangPrintf(stderr
,
512 _("%s: Error - cannot print from stdin if files or a "
513 "job ID are provided."), argv
[0]);
519 else if (num_files
< 1000 && job_id
== 0)
525 if (access(argv
[i
], R_OK
) != 0)
527 _cupsLangPrintf(stderr
, _("%s: Error - unable to access \"%s\" - %s"),
528 argv
[0], argv
[i
], strerror(errno
));
532 files
[num_files
] = argv
[i
];
537 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
544 _cupsLangPrintf(stderr
, _("%s: Error - too many files - \"%s\"."),
548 * See if we are altering an existing job...
552 return (set_job_attrs(argv
[0], job_id
, num_options
, options
));
555 * See if we have any files to print; if not, print from stdin...
560 if ((dest
= cupsGetNamedDest(NULL
, NULL
, NULL
)) != NULL
)
562 printer
= dest
->name
;
564 for (j
= 0; j
< dest
->num_options
; j
++)
565 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
566 num_options
= cupsAddOption(dest
->options
[j
].name
,
567 dest
->options
[j
].value
,
568 num_options
, &options
);
576 if ((printer
= getenv("LPDEST")) == NULL
)
578 if ((printer
= getenv("PRINTER")) != NULL
)
580 if (!strcmp(printer
, "lp"))
589 if (printer
&& !cupsGetNamedDest(NULL
, printer
, NULL
))
590 _cupsLangPrintf(stderr
,
591 _("%s: Error - %s environment variable names "
592 "non-existent destination \"%s\"."), argv
[0], val
,
594 else if (cupsLastError() == IPP_NOT_FOUND
)
595 _cupsLangPrintf(stderr
,
596 _("%s: Error - no default destination available."),
599 _cupsLangPrintf(stderr
, _("%s: Error - scheduler not responding."),
606 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
607 else if ((job_id
= cupsCreateJob(CUPS_HTTP_DEFAULT
, printer
,
608 title
? title
: "(stdin)",
609 num_options
, options
)) > 0)
611 http_status_t status
; /* Write status */
612 const char *format
; /* Document format */
613 ssize_t bytes
; /* Bytes read */
615 if (cupsGetOption("raw", num_options
, options
))
616 format
= CUPS_FORMAT_RAW
;
617 else if ((format
= cupsGetOption("document-format", num_options
,
619 format
= CUPS_FORMAT_AUTO
;
621 status
= cupsStartDocument(CUPS_HTTP_DEFAULT
, printer
, job_id
, NULL
,
624 while (status
== HTTP_CONTINUE
&&
625 (bytes
= read(0, buffer
, sizeof(buffer
))) > 0)
626 status
= cupsWriteRequestData(CUPS_HTTP_DEFAULT
, buffer
, bytes
);
628 if (status
!= HTTP_CONTINUE
)
630 _cupsLangPrintf(stderr
, _("%s: Error - unable to queue from stdin - %s."),
631 argv
[0], httpStatus(status
));
632 cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
);
633 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
637 if (cupsFinishDocument(CUPS_HTTP_DEFAULT
, printer
) != IPP_OK
)
639 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
640 cupsCancelJob2(CUPS_HTTP_DEFAULT
, printer
, job_id
, 0);
647 _cupsLangPrintf(stderr
, "%s: %s", argv
[0], cupsLastErrorString());
651 _cupsLangPrintf(stdout
, _("request id is %s-%d (%d file(s))"),
652 printer
, job_id
, num_files
);
659 * 'restart_job()' - Restart a job.
662 int /* O - Exit status */
663 restart_job(const char *command
, /* I - Command name */
664 int job_id
) /* I - Job ID */
666 ipp_t
*request
; /* IPP request */
667 char uri
[HTTP_MAX_URI
]; /* URI for job */
670 request
= ippNewRequest(IPP_RESTART_JOB
);
672 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
674 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
675 "job-uri", NULL
, uri
);
677 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
678 "requesting-user-name", NULL
, cupsUser());
680 ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT
, request
, "/jobs"));
682 if (cupsLastError() > IPP_OK_CONFLICT
)
684 _cupsLangPrintf(stderr
, "%s: %s", command
, cupsLastErrorString());
693 * 'set_job_attrs()' - Set job attributes.
696 int /* O - Exit status */
697 set_job_attrs(const char *command
, /* I - Command name */
698 int job_id
, /* I - Job ID */
699 int num_options
,/* I - Number of options */
700 cups_option_t
*options
) /* I - Options */
702 ipp_t
*request
; /* IPP request */
703 char uri
[HTTP_MAX_URI
]; /* URI for job */
706 if (num_options
== 0)
709 request
= ippNewRequest(IPP_SET_JOB_ATTRIBUTES
);
711 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
713 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
714 "job-uri", NULL
, uri
);
716 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
717 "requesting-user-name", NULL
, cupsUser());
719 cupsEncodeOptions(request
, num_options
, options
);
721 ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT
, request
, "/jobs"));
723 if (cupsLastError() > IPP_OK_CONFLICT
)
725 _cupsLangPrintf(stderr
, "%s: %s", command
, cupsLastErrorString());
734 * End of "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $".