]>
Commit | Line | Data |
---|---|---|
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 |
19 | applications, filters, printer drivers, and backends that need to interface | |
20 | with 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 |
25 | the <a href="#cups_dest_t"><code>cups_dest_t</code></a> structure which | |
26 | includes the name (<code>name</code>), instance (<code>instance</code> - | |
27 | a way of selected certain saved options), and the options and attributes | |
28 | associated 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 | |
31 | using the <a href='#cupsFreeDests'><code>cupsFreeDests</code></a> function. | |
32 | The <a href='#cupsGetDest'><code>cupsGetDest</code></a> function finds a | |
33 | specific destination for printing:</p> | |
ef416fc2 | 34 | |
5a738aea MS |
35 | <pre class='example'> |
36 | #include <cups/cups.h> | |
ef416fc2 | 37 | |
5a738aea MS |
38 | <a href='#cups_dest_t'>cups_dest_t</a> *dests; |
39 | int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&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 | |
49 | will return the default destination. Similarly, passing a <code>NULL</code> | |
50 | instance 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 | |
116 | option has a name (<code>name</code>) and value (<code>value</code>) | |
117 | associated 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 | |
119 | default options for a particular destination, along with several informational | |
120 | attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>. | |
121 | The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets | |
122 | the value for the named option. For example, the following code lists the | |
123 | available destinations and their human-readable descriptions:</p> | |
124 | ||
125 | <pre class='example'> | |
126 | #include <cups/cups.h> | |
127 | ||
128 | <a href='#cups_dest_t'>cups_dest_t</a> *dests; | |
129 | int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&dests); | |
130 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
131 | int i; | |
132 | const char *value; | |
133 | ||
134 | for (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 | |
146 | adds a single named option to an array:</p> | |
147 | ||
148 | <pre class='example'> | |
149 | #include <cups/cups.h> | |
150 | ||
151 | int 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 */ | |
155 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options); | |
156 | ||
157 | /* This adds a second option value */ | |
158 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options); | |
159 | ||
160 | /* This replaces the first option we added */ | |
161 | num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &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 <cups/cups.h> | |
168 | ||
169 | int i; | |
170 | int 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 | ||
174 | for (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, &options); | |
176 | </pre> | |
177 | ||
178 | <p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a> | |
179 | function 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 | |
188 | 2<sup>31</sup>-1 and have options and one or more files for printing to a | |
189 | single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a> | |
190 | function creates a new job with one file. The following code prints the CUPS | |
191 | test page file:</p> | |
192 | ||
193 | <pre class='example'> | |
194 | #include <cups/cups.h> | |
195 | ||
196 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
197 | int num_options; | |
198 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
199 | int job_id; | |
200 | ||
201 | /* Print a single file */ | |
202 | job_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 | |
206 | creates a job with multiple files. The files are provided in a | |
207 | <code>char *</code> array:</p> | |
208 | ||
209 | <pre class='example'> | |
210 | #include <cups/cups.h> | |
211 | ||
212 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
213 | int num_options; | |
214 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
215 | int job_id; | |
216 | char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" }; | |
217 | ||
218 | /* Print three files */ | |
219 | job_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> | |
223 | function 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>, | |
226 | and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions. | |
227 | The following example creates a job with 10 text files for printing:</p> | |
228 | ||
229 | <pre class='example'> | |
230 | #include <cups/cups.h> | |
231 | ||
232 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
233 | int num_options; | |
234 | <a href='#cups_option_t'>cups_option_t</a> *options; | |
235 | int job_id; | |
236 | int i; | |
237 | char buffer[1024]; | |
238 | ||
239 | /* Create the job */ | |
240 | job_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 */ | |
243 | if (job_id > 0) | |
244 | { | |
245 | for (i = 1; i <= 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 | |
269 | an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures. | |
270 | Each contains the job ID (<code>id</code>), destination name | |
271 | (<code>dest</code>), title (<code>title</code>), and other information | |
272 | associated with the job. The job array is freed using the | |
273 | <a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following | |
274 | example monitors a specific job ID, showing the current job state once every | |
275 | 5 seconds until the job is completed:</p> | |
276 | ||
277 | <pre class='example'> | |
278 | #include <cups/cups.h> | |
279 | ||
280 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
281 | int job_id; | |
282 | int num_jobs; | |
283 | <a href='#cups_job_t'>cups_job_t</a> *jobs; | |
284 | int i; | |
285 | ipp_jstate_t job_state = IPP_JOB_PENDING; | |
286 | ||
287 | while (job_state < IPP_JOB_STOPPED) | |
288 | { | |
289 | /* Get my jobs (1) with any state (-1) */ | |
290 | num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1); | |
291 | ||
292 | /* Loop to find my job */ | |
293 | job_state = IPP_JOB_COMPLETED; | |
294 | ||
295 | for (i = 0; i < 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 < 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 | |
339 | job ID:</p> | |
340 | ||
341 | <pre class='exmaple'> | |
342 | #include <cups/cups.h> | |
343 | ||
344 | <a href='#cups_dest_t'>cups_dest_t</a> *dest; | |
345 | int 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 | |
353 | that 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 | |
357 | error code | |
358 | (<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>) | |
359 | that was encountered, while | |
360 | <a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns | |
361 | a (localized) human-readable string that can be shown to the user. For example, | |
362 | if 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 | |
364 | the reason why the job could not be created:</p> | |
365 | ||
366 | <pre class='example'> | |
367 | #include <cups/cups.h> | |
368 | ||
369 | int job_id; | |
370 | ||
371 | if (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 | |
378 | jobs. The default mechanism for getting the username and password is to use the | |
379 | login user and a password from the console.</p> | |
380 | ||
381 | <p>To support other types of applications, in particular Graphical User | |
382 | Interfaces ("GUIs"), the CUPS API provides functions to set the default | |
383 | username and to register a callback function that returns a password string.</p> | |
384 | ||
385 | <p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a> | |
386 | function is used to set a password callback in your program. Only one | |
387 | function can be used at any time.</p> | |
388 | ||
389 | <p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the | |
390 | current username for authentication. This function can be called by your | |
391 | password callback function to change the current username as needed.</p> | |
392 | ||
393 | <p>The following example shows a simple password callback that gets a | |
394 | username and password from the user:</p> | |
395 | ||
396 | <pre class='example'> | |
397 | #include <cups/cups.h> | |
398 | ||
399 | const char * | |
400 | my_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 |
425 | fields for the username and password. The username should default to the | |
426 | string returned by the <a href="#cupsUser"><code>cupsUser</code></a> | |
427 | function.</p> |