]>
Commit | Line | Data |
---|---|---|
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 |
19 | applications, filters, printer drivers, and backends that need to interface | |
20 | with 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 | |
25 | clients (applications) to communicate with a server (the scheduler) to get a | |
26 | list of printers, send print jobs, and so forth. You identify which server | |
27 | you 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 | |
30 | to the scheduler. The <a href='api-httpipp.html' target='_top'>HTTP and IPP | |
31 | APIs</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 |
36 | the <a href="#cups_dest_t"><code>cups_dest_t</code></a> structure which | |
37 | includes the name (<code>name</code>), instance (<code>instance</code> - | |
568fa3fa MS |
38 | a way of selecting certain saved options/settings), and the options and |
39 | attributes 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 | |
42 | using the <a href='#cupsFreeDests'><code>cupsFreeDests</code></a> function. | |
43 | The <a href='#cupsGetDest'><code>cupsGetDest</code></a> function finds a | |
44 | specific destination for printing:</p> | |
ef416fc2 | 45 | |
5a738aea MS |
46 | <pre class='example'> |
47 | #include <cups/cups.h> | |
ef416fc2 | 48 | |
5a738aea MS |
49 | <a href='#cups_dest_t'>cups_dest_t</a> *dests; |
50 | int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&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 | |
60 | will return the default destination. Similarly, passing a <code>NULL</code> | |
61 | instance 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 | |
127 | option has a name (<code>name</code>) and value (<code>value</code>) | |
128 | associated 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 | |
130 | default options for a particular destination, along with several informational | |
131 | attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>. | |
132 | The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets | |
133 | the value for the named option. For example, the following code lists the | |
134 | available destinations and their human-readable descriptions:</p> | |
135 | ||
136 | <pre class='example'> | |
137 | #include <cups/cups.h> | |
138 | ||
139 | <a href='#cups_dest_t'>cups_dest_t</a> *dests; | |
140 | int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&dests); | |
141 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
142 | int i; | |
143 | const char *value; | |
144 | ||
145 | for (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 | |
157 | adds a single named option to an array:</p> | |
158 | ||
159 | <pre class='example'> | |
160 | #include <cups/cups.h> | |
161 | ||
162 | int 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 */ | |
166 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options); | |
167 | ||
168 | /* This adds a second option value */ | |
169 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options); | |
170 | ||
171 | /* This replaces the first option we added */ | |
172 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &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 <cups/cups.h> | |
179 | ||
180 | int i; | |
181 | int 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 | ||
185 | for (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, &options); | |
5a738aea MS |
188 | </pre> |
189 | ||
190 | <p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a> | |
191 | function 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 | |
200 | 2<sup>31</sup>-1 and have options and one or more files for printing to a | |
201 | single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a> | |
202 | function creates a new job with one file. The following code prints the CUPS | |
203 | test page file:</p> | |
204 | ||
205 | <pre class='example'> | |
206 | #include <cups/cups.h> | |
207 | ||
208 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
209 | int num_options; | |
210 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
211 | int job_id; | |
212 | ||
213 | /* Print a single file */ | |
568fa3fa MS |
214 | job_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 | |
219 | creates a job with multiple files. The files are provided in a | |
220 | <code>char *</code> array:</p> | |
221 | ||
222 | <pre class='example'> | |
223 | #include <cups/cups.h> | |
224 | ||
225 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
226 | int num_options; | |
227 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
228 | int job_id; | |
229 | char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" }; | |
230 | ||
231 | /* Print three files */ | |
232 | job_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> | |
236 | function 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>, | |
239 | and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions. | |
240 | The following example creates a job with 10 text files for printing:</p> | |
241 | ||
242 | <pre class='example'> | |
243 | #include <cups/cups.h> | |
244 | ||
245 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
246 | int num_options; | |
247 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
248 | int job_id; | |
249 | int i; | |
250 | char buffer[1024]; | |
251 | ||
252 | /* Create the job */ | |
568fa3fa MS |
253 | job_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 */ | |
257 | if (job_id > 0) | |
258 | { | |
259 | for (i = 1; i <= 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 | |
284 | an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures. | |
285 | Each contains the job ID (<code>id</code>), destination name | |
286 | (<code>dest</code>), title (<code>title</code>), and other information | |
287 | associated with the job. The job array is freed using the | |
288 | <a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following | |
289 | example monitors a specific job ID, showing the current job state once every | |
290 | 5 seconds until the job is completed:</p> | |
291 | ||
292 | <pre class='example'> | |
293 | #include <cups/cups.h> | |
294 | ||
295 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
296 | int job_id; | |
297 | int num_jobs; | |
298 | <a href='#cups_job_t'>cups_job_t</a> *jobs; | |
299 | int i; | |
300 | ipp_jstate_t job_state = IPP_JOB_PENDING; | |
301 | ||
302 | while (job_state < IPP_JOB_STOPPED) | |
303 | { | |
304 | /* Get my jobs (1) with any state (-1) */ | |
305 | num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1); | |
306 | ||
307 | /* Loop to find my job */ | |
308 | job_state = IPP_JOB_COMPLETED; | |
309 | ||
310 | for (i = 0; i < 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 < 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 | |
354 | job ID:</p> | |
355 | ||
568fa3fa | 356 | <pre class='example'> |
5a738aea MS |
357 | #include <cups/cups.h> |
358 | ||
359 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
360 | int 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 | |
368 | that 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 | |
372 | error code | |
373 | (<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>) | |
374 | that was encountered, while | |
375 | <a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns | |
376 | a (localized) human-readable string that can be shown to the user. For example, | |
377 | if 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 | |
379 | the reason why the job could not be created:</p> | |
380 | ||
381 | <pre class='example'> | |
382 | #include <cups/cups.h> | |
383 | ||
384 | int job_id; | |
385 | ||
386 | if (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 | |
393 | jobs. The default mechanism for getting the username and password is to use the | |
394 | login user and a password from the console.</p> | |
395 | ||
396 | <p>To support other types of applications, in particular Graphical User | |
397 | Interfaces ("GUIs"), the CUPS API provides functions to set the default | |
398 | username and to register a callback function that returns a password string.</p> | |
399 | ||
400 | <p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a> | |
401 | function is used to set a password callback in your program. Only one | |
402 | function can be used at any time.</p> | |
403 | ||
404 | <p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the | |
405 | current username for authentication. This function can be called by your | |
406 | password callback function to change the current username as needed.</p> | |
407 | ||
408 | <p>The following example shows a simple password callback that gets a | |
409 | username and password from the user:</p> | |
410 | ||
411 | <pre class='example'> | |
412 | #include <cups/cups.h> | |
413 | ||
414 | const char * | |
415 | my_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 |
440 | fields for the username and password. The username should default to the | |
441 | string returned by the <a href="#cupsUser"><code>cupsUser</code></a> | |
442 | function.</p> |