summaryrefslogtreecommitdiff
path: root/source3/printing
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-03-16 05:55:30 +0000
committerJeremy Allison <jra@samba.org>2001-03-16 05:55:30 +0000
commit65d35749b721b76ae826a9423bdefd2f673f35c6 (patch)
tree8b8cf83fdcbf25f70efa5da0c8178743586f358a /source3/printing
parent977e0be9b3b01b9deecea905b78d81d3c58726a1 (diff)
downloadsamba-65d35749b721b76ae826a9423bdefd2f673f35c6.tar.gz
samba-65d35749b721b76ae826a9423bdefd2f673f35c6.tar.bz2
samba-65d35749b721b76ae826a9423bdefd2f673f35c6.zip
Added Michael Sweet's CUPS patch to call directly into the CUPS backend.
Parameterises the printing functions so other backends can be plugged directly in (this is a good thing :-). Jeremy. (This used to be commit c0345bbaed5d1aac777f1a33ff84ad1899f2ed6d)
Diffstat (limited to 'source3/printing')
-rw-r--r--source3/printing/print_cups.c1005
-rw-r--r--source3/printing/printing.c186
2 files changed, 1023 insertions, 168 deletions
diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c
index 8739ddcec4..3ca0af537f 100644
--- a/source3/printing/print_cups.c
+++ b/source3/printing/print_cups.c
@@ -1,7 +1,7 @@
/*
* Support code for the Common UNIX Printing System ("CUPS")
*
- * Copyright 1999 by Easy Software Products
+ * Copyright 1999-2001 by Easy Software Products
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,22 +18,66 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "includes.h"
+#include "printing.h"
#include "smb.h"
#ifdef HAVE_LIBCUPS
#include <cups/cups.h>
#include <cups/language.h>
+
+/*
+ * CUPS printing interface definitions...
+ */
+
+static int cups_job_delete(int snum, struct printjob *pjob);
+static int cups_job_pause(int snum, struct printjob *pjob);
+static int cups_job_resume(int snum, struct printjob *pjob);
+static int cups_job_submit(int snum, struct printjob *pjob);
+static int cups_queue_get(int snum, print_queue_struct **q,
+ print_status_struct *status);
+static int cups_queue_pause(int snum);
+static int cups_queue_resume(int snum);
+
+
+struct printif cups_printif =
+ {
+ cups_queue_get,
+ cups_queue_pause,
+ cups_queue_resume,
+ cups_job_delete,
+ cups_job_pause,
+ cups_job_resume,
+ cups_job_submit,
+ };
+
extern int DEBUGLEVEL;
/*
+ * 'cups_passwd_cb()' - The CUPS password callback...
+ */
+
+const char * /* O - Password or NULL */
+cups_passwd_cb(const char *prompt) /* I - Prompt */
+{
+ /*
+ * Always return NULL to indicate that no password is available...
+ */
+
+ (void)prompt;
+
+ return (NULL);
+}
+
+
+/*
* 'cups_printer_fn()' - Call a function for every printer known to the
* system.
*/
-void cups_printer_fn(void (*fn)(char *, char *))
+void
+cups_printer_fn(void (*fn)(char *, char *)) /* I - Function to call */
{
http_t *http; /* HTTP connection to server */
ipp_t *request, /* IPP Request */
@@ -41,15 +85,34 @@ void cups_printer_fn(void (*fn)(char *, char *))
ipp_attribute_t *attr; /* Current attribute */
cups_lang_t *language; /* Default language */
char *name, /* printer-name attribute */
- *make_model; /* make_model attribute */
+ *make_model, /* printer-make-and-model attribute */
+ *info; /* printer-info attribute */
+ static const char *requested[] =/* Requested attributes */
+ {
+ "printer-name",
+ "printer-make-and-model",
+ "printer-info"
+ };
+ DEBUG(5,("cups_printer_fn(%p)\n", fn));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
/*
* Try to connect to the server...
*/
if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
return;
+ }
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
@@ -57,6 +120,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
*
* attributes-charset
* attributes-natural-language
+ * requested-attributes
*/
request = ippNew();
@@ -72,12 +136,19 @@ void cups_printer_fn(void (*fn)(char *, char *))
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, language->language);
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ (sizeof(requested) / sizeof(requested[0])),
+ NULL, requested);
+
/*
* Do the request and get back a response...
*/
if ((response = cupsDoRequest(http, request, "/")) == NULL)
{
+ DEBUG(0,("Unable to get printer list - %s\n",
+ ippErrorString(cupsLastError())));
httpClose(http);
return;
}
@@ -100,6 +171,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
name = NULL;
make_model = NULL;
+ info = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
@@ -111,6 +183,10 @@ void cups_printer_fn(void (*fn)(char *, char *))
attr->value_tag == IPP_TAG_TEXT)
make_model = attr->values[0].string.text;
+ if (strcmp(attr->name, "printer-info") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ info = attr->values[0].string.text;
+
attr = attr->next;
}
@@ -121,7 +197,10 @@ void cups_printer_fn(void (*fn)(char *, char *))
if (name == NULL)
break;
- (*fn)(unix_to_dos(name,False), make_model);
+ if (info == NULL || !info[0])
+ (*fn)(unix_to_dos(name,False), make_model);
+ else
+ (*fn)(unix_to_dos(name,False), info);
}
ippDelete(response);
@@ -130,31 +209,46 @@ void cups_printer_fn(void (*fn)(char *, char *))
/*
- * provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming
- * systems.
+ * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok()
+ * for CUPS.
*/
-int cups_printername_ok(char *name)
+
+int /* O - 1 if printer name OK */
+cups_printername_ok(char *name) /* I - Name of printer */
{
http_t *http; /* HTTP connection to server */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
- ipp_attribute_t *attr; /* Current attribute */
cups_lang_t *language; /* Default language */
char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+ DEBUG(5,("cups_printername_ok(\"%s\")\n", name));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
/*
* Try to connect to the server...
*/
if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
return (0);
+ }
/*
- * Build a IPP_GET_PRINTER_ATTRS request, which requires the following
+ * Build an IPP_GET_PRINTER_ATTRS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
+ * requested-attributes
* printer-uri
*/
@@ -171,7 +265,11 @@ int cups_printername_ok(char *name)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, language->language);
- slprintf(uri, sizeof(uri)-1, "ipp://localhost/printers/%s", dos_to_unix(name,False));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes", NULL, "printer-uri");
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
+ dos_to_unix(name, False));
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, uri);
@@ -182,6 +280,8 @@ int cups_printername_ok(char *name)
if ((response = cupsDoRequest(http, request, "/")) == NULL)
{
+ DEBUG(0,("Unable to get printer status for %s - %s\n", name,
+ ippErrorString(cupsLastError())));
httpClose(http);
return (0);
}
@@ -190,6 +290,8 @@ int cups_printername_ok(char *name)
if (response->request.status.status_code >= IPP_OK_CONFLICT)
{
+ DEBUG(0,("Unable to get printer status for %s - %s\n", name,
+ ippErrorString(response->request.status.status_code)));
ippDelete(response);
return (0);
}
@@ -200,6 +302,887 @@ int cups_printername_ok(char *name)
}
}
+
+/*
+ * 'cups_job_delete()' - Delete a job.
+ */
+
+static int
+cups_job_delete(int snum, struct printjob *pjob)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_CANCEL_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_CANCEL_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
+
+ 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());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ ret = 1;
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
+/*
+ * 'cups_job_pause()' - Pause a job.
+ */
+
+static int
+cups_job_pause(int snum, struct printjob *pjob)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_HOLD_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_HOLD_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
+
+ 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());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ ret = 1;
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
+/*
+ * 'cups_job_resume()' - Resume a paused job.
+ */
+
+static int
+cups_job_resume(int snum, struct printjob *pjob)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_RELEASE_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_RELEASE_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
+
+ 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());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ ret = 1;
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
+/*
+ * 'cups_job_submit()' - Submit a job for printing.
+ */
+
+static int
+cups_job_submit(int snum, struct printjob *pjob)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_PRINT_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ * [document-data]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
+ PRINTERNAME(snum));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+ pjob->jobname);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
+
+ ret = 1;
+ if ((response = cupsDoFileRequest(http, request, uri,
+ pjob->filename)) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
+/*
+ * 'cups_queue_get()' - Get all the jobs in the print queue.
+ */
+
+static int
+cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
+{
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+ int qcount, /* Number of active queue entries */
+ qalloc; /* Number of queue entries allocated */
+ print_queue_struct *queue, /* Queue entries */
+ *temp; /* Temporary pointer for queue */
+ const char *user_name, /* job-originating-user-name attribute */
+ *job_name; /* job-name attribute */
+ int job_id; /* job-id attribute */
+ int job_k_octets; /* job-k-octets attribute */
+ time_t job_time; /* time-at-creation attribute */
+ ipp_jstate_t job_status; /* job-status attribute */
+ int job_priority; /* job-priority attribute */
+ static const char *jattrs[] = /* Requested job attributes */
+ {
+ "job-id",
+ "job-k-octets",
+ "job-name",
+ "job-originating-user-name",
+ "job-priority",
+ "job-state",
+ "time-at-creation",
+ };
+ static const char *pattrs[] = /* Requested printer attributes */
+ {
+ "printer-state",
+ "printer-state-message"
+ };
+
+
+ DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (0);
+ }
+
+ /*
+ * Generate the printer URI...
+ */
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
+ PRINTERNAME(snum));
+
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ (sizeof(jattrs) / sizeof(jattrs[0])),
+ NULL, jattrs);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) == NULL)
+ {
+ DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
+ ippErrorString(cupsLastError())));
+ httpClose(http);
+ return (0);
+ }
+
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ {
+ DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
+ ippErrorString(response->request.status.status_code)));
+ ippDelete(response);
+ httpClose(http);
+
+ return (0);
+ }
+
+ /*
+ * Process the jobs...
+ */
+
+ qcount = 0;
+ qalloc = 0;
+ queue = NULL;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Allocate memory as needed...
+ */
+ if (qcount >= qalloc)
+ {
+ qalloc += 16;
+
+ if (qalloc == 16)
+ temp = malloc(sizeof(print_queue_struct) * qalloc);
+ else
+ temp = realloc(queue, sizeof(print_queue_struct) * qalloc);
+
+ if (temp == NULL)
+ {
+ ippDelete(response);
+ httpClose(http);
+
+ return (qcount);
+ }
+
+ queue = temp;
+ }
+
+ temp = queue + qcount;
+ memset(temp, 0, sizeof(print_queue_struct));
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ job_id = 0;
+ job_priority = 50;
+ job_status = IPP_JOB_PENDING;
+ job_time = 0;
+ job_k_octets = 0;
+ user_name = NULL;
+ job_name = NULL;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (attr->name == NULL)
+ {
+ attr = attr->next;
+ break;
+ }
+
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ job_id = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ job_k_octets = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-priority") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ job_priority = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ job_status = (ipp_jstate_t)(attr->values[0].integer);
+
+ if (strcmp(attr->name, "time-at-creation") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ job_time = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ job_name = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ user_name = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (user_name == NULL || job_name == NULL || job_id == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ temp->job = job_id;
+ temp->size = job_k_octets * 1024;
+ temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
+ job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
+ job_status == IPP_JOB_HELD ? LPQ_PAUSED :
+ LPQ_PRINTING;
+ temp->priority = job_priority;
+ temp->time = job_time;
+ strncpy(temp->user, user_name, sizeof(temp->user) - 1);
+ strncpy(temp->file, job_name, sizeof(temp->file) - 1);
+
+ qcount ++;
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ (sizeof(pattrs) / sizeof(pattrs[0])),
+ NULL, pattrs);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) == NULL)
+ {
+ DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+ httpClose(http);
+ return (qcount);
+ }
+
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ {
+ DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(response->request.status.status_code)));
+ ippDelete(response);
+ httpClose(http);
+
+ return (qcount);
+ }
+
+ /*
+ * Get the current printer status and convert it to the SAMBA values.
+ */
+
+ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
+ {
+ if (attr->values[0].integer == IPP_PRINTER_STOPPED)
+ status->status = LPSTAT_STOPPED;
+ else
+ status->status = LPSTAT_OK;
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-state-message",
+ IPP_TAG_TEXT)) != NULL)
+ fstrcpy(status->message, attr->values[0].string.text);
+
+ ippDelete(response);
+
+ /*
+ * Return the job queue...
+ */
+
+ httpClose(http);
+
+ *q = queue;
+ return (qcount);
+}
+
+
+/*
+ * 'cups_queue_pause()' - Pause a print queue.
+ */
+
+static int
+cups_queue_pause(int snum)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_queue_pause(%d)\n", snum));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_PAUSE_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_PAUSE_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
+ PRINTERNAME(snum));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ ret = 1;
+
+ if ((response = cupsDoRequest(http, request, "/admin")) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
+/*
+ * 'cups_queue_resume()' - Restart a print queue.
+ */
+
+static int
+cups_queue_resume(int snum)
+{
+ int ret; /* Return value */
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+
+ DEBUG(5,("cups_queue_resume(%d)\n", snum));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno)));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_RESUME_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_RESUME_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
+ PRINTERNAME(snum));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ ret = 1;
+
+ if ((response = cupsDoRequest(http, request, "/admin")) != NULL)
+ {
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+ else
+ ret = 0;
+
+ ippDelete(response);
+ }
+ else
+ DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
+ ippErrorString(cupsLastError())));
+
+ httpClose(http);
+
+ return (ret);
+}
+
+
#else
/* this keeps fussy compilers happy */
void print_cups_dummy(void) {}
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index 241135f744..84ed1a3993 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -19,10 +19,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "includes.h"
+#include "printing.h"
extern int DEBUGLEVEL;
+/* Current printer interface */
+struct printif *current_printif = &generic_printif;
+
/*
the printing backend revolves around a tdb database that stores the
SMB view of the print queue
@@ -37,34 +40,10 @@ extern int DEBUGLEVEL;
jobids are assigned when a job starts spooling.
*/
-#define NEXT_JOBID(j) ((j+1) % PRINT_MAX_JOBID > 0 ? (j+1) % PRINT_MAX_JOBID : 1)
-
-
-struct printjob {
- pid_t pid; /* which process launched the job */
- int sysjob; /* the system (lp) job number */
- int fd; /* file descriptor of open file if open */
- time_t starttime; /* when the job started spooling */
- int status; /* the status of this job */
- size_t size; /* the size of the job so far */
- BOOL spooled; /* has it been sent to the spooler yet? */
- BOOL smbjob; /* set if the job is a SMB job */
- fstring filename; /* the filename used to spool the file */
- fstring jobname; /* the job name given to us by the client */
- fstring user; /* the user who started the job */
- fstring qname; /* name of the print queue the job was sent to */
-};
-
/* the open printing.tdb database */
static TDB_CONTEXT *tdb;
static pid_t local_pid;
-#define PRINT_MAX_JOBID 10000
-#define UNIX_JOB_START PRINT_MAX_JOBID
-
-#define PRINT_SPOOL_PREFIX "smbprn."
-#define PRINT_DATABASE_VERSION 2
-
static int get_queue_status(int, print_status_struct *);
/****************************************************************************
@@ -92,6 +71,13 @@ BOOL print_backend_init(void)
}
tdb_unlock_bystring(tdb, sversion);
+ /* select the appropriate printing interface... */
+#ifdef HAVE_LIBCUPS
+ if (strcmp(lp_printcapname(), "cups") == 0)
+ current_printif = &cups_printif;
+#endif /* HAVE_LIBCUPS */
+
+ /* do NT print initialization... */
return nt_printing_init();
}
@@ -138,51 +124,6 @@ static BOOL print_job_store(int jobid, struct printjob *pjob)
}
/****************************************************************************
-run a given print command
-a null terminated list of value/substitute pairs is provided
-for local substitution strings
-****************************************************************************/
-static int print_run_command(int snum,char *command,
- char *outfile,
- ...)
-{
- pstring syscmd;
- char *p, *arg;
- int ret;
- va_list ap;
-
- if (!command || !*command) return -1;
-
- if (!VALID_SNUM(snum)) {
- DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
- return -1;
- }
-
- pstrcpy(syscmd, command);
-
- va_start(ap, outfile);
- while ((arg = va_arg(ap, char *))) {
- char *value = va_arg(ap,char *);
- pstring_sub(syscmd, arg, value);
- }
- va_end(ap);
-
- p = PRINTERNAME(snum);
-
- pstring_sub(syscmd, "%p", p);
- standard_sub_snum(snum,syscmd);
-
- /* Convert script args to unix-codepage */
- dos_to_unix(syscmd, True);
- ret = smbrun(syscmd,outfile,False);
-
- DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
-
- return ret;
-}
-
-
-/****************************************************************************
parse a file name from the system spooler to generate a jobid
****************************************************************************/
static int print_parse_jobid(char *fname)
@@ -378,11 +319,7 @@ update the internal database from the system print queue for a queue
static void print_queue_update(int snum)
{
- char *path = lp_pathname(snum);
- char *cmd = lp_lpqcommand(snum);
- char **qlines;
- pstring tmp_file;
- int numlines, i, qcount;
+ int i, qcount;
print_queue_struct *queue = NULL;
print_status_struct status;
print_status_struct old_status;
@@ -446,31 +383,10 @@ static void print_queue_update(int snum)
slprintf(cachestr, sizeof(cachestr), "CACHE/%s", printer_name);
tdb_store_int(tdb, cachestr, (int)time(NULL));
- slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
-
- unlink(tmp_file);
- print_run_command(snum, cmd, tmp_file, NULL);
-
- numlines = 0;
- qlines = file_lines_load(tmp_file, &numlines, True);
- unlink(tmp_file);
-
- /* turn the lpq output into a series of job structures */
- qcount = 0;
+ /* get the current queue using the appropriate interface */
ZERO_STRUCT(status);
- if (numlines)
- queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
-
- if (queue) {
- for (i=0; i<numlines; i++) {
- /* parse the line */
- if (parse_lpq_entry(snum,qlines[i],
- &queue[qcount],&status,qcount==0)) {
- qcount++;
- }
- }
- }
- file_lines_free(qlines);
+
+ qcount = (*(current_printif->queue_get))(snum, &queue, &status);
DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
"s" : "", printer_name));
@@ -658,17 +574,14 @@ static BOOL print_job_delete1(int jobid)
pjob->status = LPQ_DELETING;
print_job_store(jobid, pjob);
- if (pjob->spooled && pjob->sysjob != -1) {
- fstring jobstr;
-
- /* need to delete the spooled entry */
- slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
- result = print_run_command(
- snum,
- lp_lprmcommand(snum), NULL,
- "%j", jobstr,
- "%T", http_timestring(pjob->starttime),
- NULL);
+ if (pjob->spooled && pjob->sysjob != -1)
+ result = (*(current_printif->job_delete))(snum, pjob);
+
+ /* Delete the tdb entry if the delete suceeded or the job hasn't
+ been spooled. */
+
+ if (result == 0) {
+ tdb_delete(tdb, print_key(jobid));
}
return (result == 0);
@@ -739,17 +652,14 @@ BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
struct printjob *pjob = print_job_find(jobid);
int snum, ret = -1;
char *printer_name;
- fstring jobstr;
- BOOL owner;
if (!pjob || !user) return False;
if (!pjob->spooled || pjob->sysjob == -1) return False;
snum = print_job_snum(jobid);
- owner = is_owner(user, jobid);
- if (!owner &&
+ if (!is_owner(user, jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("pause denied by security descriptor\n"));
*errcode = ERROR_ACCESS_DENIED;
@@ -757,11 +667,7 @@ BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
}
/* need to pause the spooled entry */
- slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
- ret = print_run_command(snum,
- lp_lppausecommand(snum), NULL,
- "%j", jobstr,
- NULL);
+ ret = (*(current_printif->job_pause))(snum, pjob);
if (ret != 0) {
*errcode = ERROR_INVALID_PARAMETER;
@@ -790,7 +696,6 @@ BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
struct printjob *pjob = print_job_find(jobid);
char *printer_name;
int snum, ret;
- fstring jobstr;
if (!pjob || !user) return False;
@@ -805,11 +710,7 @@ BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
return False;
}
- slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
- ret = print_run_command(snum,
- lp_lpresumecommand(snum), NULL,
- "%j", jobstr,
- NULL);
+ ret = (*(current_printif->job_resume))(snum, pjob);
if (ret != 0) {
*errcode = ERROR_INVALID_PARAMETER;
@@ -1056,10 +957,6 @@ BOOL print_job_end(int jobid, BOOL normal_close)
struct printjob *pjob = print_job_find(jobid);
int snum, ret;
SMB_STRUCT_STAT sbuf;
- pstring current_directory;
- pstring print_directory;
- char *wd, *p;
- pstring jobname;
if (!pjob)
return False;
@@ -1096,30 +993,7 @@ BOOL print_job_end(int jobid, BOOL normal_close)
return True;
}
- /* we print from the directory path to give the best chance of
- parsing the lpq output */
- wd = sys_getwd(current_directory);
- if (!wd) goto fail;
-
- pstrcpy(print_directory, pjob->filename);
- p = strrchr(print_directory,'/');
- if (!p) goto fail;
- *p++ = 0;
-
- if (chdir(print_directory) != 0) goto fail;
-
- pstrcpy(jobname, pjob->jobname);
- pstring_sub(jobname, "'", "_");
-
- /* send it to the system spooler */
- ret = print_run_command(snum,
- lp_printcommand(snum), NULL,
- "%s", p,
- "%J", jobname,
- "%f", p,
- NULL);
-
- chdir(wd);
+ ret = (*(current_printif->job_submit))(snum, pjob);
if (ret) goto fail;
@@ -1310,8 +1184,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
return False;
}
- ret = print_run_command(snum, lp_queuepausecommand(snum), NULL,
- NULL);
+ ret = (*(current_printif->queue_pause))(snum);
if (ret != 0) {
*errcode = ERROR_INVALID_PARAMETER;
@@ -1343,8 +1216,7 @@ BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
return False;
}
- ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
- NULL);
+ ret = (*(current_printif->queue_resume))(snum);
if (ret != 0) {
*errcode = ERROR_INVALID_PARAMETER;