]>
Commit | Line | Data |
---|---|---|
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 |
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 | |
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 | |
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> | |
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 | |
128 | option has a name (<code>name</code>) and value (<code>value</code>) | |
129 | associated 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 | |
131 | default options for a particular destination, along with several informational | |
132 | attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>. | |
133 | The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets | |
134 | the value for the named option. For example, the following code lists the | |
135 | available destinations and their human-readable descriptions:</p> | |
136 | ||
137 | <pre class='example'> | |
138 | #include <cups/cups.h> | |
139 | ||
140 | <a href='#cups_dest_t'>cups_dest_t</a> *dests; | |
141 | int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&dests); | |
142 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
143 | int i; | |
144 | const char *value; | |
145 | ||
146 | for (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 | |
158 | adds a single named option to an array:</p> | |
159 | ||
160 | <pre class='example'> | |
161 | #include <cups/cups.h> | |
162 | ||
163 | int 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 */ | |
167 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options); | |
168 | ||
169 | /* This adds a second option value */ | |
170 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options); | |
171 | ||
172 | /* This replaces the first option we added */ | |
173 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &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 <cups/cups.h> | |
180 | ||
181 | int i; | |
182 | int 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 | 186 | for (i = 0; i < 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, &options); | |
5a738aea MS |
189 | </pre> |
190 | ||
191 | <p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a> | |
192 | function 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 | |
201 | 2<sup>31</sup>-1 and have options and one or more files for printing to a | |
202 | single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a> | |
203 | function creates a new job with one file. The following code prints the CUPS | |
204 | test page file:</p> | |
205 | ||
206 | <pre class='example'> | |
207 | #include <cups/cups.h> | |
208 | ||
209 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
210 | int num_options; | |
211 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
212 | int job_id; | |
213 | ||
214 | /* Print a single file */ | |
568fa3fa MS |
215 | job_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 | |
220 | creates a job with multiple files. The files are provided in a | |
221 | <code>char *</code> array:</p> | |
222 | ||
223 | <pre class='example'> | |
224 | #include <cups/cups.h> | |
225 | ||
226 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
227 | int num_options; | |
228 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
229 | int job_id; | |
230 | char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" }; | |
231 | ||
232 | /* Print three files */ | |
233 | job_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> | |
237 | function 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>, |
240 | and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions. | |
241 | The following example creates a job with 10 text files for printing:</p> | |
242 | ||
243 | <pre class='example'> | |
244 | #include <cups/cups.h> | |
245 | ||
246 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
247 | int num_options; | |
248 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
249 | int job_id; | |
250 | int i; | |
251 | char buffer[1024]; | |
252 | ||
253 | /* Create the job */ | |
568fa3fa MS |
254 | job_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 */ | |
258 | if (job_id > 0) | |
259 | { | |
260 | for (i = 1; i <= 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 | |
285 | an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures. | |
286 | Each contains the job ID (<code>id</code>), destination name | |
287 | (<code>dest</code>), title (<code>title</code>), and other information | |
288 | associated with the job. The job array is freed using the | |
289 | <a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following | |
290 | example monitors a specific job ID, showing the current job state once every | |
291 | 5 seconds until the job is completed:</p> | |
292 | ||
293 | <pre class='example'> | |
294 | #include <cups/cups.h> | |
295 | ||
296 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
297 | int job_id; | |
298 | int num_jobs; | |
299 | <a href='#cups_job_t'>cups_job_t</a> *jobs; | |
300 | int i; | |
301 | ipp_jstate_t job_state = IPP_JOB_PENDING; | |
7374e9e5 | 302 | |
5a738aea MS |
303 | while (job_state < IPP_JOB_STOPPED) |
304 | { | |
305 | /* Get my jobs (1) with any state (-1) */ | |
306 | num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1); | |
307 | ||
308 | /* Loop to find my job */ | |
309 | job_state = IPP_JOB_COMPLETED; | |
310 | ||
311 | for (i = 0; i < 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 < 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 | |
355 | job ID:</p> | |
356 | ||
568fa3fa | 357 | <pre class='example'> |
5a738aea MS |
358 | #include <cups/cups.h> |
359 | ||
360 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
361 | int 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 | |
369 | that 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 | |
373 | error code | |
374 | (<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>) | |
375 | that was encountered, while | |
376 | <a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns | |
377 | a (localized) human-readable string that can be shown to the user. For example, | |
378 | if 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 | |
380 | the reason why the job could not be created:</p> | |
381 | ||
382 | <pre class='example'> | |
383 | #include <cups/cups.h> | |
384 | ||
385 | int job_id; | |
386 | ||
387 | if (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 | |
394 | jobs. The default mechanism for getting the username and password is to use the | |
395 | login user and a password from the console.</p> | |
396 | ||
397 | <p>To support other types of applications, in particular Graphical User | |
398 | Interfaces ("GUIs"), the CUPS API provides functions to set the default | |
399 | username and to register a callback function that returns a password string.</p> | |
400 | ||
401 | <p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a> | |
402 | function is used to set a password callback in your program. Only one | |
403 | function can be used at any time.</p> | |
404 | ||
405 | <p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the | |
406 | current username for authentication. This function can be called by your | |
407 | password callback function to change the current username as needed.</p> | |
408 | ||
409 | <p>The following example shows a simple password callback that gets a | |
410 | username and password from the user:</p> | |
411 | ||
412 | <pre class='example'> | |
413 | #include <cups/cups.h> | |
414 | ||
415 | const char * | |
416 | my_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 |
441 | fields for the username and password. The username should default to the | |
442 | string returned by the <a href="#cupsUser"><code>cupsUser</code></a> | |
443 | function.</p> |