mirror of
https://github.com/MopriaAlliance/CUPS-for-Android.git
synced 2025-08-03 10:54:38 +08:00
444 lines
15 KiB
Plaintext
444 lines
15 KiB
Plaintext
<!--
|
|
"$Id: api-cups.shtml 7337 2008-02-22 04:44:04Z mike $"
|
|
|
|
API introduction for CUPS.
|
|
|
|
Copyright 2007-2013 by Apple Inc.
|
|
Copyright 1997-2006 by Easy Software Products, all rights reserved.
|
|
|
|
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/".
|
|
-->
|
|
|
|
<h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
|
|
|
|
<p>The CUPS API provides the convenience functions needed to support
|
|
applications, filters, printer drivers, and backends that need to interface
|
|
with the CUPS scheduler.</p>
|
|
|
|
<h3><a name='CLIENTS_AND_SERVERS'>Clients and Servers</a></h3>
|
|
|
|
<p>CUPS is based on the Internet Printing Protocol ("IPP"), which allows
|
|
clients (applications) to communicate with a server (the scheduler) to get a
|
|
list of printers, send print jobs, and so forth. You identify which server
|
|
you want to communicate with using a pointer to the opaque structure
|
|
<code>http_t</code>. All of the examples in this document use the
|
|
<code>CUPS_HTTP_DEFAULT</code> constant, referring to the default connection
|
|
to the scheduler. The <a href='api-httpipp.html' target='_top'>HTTP and IPP
|
|
APIs</a> document provides more information on server connections.</p>
|
|
|
|
<h3><a name='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
|
|
|
|
<p>Printers and classes (collections of printers) are accessed through
|
|
the <a href="#cups_dest_t"><code>cups_dest_t</code></a> structure which
|
|
includes the name (<code>name</code>), instance (<code>instance</code> -
|
|
a way of selecting certain saved options/settings), and the options and
|
|
attributes associated with that destination (<code>num_options</code> and
|
|
<code>options</code>). Destinations are created using the
|
|
<a href="#cupsGetDests"><code>cupsGetDests</code></a> function and freed
|
|
using the <a href='#cupsFreeDests'><code>cupsFreeDests</code></a> function.
|
|
The <a href='#cupsGetDest'><code>cupsGetDest</code></a> function finds a
|
|
specific destination for printing:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dests;
|
|
int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&dests);
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest = <a href='#cupsGetDest'>cupsGetDest</a>("name", NULL, num_dests, dests);
|
|
|
|
/* do something with dest */
|
|
|
|
<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
|
|
</pre>
|
|
|
|
<p>Passing <code>NULL</code> to
|
|
<a href='#cupsGetDest'><code>cupsGetDest</code></a> for the destination name
|
|
will return the default destination. Similarly, passing a <code>NULL</code>
|
|
instance will return the default instance for that destination.</p>
|
|
|
|
<div class='table'><table summary='Table 1: Printer Attributes' width='80%'>
|
|
<caption>Table 1: <a name='TABLE1'>Printer Attributes</a></caption>
|
|
<thead>
|
|
<tr>
|
|
<th>Attribute Name</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>"auth-info-required"</td>
|
|
<td>The type of authentication required for printing to this
|
|
destination: "none", "username,password", "domain,username,password",
|
|
or "negotiate" (Kerberos)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-info"</td>
|
|
<td>The human-readable description of the destination such as "My
|
|
Laser Printer".</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-is-accepting-jobs"</td>
|
|
<td>"true" if the destination is accepting new jobs, "false" if
|
|
not.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-is-shared"</td>
|
|
<td>"true" if the destination is being shared with other computers,
|
|
"false" if not.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-location"</td>
|
|
<td>The human-readable location of the destination such as "Lab 4".</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-make-and-model"</td>
|
|
<td>The human-readable make and model of the destination such as "HP
|
|
LaserJet 4000 Series".</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-state"</td>
|
|
<td>"3" if the destination is idle, "4" if the destination is printing
|
|
a job, and "5" if the destination is stopped.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-state-change-time"</td>
|
|
<td>The UNIX time when the destination entered the current state.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-state-reasons"</td>
|
|
<td>Additional comma-delimited state keywords for the destination
|
|
such as "media-tray-empty-error" and "toner-low-warning".</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"printer-type"</td>
|
|
<td>The <a href='#cups_printer_t'><code>cups_printer_t</code></a>
|
|
value associated with the destination.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table></div>
|
|
|
|
<h3><a name='OPTIONS'>Options</a></h3>
|
|
|
|
<p>Options are stored in arrays of
|
|
<a href='#cups_option_t'><code>cups_option_t</code></a> structures. Each
|
|
option has a name (<code>name</code>) and value (<code>value</code>)
|
|
associated with it. The <a href='#cups_dest_t'><code>cups_dest_t</code></a>
|
|
<code>num_options</code> and <code>options</code> members contain the
|
|
default options for a particular destination, along with several informational
|
|
attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>.
|
|
The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets
|
|
the value for the named option. For example, the following code lists the
|
|
available destinations and their human-readable descriptions:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dests;
|
|
int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&dests);
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int i;
|
|
const char *value;
|
|
|
|
for (i = num_dests, dest = dests; i > 0; i --, dest ++)
|
|
if (dest->instance == NULL)
|
|
{
|
|
value = <a href='#cupsGetOption'>cupsGetOption</a>("printer-info", dest->num_options, dest->options);
|
|
printf("%s (%s)\n", dest->name, value ? value : "no description");
|
|
}
|
|
|
|
<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
|
|
</pre>
|
|
|
|
<p>You can create your own option arrays using the
|
|
<a href='#cupsAddOption'><code>cupsAddOption</code></a> function, which
|
|
adds a single named option to an array:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
int num_options = 0;
|
|
<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
|
|
|
|
/* The returned num_options value is updated as needed */
|
|
num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options);
|
|
|
|
/* This adds a second option value */
|
|
num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options);
|
|
|
|
/* This replaces the first option we added */
|
|
num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &options);
|
|
</pre>
|
|
|
|
<p>Use a <code>for</code> loop to copy the options from a destination:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
int i;
|
|
int num_options = 0;
|
|
<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
|
|
for (i = 0; i < dest->num_options; i ++)
|
|
num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
|
|
num_options, &options);
|
|
</pre>
|
|
|
|
<p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a>
|
|
function to free the options array when you are done using it:</p>
|
|
|
|
<pre class='example'>
|
|
<a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
|
|
</pre>
|
|
|
|
<h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
|
|
|
|
<p>Print jobs are identified by a locally-unique job ID number from 1 to
|
|
2<sup>31</sup>-1 and have options and one or more files for printing to a
|
|
single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a>
|
|
function creates a new job with one file. The following code prints the CUPS
|
|
test page file:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int num_options;
|
|
<a href='#cups_option_t'>cups_option_t</a> *options;
|
|
int job_id;
|
|
|
|
/* Print a single file */
|
|
job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
|
|
"Test Print", num_options, options);
|
|
</pre>
|
|
|
|
<p>The <a href='#cupsPrintFiles'><code>cupsPrintFiles</code></a> function
|
|
creates a job with multiple files. The files are provided in a
|
|
<code>char *</code> array:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int num_options;
|
|
<a href='#cups_option_t'>cups_option_t</a> *options;
|
|
int job_id;
|
|
char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
|
|
|
|
/* Print three files */
|
|
job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
|
|
</pre>
|
|
|
|
<p>Finally, the <a href='#cupsCreateJob'><code>cupsCreateJob</code></a>
|
|
function creates a new job with no files in it. Files are added using the
|
|
<a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
|
|
<a href='api-httpipp.html#cupsWriteRequestData'><code>cupsWriteRequestData</code></a>,
|
|
and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions.
|
|
The following example creates a job with 10 text files for printing:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int num_options;
|
|
<a href='#cups_option_t'>cups_option_t</a> *options;
|
|
int job_id;
|
|
int i;
|
|
char buffer[1024];
|
|
|
|
/* Create the job */
|
|
job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
|
|
num_options, options);
|
|
|
|
/* If the job is created, add 10 files */
|
|
if (job_id > 0)
|
|
{
|
|
for (i = 1; i <= 10; i ++)
|
|
{
|
|
snprintf(buffer, sizeof(buffer), "file%d.txt", i);
|
|
|
|
<a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
|
|
CUPS_FORMAT_TEXT, i == 10);
|
|
|
|
snprintf(buffer, sizeof(buffer),
|
|
"File %d\n"
|
|
"\n"
|
|
"One fish,\n"
|
|
"Two fish,\n
|
|
"Red fish,\n
|
|
"Blue fish\n", i);
|
|
|
|
/* cupsWriteRequestData can be called as many times as needed */
|
|
<a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
|
|
|
|
<a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>Once you have created a job, you can monitor its status using the
|
|
<a href='#cupsGetJobs'><code>cupsGetJobs</code></a> function, which returns
|
|
an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures.
|
|
Each contains the job ID (<code>id</code>), destination name
|
|
(<code>dest</code>), title (<code>title</code>), and other information
|
|
associated with the job. The job array is freed using the
|
|
<a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following
|
|
example monitors a specific job ID, showing the current job state once every
|
|
5 seconds until the job is completed:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int job_id;
|
|
int num_jobs;
|
|
<a href='#cups_job_t'>cups_job_t</a> *jobs;
|
|
int i;
|
|
ipp_jstate_t job_state = IPP_JOB_PENDING;
|
|
|
|
while (job_state < IPP_JOB_STOPPED)
|
|
{
|
|
/* Get my jobs (1) with any state (-1) */
|
|
num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1);
|
|
|
|
/* Loop to find my job */
|
|
job_state = IPP_JOB_COMPLETED;
|
|
|
|
for (i = 0; i < num_jobs; i ++)
|
|
if (jobs[i].id == job_id)
|
|
{
|
|
job_state = jobs[i].state;
|
|
break;
|
|
}
|
|
|
|
/* Free the job array */
|
|
<a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
|
|
|
|
/* Show the current state */
|
|
switch (job_state)
|
|
{
|
|
case IPP_JOB_PENDING :
|
|
printf("Job %d is pending.\n", job_id);
|
|
break;
|
|
case IPP_JOB_HELD :
|
|
printf("Job %d is held.\n", job_id);
|
|
break;
|
|
case IPP_JOB_PROCESSING :
|
|
printf("Job %d is processing.\n", job_id);
|
|
break;
|
|
case IPP_JOB_STOPPED :
|
|
printf("Job %d is stopped.\n", job_id);
|
|
break;
|
|
case IPP_JOB_CANCELED :
|
|
printf("Job %d is canceled.\n", job_id);
|
|
break;
|
|
case IPP_JOB_ABORTED :
|
|
printf("Job %d is aborted.\n", job_id);
|
|
break;
|
|
case IPP_JOB_COMPLETED :
|
|
printf("Job %d is completed.\n", job_id);
|
|
break;
|
|
}
|
|
|
|
/* Sleep if the job is not finished */
|
|
if (job_state < IPP_JOB_STOPPED)
|
|
sleep(5);
|
|
}
|
|
</pre>
|
|
|
|
<p>To cancel a job, use the
|
|
<a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
|
|
job ID:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
<a href='#cups_dest_t'>cups_dest_t</a> *dest;
|
|
int job_id;
|
|
|
|
<a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
|
|
</pre>
|
|
|
|
<h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
|
|
|
|
<p>If any of the CUPS API printing functions returns an error, the reason for
|
|
that error can be found by calling the
|
|
<a href='#cupsLastError'><code>cupsLastError</code></a> and
|
|
<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> functions.
|
|
<a href='#cupsLastError'><code>cupsLastError</code></a> returns the last IPP
|
|
error code
|
|
(<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>)
|
|
that was encountered, while
|
|
<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns
|
|
a (localized) human-readable string that can be shown to the user. For example,
|
|
if any of the job creation functions returns a job ID of 0, you can use
|
|
<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> to show
|
|
the reason why the job could not be created:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
int job_id;
|
|
|
|
if (job_id == 0)
|
|
puts(cupsLastErrorString());
|
|
</pre>
|
|
|
|
<h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
|
|
|
|
<p>CUPS supports authentication of any request, including submission of print
|
|
jobs. The default mechanism for getting the username and password is to use the
|
|
login user and a password from the console.</p>
|
|
|
|
<p>To support other types of applications, in particular Graphical User
|
|
Interfaces ("GUIs"), the CUPS API provides functions to set the default
|
|
username and to register a callback function that returns a password string.</p>
|
|
|
|
<p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a>
|
|
function is used to set a password callback in your program. Only one
|
|
function can be used at any time.</p>
|
|
|
|
<p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the
|
|
current username for authentication. This function can be called by your
|
|
password callback function to change the current username as needed.</p>
|
|
|
|
<p>The following example shows a simple password callback that gets a
|
|
username and password from the user:</p>
|
|
|
|
<pre class='example'>
|
|
#include <cups/cups.h>
|
|
|
|
const char *
|
|
my_password_cb(const char *prompt)
|
|
{
|
|
char user[65];
|
|
|
|
|
|
puts(prompt);
|
|
|
|
/* Get a username from the user */
|
|
printf("Username: ");
|
|
if (fgets(user, sizeof(user), stdin) == NULL)
|
|
return (NULL);
|
|
|
|
/* Strip the newline from the string and set the user */
|
|
user[strlen(user) - 1] = '\0';
|
|
|
|
<a href='#cupsSetUser'>cupsSetUser</a>(user);
|
|
|
|
/* Use getpass() to ask for the password... */
|
|
return (getpass("Password: "));
|
|
}
|
|
|
|
<a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
|
|
</pre>
|
|
|
|
<p>Similarly, a GUI could display the prompt string in a window with input
|
|
fields for the username and password. The username should default to the
|
|
string returned by the <a href="#cupsUser"><code>cupsUser</code></a>
|
|
function.</p>
|