2 "$Id: api-cups.shtml 6649 2007-07-11 21:46:42Z mike $"
4 CUPS API introduction for the Common UNIX Printing System (CUPS).
6 Copyright 2007-2008 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='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
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>
36 #include <cups/cups.h>
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);
42 /* do something wiith dest */
44 <a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
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>
52 <div class='table'><table summary='Table 1: Printer Attributes' width='80%'>
53 <caption>Table 1: <a name='TABLE1'>Printer Attributes</a></caption>
56 <th>Attribute Name</th>
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>
68 <td>"printer-info"</td>
69 <td>The human-readable description of the destination such as "My
73 <td>"printer-is-accepting-jobs"</td>
74 <td>"1" if the destination is accepting new jobs, "0" if not.</td>
77 <td>"printer-is-shared"</td>
78 <td>"1" if the destination is being shared with other computers, "0" if
82 <td>"printer-location"</td>
83 <td>The human-readable location of the destination such as "Lab 4".</td>
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>
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>
96 <td>"printer-state-change-time"</td>
97 <td>The UNIX time when the destination entered the current state.</td>
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>
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>
112 <h3><a name='OPTIONS'>Options</a></h3>
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>
125 <pre class='example'>
126 #include <cups/cups.h>
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;
134 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
135 if (dest->instance == NULL)
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");
141 <a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
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>
148 <pre class='example'>
149 #include <cups/cups.h>
152 <a href='#cups_option_t'>cups_option_t</a> *options = NULL;
154 /* The returned num_options value is updated as needed */
155 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &options);
157 /* This adds a second option value */
158 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &options);
160 /* This replaces the first option we added */
161 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &options);
164 <p>Use a <code>for</code> loop to copy the options from a destination:</p>
166 <pre class='example'>
167 #include <cups/cups.h>
171 <a href='#cups_option_t'>cups_option_t</a> *options = NULL;
172 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
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);
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>
181 <pre class='example'>
182 <a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
185 <h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
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
193 <pre class='example'>
194 #include <cups/cups.h>
196 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
198 <a href='#cups_option_t'>cups_option_t</a> *options;
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);
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>
209 <pre class='example'>
210 #include <cups/cups.h>
212 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
214 <a href='#cups_option_t'>cups_option_t</a> *options;
216 char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
218 /* Print three files */
219 job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
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>
229 <pre class='example'>
230 #include <cups/cups.h>
232 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
234 <a href='#cups_option_t'>cups_option_t</a> *options;
240 job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files", num_options, options);
242 /* If the job is created, add 10 files */
245 for (i = 1; i <= 10; i ++)
247 snprintf(buffer, sizeof(buffer), "file%d.txt", i);
249 <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer, CUPS_FORMAT_TEXT, i == 10);
251 snprintf(buffer, sizeof(buffer),
259 /* cupsWriteRequestData can be called as many times as needed */
260 <a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
262 <a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
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>
277 <pre class='example'>
278 #include <cups/cups.h>
280 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
283 <a href='#cups_job_t'>cups_job_t</a> *jobs;
285 ipp_jstate_t job_state = IPP_JOB_PENDING;
287 while (job_state < IPP_JOB_STOPPED)
289 /* Get my jobs (1) with any state (-1) */
290 num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&jobs, dest->name, 1, -1);
292 /* Loop to find my job */
293 job_state = IPP_JOB_COMPLETED;
295 for (i = 0; i < num_jobs; i ++)
296 if (jobs[i].id == job_id)
298 job_state = jobs[i].state;
302 /* Free the job array */
303 <a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
305 /* Show the current state */
308 case IPP_JOB_PENDING :
309 printf("Job %d is pending.\n", job_id);
312 printf("Job %d is held.\n", job_id);
314 case IPP_JOB_PROCESSING :
315 printf("Job %d is processing.\n", job_id);
317 case IPP_JOB_STOPPED :
318 printf("Job %d is stopped.\n", job_id);
320 case IPP_JOB_CANCELED :
321 printf("Job %d is canceled.\n", job_id);
323 case IPP_JOB_ABORTED :
324 printf("Job %d is aborted.\n", job_id);
326 case IPP_JOB_COMPLETED :
327 printf("Job %d is completed.\n", job_id);
331 /* Sleep if the job is not finished */
332 if (job_state < IPP_JOB_STOPPED)
337 <p>To cancel a job, use the
338 <a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
341 <pre class='exmaple'>
342 #include <cups/cups.h>
344 <a href='#cups_dest_t'>cups_dest_t</a> *dest;
347 <a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
350 <h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
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
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>
366 <pre class='example'>
367 #include <cups/cups.h>
372 puts(cupsLastErrorString());
375 <h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
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>
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>
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>
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>
393 <p>The following example shows a simple password callback that gets a
394 username and password from the user:</p>
396 <pre class='example'>
397 #include <cups/cups.h>
400 my_password_cb(const char *prompt)
407 /* Get a username from the user */
408 printf("Username: ");
409 if (fgets(user, sizeof(user), stdin) == NULL)
412 /* Strip the newline from the string and set the user */
413 user[strlen(user) - 1] = '\0';
415 <a href='#cupsSetUser'>cupsSetUser</a>(user);
417 /* Use getpass() to ask for the password... */
418 return (getpass("Password: "));
421 <a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
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>