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