]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/api-cups.shtml
Merge changes from CUPS 1.4svn-r7696.
[thirdparty/cups.git] / cups / api-cups.shtml
CommitLineData
ef416fc2 1<!--
75bd9771 2 "$Id: api-cups.shtml 7337 2008-02-22 04:44:04Z mike $"
ef416fc2 3
4 CUPS API introduction for the Common UNIX Printing System (CUPS).
5
5a738aea 6 Copyright 2007-2008 by Apple Inc.
bc44d920 7 Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 8
9 These coded instructions, statements, and computer programs are the
bc44d920 10 property of Apple Inc. and are protected by Federal copyright
11 law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 which should have been included with this file. If this file is
13 file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14-->
15
5a738aea 16<h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
ef416fc2 17
5a738aea
MS
18<p>The CUPS API provides the convenience functions needed to support
19applications, filters, printer drivers, and backends that need to interface
20with the CUPS scheduler.</p>
ecdc0628 21
568fa3fa
MS
22<h3><a name='CLIENTS_AND_SERVERS'>Clients and Servers</a></h3>
23
24<p>CUPS is based on the Internet Printing Protocol ("IPP"), which allows
25clients (applications) to communicate with a server (the scheduler) to get a
26list of printers, send print jobs, and so forth. You identify which server
27you want to communicate with using a pointer to the opaque structure
28<code>http_t</code>. All of the examples in this document use the
29<code>CUPS_HTTP_DEFAULT</code> constant, referring to the default connection
30to the scheduler. The <a href='api-httpipp.html' target='_top'>HTTP and IPP
31APIs</a> document provides more information on server connections.</p>
32
5a738aea 33<h3><a name='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
ef416fc2 34
5a738aea
MS
35<p>Printers and classes (collections of printers) are accessed through
36the <a href="#cups_dest_t"><code>cups_dest_t</code></a> structure which
37includes the name (<code>name</code>), instance (<code>instance</code> -
568fa3fa
MS
38a way of selecting certain saved options/settings), and the options and
39attributes associated with that destination (<code>num_options</code> and
5a738aea
MS
40<code>options</code>). Destinations are created using the
41<a href="#cupsGetDests"><code>cupsGetDests</code></a> function and freed
42using the <a href='#cupsFreeDests'><code>cupsFreeDests</code></a> function.
43The <a href='#cupsGetDest'><code>cupsGetDest</code></a> function finds a
44specific destination for printing:</p>
ef416fc2 45
5a738aea
MS
46<pre class='example'>
47#include &lt;cups/cups.h&gt;
ef416fc2 48
5a738aea
MS
49<a href='#cups_dest_t'>cups_dest_t</a> *dests;
50int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
51<a href='#cups_dest_t'>cups_dest_t</a> *dest = <a href='#cupsGetDest'>cupsGetDest</a>("name", NULL, num_dests, dests);
ef416fc2 52
5a738aea
MS
53/* do something wiith dest */
54
55<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
ef416fc2 56</pre>
57
5a738aea
MS
58<p>Passing <code>NULL</code> to
59<a href='#cupsGetDest'><code>cupsGetDest</code></a> for the destination name
60will return the default destination. Similarly, passing a <code>NULL</code>
61instance will return the default instance for that destination.</p>
62
63<div class='table'><table summary='Table 1: Printer Attributes' width='80%'>
64<caption>Table 1: <a name='TABLE1'>Printer Attributes</a></caption>
65<thead>
66<tr>
67 <th>Attribute Name</th>
68 <th>Description</th>
69</tr>
70</thead>
71<tbody>
72<tr>
73 <td>"auth-info-required"</td>
74 <td>The type of authentication required for printing to this
75 destination: "none", "username,password", "domain,username,password",
76 or "negotiate" (Kerberos)</td>
77</tr>
78<tr>
79 <td>"printer-info"</td>
80 <td>The human-readable description of the destination such as "My
81 Laser Printer".</td>
82</tr>
83<tr>
84 <td>"printer-is-accepting-jobs"</td>
85 <td>"1" if the destination is accepting new jobs, "0" if not.</td>
86</tr>
87<tr>
88 <td>"printer-is-shared"</td>
89 <td>"1" if the destination is being shared with other computers, "0" if
90 not.</td>
91</tr>
92<tr>
93 <td>"printer-location"</td>
94 <td>The human-readable location of the destination such as "Lab 4".</td>
95</tr>
96<tr>
97 <td>"printer-make-and-model"</td>
98 <td>The human-readable make and model of the destination such as "HP
99 LaserJet 4000 Series".</td>
100</tr>
101<tr>
102 <td>"printer-state"</td>
103 <td>"3" if the destination is idle, "4" if the destination is printing
104 a job, and "5" if the destination is stopped.</td>
105</tr>
106<tr>
107 <td>"printer-state-change-time"</td>
108 <td>The UNIX time when the destination entered the current state.</td>
109</tr>
110<tr>
111 <td>"printer-state-reasons"</td>
112 <td>Additional comma-delimited state keywords for the destination
113 such as "media-tray-empty-error" and "toner-low-warning".</td>
114</tr>
115<tr>
116 <td>"printer-type"</td>
117 <td>The <a href='#cups_printer_t'><code>cups_printer_t</code></a>
118 value associated with the destination.</td>
119</tr>
120</tbody>
121</table></div>
122
123<h3><a name='OPTIONS'>Options</a></h3>
124
125<p>Options are stored in arrays of
126<a href='#cups_option_t'><code>cups_option_t</code></a> structures. Each
127option has a name (<code>name</code>) and value (<code>value</code>)
128associated with it. The <a href='#cups_dest_t'><code>cups_dest_t</code></a>
129<code>num_options</code> and <code>options</code> members contain the
130default options for a particular destination, along with several informational
131attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>.
132The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets
133the value for the named option. For example, the following code lists the
134available destinations and their human-readable descriptions:</p>
135
136<pre class='example'>
137#include &lt;cups/cups.h&gt;
138
139<a href='#cups_dest_t'>cups_dest_t</a> *dests;
140int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
141<a href='#cups_dest_t'>cups_dest_t</a> *dest;
142int i;
143const char *value;
144
145for (i = num_dests, dest = dests; i > 0; i --, dest ++)
146 if (dest->instance == NULL)
147 {
148 value = <a href='#cupsGetOption'>cupsGetOption</a>("printer-info", dest->num_options, dest->options);
149 printf("%s (%s)\n", dest->name, value ? value : "no description");
150 }
151
152<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
153</pre>
154
155<p>You can create your own option arrays using the
156<a href='#cupsAddOption'><code>cupsAddOption</code></a> function, which
157adds a single named option to an array:</p>
158
159<pre class='example'>
160#include &lt;cups/cups.h&gt;
161
162int num_options = 0;
163<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
164
165/* The returned num_options value is updated as needed */
166num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &amp;options);
167
168/* This adds a second option value */
169num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &amp;options);
170
171/* This replaces the first option we added */
172num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &amp;options);
173</pre>
174
175<p>Use a <code>for</code> loop to copy the options from a destination:</p>
176
177<pre class='example'>
178#include &lt;cups/cups.h&gt;
179
180int i;
181int num_options = 0;
182<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
183<a href='#cups_dest_t'>cups_dest_t</a> *dest;
184
185for (i = 0; i < dest->num_options; i ++)
568fa3fa
MS
186 num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
187 num_options, &amp;options);
5a738aea
MS
188</pre>
189
190<p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a>
191function to free the options array when you are done using it:</p>
192
193<pre class='example'>
194<a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
195</pre>
196
197<h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
198
199<p>Print jobs are identified by a locally-unique job ID number from 1 to
2002<sup>31</sup>-1 and have options and one or more files for printing to a
201single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a>
202function creates a new job with one file. The following code prints the CUPS
203test page file:</p>
204
205<pre class='example'>
206#include &lt;cups/cups.h&gt;
207
208<a href='#cups_dest_t'>cups_dest_t</a> *dest;
209int num_options;
210<a href='#cups_option_t'>cups_option_t</a> *options;
211int job_id;
212
213/* Print a single file */
568fa3fa
MS
214job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
215 "Test Print", num_options, options);
5a738aea
MS
216</pre>
217
218<p>The <a href='#cupsPrintFiles'><code>cupsPrintFiles</code></a> function
219creates a job with multiple files. The files are provided in a
220<code>char *</code> array:</p>
221
222<pre class='example'>
223#include &lt;cups/cups.h&gt;
224
225<a href='#cups_dest_t'>cups_dest_t</a> *dest;
226int num_options;
227<a href='#cups_option_t'>cups_option_t</a> *options;
228int job_id;
229char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
230
231/* Print three files */
232job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
233</pre>
234
235<p>Finally, the <a href='#cupsCreateJob'><code>cupsCreateJob</code></a>
236function creates a new job with no files in it. Files are added using the
237<a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
238<a href='api-httpipp.html#cupsWriteRequestData'><code>cupsWriteRequestData</code></a>,
239and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions.
240The following example creates a job with 10 text files for printing:</p>
241
242<pre class='example'>
243#include &lt;cups/cups.h&gt;
244
245<a href='#cups_dest_t'>cups_dest_t</a> *dest;
246int num_options;
247<a href='#cups_option_t'>cups_option_t</a> *options;
248int job_id;
249int i;
250char buffer[1024];
251
252/* Create the job */
568fa3fa
MS
253job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
254 num_options, options);
5a738aea
MS
255
256/* If the job is created, add 10 files */
257if (job_id > 0)
258{
259 for (i = 1; i &lt;= 10; i ++)
260 {
261 snprintf(buffer, sizeof(buffer), "file%d.txt", i);
262
568fa3fa
MS
263 <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
264 CUPS_FORMAT_TEXT, i == 10);
5a738aea
MS
265
266 snprintf(buffer, sizeof(buffer),
267 "File %d\n"
268 "\n"
269 "One fish,\n"
270 "Two fish,\n
271 "Red fish,\n
272 "Blue fish\n", i);
273
274 /* cupsWriteRequestData can be called as many times as needed */
275 <a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
276
277 <a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
278 }
279}
280</pre>
281
282<p>Once you have created a job, you can monitor its status using the
283<a href='#cupsGetJobs'><code>cupsGetJobs</code></a> function, which returns
284an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures.
285Each contains the job ID (<code>id</code>), destination name
286(<code>dest</code>), title (<code>title</code>), and other information
287associated with the job. The job array is freed using the
288<a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following
289example monitors a specific job ID, showing the current job state once every
2905 seconds until the job is completed:</p>
291
292<pre class='example'>
293#include &lt;cups/cups.h&gt;
294
295<a href='#cups_dest_t'>cups_dest_t</a> *dest;
296int job_id;
297int num_jobs;
298<a href='#cups_job_t'>cups_job_t</a> *jobs;
299int i;
300ipp_jstate_t job_state = IPP_JOB_PENDING;
301
302while (job_state &lt; IPP_JOB_STOPPED)
303{
304 /* Get my jobs (1) with any state (-1) */
305 num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&amp;jobs, dest->name, 1, -1);
306
307 /* Loop to find my job */
308 job_state = IPP_JOB_COMPLETED;
309
310 for (i = 0; i &lt; num_jobs; i ++)
311 if (jobs[i].id == job_id)
312 {
313 job_state = jobs[i].state;
314 break;
315 }
316
317 /* Free the job array */
318 <a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
319
320 /* Show the current state */
321 switch (job_state)
322 {
323 case IPP_JOB_PENDING :
324 printf("Job %d is pending.\n", job_id);
325 break;
326 case IPP_JOB_HELD :
327 printf("Job %d is held.\n", job_id);
328 break;
329 case IPP_JOB_PROCESSING :
330 printf("Job %d is processing.\n", job_id);
331 break;
332 case IPP_JOB_STOPPED :
333 printf("Job %d is stopped.\n", job_id);
334 break;
335 case IPP_JOB_CANCELED :
336 printf("Job %d is canceled.\n", job_id);
337 break;
338 case IPP_JOB_ABORTED :
339 printf("Job %d is aborted.\n", job_id);
340 break;
341 case IPP_JOB_COMPLETED :
342 printf("Job %d is completed.\n", job_id);
343 break;
344 }
345
346 /* Sleep if the job is not finished */
347 if (job_state &lt; IPP_JOB_STOPPED)
348 sleep(5);
349}
350</pre>
351
352<p>To cancel a job, use the
353<a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
354job ID:</p>
355
568fa3fa 356<pre class='example'>
5a738aea
MS
357#include &lt;cups/cups.h&gt;
358
359<a href='#cups_dest_t'>cups_dest_t</a> *dest;
360int job_id;
361
362<a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
363</pre>
364
365<h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
366
367<p>If any of the CUPS API printing functions returns an error, the reason for
368that error can be found by calling the
369<a href='#cupsLastError'><code>cupsLastError</code></a> and
370<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> functions.
371<a href='#cupsLastError'><code>cupsLastError</code></a> returns the last IPP
372error code
373(<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>)
374that was encountered, while
375<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns
376a (localized) human-readable string that can be shown to the user. For example,
377if any of the job creation functions returns a job ID of 0, you can use
378<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> to show
379the reason why the job could not be created:</p>
380
381<pre class='example'>
382#include &lt;cups/cups.h&gt;
383
384int job_id;
385
386if (job_id == 0)
387 puts(cupsLastErrorString());
388</pre>
389
390<h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
391
392<p>CUPS supports authentication of any request, including submission of print
393jobs. The default mechanism for getting the username and password is to use the
394login user and a password from the console.</p>
395
396<p>To support other types of applications, in particular Graphical User
397Interfaces ("GUIs"), the CUPS API provides functions to set the default
398username and to register a callback function that returns a password string.</p>
399
400<p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a>
401function is used to set a password callback in your program. Only one
402function can be used at any time.</p>
403
404<p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the
405current username for authentication. This function can be called by your
406password callback function to change the current username as needed.</p>
407
408<p>The following example shows a simple password callback that gets a
409username and password from the user:</p>
410
411<pre class='example'>
412#include &lt;cups/cups.h&gt;
413
414const char *
415my_password_cb(const char *prompt)
416{
417 char user[65];
418
419
420 puts(prompt);
421
422 /* Get a username from the user */
423 printf("Username: ");
424 if (fgets(user, sizeof(user), stdin) == NULL)
425 return (NULL);
426
427 /* Strip the newline from the string and set the user */
428 user[strlen(user) - 1] = '\0';
429
430 <a href='#cupsSetUser'>cupsSetUser</a>(user);
431
432 /* Use getpass() to ask for the password... */
433 return (getpass("Password: "));
434}
435
436<a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
437</pre>
ef416fc2 438
5a738aea
MS
439<p>Similarly, a GUI could display the prompt string in a window with input
440fields for the username and password. The username should default to the
441string returned by the <a href="#cupsUser"><code>cupsUser</code></a>
442function.</p>