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