summaryrefslogtreecommitdiff
path: root/systemv/lp.c
diff options
context:
space:
mode:
Diffstat (limited to 'systemv/lp.c')
-rw-r--r--systemv/lp.c723
1 files changed, 723 insertions, 0 deletions
diff --git a/systemv/lp.c b/systemv/lp.c
new file mode 100644
index 0000000..af47132
--- /dev/null
+++ b/systemv/lp.c
@@ -0,0 +1,723 @@
+/*
+ * "$Id: lp.c 9636 2011-03-21 22:02:00Z mike $"
+ *
+ * "lp" command for CUPS.
+ *
+ * Copyright 2007-2011 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. 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
+ * file is missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * Contents:
+ *
+ * main() - Parse options and send files for printing.
+ * restart_job() - Restart a job.
+ * set_job_attrs() - Set job attributes.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups-private.h>
+
+
+/*
+ * Local functions.
+ */
+
+int restart_job(const char *command, int job_id);
+int set_job_attrs(const char *command, int job_id, int num_options,
+ cups_option_t *options);
+
+
+/*
+ * 'main()' - Parse options and send files for printing.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping vars */
+ int job_id; /* Job ID */
+ char *printer, /* Printer name */
+ *instance, /* Instance name */
+ *val, /* Option value */
+ *title; /* Job title */
+ int priority; /* Job priority (1-100) */
+ int num_copies; /* Number of copies per file */
+ int num_files; /* Number of files to print */
+ const char *files[1000]; /* Files to print */
+ cups_dest_t *dest; /* Selected destination */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ int end_options; /* No more options? */
+ int silent; /* Silent or verbose output? */
+ char buffer[8192]; /* Copy buffer */
+
+
+#ifdef __sun
+ /*
+ * Solaris does some rather strange things to re-queue remote print
+ * jobs. On bootup, the "lp" command is run as "printd" to re-spool
+ * any remote jobs in /var/spool/print. Since CUPS doesn't need this
+ * nonsense, we just need to add the necessary check here to prevent
+ * lp from causing boot problems...
+ */
+
+ if ((val = strrchr(argv[0], '/')) != NULL)
+ val ++;
+ else
+ val = argv[0];
+
+ if (!strcmp(val, "printd"))
+ return (0);
+#endif /* __sun */
+
+ _cupsSetLocale(argv);
+
+ silent = 0;
+ printer = NULL;
+ dest = NULL;
+ num_options = 0;
+ options = NULL;
+ num_files = 0;
+ title = NULL;
+ job_id = 0;
+ end_options = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-' && argv[i][1] && !end_options)
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+#else
+ _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)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected username after \"-U\" "
+ "option."), argv[0]);
+ return (1);
+ }
+
+ cupsSetUser(argv[i]);
+ }
+ break;
+
+ case 'c' : /* Copy to spool dir (always enabled) */
+ break;
+
+ case 'd' : /* Destination printer or class */
+ if (argv[i][2] != '\0')
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected destination after "
+ "\"-d\" option."), argv[0]);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if ((dest = cupsGetNamedDest(NULL, printer, instance)) != 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 'f' : /* Form */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected form after \"-f\" "
+ "option."),
+ argv[0]);
+ return (1);
+ }
+ }
+
+ _cupsLangPrintf(stderr, _("%s: Warning - form option ignored."),
+ argv[0]);
+ break;
+
+ case 'h' : /* Destination host */
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected hostname after "
+ "\"-h\" option."), argv[0]);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'i' : /* Change job */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Expected job ID after \"-i\" option."),
+ argv[0]);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ if (num_files > 0)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - cannot print files and alter "
+ "jobs simultaneously."), argv[0]);
+ return (1);
+ }
+
+ if (strrchr(val, '-') != NULL)
+ job_id = atoi(strrchr(val, '-') + 1);
+ else
+ job_id = atoi(val);
+
+ if (job_id < 0)
+ {
+ _cupsLangPrintf(stderr, _("%s: Error - bad job ID."), argv[0]);
+ break;
+ }
+ break;
+
+ case 'm' : /* Send email when job is done */
+#ifdef __sun
+ case 'p' : /* Notify on completion */
+#endif /* __sun */
+ case 'w' : /* Write to console or email */
+ {
+ 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);
+ }
+
+ silent = 1;
+ break;
+
+ case 'n' : /* Number of copies */
+ if (argv[i][2] != '\0')
+ num_copies = atoi(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected copies after "
+ "\"-n\" option."), argv[0]);
+ return (1);
+ }
+
+ num_copies = atoi(argv[i]);
+ }
+
+ sprintf(buffer, "%d", num_copies);
+ num_options = cupsAddOption("copies", buffer, num_options,
+ &options);
+ break;
+
+ case 'o' : /* Option */
+ if (argv[i][2] != '\0')
+ num_options = cupsParseOptions(argv[i] + 2, num_options,
+ &options);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected option=value after "
+ "\"-o\" option."), argv[0]);
+ return (1);
+ }
+
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+ }
+ break;
+
+#ifndef __sun
+ case 'p' : /* Queue priority */
+#endif /* !__sun */
+ case 'q' : /* Queue priority */
+ if (argv[i][2] != '\0')
+ priority = atoi(argv[i] + 2);
+ else
+ {
+ if ((i + 1) >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected priority after "
+ "\"-%c\" option."), argv[0], argv[i][1]);
+ return (1);
+ }
+
+ i ++;
+
+ priority = atoi(argv[i]);
+ }
+
+ /*
+ * For 100% Solaris compatibility, need to add:
+ *
+ * priority = 99 * (39 - priority) / 39 + 1;
+ *
+ * However, to keep CUPS lp the same across all platforms
+ * we will break compatibility this far...
+ */
+
+ if (priority < 1 || priority > 100)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - priority must be between 1 and "
+ "100."), argv[0]);
+ return (1);
+ }
+
+ sprintf(buffer, "%d", priority);
+ num_options = cupsAddOption("job-priority", buffer, num_options,
+ &options);
+ break;
+
+ case 's' : /* Silent */
+ silent = 1;
+ break;
+
+ case 't' : /* Title */
+ if (argv[i][2] != '\0')
+ title = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected title after "
+ "\"-t\" option."), argv[0]);
+ return (1);
+ }
+
+ title = argv[i];
+ }
+ break;
+
+ case 'y' : /* mode-list */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected mode list after "
+ "\"-y\" option."), argv[0]);
+ return (1);
+ }
+ }
+
+ _cupsLangPrintf(stderr,
+ _("%s: Warning - mode option ignored."), argv[0]);
+ break;
+
+ case 'H' : /* Hold job */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected hold name after "
+ "\"-H\" option."), argv[0]);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ if (!strcmp(val, "hold"))
+ num_options = cupsAddOption("job-hold-until", "indefinite",
+ num_options, &options);
+ else if (!strcmp(val, "resume") ||
+ !strcmp(val, "release"))
+ num_options = cupsAddOption("job-hold-until", "no-hold",
+ num_options, &options);
+ else if (!strcmp(val, "immediate"))
+ {
+ num_options = cupsAddOption("job-hold-until", "no-hold",
+ num_options, &options);
+ num_options = cupsAddOption("job-priority", "100",
+ num_options, &options);
+ }
+ else if (!strcmp(val, "restart"))
+ {
+ if (job_id < 1)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Need job ID (\"-i jobid\") before "
+ "\"-H restart\"."), argv[0]);
+ return (1);
+ }
+
+ if (restart_job(argv[0], job_id))
+ return (1);
+ }
+ else
+ num_options = cupsAddOption("job-hold-until", val,
+ num_options, &options);
+ break;
+
+ case 'P' : /* Page list */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected page list after "
+ "\"-P\" option."), argv[0]);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ num_options = cupsAddOption("page-ranges", val, num_options,
+ &options);
+ break;
+
+ case 'S' : /* character set */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected character set after "
+ "\"-S\" option."), argv[0]);
+ return (1);
+ }
+ }
+
+ _cupsLangPrintf(stderr,
+ _("%s: Warning - character set option ignored."),
+ argv[0]);
+ break;
+
+ case 'T' : /* Content-Type */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - expected content type after "
+ "\"-T\" option."), argv[0]);
+ return (1);
+ }
+ }
+
+ _cupsLangPrintf(stderr,
+ _("%s: Warning - content type option ignored."),
+ argv[0]);
+ break;
+
+ case '-' : /* Stop processing options */
+ end_options = 1;
+ break;
+
+ default :
+ _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."),
+ argv[0], argv[i][1]);
+ return (1);
+ }
+ else if (!strcmp(argv[i], "-"))
+ {
+ if (num_files || job_id)
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Error - cannot print from stdin if files or a "
+ "job ID are provided."), argv[0]);
+ return (1);
+ }
+
+ break;
+ }
+ else if (num_files < 1000 && job_id == 0)
+ {
+ /*
+ * Print a file...
+ */
+
+ if (access(argv[i], R_OK) != 0)
+ {
+ _cupsLangPrintf(stderr, _("%s: Error - unable to access \"%s\" - %s"),
+ argv[0], argv[i], strerror(errno));
+ return (1);
+ }
+
+ files[num_files] = argv[i];
+ num_files ++;
+
+ if (title == NULL)
+ {
+ if ((title = strrchr(argv[i], '/')) != NULL)
+ title ++;
+ else
+ title = argv[i];
+ }
+ }
+ else
+ _cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."),
+ argv[0], argv[i]);
+
+ /*
+ * See if we are altering an existing job...
+ */
+
+ if (job_id)
+ return (set_job_attrs(argv[0], job_id, num_options, options));
+
+ /*
+ * See if we have any files to print; if not, print from stdin...
+ */
+
+ if (printer == NULL)
+ {
+ if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL)
+ {
+ printer = dest->name;
+
+ 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);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ val = NULL;
+
+ if ((printer = getenv("LPDEST")) == NULL)
+ {
+ if ((printer = getenv("PRINTER")) != NULL)
+ {
+ if (!strcmp(printer, "lp"))
+ printer = NULL;
+ else
+ val = "PRINTER";
+ }
+ }
+ else
+ val = "LPDEST";
+
+ if (printer && !cupsGetNamedDest(NULL, printer, NULL))
+ _cupsLangPrintf(stderr,
+ _("%s: Error - %s environment variable names "
+ "non-existent destination \"%s\"."), argv[0], val,
+ printer);
+ else if (cupsLastError() == IPP_NOT_FOUND)
+ _cupsLangPrintf(stderr,
+ _("%s: Error - no default destination available."),
+ argv[0]);
+ else
+ _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."),
+ argv[0]);
+
+ return (1);
+ }
+
+ if (num_files > 0)
+ job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
+ else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
+ title ? title : "(stdin)",
+ num_options, options)) > 0)
+ {
+ http_status_t status; /* Write status */
+ const char *format; /* Document format */
+ ssize_t bytes; /* Bytes read */
+
+
+ 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);
+
+ while (status == HTTP_CONTINUE &&
+ (bytes = read(0, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
+
+ if (status != HTTP_CONTINUE)
+ {
+ _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."),
+ argv[0], httpStatus(status));
+ return (1);
+ }
+
+ if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
+ job_id = 0;
+ }
+
+ if (job_id < 1)
+ {
+ _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
+ return (1);
+ }
+ else if (!silent)
+ _cupsLangPrintf(stdout, _("request id is %s-%d (%d file(s))"),
+ printer, job_id, num_files);
+
+ return (0);
+}
+
+
+/*
+ * 'restart_job()' - Restart a job.
+ */
+
+int /* O - Exit status */
+restart_job(const char *command, /* I - Command name */
+ int job_id) /* I - Job ID */
+{
+ ipp_t *request; /* IPP request */
+ char uri[HTTP_MAX_URI]; /* URI for job */
+
+
+ request = ippNewRequest(IPP_RESTART_JOB);
+
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
+
+ if (cupsLastError() > IPP_OK_CONFLICT)
+ {
+ _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'set_job_attrs()' - Set job attributes.
+ */
+
+int /* O - Exit status */
+set_job_attrs(const char *command, /* I - Command name */
+ int job_id, /* I - Job ID */
+ int num_options,/* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ ipp_t *request; /* IPP request */
+ char uri[HTTP_MAX_URI]; /* URI for job */
+
+
+ if (num_options == 0)
+ return (0);
+
+ request = ippNewRequest(IPP_SET_JOB_ATTRIBUTES);
+
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ cupsEncodeOptions(request, num_options, options);
+
+ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
+
+ if (cupsLastError() > IPP_OK_CONFLICT)
+ {
+ _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id: lp.c 9636 2011-03-21 22:02:00Z mike $".
+ */