X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=berkeley%2Flpr.c;h=a9aed3ca4007cbfaecfccbe7613e05b993c605c8;hb=860f3d3b1352017748657281562445be84f9a5f1;hp=893c62bf327d719737ba96ac9fde39514e0027cd;hpb=f7deaa1a21758ec90bf23314af018481ea8aea7f;p=thirdparty%2Fcups.git diff --git a/berkeley/lpr.c b/berkeley/lpr.c index 893c62bf3..a9aed3ca4 100644 --- a/berkeley/lpr.c +++ b/berkeley/lpr.c @@ -1,62 +1,25 @@ /* - * "$Id: lpr.c 5925 2006-09-05 19:43:11Z mike $" + * "lpr" command for CUPS. * - * "lpr" command for the Common UNIX Printing System (CUPS). + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products. * - * Copyright 1997-2006 by Easy Software Products. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * Contents: - * - * main() - Parse options and send files for printing. - * sighandler() - Signal catcher for when we print from stdin... + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* * Include necessary headers... */ -#include -#include -#include - -#include -#include -#include - -#ifndef WIN32 -# include -# include - - -/* - * Local functions. - */ - -void sighandler(int); -#endif /* !WIN32 */ +#include /* - * Globals... + * Local functions... */ -char tempfile[1024]; /* Temporary file for printing from stdin */ +static void usage(void) _CUPS_NORETURN; /* @@ -71,264 +34,263 @@ main(int argc, /* I - Number of command-line arguments */ int job_id; /* Job ID */ char ch; /* Option character */ char *printer, /* Destination printer or class */ - *instance; /* Instance */ - const char *title, /* Job title */ - *val; /* Environment variable name */ + *instance, /* Instance */ + *opt; /* Option pointer */ + const char *title; /* Job title */ int num_copies; /* Number of copies per file */ int num_files; /* Number of files to print */ const char *files[1000]; /* Files to print */ - int num_dests; /* Number of destinations */ - cups_dest_t *dests, /* Destinations */ - *dest; /* Selected destination */ + cups_dest_t *dest; /* Selected destination */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ int deletefile; /* Delete file after print? */ char buffer[8192]; /* Copy buffer */ - ssize_t bytes; /* Bytes copied */ - off_t filesize; /* Size of temp file */ - int temp; /* Temporary file descriptor */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Signal action */ - struct sigaction oldaction; /* Old signal action */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ _cupsSetLocale(argv); deletefile = 0; printer = NULL; - num_dests = 0; - dests = NULL; + dest = NULL; num_options = 0; options = NULL; num_files = 0; title = NULL; for (i = 1; i < argc; i ++) - if (argv[i][0] == '-') - switch (ch = argv[i][1]) + { + if (!strcmp(argv[i], "--help")) + usage(); + else if (argv[i][0] == '-') + { + for (opt = argv[i] + 1; *opt; opt ++) { - case 'E' : /* Encrypt */ + switch (ch = *opt) + { + case 'E' : /* Encrypt */ #ifdef HAVE_SSL - cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); + cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); #else - _cupsLangPrintf(stderr, - _("%s: Sorry, no encryption support compiled in!\n"), - argv[0]); + _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ - break; - - case 'U' : /* Username */ - if (argv[i][2] != '\0') - cupsSetUser(argv[i] + 2); - else - { - i ++; - if (i >= argc) + break; + + case 'U' : /* Username */ + if (opt[1] != '\0') + { + cupsSetUser(opt + 1); + opt += strlen(opt) - 1; + } + else { - _cupsLangPrintf(stderr, - _("%s: Error - expected username after " - "\'-U\' option!\n"), - argv[0]); - return (1); + i ++; + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]); + usage(); + } + + cupsSetUser(argv[i]); } + break; - cupsSetUser(argv[i]); - } - break; - - case 'H' : /* Connect to host */ - if (argv[i][2] != '\0') - cupsSetServer(argv[i] + 2); - else - { - i ++; - - if (i >= argc) + case 'H' : /* Connect to host */ + if (opt[1] != '\0') { - _cupsLangPrintf(stderr, - _("%s: Error - expected hostname after " - "\'-H\' option!\n"), - argv[0]); - return (1); - } + cupsSetServer(opt + 1); + opt += strlen(opt) - 1; + } else - cupsSetServer(argv[i]); - } - break; - - case '1' : /* TROFF font set 1 */ - case '2' : /* TROFF font set 2 */ - case '3' : /* TROFF font set 3 */ - case '4' : /* TROFF font set 4 */ - case 'i' : /* indent */ - case 'w' : /* width */ - if (argv[i][2] == '\0') - { - i ++; - - if (i >= argc) { - _cupsLangPrintf(stderr, - _("%s: Error - expected value after \'-%c\' " - "option!\n"), argv[0], ch); - return (1); + i ++; + + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-H\" option."), argv[0]); + usage(); + } + else + cupsSetServer(argv[i]); } - } - - case 'c' : /* CIFPLOT */ - case 'd' : /* DVI */ - case 'f' : /* FORTRAN */ - case 'g' : /* plot */ - case 'n' : /* Ditroff */ - case 't' : /* Troff */ - case 'v' : /* Raster image */ - _cupsLangPrintf(stderr, - _("%s: Warning - \'%c\' format modifier not " - "supported - output may not be correct!\n"), - argv[0], ch); - break; - - case 'o' : /* Option */ - if (argv[i][2] != '\0') - num_options = cupsParseOptions(argv[i] + 2, num_options, &options); - else - { - i ++; - if (i >= argc) + break; + + case '1' : /* TROFF font set 1 */ + case '2' : /* TROFF font set 2 */ + case '3' : /* TROFF font set 3 */ + case '4' : /* TROFF font set 4 */ + case 'i' : /* indent */ + case 'w' : /* width */ + if (opt[1] != '\0') { - _cupsLangPrintf(stderr, - _("%s: error - expected option=value after " - "\'-o\' option!\n"), - argv[0]); - return (1); + opt += strlen(opt) - 1; + } + else + { + i ++; + + if (i >= argc) + { + _cupsLangPrintf(stderr, + _("%s: Error - expected value after \"-%c\" " + "option."), argv[0], ch); + usage(); + } } - num_options = cupsParseOptions(argv[i], num_options, &options); - } - break; - - case 'l' : /* Literal/raw */ - num_options = cupsAddOption("raw", "", num_options, &options); - break; - - case 'p' : /* Prettyprint */ - num_options = cupsAddOption("prettyprint", "", num_options, - &options); - break; - - case 'h' : /* Suppress burst page */ - num_options = cupsAddOption("job-sheets", "none", num_options, - &options); - break; - - case 's' : /* Don't use symlinks */ - break; - - case 'm' : /* Mail on completion */ - { - char email[1024]; /* EMail address */ - - - snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), - httpGetHostname(NULL, buffer, sizeof(buffer))); - num_options = cupsAddOption("notify-recipient", email, - num_options, &options); - } - break; - - case 'q' : /* Queue file but don't print */ - num_options = cupsAddOption("job-hold-until", "indefinite", - num_options, &options); - break; - - case 'r' : /* Remove file after printing */ - deletefile = 1; - break; - - case 'P' : /* Destination printer or class */ - if (argv[i][2] != '\0') - printer = argv[i] + 2; - else - { - i ++; - if (i >= argc) + case 'c' : /* CIFPLOT */ + case 'd' : /* DVI */ + case 'f' : /* FORTRAN */ + case 'g' : /* plot */ + case 'n' : /* Ditroff */ + case 't' : /* Troff */ + case 'v' : /* Raster image */ + _cupsLangPrintf(stderr, _("%s: Warning - \"%c\" format modifier not supported - output may not be correct."), argv[0], ch); + break; + + case 'o' : /* Option */ + if (opt[1] != '\0') { - _cupsLangPrintf(stderr, - _("%s: Error - expected destination after " - "\'-P\' option!\n"), - argv[0]); - return (1); + num_options = cupsParseOptions(opt + 1, num_options, &options); + opt += strlen(opt) - 1; } + else + { + i ++; + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected option=value after \"-o\" option."), argv[0]); + usage(); + } + + num_options = cupsParseOptions(argv[i], num_options, &options); + } + break; + + case 'l' : /* Literal/raw */ + num_options = cupsAddOption("raw", "true", num_options, &options); + break; + + case 'p' : /* Prettyprint */ + num_options = cupsAddOption("prettyprint", "true", num_options, &options); + break; + + case 'h' : /* Suppress burst page */ + num_options = cupsAddOption("job-sheets", "none", num_options, &options); + break; + + case 's' : /* Don't use symlinks */ + break; + + case 'm' : /* Mail on completion */ + { + char email[1024]; /* EMail address */ + + snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL, buffer, sizeof(buffer))); + num_options = cupsAddOption("notify-recipient-uri", email, num_options, &options); + } + break; + + case 'q' : /* Queue file but don't print */ + num_options = cupsAddOption("job-hold-until", "indefinite", num_options, &options); + break; + + case 'r' : /* Remove file after printing */ + deletefile = 1; + break; + + case 'P' : /* Destination printer or class */ + if (opt[1] != '\0') + { + printer = opt + 1; + opt += strlen(opt) - 1; + } + else + { + i ++; + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected destination after \"-P\" option."), argv[0]); + usage(); + } + + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; - printer = argv[i]; - } - - if ((instance = strrchr(printer, '/')) != NULL) - *instance++ = '\0'; - - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) - { - for (j = 0; j < dest->num_options; j ++) - if (cupsGetOption(dest->options[j].name, num_options, - options) == NULL) - num_options = cupsAddOption(dest->options[j].name, - dest->options[j].value, - num_options, &options); - } - break; - - case '#' : /* Number of copies */ - if (argv[i][2] != '\0') - num_copies = atoi(argv[i] + 2); - else - { - i ++; - if (i >= argc) + if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL) { - _cupsLangPrintf(stderr, - _("%s: Error - expected copy count after " - "\'-#\' option!\n"), - argv[0]); + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, + options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || + cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) + { + _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); return (1); } + break; + + case '#' : /* Number of copies */ + if (opt[1] != '\0') + { + num_copies = atoi(opt + 1); + opt += strlen(opt) - 1; + } + else + { + i ++; + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected copies after \"-#\" option."), argv[0]); + usage(); + } + + num_copies = atoi(argv[i]); + } - num_copies = atoi(argv[i]); - } - - sprintf(buffer, "%d", num_copies); - num_options = cupsAddOption("copies", buffer, num_options, &options); - break; - - case 'C' : /* Class */ - case 'J' : /* Job name */ - case 'T' : /* Title */ - if (argv[i][2] != '\0') - title = argv[i] + 2; - else - { - i ++; - if (i >= argc) + if (num_copies < 1) { - _cupsLangPrintf(stderr, - _("%s: Error - expected name after \'-%c\' " - "option!\n"), argv[0], ch); + _cupsLangPrintf(stderr, _("%s: Error - copies must be 1 or more."), argv[0]); return (1); } - title = argv[i]; - } - break; + sprintf(buffer, "%d", num_copies); + num_options = cupsAddOption("copies", buffer, num_options, &options); + break; + + case 'C' : /* Class */ + case 'J' : /* Job name */ + case 'T' : /* Title */ + if (opt[1] != '\0') + { + title = opt + 1; + opt += strlen(opt) - 1; + } + else + { + i ++; + if (i >= argc) + { + _cupsLangPrintf(stderr, _("%s: Error - expected name after \"-%c\" option."), argv[0], ch); + usage(); + } + + title = argv[i]; + } + break; - default : - _cupsLangPrintf(stderr, - _("%s: Error - unknown option \'%c\'!\n"), - argv[0], argv[i][1]); - return (1); + default : + _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], *opt); + return (1); + } } + } else if (num_files < 1000) { /* @@ -338,7 +300,7 @@ main(int argc, /* I - Number of command-line arguments */ if (access(argv[i], R_OK) != 0) { _cupsLangPrintf(stderr, - _("%s: Error - unable to access \"%s\" - %s\n"), + _("%s: Error - unable to access \"%s\" - %s"), argv[0], argv[i], strerror(errno)); return (1); } @@ -355,19 +317,18 @@ main(int argc, /* I - Number of command-line arguments */ } } else - _cupsLangPrintf(stderr, - _("%s: Error - too many files - \"%s\"\n"), - argv[0], argv[i]); + { + _cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."), argv[0], argv[i]); + } + } + /* * See if we have any files to print; if not, print from stdin... */ if (printer == NULL) { - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) + if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) { printer = dest->name; @@ -377,38 +338,22 @@ main(int argc, /* I - Number of command-line arguments */ dest->options[j].value, num_options, &options); } + else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || + cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) + { + _cupsLangPrintf(stderr, + _("%s: Error - add '/version=1.1' to server " + "name."), argv[0]); + return (1); + } } if (printer == NULL) { - val = NULL; - - if ((printer = getenv("LPDEST")) == NULL) - { - if ((printer = getenv("PRINTER")) != NULL) - { - if (!strcmp(printer, "lp")) - printer = NULL; - else - val = "PRINTER"; - } - } + if (!cupsGetNamedDest(NULL, NULL, NULL) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND) + _cupsLangPrintf(stderr, _("%s: Error - %s"), argv[0], cupsLastErrorString()); else - val = "LPDEST"; - - if (printer && !cupsGetDest(printer, NULL, num_dests, dests)) - _cupsLangPrintf(stderr, - _("%s: Error - %s environment variable names " - "non-existent destination \"%s\"!\n"), - argv[0], val, printer); - else if (cupsLastError() == IPP_NOT_FOUND) - _cupsLangPrintf(stderr, - _("%s: Error - no default destination available.\n"), - argv[0]); - else - _cupsLangPrintf(stderr, - _("%s: Error - scheduler not responding!\n"), - argv[0]); + _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]); return (1); } @@ -427,77 +372,47 @@ main(int argc, /* I - Number of command-line arguments */ unlink(files[i]); } } - else + else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, + title ? title : "(stdin)", + num_options, options)) > 0) { - num_files = 1; - -#ifndef WIN32 -# if defined(HAVE_SIGSET) - sigset(SIGHUP, sighandler); - if (sigset(SIGINT, sighandler) == SIG_IGN) - sigset(SIGINT, SIG_IGN); - sigset(SIGTERM, sighandler); -# elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - action.sa_handler = sighandler; - - sigaction(SIGHUP, &action, NULL); - sigaction(SIGINT, NULL, &oldaction); - if (oldaction.sa_handler != SIG_IGN) - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); -# else - signal(SIGHUP, sighandler); - if (signal(SIGINT, sighandler) == SIG_IGN) - signal(SIGINT, SIG_IGN); - signal(SIGTERM, sighandler); -# endif -#endif /* !WIN32 */ - - if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0) - { - _cupsLangPrintf(stderr, - _("%s: Error - unable to create temporary file " - "\"%s\" - %s\n"), - argv[0], tempfile, strerror(errno)); - return (1); - } + http_status_t status; /* Write status */ + const char *format; /* Document format */ + ssize_t bytes; /* Bytes read */ - while ((bytes = read(0, buffer, sizeof(buffer))) > 0) - if (write(temp, buffer, bytes) < 0) - { - _cupsLangPrintf(stderr, - _("%s: Error - unable to write to temporary file " - "\"%s\" - %s\n"), - argv[0], tempfile, strerror(errno)); - close(temp); - unlink(tempfile); - return (1); - } + if (cupsGetOption("raw", num_options, options)) + format = CUPS_FORMAT_RAW; + else if ((format = cupsGetOption("document-format", num_options, + options)) == NULL) + format = CUPS_FORMAT_AUTO; + + status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL, + format, 1); - filesize = lseek(temp, 0, SEEK_CUR); - close(temp); + while (status == HTTP_CONTINUE && + (bytes = read(0, buffer, sizeof(buffer))) > 0) + status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes); - if (filesize <= 0) + if (status != HTTP_CONTINUE) { - _cupsLangPrintf(stderr, - _("%s: Error - stdin is empty, so no job has been sent.\n"), - argv[0]); - unlink(tempfile); + _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."), + argv[0], httpStatus(status)); + cupsFinishDocument(CUPS_HTTP_DEFAULT, printer); + cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); return (1); } - if (title) - job_id = cupsPrintFile(printer, tempfile, title, num_options, options); - else - job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options); - - unlink(tempfile); + if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK) + { + _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); + cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); + return (1); + } } if (job_id < 1) { - _cupsLangPrintf(stderr, "%s: %s\n", argv[0], cupsLastErrorString()); + _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); return (1); } @@ -505,29 +420,36 @@ main(int argc, /* I - Number of command-line arguments */ } -#ifndef WIN32 /* - * 'sighandler()' - Signal catcher for when we print from stdin... + * 'usage()' - Show program usage and exit. */ -void -sighandler(int s) /* I - Signal number */ +static void +usage(void) { - /* - * Remove the temporary file we're using to print from stdin... - */ - - unlink(tempfile); - - /* - * Exit... - */ - - exit(s); + _cupsLangPuts(stdout, _("Usage: lpr [options] [file(s)]")); + _cupsLangPuts(stdout, _("Options:")); + _cupsLangPuts(stdout, _("-# num-copies Specify the number of copies to print")); + _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); + _cupsLangPuts(stdout, _("-H server[:port] Connect to the named server and port")); + _cupsLangPuts(stdout, _("-m Send an email notification when the job completes")); + _cupsLangPuts(stdout, _("-o option[=value] Specify a printer-specific option")); + _cupsLangPuts(stdout, _("-o job-sheets=standard Print a banner page with the job")); + _cupsLangPuts(stdout, _("-o media=size Specify the media size to use")); + _cupsLangPuts(stdout, _("-o number-up=N Specify that input pages should be printed N-up (1, 2, 4, 6, 9, and 16 are supported)")); + _cupsLangPuts(stdout, _("-o orientation-requested=N\n" + " Specify portrait (3) or landscape (4) orientation")); + _cupsLangPuts(stdout, _("-o print-quality=N Specify the print quality - draft (3), normal (4), or best (5)")); + _cupsLangPuts(stdout, _("-o sides=one-sided Specify 1-sided printing")); + _cupsLangPuts(stdout, _("-o sides=two-sided-long-edge\n" + " Specify 2-sided portrait printing")); + _cupsLangPuts(stdout, _("-o sides=two-sided-short-edge\n" + " Specify 2-sided landscape printing")); + _cupsLangPuts(stdout, _("-q Specify the job should be held for printing")); + _cupsLangPuts(stdout, _("-r Remove the file(s) after submission")); + _cupsLangPuts(stdout, _("-P destination Specify the destination")); + _cupsLangPuts(stdout, _("-T title Specify the job title")); + _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication")); + + exit(1); } -#endif /* !WIN32 */ - - -/* - * End of "$Id: lpr.c 5925 2006-09-05 19:43:11Z mike $". - */