cupsPrintFile() has no streaming equivalent?
mike
dizaemon at hotmail.com
Fri Feb 23 13:44:59 PST 2007
> > > If you look at the cupsDoFileRequest code in cups/request.c,
> > > you'll see how to use the lower-level HTTP and IPP APIs to stream
> > > your content to the CUPS server.
[snip]
> > if there was some type of chunked/segmented file transfer method
> > where set blocks of the file are transferred at a time, then perhaps
> > the streaming method would work. is there such support in cups?
[snip]
> so it would appear that transmitting the data as a sequence of chunks is
> possible, according to the RFC. i'm still reading, but i thought i'd
> mention it in case anyone has any insight into how CUPS implements
> chunked IPP_PRINT_JOB requests.
after finally figuring out that the http code automatically does chunked
transfer encoding when HTTP_FIELD_TRANSFER_ENCODING is set to "chunked",
i've got a diff against cups-1.2 that implements cupsPrintStream.
please test it out for me and let me know what you think!
-mike
--- snip --- snip --- snip ---
Index: cups/request.c
===================================================================
--- cups/request.c (revision 6305)
+++ cups/request.c (working copy)
@@ -36,6 +36,7 @@
#include "globals.h"
#include "debug.h"
+#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
@@ -48,34 +49,33 @@
/*
- * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ * 'cupsDoStreamRequest()' - Do a stream request with a file.
*
* This function sends the IPP request to the specified server, retrying
* and authenticating as necessary. The request is freed with ippDelete()
* after receiving a valid IPP response.
*/
-ipp_t * /* O - Response data */
-cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
- ipp_t *request, /* I - IPP request */
- const char *resource, /* I - HTTP resource for POST */
- const char *filename) /* I - File to send or NULL for none */
+ipp_t * /* O - Response data */
+cupsDoStreamRequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ cups_stream_cb_t fpread, /* I - function pointer for read */
+ void *arg) /* I - arbitrary arg to pass to fp */
{
ipp_t *response; /* IPP response data */
size_t length; /* Content-Length value */
http_status_t status; /* Status of HTTP request */
int got_status; /* Did we get the status? */
ipp_state_t state; /* State of IPP processing */
- FILE *file; /* File to send */
- struct stat fileinfo; /* File information */
int bytes; /* Number of bytes read/written */
char buffer[32768]; /* Output buffer */
http_status_t expect; /* Expect: header to use */
-
- DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+ DEBUG_printf(("cupsDoStreamRequest(%p, %p, \'%s\', %p, %p)\n",
http, request, resource ? resource : "(null)",
- filename ? filename : "(null)"));
+ fpread ? fpread : "(null)",
+ arg ? arg : "(null)"));
if (http == NULL || request == NULL || resource == NULL)
{
@@ -88,60 +88,6 @@
}
/*
- * See if we have a file to send...
- */
-
- if (filename != NULL)
- {
- if (stat(filename, &fileinfo))
- {
- /*
- * Can't get file information!
- */
-
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
-
- ippDelete(request);
-
- return (NULL);
- }
-
-#ifdef WIN32
- if (fileinfo.st_mode & _S_IFDIR)
-#else
- if (S_ISDIR(fileinfo.st_mode))
-#endif /* WIN32 */
- {
- /*
- * Can't send a directory...
- */
-
- ippDelete(request);
-
- _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
-
- return (NULL);
- }
-
- if ((file = fopen(filename, "rb")) == NULL)
- {
- /*
- * Can't open file!
- */
-
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
-
- ippDelete(request);
-
- return (NULL);
- }
- }
- else
- file = NULL;
-
- /*
* Loop until we can send the request without authorization problems.
*/
@@ -151,29 +97,30 @@
while (response == NULL)
{
- DEBUG_puts("cupsDoFileRequest: setup...");
+ DEBUG_puts("cupsDoStreamRequest: setup...");
/*
* Setup the HTTP variables needed...
*/
length = ippLength(request);
- if (filename)
- length += fileinfo.st_size;
httpClearFields(http);
- httpSetLength(http, length);
+ if (fpread)
+ httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+ else
+ httpSetLength(http, length);
httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
httpSetExpect(http, expect);
- DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+ DEBUG_printf(("cupsDoStreamRequest: authstring=\"%s\"\n", http->authstring));
/*
* Try the request...
*/
- DEBUG_puts("cupsDoFileRequest: post...");
+ DEBUG_puts("cupsDoStreamRequest: post...");
if (httpPost(http, resource))
{
@@ -190,7 +137,7 @@
* Send the IPP data...
*/
- DEBUG_puts("cupsDoFileRequest: ipp write...");
+ DEBUG_puts("cupsDoStreamRequest: ipp write...");
request->state = IPP_IDLE;
status = HTTP_CONTINUE;
@@ -219,18 +166,19 @@
else if (httpCheck(http))
status = httpUpdate(http);
- if (status == HTTP_CONTINUE && state == IPP_DATA && filename)
+ DEBUG_printf(("cupsDoStreamRequest: fpread=%p\n", fpread));
+
+ if (status == HTTP_CONTINUE && state == IPP_DATA && fpread)
{
- DEBUG_puts("cupsDoFileRequest: file write...");
+ DEBUG_puts("cupsDoStreamRequest: file write...");
/*
* Send the file...
*/
- rewind(file);
-
- while ((bytes = (int)fread(buffer, 1, sizeof(buffer), file)) > 0)
+ while ((bytes = (int)fpread(buffer, 1, sizeof(buffer), arg)) > 0)
{
+ DEBUG_printf(("cupsDoStreamRequest: read %d bytes from stream\n", bytes));
if (httpCheck(http))
{
if ((status = httpUpdate(http)) != HTTP_CONTINUE)
@@ -239,23 +187,28 @@
if (httpWrite2(http, buffer, bytes) < bytes)
break;
+
+ httpFlushWrite(http);
}
+
+ httpWrite2(http, "", 0);
+ httpFlushWrite(http);
}
/*
* Get the server's return status...
*/
- DEBUG_puts("cupsDoFileRequest: update...");
+ DEBUG_puts("cupsDoStreamRequest: update...");
while (status == HTTP_CONTINUE)
status = httpUpdate(http);
- DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
+ DEBUG_printf(("cupsDoStreamRequest: status = %d\n", status));
if (status == HTTP_UNAUTHORIZED)
{
- DEBUG_puts("cupsDoFileRequest: unauthorized...");
+ DEBUG_puts("cupsDoStreamRequest: unauthorized...");
/*
* Flush any error message...
@@ -280,7 +233,7 @@
}
else if (status == HTTP_ERROR)
{
- DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
+ DEBUG_printf(("cupsDoStreamRequest: http->error=%d (%s)\n", http->error,
strerror(http->error)));
#ifdef WIN32
@@ -324,7 +277,7 @@
}
else if (status != HTTP_OK)
{
- DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+ DEBUG_printf(("cupsDoStreamRequest: error %d...\n", status));
/*
* Flush any error message...
@@ -339,7 +292,7 @@
* Read the response...
*/
- DEBUG_puts("cupsDoFileRequest: response...");
+ DEBUG_puts("cupsDoStreamRequest: response...");
response = ippNew();
@@ -362,13 +315,6 @@
}
/*
- * Close the file if needed...
- */
-
- if (filename != NULL)
- fclose(file);
-
- /*
* Flush any remaining data...
*/
@@ -436,6 +382,87 @@
/*
+ * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary. The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t * /* O - Response data */
+cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ const char *filename) /* I - File to send or NULL for none */
+{
+ FILE *file; /* File to send */
+ struct stat fileinfo; /* File information */
+ ipp_t *response; /* IPP response data */
+
+ DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+ http, request, resource ? resource : "(null)",
+ filename ? filename : "(null)"));
+
+ if (filename != NULL)
+ {
+ if (stat(filename, &fileinfo))
+ {
+ /*
+ * Can't get file information!
+ */
+
+ _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ strerror(errno));
+
+ ippDelete(request);
+
+ return (NULL);
+ }
+
+#ifdef WIN32
+ if (fileinfo.st_mode & _S_IFDIR)
+#else
+ if (S_ISDIR(fileinfo.st_mode))
+#endif /* WIN32 */
+ {
+ /*
+ * Can't send a directory...
+ */
+
+ ippDelete(request);
+
+ _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
+
+ return (NULL);
+ }
+
+ if ((file = fopen(filename, "rb")) == NULL)
+ {
+ /*
+ * Can't open file!
+ */
+
+ _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ strerror(errno));
+
+ ippDelete(request);
+
+ return (NULL);
+ }
+ }
+ else
+ file = NULL;
+
+ response = cupsDoStreamRequest(http, request, resource, file ? (cups_stream_cb_t) fread : NULL, file);
+
+ if (file)
+ fclose(file);
+
+ return (response);
+}
+
+
+/*
* 'cupsDoRequest()' - Do an IPP request.
*
* This function sends the IPP request to the specified server, retrying
Index: berkeley/lpr.c
===================================================================
--- berkeley/lpr.c (revision 6305)
+++ berkeley/lpr.c (working copy)
@@ -429,70 +429,7 @@
}
else
{
- 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);
- }
-
- 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);
- }
-
- filesize = lseek(temp, 0, SEEK_CUR);
- close(temp);
-
- if (filesize <= 0)
- {
- _cupsLangPrintf(stderr,
- _("%s: Error - stdin is empty, so no job has been sent.\n"),
- argv[0]);
- unlink(tempfile);
- 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);
+ job_id = cupsPrintStream(NULL, printer, (cups_stream_cb_t) fread, stdin, title, num_options, options);
}
if (job_id < 1)
@@ -504,30 +441,6 @@
return (0);
}
-
-#ifndef WIN32
/*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s) /* I - Signal number */
-{
- /*
- * Remove the temporary file we're using to print from stdin...
- */
-
- unlink(tempfile);
-
- /*
- * Exit...
- */
-
- exit(s);
-}
-#endif /* !WIN32 */
-
-
-/*
* End of "$Id$".
*/
Index: cups/cups.h
===================================================================
--- cups/cups.h (revision 6305)
+++ cups/cups.h (working copy)
@@ -110,6 +110,8 @@
CUPS_PRINTER_OPTIONS = 0xe6fffc /* ~(CLASS | REMOTE | IMPLICIT) */
};
+typedef size_t (*cups_stream_cb_t)(void *, size_t, size_t, void *);
+ /**** Streaming callback ****/
typedef const char *(*cups_password_cb_t)(const char *);
/**** Password callback ****/
@@ -243,6 +245,15 @@
cups_option_t **options);
extern cups_file_t *cupsTempFile2(char *filename, int len);
+/**** New in CUPS 1.2.? ****/
+extern int cupsPrintStream(http_t *http, const char *printer,
+ cups_stream_cb_t fpread, void *arg,
+ const char *title, int num_options,
+ cups_option_t *options);
+extern ipp_t *cupsDoStreamRequest(http_t *http, ipp_t *request,
+ const char *resource,
+ cups_stream_cb_t fpread,
+ void *arg);
# ifdef __cplusplus
}
Index: cups/request.c
===================================================================
--- cups/request.c (revision 6305)
+++ cups/request.c (working copy)
@@ -36,6 +36,7 @@
#include "globals.h"
#include "debug.h"
+#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
@@ -48,34 +49,33 @@
/*
- * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ * 'cupsDoStreamRequest()' - Do a stream request with a file.
*
* This function sends the IPP request to the specified server, retrying
* and authenticating as necessary. The request is freed with ippDelete()
* after receiving a valid IPP response.
*/
-ipp_t * /* O - Response data */
-cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
- ipp_t *request, /* I - IPP request */
- const char *resource, /* I - HTTP resource for POST */
- const char *filename) /* I - File to send or NULL for none */
+ipp_t * /* O - Response data */
+cupsDoStreamRequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ cups_stream_cb_t fpread, /* I - function pointer for read */
+ void *arg) /* I - arbitrary arg to pass to fp */
{
ipp_t *response; /* IPP response data */
size_t length; /* Content-Length value */
http_status_t status; /* Status of HTTP request */
int got_status; /* Did we get the status? */
ipp_state_t state; /* State of IPP processing */
- FILE *file; /* File to send */
- struct stat fileinfo; /* File information */
int bytes; /* Number of bytes read/written */
char buffer[32768]; /* Output buffer */
http_status_t expect; /* Expect: header to use */
-
- DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+ DEBUG_printf(("cupsDoStreamRequest(%p, %p, \'%s\', %p, %p)\n",
http, request, resource ? resource : "(null)",
- filename ? filename : "(null)"));
+ fpread ? fpread : "(null)",
+ arg ? arg : "(null)"));
if (http == NULL || request == NULL || resource == NULL)
{
@@ -88,60 +88,6 @@
}
/*
- * See if we have a file to send...
- */
-
- if (filename != NULL)
- {
- if (stat(filename, &fileinfo))
- {
- /*
- * Can't get file information!
- */
-
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
-
- ippDelete(request);
-
- return (NULL);
- }
-
-#ifdef WIN32
- if (fileinfo.st_mode & _S_IFDIR)
-#else
- if (S_ISDIR(fileinfo.st_mode))
-#endif /* WIN32 */
- {
- /*
- * Can't send a directory...
- */
-
- ippDelete(request);
-
- _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
-
- return (NULL);
- }
-
- if ((file = fopen(filename, "rb")) == NULL)
- {
- /*
- * Can't open file!
- */
-
- _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
- strerror(errno));
-
- ippDelete(request);
-
- return (NULL);
- }
- }
- else
- file = NULL;
-
- /*
* Loop until we can send the request without authorization problems.
*/
@@ -151,29 +97,30 @@
while (response == NULL)
{
- DEBUG_puts("cupsDoFileRequest: setup...");
+ DEBUG_puts("cupsDoStreamRequest: setup...");
/*
* Setup the HTTP variables needed...
*/
length = ippLength(request);
- if (filename)
- length += fileinfo.st_size;
httpClearFields(http);
- httpSetLength(http, length);
+ if (fpread)
+ httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+ else
+ httpSetLength(http, length);
httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
httpSetExpect(http, expect);
- DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+ DEBUG_printf(("cupsDoStreamRequest: authstring=\"%s\"\n", http->authstring));
/*
* Try the request...
*/
- DEBUG_puts("cupsDoFileRequest: post...");
+ DEBUG_puts("cupsDoStreamRequest: post...");
if (httpPost(http, resource))
{
@@ -190,7 +137,7 @@
* Send the IPP data...
*/
- DEBUG_puts("cupsDoFileRequest: ipp write...");
+ DEBUG_puts("cupsDoStreamRequest: ipp write...");
request->state = IPP_IDLE;
status = HTTP_CONTINUE;
@@ -219,18 +166,19 @@
else if (httpCheck(http))
status = httpUpdate(http);
- if (status == HTTP_CONTINUE && state == IPP_DATA && filename)
+ DEBUG_printf(("cupsDoStreamRequest: fpread=%p\n", fpread));
+
+ if (status == HTTP_CONTINUE && state == IPP_DATA && fpread)
{
- DEBUG_puts("cupsDoFileRequest: file write...");
+ DEBUG_puts("cupsDoStreamRequest: file write...");
/*
* Send the file...
*/
- rewind(file);
-
- while ((bytes = (int)fread(buffer, 1, sizeof(buffer), file)) > 0)
+ while ((bytes = (int)fpread(buffer, 1, sizeof(buffer), arg)) > 0)
{
+ DEBUG_printf(("cupsDoStreamRequest: read %d bytes from stream\n", bytes));
if (httpCheck(http))
{
if ((status = httpUpdate(http)) != HTTP_CONTINUE)
@@ -239,23 +187,28 @@
if (httpWrite2(http, buffer, bytes) < bytes)
break;
+
+ httpFlushWrite(http);
}
+
+ httpWrite2(http, "", 0);
+ httpFlushWrite(http);
}
/*
* Get the server's return status...
*/
- DEBUG_puts("cupsDoFileRequest: update...");
+ DEBUG_puts("cupsDoStreamRequest: update...");
while (status == HTTP_CONTINUE)
status = httpUpdate(http);
- DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
+ DEBUG_printf(("cupsDoStreamRequest: status = %d\n", status));
if (status == HTTP_UNAUTHORIZED)
{
- DEBUG_puts("cupsDoFileRequest: unauthorized...");
+ DEBUG_puts("cupsDoStreamRequest: unauthorized...");
/*
* Flush any error message...
@@ -280,7 +233,7 @@
}
else if (status == HTTP_ERROR)
{
- DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
+ DEBUG_printf(("cupsDoStreamRequest: http->error=%d (%s)\n", http->error,
strerror(http->error)));
#ifdef WIN32
@@ -324,7 +277,7 @@
}
else if (status != HTTP_OK)
{
- DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+ DEBUG_printf(("cupsDoStreamRequest: error %d...\n", status));
/*
* Flush any error message...
@@ -339,7 +292,7 @@
* Read the response...
*/
- DEBUG_puts("cupsDoFileRequest: response...");
+ DEBUG_puts("cupsDoStreamRequest: response...");
response = ippNew();
@@ -362,13 +315,6 @@
}
/*
- * Close the file if needed...
- */
-
- if (filename != NULL)
- fclose(file);
-
- /*
* Flush any remaining data...
*/
@@ -436,6 +382,87 @@
/*
+ * 'cupsDoFileRequest()' - Do an IPP request with a file.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary. The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t * /* O - Response data */
+cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ const char *filename) /* I - File to send or NULL for none */
+{
+ FILE *file; /* File to send */
+ struct stat fileinfo; /* File information */
+ ipp_t *response; /* IPP response data */
+
+ DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+ http, request, resource ? resource : "(null)",
+ filename ? filename : "(null)"));
+
+ if (filename != NULL)
+ {
+ if (stat(filename, &fileinfo))
+ {
+ /*
+ * Can't get file information!
+ */
+
+ _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ strerror(errno));
+
+ ippDelete(request);
+
+ return (NULL);
+ }
+
+#ifdef WIN32
+ if (fileinfo.st_mode & _S_IFDIR)
+#else
+ if (S_ISDIR(fileinfo.st_mode))
+#endif /* WIN32 */
+ {
+ /*
+ * Can't send a directory...
+ */
+
+ ippDelete(request);
+
+ _cupsSetError(IPP_NOT_POSSIBLE, strerror(EISDIR));
+
+ return (NULL);
+ }
+
+ if ((file = fopen(filename, "rb")) == NULL)
+ {
+ /*
+ * Can't open file!
+ */
+
+ _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+ strerror(errno));
+
+ ippDelete(request);
+
+ return (NULL);
+ }
+ }
+ else
+ file = NULL;
+
+ response = cupsDoStreamRequest(http, request, resource, file ? (cups_stream_cb_t) fread : NULL, file);
+
+ if (file)
+ fclose(file);
+
+ return (response);
+}
+
+
+/*
* 'cupsDoRequest()' - Do an IPP request.
*
* This function sends the IPP request to the specified server, retrying
--- snip --- snip --- snip ---
More information about the cups
mailing list