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