]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/api-cups.shtml
Fix build errors on Fedora.
[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
eac3a0a0 4 API introduction for CUPS.
ef416fc2 5
7374e9e5 6 Copyright 2007-2013 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
eac3a0a0 53/* do something with dest */
5a738aea
MS
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>
71e16022
MS
85 <td>"true" if the destination is accepting new jobs, "false" if
86 not.</td>
5a738aea
MS
87</tr>
88<tr>
89 <td>"printer-is-shared"</td>
71e16022
MS
90 <td>"true" if the destination is being shared with other computers,
91 "false" if not.</td>
5a738aea
MS
92</tr>
93<tr>
94 <td>"printer-location"</td>
95 <td>The human-readable location of the destination such as "Lab 4".</td>
96</tr>
97<tr>
98 <td>"printer-make-and-model"</td>
99 <td>The human-readable make and model of the destination such as "HP
100 LaserJet 4000 Series".</td>
101</tr>
102<tr>
103 <td>"printer-state"</td>
104 <td>"3" if the destination is idle, "4" if the destination is printing
105 a job, and "5" if the destination is stopped.</td>
106</tr>
107<tr>
108 <td>"printer-state-change-time"</td>
109 <td>The UNIX time when the destination entered the current state.</td>
110</tr>
111<tr>
112 <td>"printer-state-reasons"</td>
113 <td>Additional comma-delimited state keywords for the destination
114 such as "media-tray-empty-error" and "toner-low-warning".</td>
115</tr>
116<tr>
117 <td>"printer-type"</td>
118 <td>The <a href='#cups_printer_t'><code>cups_printer_t</code></a>
119 value associated with the destination.</td>
120</tr>
121</tbody>
122</table></div>
123
124<h3><a name='OPTIONS'>Options</a></h3>
125
126<p>Options are stored in arrays of
127<a href='#cups_option_t'><code>cups_option_t</code></a> structures. Each
128option has a name (<code>name</code>) and value (<code>value</code>)
129associated with it. The <a href='#cups_dest_t'><code>cups_dest_t</code></a>
130<code>num_options</code> and <code>options</code> members contain the
131default options for a particular destination, along with several informational
132attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>.
133The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets
134the value for the named option. For example, the following code lists the
135available destinations and their human-readable descriptions:</p>
136
137<pre class='example'>
138#include &lt;cups/cups.h&gt;
139
140<a href='#cups_dest_t'>cups_dest_t</a> *dests;
141int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
142<a href='#cups_dest_t'>cups_dest_t</a> *dest;
143int i;
144const char *value;
145
146for (i = num_dests, dest = dests; i > 0; i --, dest ++)
147 if (dest->instance == NULL)
148 {
149 value = <a href='#cupsGetOption'>cupsGetOption</a>("printer-info", dest->num_options, dest->options);
150 printf("%s (%s)\n", dest->name, value ? value : "no description");
151 }
152
153<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
154</pre>
155
156<p>You can create your own option arrays using the
157<a href='#cupsAddOption'><code>cupsAddOption</code></a> function, which
158adds a single named option to an array:</p>
159
160<pre class='example'>
161#include &lt;cups/cups.h&gt;
162
163int num_options = 0;
164<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
165
166/* The returned num_options value is updated as needed */
167num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &amp;options);
168
169/* This adds a second option value */
170num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &amp;options);
171
172/* This replaces the first option we added */
173num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &amp;options);
174</pre>
175
176<p>Use a <code>for</code> loop to copy the options from a destination:</p>
177
178<pre class='example'>
179#include &lt;cups/cups.h&gt;
180
181int i;
182int num_options = 0;
183<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
184<a href='#cups_dest_t'>cups_dest_t</a> *dest;
185
7374e9e5 186for (i = 0; i &lt; dest->num_options; i ++)
568fa3fa
MS
187 num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
188 num_options, &amp;options);
5a738aea
MS
189</pre>
190
191<p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a>
192function to free the options array when you are done using it:</p>
193
194<pre class='example'>
195<a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
196</pre>
197
198<h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
199
200<p>Print jobs are identified by a locally-unique job ID number from 1 to
2012<sup>31</sup>-1 and have options and one or more files for printing to a
202single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a>
203function creates a new job with one file. The following code prints the CUPS
204test page file:</p>
205
206<pre class='example'>
207#include &lt;cups/cups.h&gt;
208
209<a href='#cups_dest_t'>cups_dest_t</a> *dest;
210int num_options;
211<a href='#cups_option_t'>cups_option_t</a> *options;
212int job_id;
213
214/* Print a single file */
568fa3fa
MS
215job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
216 "Test Print", num_options, options);
5a738aea
MS
217</pre>
218
219<p>The <a href='#cupsPrintFiles'><code>cupsPrintFiles</code></a> function
220creates a job with multiple files. The files are provided in a
221<code>char *</code> array:</p>
222
223<pre class='example'>
224#include &lt;cups/cups.h&gt;
225
226<a href='#cups_dest_t'>cups_dest_t</a> *dest;
227int num_options;
228<a href='#cups_option_t'>cups_option_t</a> *options;
229int job_id;
230char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
231
232/* Print three files */
233job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
234</pre>
235
236<p>Finally, the <a href='#cupsCreateJob'><code>cupsCreateJob</code></a>
237function creates a new job with no files in it. Files are added using the
7374e9e5 238<a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
5a738aea
MS
239<a href='api-httpipp.html#cupsWriteRequestData'><code>cupsWriteRequestData</code></a>,
240and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions.
241The following example creates a job with 10 text files for printing:</p>
242
243<pre class='example'>
244#include &lt;cups/cups.h&gt;
245
246<a href='#cups_dest_t'>cups_dest_t</a> *dest;
247int num_options;
248<a href='#cups_option_t'>cups_option_t</a> *options;
249int job_id;
250int i;
251char buffer[1024];
252
253/* Create the job */
568fa3fa
MS
254job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
255 num_options, options);
5a738aea
MS
256
257/* If the job is created, add 10 files */
258if (job_id > 0)
259{
260 for (i = 1; i &lt;= 10; i ++)
261 {
262 snprintf(buffer, sizeof(buffer), "file%d.txt", i);
263
568fa3fa
MS
264 <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
265 CUPS_FORMAT_TEXT, i == 10);
5a738aea
MS
266
267 snprintf(buffer, sizeof(buffer),
268 "File %d\n"
269 "\n"
270 "One fish,\n"
271 "Two fish,\n
272 "Red fish,\n
273 "Blue fish\n", i);
274
275 /* cupsWriteRequestData can be called as many times as needed */
276 <a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
277
278 <a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
279 }
280}
281</pre>
282
283<p>Once you have created a job, you can monitor its status using the
284<a href='#cupsGetJobs'><code>cupsGetJobs</code></a> function, which returns
285an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures.
286Each contains the job ID (<code>id</code>), destination name
287(<code>dest</code>), title (<code>title</code>), and other information
288associated with the job. The job array is freed using the
289<a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following
290example monitors a specific job ID, showing the current job state once every
2915 seconds until the job is completed:</p>
292
293<pre class='example'>
294#include &lt;cups/cups.h&gt;
295
296<a href='#cups_dest_t'>cups_dest_t</a> *dest;
297int job_id;
298int num_jobs;
299<a href='#cups_job_t'>cups_job_t</a> *jobs;
300int i;
301ipp_jstate_t job_state = IPP_JOB_PENDING;
7374e9e5 302
5a738aea
MS
303while (job_state &lt; IPP_JOB_STOPPED)
304{
305 /* Get my jobs (1) with any state (-1) */
306 num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&amp;jobs, dest->name, 1, -1);
307
308 /* Loop to find my job */
309 job_state = IPP_JOB_COMPLETED;
310
311 for (i = 0; i &lt; num_jobs; i ++)
312 if (jobs[i].id == job_id)
313 {
314 job_state = jobs[i].state;
315 break;
316 }
317
318 /* Free the job array */
319 <a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
320
321 /* Show the current state */
322 switch (job_state)
323 {
324 case IPP_JOB_PENDING :
325 printf("Job %d is pending.\n", job_id);
326 break;
327 case IPP_JOB_HELD :
328 printf("Job %d is held.\n", job_id);
329 break;
330 case IPP_JOB_PROCESSING :
331 printf("Job %d is processing.\n", job_id);
332 break;
333 case IPP_JOB_STOPPED :
334 printf("Job %d is stopped.\n", job_id);
335 break;
336 case IPP_JOB_CANCELED :
337 printf("Job %d is canceled.\n", job_id);
338 break;
339 case IPP_JOB_ABORTED :
340 printf("Job %d is aborted.\n", job_id);
341 break;
342 case IPP_JOB_COMPLETED :
343 printf("Job %d is completed.\n", job_id);
344 break;
345 }
346
347 /* Sleep if the job is not finished */
348 if (job_state &lt; IPP_JOB_STOPPED)
349 sleep(5);
350}
351</pre>
352
353<p>To cancel a job, use the
354<a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
355job ID:</p>
356
568fa3fa 357<pre class='example'>
5a738aea
MS
358#include &lt;cups/cups.h&gt;
359
360<a href='#cups_dest_t'>cups_dest_t</a> *dest;
361int job_id;
362
363<a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
364</pre>
365
366<h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
367
368<p>If any of the CUPS API printing functions returns an error, the reason for
369that error can be found by calling the
370<a href='#cupsLastError'><code>cupsLastError</code></a> and
371<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> functions.
372<a href='#cupsLastError'><code>cupsLastError</code></a> returns the last IPP
373error code
374(<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>)
375that was encountered, while
376<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns
377a (localized) human-readable string that can be shown to the user. For example,
378if any of the job creation functions returns a job ID of 0, you can use
379<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> to show
380the reason why the job could not be created:</p>
381
382<pre class='example'>
383#include &lt;cups/cups.h&gt;
384
385int job_id;
386
387if (job_id == 0)
388 puts(cupsLastErrorString());
389</pre>
390
391<h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
392
393<p>CUPS supports authentication of any request, including submission of print
394jobs. The default mechanism for getting the username and password is to use the
395login user and a password from the console.</p>
396
397<p>To support other types of applications, in particular Graphical User
398Interfaces ("GUIs"), the CUPS API provides functions to set the default
399username and to register a callback function that returns a password string.</p>
400
401<p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a>
402function is used to set a password callback in your program. Only one
403function can be used at any time.</p>
404
405<p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the
406current username for authentication. This function can be called by your
407password callback function to change the current username as needed.</p>
408
409<p>The following example shows a simple password callback that gets a
410username and password from the user:</p>
411
412<pre class='example'>
413#include &lt;cups/cups.h&gt;
414
415const char *
416my_password_cb(const char *prompt)
417{
418 char user[65];
419
420
421 puts(prompt);
422
423 /* Get a username from the user */
424 printf("Username: ");
425 if (fgets(user, sizeof(user), stdin) == NULL)
426 return (NULL);
427
428 /* Strip the newline from the string and set the user */
429 user[strlen(user) - 1] = '\0';
430
431 <a href='#cupsSetUser'>cupsSetUser</a>(user);
432
433 /* Use getpass() to ask for the password... */
434 return (getpass("Password: "));
435}
436
437<a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
438</pre>
ef416fc2 439
5a738aea
MS
440<p>Similarly, a GUI could display the prompt string in a window with input
441fields for the username and password. The username should default to the
442string returned by the <a href="#cupsUser"><code>cupsUser</code></a>
443function.</p>