Home | History | Annotate | Download | only in cups
      1 <!--
      2   API introduction for CUPS.
      3 
      4   Copyright 2007-2013 by Apple Inc.
      5   Copyright 1997-2006 by Easy Software Products, all rights reserved.
      6 
      7   These coded instructions, statements, and computer programs are the
      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/".
     12 -->
     13 
     14 <h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
     15 
     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>
     19 
     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 
     31 <h3><a name='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
     32 
     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> -
     36 a way of selecting certain saved options/settings), and the options and
     37 attributes associated with that destination (<code>num_options</code> and
     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>
     43 
     44 <pre class='example'>
     45 #include &lt;cups/cups.h&gt;
     46 
     47 <a href='#cups_dest_t'>cups_dest_t</a> *dests;
     48 int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
     49 <a href='#cups_dest_t'>cups_dest_t</a> *dest = <a href='#cupsGetDest'>cupsGetDest</a>("name", NULL, num_dests, dests);
     50 
     51 /* do something with dest */
     52 
     53 <a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
     54 </pre>
     55 
     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>
     83 	<td>"true" if the destination is accepting new jobs, "false" if
     84 	not.</td>
     85 </tr>
     86 <tr>
     87 	<td>"printer-is-shared"</td>
     88 	<td>"true" if the destination is being shared with other computers,
     89 	"false" if not.</td>
     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 &lt;cups/cups.h&gt;
    137 
    138 <a href='#cups_dest_t'>cups_dest_t</a> *dests;
    139 int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;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 &lt;cups/cups.h&gt;
    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, &amp;options);
    166 
    167 /* This adds a second option value */
    168 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &amp;options);
    169 
    170 /* This replaces the first option we added */
    171 num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &amp;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 &lt;cups/cups.h&gt;
    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 
    184 for (i = 0; i &lt; dest->num_options; i ++)
    185   num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
    186                               num_options, &amp;options);
    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 &lt;cups/cups.h&gt;
    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 */
    213 job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
    214                         "Test Print", num_options, options);
    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 &lt;cups/cups.h&gt;
    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
    236 <a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
    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 &lt;cups/cups.h&gt;
    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 */
    252 job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
    253                        num_options, options);
    254 
    255 /* If the job is created, add 10 files */
    256 if (job_id > 0)
    257 {
    258   for (i = 1; i &lt;= 10; i ++)
    259   {
    260     snprintf(buffer, sizeof(buffer), "file%d.txt", i);
    261 
    262     <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
    263                       CUPS_FORMAT_TEXT, i == 10);
    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 &lt;cups/cups.h&gt;
    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;
    300 
    301 while (job_state &lt; IPP_JOB_STOPPED)
    302 {
    303   /* Get my jobs (1) with any state (-1) */
    304   num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&amp;jobs, dest->name, 1, -1);
    305 
    306   /* Loop to find my job */
    307   job_state = IPP_JOB_COMPLETED;
    308 
    309   for (i = 0; i &lt; 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 &lt; 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 
    355 <pre class='example'>
    356 #include &lt;cups/cups.h&gt;
    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 &lt;cups/cups.h&gt;
    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 &lt;cups/cups.h&gt;
    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>
    437 
    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>
    442