2 "$Id: api-cups.shtml 7337 2008-02-22 04:44:04Z mike $"
4 API introduction for CUPS.
6 Copyright 2007-2013 by Apple Inc.
7 Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 These coded instructions, statements, and computer programs are the
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/".
16 <h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
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>
22 <h3><a name='CLIENTS_AND_SERVERS'>Clients and Servers</a></h3>
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>
33 <h3><a name='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
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> -
38 a way of selecting certain saved options/settings), and the options and
39 attributes associated with that destination (<code>num_options</code> and
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>
47 #include <cups/cups.h>
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);
53 /* do something with dest */
55 <a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
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>
63 <div class='table'><table summary='Table 1: Printer Attributes' width='80%'>
64 <caption>Table 1: <a name='TABLE1'>Printer Attributes</a></caption>
67 <th>Attribute Name</th>
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>
79 <td>"printer-info"</td>
80 <td>The human-readable description of the destination such as "My
84 <td>"printer-is-accepting-jobs"</td>
85 <td>"true" if the destination is accepting new jobs, "false" if
89 <td>"printer-is-shared"</td>
90 <td>"true" if the destination is being shared with other computers,
94 <td>"printer-location"</td>
95 <td>The human-readable location of the destination such as "Lab 4".</td>
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>
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>
108 <td>"printer-state-change-time"</td>
109 <td>The UNIX time when the destination entered the current state.</td>
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>
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>
124 <h3><a name='OPTIONS'>Options</a></h3>
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>
137 <pre class='example'>
138 #include <cups/cups.h>
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;
146 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
147 if (dest->instance == NULL)
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");
153 <a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
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>
160 <pre class='example'>
161 #include <cups/cups.h>
164 <a href='#cups_option_t'>cups_option_t</a> *options = NULL;
166 /* The returned num_options value is updated as needed */
167 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options);
169 /* This adds a second option value */
170 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options);
172 /* This replaces the first option we added */
173 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &options);
176 <p>Use a <code>for</code> loop to copy the options from a destination:</p>
178 <pre class='example'>
179 #include <cups/cups.h>
183 <a href='#cups_option_t'>cups_option_t</a> *options = NULL;
184 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
186 for (i = 0; i < dest->num_options; i ++)
187 num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
188 num_options, &options);
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>
194 <pre class='example'>
195 <a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
198 <h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
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
206 <pre class='example'>
207 #include <cups/cups.h>
209 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
211 <a href='#cups_option_t'>cups_option_t</a> *options;
214 /* Print a single file */
215 job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
216 "Test Print", num_options, options);
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>
223 <pre class='example'>
224 #include <cups/cups.h>
226 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
228 <a href='#cups_option_t'>cups_option_t</a> *options;
230 char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
232 /* Print three files */
233 job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
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
238 <a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
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>
243 <pre class='example'>
244 #include <cups/cups.h>
246 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
248 <a href='#cups_option_t'>cups_option_t</a> *options;
254 job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
255 num_options, options);
257 /* If the job is created, add 10 files */
260 for (i = 1; i <= 10; i ++)
262 snprintf(buffer, sizeof(buffer), "file%d.txt", i);
264 <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
265 CUPS_FORMAT_TEXT, i == 10);
267 snprintf(buffer, sizeof(buffer),
275 /* cupsWriteRequestData can be called as many times as needed */
276 <a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
278 <a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
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>
293 <pre class='example'>
294 #include <cups/cups.h>
296 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
299 <a href='#cups_job_t'>cups_job_t</a> *jobs;
301 ipp_jstate_t job_state = IPP_JOB_PENDING;
303 while (job_state < IPP_JOB_STOPPED)
305 /* Get my jobs (1) with any state (-1) */
306 num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1);
308 /* Loop to find my job */
309 job_state = IPP_JOB_COMPLETED;
311 for (i = 0; i < num_jobs; i ++)
312 if (jobs[i].id == job_id)
314 job_state = jobs[i].state;
318 /* Free the job array */
319 <a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
321 /* Show the current state */
324 case IPP_JOB_PENDING :
325 printf("Job %d is pending.\n", job_id);
328 printf("Job %d is held.\n", job_id);
330 case IPP_JOB_PROCESSING :
331 printf("Job %d is processing.\n", job_id);
333 case IPP_JOB_STOPPED :
334 printf("Job %d is stopped.\n", job_id);
336 case IPP_JOB_CANCELED :
337 printf("Job %d is canceled.\n", job_id);
339 case IPP_JOB_ABORTED :
340 printf("Job %d is aborted.\n", job_id);
342 case IPP_JOB_COMPLETED :
343 printf("Job %d is completed.\n", job_id);
347 /* Sleep if the job is not finished */
348 if (job_state < IPP_JOB_STOPPED)
353 <p>To cancel a job, use the
354 <a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
357 <pre class='example'>
358 #include <cups/cups.h>
360 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
363 <a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
366 <h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
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
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>
382 <pre class='example'>
383 #include <cups/cups.h>
388 puts(cupsLastErrorString());
391 <h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
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>
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>
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>
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>
409 <p>The following example shows a simple password callback that gets a
410 username and password from the user:</p>
412 <pre class='example'>
413 #include <cups/cups.h>
416 my_password_cb(const char *prompt)
423 /* Get a username from the user */
424 printf("Username: ");
425 if (fgets(user, sizeof(user), stdin) == NULL)
428 /* Strip the newline from the string and set the user */
429 user[strlen(user) - 1] = '\0';
431 <a href='#cupsSetUser'>cupsSetUser</a>(user);
433 /* Use getpass() to ask for the password... */
434 return (getpass("Password: "));
437 <a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
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>