Home | History | Annotate | Download | only in cups
      1 ---
      2 title: CUPS Programming Manual
      3 author: Michael R Sweet
      4 copyright: Copyright  2007-2017 by Apple Inc. All Rights Reserved.
      5 version: 2.2.5
      6 ...
      7 
      8 > Please [file issues on Github](https://github.com/apple/cups/issues) to
      9 > provide feedback on this document.
     10 
     11 
     12 # Introduction
     13 
     14 CUPS provides the "cups" library to talk to the different parts of CUPS and with
     15 Internet Printing Protocol (IPP) printers. The "cups" library functions are
     16 accessed by including the `<cups/cups.h>` header.
     17 
     18 CUPS is based on the Internet Printing Protocol ("IPP"), which allows clients
     19 (applications) to communicate with a server (the scheduler, printers, etc.) to
     20 get a list of destinations, send print jobs, and so forth.  You identify which
     21 server you want to communicate with using a pointer to the opaque structure
     22 `http_t`.  The `CUPS_HTTP_DEFAULT` constant can be used when you want to talk to
     23 the CUPS scheduler.
     24 
     25 
     26 ## Guidelines
     27 
     28 When writing software that uses the "cups" library:
     29 
     30 - Do not use undocumented or deprecated APIs,
     31 - Do not rely on pre-configured printers,
     32 - Do not assume that printers support specific features or formats, and
     33 - Do not rely on implementation details (PPDs, etc.)
     34 
     35 CUPS is designed to insulate users and developers from the implementation
     36 details of printers and file formats.  The goal is to allow an application to
     37 supply a print file in a standard format with the user intent ("print four
     38 copies, two-sided on A4 media, and staple each copy") and have the printing
     39 system manage the printer communication and format conversion needed.
     40 
     41 Similarly, printer and job management applications can use standard query
     42 operations to obtain the status information in a common, generic form and use
     43 standard management operations to control the state of those printers and jobs.
     44 
     45 
     46 ## Terms Used in This Document
     47 
     48 A *Destination* is a printer or print queue that accepts print jobs.  A
     49 *Print Job* is one or more documents that are processed by a destination
     50 using options supplied when creating the job.  A *Document* is a file (JPEG
     51 image, PDF file, etc.) suitable for printing.  An *Option* controls some aspect
     52 of printing, such as the media used. *Media* is the sheets or roll that is
     53 printed on.  An *Attribute* is an option encoded for an Internet Printing
     54 Protocol (IPP) request.
     55 
     56 
     57 ## Compiling Programs That Use the CUPS API
     58 
     59 The CUPS libraries can be used from any C, C++, or Objective C program.
     60 The method of compiling against the libraries varies depending on the
     61 operating system and installation of CUPS. The following sections show how
     62 to compile a simple program (shown below) in two common environments.
     63 
     64 The following simple program lists the available destinations:
     65 
     66     #include <stdio.h>
     67     #include <cups/cups.h>
     68 
     69     int print_dest(void *user_data, unsigned flags, cups_dest_t *dest)
     70     {
     71       if (dest->instance)
     72         printf("%s/%s\n", dest->name, dest->instance);
     73       else
     74         puts(dest->name);
     75 
     76       return (1);
     77     }
     78 
     79     int main(void)
     80     {
     81       cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, 0, 0, print_dest, NULL);
     82 
     83       return (0);
     84     }
     85 
     86 
     87 ### Compiling with Xcode
     88 
     89 In Xcode, choose *New Project...* from the *File* menu (or press SHIFT+CMD+N),
     90 then select the *Command Line Tool* under the macOS Application project type.
     91 Click *Next* and enter a name for the project, for example "firstcups".  Click
     92 *Next* and choose a project directory. The click *Next* to create the project.
     93 
     94 In the project window, click on the *Build Phases* group and expand the
     95 *Link Binary with Libraries* section. Click *+*, type "libcups" to show the
     96 library, and then double-click on `libcups.tbd`.
     97 
     98 Finally, click on the `main.c` file in the sidebar and copy the example program
     99 to the file.  Build and run (CMD+R) to see the list of destinations.
    100 
    101 
    102 ### Compiling with GCC
    103 
    104 From the command-line, create a file called `sample.c` using your favorite
    105 editor, copy the example to this file, and save.  Then run the following command
    106 to compile it with GCC and run it:
    107 
    108     gcc -o simple `cups-config --cflags` simple.c `cups-config --libs`
    109     ./simple
    110 
    111 The `cups-config` command provides the compiler flags (`cups-config --cflags`)
    112 and libraries (`cups-config --libs`) needed for the local system.
    113 
    114 
    115 # Working with Destinations
    116 
    117 Destinations, which in CUPS represent individual printers or classes
    118 (collections or pools) of printers, are represented by the `cups_dest_t`
    119 structure which includes the name \(`name`), instance \(`instance`, saved
    120 options/settings), whether the destination is the default for the user
    121 \(`is_default`), and the options and basic information associated with that
    122 destination \(`num_options` and `options`).
    123 
    124 Historically destinations have been manually maintained by the administrator of
    125 a system or network, but CUPS also supports dynamic discovery of destinations on
    126 the current network.
    127 
    128 
    129 ## Finding Available Destinations
    130 
    131 The `cupsEnumDests` function finds all of the available destinations:
    132 
    133      int
    134      cupsEnumDests(unsigned flags, int msec, int *cancel,
    135                    cups_ptype_t type, cups_ptype_t mask,
    136                    cups_dest_cb_t cb, void *user_data)
    137 
    138 The `flags` argument specifies enumeration options, which at present must be
    139 `CUPS_DEST_FLAGS_NONE`.
    140 
    141 The `msec` argument specifies the maximum amount of time that should be used for
    142 enumeration in milliseconds - interactive applications should keep this value to
    143 5000 or less when run on the main thread.
    144 
    145 The `cancel` argument points to an integer variable that, when set to a non-zero
    146 value, will cause enumeration to stop as soon as possible.  It can be `NULL` if
    147 not needed.
    148 
    149 The `type` and `mask` arguments are bitfields that allow the caller to filter
    150 the destinations based on categories and/or capabilities.  The destination's
    151 "printer-type" value is masked by the `mask` value and compared to the `type`
    152 value when filtering.  For example, to only enumerate destinations that are
    153 hosted on the local system, pass `CUPS_PRINTER_LOCAL` for the `type` argument
    154 and `CUPS_PRINTER_DISCOVERED` for the `mask` argument.  The following constants
    155 can be used for filtering:
    156 
    157 - `CUPS_PRINTER_CLASS`: A collection of destinations.
    158 - `CUPS_PRINTER_FAX`: A facsimile device.
    159 - `CUPS_PRINTER_LOCAL`: A local printer or class.  This constant has the value 0
    160   (no bits set) and is only used for the `type` argument and is paired with the
    161   `CUPS_PRINTER_REMOTE` or `CUPS_PRINTER_DISCOVERED` constant passed in the
    162   `mask` argument.
    163 - `CUPS_PRINTER_REMOTE`: A remote (shared) printer or class.
    164 - `CUPS_PRINTER_DISCOVERED`: An available network printer or class.
    165 - `CUPS_PRINTER_BW`: Can do B&W printing.
    166 - `CUPS_PRINTER_COLOR`: Can do color printing.
    167 - `CUPS_PRINTER_DUPLEX`: Can do two-sided printing.
    168 - `CUPS_PRINTER_STAPLE`: Can staple output.
    169 - `CUPS_PRINTER_COLLATE`: Can quickly collate copies.
    170 - `CUPS_PRINTER_PUNCH`: Can punch output.
    171 - `CUPS_PRINTER_COVER`: Can cover output.
    172 - `CUPS_PRINTER_BIND`: Can bind output.
    173 - `CUPS_PRINTER_SORT`: Can sort output (mailboxes, etc.)
    174 - `CUPS_PRINTER_SMALL`: Can print on Letter/Legal/A4-size media.
    175 - `CUPS_PRINTER_MEDIUM`: Can print on Tabloid/B/C/A3/A2-size media.
    176 - `CUPS_PRINTER_LARGE`: Can print on D/E/A1/A0-size media.
    177 - `CUPS_PRINTER_VARIABLE`: Can print on rolls and custom-size media.
    178 
    179 The `cb` argument specifies a function to call for every destination that is
    180 found:
    181 
    182     typedef int (*cups_dest_cb_t)(void *user_data,
    183                                   unsigned flags,
    184                                   cups_dest_t *dest);
    185 
    186 The callback function receives a copy of the `user_data` argument along with a
    187 bitfield \(`flags`) and the destination that was found.  The `flags` argument
    188 can have any of the following constant (bit) values set:
    189 
    190 - `CUPS_DEST_FLAGS_MORE`: There are more destinations coming.
    191 - `CUPS_DEST_FLAGS_REMOVED`: The destination has gone away and should be removed
    192   from the list of destinations a user can select.
    193 - `CUPS_DEST_FLAGS_ERROR`: An error occurred.  The reason for the error can be
    194   found by calling the `cupsLastError` and/or `cupsLastErrorString` functions.
    195 
    196 The callback function returns 0 to stop enumeration or 1 to continue.
    197 
    198 > Note that the callback function will likely be called multiple times for the
    199 > same destination, so it is up to the caller to suppress any duplicate
    200 > destinations.
    201 
    202 The following example shows how to use `cupsEnumDests` to get a filtered array
    203 of destinations:
    204 
    205     typedef struct
    206     {
    207       int num_dests;
    208       cups_dest_t *dests;
    209     } my_user_data_t;
    210 
    211     int
    212     my_dest_cb(my_user_data_t *user_data, unsigned flags,
    213                cups_dest_t *dest)
    214     {
    215       if (flags & CUPS_DEST_FLAGS_REMOVED)
    216       {
    217        /*
    218         * Remove destination from array...
    219         */
    220 
    221         user_data->num_dests =
    222             cupsRemoveDest(dest->name, dest->instance,
    223                            user_data->num_dests,
    224                            &(user_data->dests));
    225       }
    226       else
    227       {
    228        /*
    229         * Add destination to array...
    230         */
    231 
    232         user_data->num_dests =
    233             cupsCopyDest(dest, user_data->num_dests,
    234                          &(user_data->dests));
    235       }
    236 
    237       return (1);
    238     }
    239 
    240     int
    241     my_get_dests(cups_ptype_t type, cups_ptype_t mask,
    242                  cups_dest_t **dests)
    243     {
    244       my_user_data_t user_data = { 0, NULL };
    245 
    246       if (!cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, type,
    247                          mask, (cups_dest_cb_t)my_dest_cb,
    248                          &user_data))
    249       {
    250        /*
    251         * An error occurred, free all of the destinations and
    252         * return...
    253         */
    254 
    255         cupsFreeDests(user_data.num_dests, user_dasta.dests);
    256 
    257         *dests = NULL;
    258 
    259         return (0);
    260       }
    261 
    262      /*
    263       * Return the destination array...
    264       */
    265 
    266       *dests = user_data.dests;
    267 
    268       return (user_data.num_dests);
    269     }
    270 
    271 
    272 ## Basic Destination Information
    273 
    274 The `num_options` and `options` members of the `cups_dest_t` structure provide
    275 basic attributes about the destination in addition to the user default options
    276 and values for that destination.  The following names are predefined for various
    277 destination attributes:
    278 
    279 - "auth-info-required": The type of authentication required for printing to this
    280   destination: "none", "username,password", "domain,username,password", or
    281   "negotiate" (Kerberos).
    282 - "printer-info": The human-readable description of the destination such as "My
    283   Laser Printer".
    284 - "printer-is-accepting-jobs": "true" if the destination is accepting new jobs,
    285   "false" otherwise.
    286 - "printer-is-shared": "true" if the destination is being shared with other
    287   computers, "false" otherwise.
    288 - "printer-location": The human-readable location of the destination such as
    289   "Lab 4".
    290 - "printer-make-and-model": The human-readable make and model of the destination
    291   such as "ExampleCorp LaserPrinter 4000 Series".
    292 - "printer-state": "3" if the destination is idle, "4" if the destination is
    293   printing a job, and "5" if the destination is stopped.
    294 - "printer-state-change-time": The UNIX time when the destination entered the
    295   current state.
    296 - "printer-state-reasons": Additional comma-delimited state keywords for the
    297   destination such as "media-tray-empty-error" and "toner-low-warning".
    298 - "printer-type": The `cups_ptype_t` value associated with the destination.
    299 - "printer-uri-supported": The URI associated with the destination; if not set,
    300   this destination was discovered but is not yet setup as a local printer.
    301 
    302 Use the `cupsGetOption` function to retrieve the value.  For example, the
    303 following code gets the make and model of a destination:
    304 
    305     const char *model = cupsGetOption("printer-make-and-model",
    306                                       dest->num_options,
    307                                       dest->options);
    308 
    309 
    310 ## Detailed Destination Information
    311 
    312 Once a destination has been chosen, the `cupsCopyDestInfo` function can be used
    313 to gather detailed information about the destination:
    314 
    315     cups_dinfo_t *
    316     cupsCopyDestInfo(http_t *http, cups_dest_t *dest);
    317 
    318 The `http` argument specifies a connection to the CUPS scheduler and is
    319 typically the constant `CUPS_HTTP_DEFAULT`.  The `dest` argument specifies the
    320 destination to query.
    321 
    322 The `cups_dinfo_t` structure that is returned contains a snapshot of the
    323 supported options and their supported, ready, and default values.  It also can
    324 report constraints between different options and values, and recommend changes
    325 to resolve those constraints.
    326 
    327 
    328 ### Getting Supported Options and Values
    329 
    330 The `cupsCheckDestSupported` function can be used to test whether a particular
    331 option or option and value is supported:
    332 
    333     int
    334     cupsCheckDestSupported(http_t *http, cups_dest_t *dest,
    335                            cups_dinfo_t *info,
    336                            const char *option,
    337                            const char *value);
    338 
    339 The `option` argument specifies the name of the option to check.  The following
    340 constants can be used to check the various standard options:
    341 
    342 - `CUPS_COPIES`: Controls the number of copies that are produced.
    343 - `CUPS_FINISHINGS`: A comma-delimited list of integer constants that control
    344   the finishing processes that are applied to the job, including stapling,
    345   punching, and folding.
    346 - `CUPS_MEDIA`: Controls the media size that is used, typically one of the
    347   following: `CUPS_MEDIA_3X5`, `CUPS_MEDIA_4X6`, `CUPS_MEDIA_5X7`,
    348   `CUPS_MEDIA_8X10`, `CUPS_MEDIA_A3`, `CUPS_MEDIA_A4`, `CUPS_MEDIA_A5`,
    349   `CUPS_MEDIA_A6`, `CUPS_MEDIA_ENV10`, `CUPS_MEDIA_ENVDL`, `CUPS_MEDIA_LEGAL`,
    350   `CUPS_MEDIA_LETTER`, `CUPS_MEDIA_PHOTO_L`, `CUPS_MEDIA_SUPERBA3`, or
    351   `CUPS_MEDIA_TABLOID`.
    352 - `CUPS_MEDIA_SOURCE`: Controls where the media is pulled from, typically either
    353   `CUPS_MEDIA_SOURCE_AUTO` or `CUPS_MEDIA_SOURCE_MANUAL`.
    354 - `CUPS_MEDIA_TYPE`: Controls the type of media that is used, typically one of
    355   the following: `CUPS_MEDIA_TYPE_AUTO`, `CUPS_MEDIA_TYPE_ENVELOPE`,
    356   `CUPS_MEDIA_TYPE_LABELS`, `CUPS_MEDIA_TYPE_LETTERHEAD`,
    357   `CUPS_MEDIA_TYPE_PHOTO`, `CUPS_MEDIA_TYPE_PHOTO_GLOSSY`,
    358   `CUPS_MEDIA_TYPE_PHOTO_MATTE`, `CUPS_MEDIA_TYPE_PLAIN`, or
    359   `CUPS_MEDIA_TYPE_TRANSPARENCY`.
    360 - `CUPS_NUMBER_UP`: Controls the number of document pages that are placed on
    361   each media side.
    362 - `CUPS_ORIENTATION`: Controls the orientation of document pages placed on the
    363   media: `CUPS_ORIENTATION_PORTRAIT` or `CUPS_ORIENTATION_LANDSCAPE`.
    364 - `CUPS_PRINT_COLOR_MODE`: Controls whether the output is in color
    365   \(`CUPS_PRINT_COLOR_MODE_COLOR`), grayscale
    366   \(`CUPS_PRINT_COLOR_MODE_MONOCHROME`), or either
    367   \(`CUPS_PRINT_COLOR_MODE_AUTO`).
    368 - `CUPS_PRINT_QUALITY`: Controls the generate quality of the output:
    369   `CUPS_PRINT_QUALITY_DRAFT`, `CUPS_PRINT_QUALITY_NORMAL`, or
    370   `CUPS_PRINT_QUALITY_HIGH`.
    371 - `CUPS_SIDES`: Controls whether prints are placed on one or both sides of the
    372   media: `CUPS_SIDES_ONE_SIDED`, `CUPS_SIDES_TWO_SIDED_PORTRAIT`, or
    373   `CUPS_SIDES_TWO_SIDED_LANDSCAPE`.
    374 
    375 If the `value` argument is `NULL`, the `cupsCheckDestSupported` function returns
    376 whether the option is supported by the destination.  Otherwise, the function
    377 returns whether the specified value of the option is supported.
    378 
    379 The `cupsFindDestSupported` function returns the IPP attribute containing the
    380 supported values for a given option:
    381 
    382      ipp_attribute_t *
    383      cupsFindDestSupported(http_t *http, cups_dest_t *dest,
    384                            cups_dinfo_t *dinfo,
    385                            const char *option);
    386 
    387 For example, the following code prints the supported finishing processes for a
    388 destination, if any, to the standard output:
    389 
    390     cups_dinfo_t *info = cupsCopyDestInfo(CUPS_HTTP_DEFAULT,
    391                                           dest);
    392 
    393     if (cupsCheckDestSupported(CUPS_HTTP_DEFAULT, dest, info,
    394                                CUPS_FINISHINGS, NULL))
    395     {
    396       ipp_attribute_t *finishings =
    397           cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
    398                                 CUPS_FINISHINGS);
    399       int i, count = ippGetCount(finishings);
    400 
    401       puts("finishings supported:");
    402       for (i = 0; i < count; i ++)
    403         printf("  %d\n", ippGetInteger(finishings, i));
    404     }
    405     else
    406       puts("finishings not supported.");
    407 
    408 The "job-creation-attributes" option can be queried to get a list of supported
    409 options.  For example, the following code prints the list of supported options
    410 to the standard output:
    411 
    412     ipp_attribute_t *attrs =
    413         cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
    414                               "job-creation-attributes");
    415     int i, count = ippGetCount(attrs);
    416 
    417     for (i = 0; i < count; i ++)
    418       puts(ippGetString(attrs, i, NULL));
    419 
    420 
    421 ### Getting Default Values
    422 
    423 There are two sets of default values - user defaults that are available via the
    424 `num_options` and `options` members of the `cups_dest_t` structure, and
    425 destination defaults that available via the `cups_dinfo_t` structure and the
    426 `cupsFindDestDefault` function which returns the IPP attribute containing the
    427 default value(s) for a given option:
    428 
    429     ipp_attribute_t *
    430     cupsFindDestDefault(http_t *http, cups_dest_t *dest,
    431                         cups_dinfo_t *dinfo,
    432                         const char *option);
    433 
    434 The user defaults from `cupsGetOption` should always take preference over the
    435 destination defaults.  For example, the following code prints the default
    436 finishings value(s) to the standard output:
    437 
    438     const char *def_value =
    439         cupsGetOption(CUPS_FINISHINGS, dest->num_options,
    440                       dest->options);
    441     ipp_attribute_t *def_attr =
    442         cupsFindDestDefault(CUPS_HTTP_DEFAULT, dest, info,
    443                             CUPS_FINISHINGS);
    444 
    445     if (def_value != NULL)
    446     {
    447       printf("Default finishings: %s\n", def_value);
    448     }
    449     else
    450     {
    451       int i, count = ippGetCount(def_attr);
    452 
    453       printf("Default finishings: %d",
    454              ippGetInteger(def_attr, 0));
    455       for (i = 1; i < count; i ++)
    456         printf(",%d", ippGetInteger(def_attr, i));
    457       putchar('\n');
    458     }
    459 
    460 
    461 ### Getting Ready (Loaded) Values
    462 
    463 The finishings and media options also support queries for the ready, or loaded,
    464 values.  For example, a printer may have punch and staple finishers installed
    465 but be out of staples - the supported values will list both punch and staple
    466 finishing processes but the ready values will only list the punch processes.
    467 Similarly, a printer may support hundreds of different sizes of media but only
    468 have a single size loaded at any given time - the ready values are limited to
    469 the media that is actually in the printer.
    470 
    471 The `cupsFindDestReady` function finds the IPP attribute containing the ready
    472 values for a given option:
    473 
    474     ipp_attribute_t *
    475     cupsFindDestReady(http_t *http, cups_dest_t *dest,
    476                       cups_dinfo_t *dinfo, const char *option);
    477 
    478 For example, the following code lists the ready finishing processes:
    479 
    480     ipp_attribute_t *ready_finishings =
    481         cupsFindDestReady(CUPS_HTTP_DEFAULT, dest, info,
    482                           CUPS_FINISHINGS);
    483 
    484     if (ready_finishings != NULL)
    485     {
    486       int i, count = ippGetCount(ready_finishings);
    487 
    488       puts("finishings ready:");
    489       for (i = 0; i < count; i ++)
    490         printf("  %d\n", ippGetInteger(ready_finishings, i));
    491     }
    492     else
    493       puts("no finishings are ready.");
    494 
    495 
    496 ### Media Size Options
    497 
    498 CUPS provides functions for querying the dimensions and margins for each of the
    499 supported media size options.  The `cups_size_t` structure is used to describe a
    500 media size:
    501 
    502     typedef struct cups_size_s
    503     {
    504       char media[128];
    505       int width, length;
    506       int bottom, left, right, top;
    507     } cups_size_t;
    508 
    509 The `width` and `length` members specify the dimensions of the media in
    510 hundredths of millimeters (1/2540th of an inch).  The `bottom`, `left`, `right`,
    511 and `top` members specify the margins of the printable area, also in hundredths
    512 of millimeters.
    513 
    514 The `cupsGetDestMediaByName` and `cupsGetDestMediaBySize` functions lookup the
    515 media size information using a standard media size name or dimensions in
    516 hundredths of millimeters:
    517 
    518     int
    519     cupsGetDestMediaByName(http_t *http, cups_dest_t *dest,
    520                            cups_dinfo_t *dinfo,
    521                            const char *media,
    522                            unsigned flags, cups_size_t *size);
    523 
    524     int
    525     cupsGetDestMediaBySize(http_t *http, cups_dest_t *dest,
    526                            cups_dinfo_t *dinfo,
    527                            int width, int length,
    528                            unsigned flags, cups_size_t *size);
    529 
    530 The `media`, `width`, and `length` arguments specify the size to lookup.  The
    531 `flags` argument specifies a bitfield controlling various lookup options:
    532 
    533 - `CUPS_MEDIA_FLAGS_DEFAULT`: Find the closest size supported by the printer.
    534 - `CUPS_MEDIA_FLAGS_BORDERLESS`: Find a borderless size.
    535 - `CUPS_MEDIA_FLAGS_DUPLEX`: Find a size compatible with two-sided printing.
    536 - `CUPS_MEDIA_FLAGS_EXACT`: Find an exact match for the size.
    537 - `CUPS_MEDIA_FLAGS_READY`: If the printer supports media sensing or
    538   configuration of the media in each tray/source, find the size amongst the
    539   "ready" media.
    540 
    541 If a matching size is found for the destination, the size information is stored
    542 in the structure pointed to by the `size` argument and 1 is returned.  Otherwise
    543 0 is returned.
    544 
    545 For example, the following code prints the margins for two-sided printing on US
    546 Letter media:
    547 
    548     cups_size_t size;
    549 
    550     if (cupsGetDestMediaByName(CUPS_HTTP_DEFAULT, dest, info,
    551                                CUPS_MEDIA_LETTER,
    552                                CUPS_MEDIA_FLAGS_DUPLEX, &size))
    553     {
    554       puts("Margins for duplex US Letter:");
    555       printf("  Bottom: %.2fin\n", size.bottom / 2540.0);
    556       printf("    Left: %.2fin\n", size.left / 2540.0);
    557       printf("   Right: %.2fin\n", size.right / 2540.0);
    558       printf("     Top: %.2fin\n", size.top / 2540.0);
    559     }
    560     else
    561       puts("Margins for duplex US Letter are not available.");
    562 
    563 You can also enumerate all of the sizes that match a given `flags` value using
    564 the `cupsGetDestMediaByIndex` and `cupsGetDestMediaCount` functions:
    565 
    566     int
    567     cupsGetDestMediaByIndex(http_t *http, cups_dest_t *dest,
    568                             cups_dinfo_t *dinfo, int n,
    569                             unsigned flags, cups_size_t *size);
    570 
    571     int
    572     cupsGetDestMediaCount(http_t *http, cups_dest_t *dest,
    573                           cups_dinfo_t *dinfo, unsigned flags);
    574 
    575 For example, the following code prints the list of ready media and corresponding
    576 margins:
    577 
    578     cups_size_t size;
    579     int i;
    580     int count = cupsGetDestMediaCount(CUPS_HTTP_DEFAULT,
    581                                       dest, info,
    582                                       CUPS_MEDIA_FLAGS_READY);
    583 
    584     for (i = 0; i < count; i ++)
    585     {
    586       if (cupsGetDestMediaByIndex(CUPS_HTTP_DEFAULT, dest, info,
    587                                   i, CUPS_MEDIA_FLAGS_READY,
    588                                   &size))
    589       {
    590         printf("%s:\n", size.name);
    591         printf("   Width: %.2fin\n", size.width / 2540.0);
    592         printf("  Length: %.2fin\n", size.length / 2540.0);
    593         printf("  Bottom: %.2fin\n", size.bottom / 2540.0);
    594         printf("    Left: %.2fin\n", size.left / 2540.0);
    595         printf("   Right: %.2fin\n", size.right / 2540.0);
    596         printf("     Top: %.2fin\n", size.top / 2540.0);
    597       }
    598     }
    599 
    600 Finally, the `cupsGetDestMediaDefault` function returns the default media size:
    601 
    602     int
    603     cupsGetDestMediaDefault(http_t *http, cups_dest_t *dest,
    604                             cups_dinfo_t *dinfo, unsigned flags,
    605                             cups_size_t *size);
    606 
    607 
    608 ### Localizing Options and Values
    609 
    610 CUPS provides three functions to get localized, human-readable strings in the
    611 user's current locale for options and values: `cupsLocalizeDestMedia`,
    612 `cupsLocalizeDestOption`, and `cupsLocalizeDestValue`:
    613 
    614     const char *
    615     cupsLocalizeDestMedia(http_t *http, cups_dest_t *dest,
    616                           cups_dinfo_t *info, unsigned flags,
    617                           cups_size_t *size);
    618 
    619     const char *
    620     cupsLocalizeDestOption(http_t *http, cups_dest_t *dest,
    621                            cups_dinfo_t *info,
    622                            const char *option);
    623 
    624     const char *
    625     cupsLocalizeDestValue(http_t *http, cups_dest_t *dest,
    626                           cups_dinfo_t *info,
    627                           const char *option, const char *value);
    628 
    629 
    630 ## Submitting a Print Job
    631 
    632 Once you are ready to submit a print job, you create a job using the
    633 `cupsCreateDestJob` function:
    634 
    635     ipp_status_t
    636     cupsCreateDestJob(http_t *http, cups_dest_t *dest,
    637                       cups_dinfo_t *info, int *job_id,
    638                       const char *title, int num_options,
    639                       cups_option_t *options);
    640 
    641 The `title` argument specifies a name for the print job such as "My Document".
    642 The `num_options` and `options` arguments specify the options for the print
    643 job which are allocated using the `cupsAddOption` function.
    644 
    645 When successful, the job's numeric identifier is stored in the integer pointed
    646 to by the `job_id` argument and `IPP_STATUS_OK` is returned.  Otherwise, an IPP
    647 error status is returned.
    648 
    649 For example, the following code creates a new job that will print 42 copies of a
    650 two-sided US Letter document:
    651 
    652     int job_id = 0;
    653     int num_options = 0;
    654     cups_option_t *options = NULL;
    655 
    656     num_options = cupsAddOption(CUPS_COPIES, "42",
    657                                 num_options, &options);
    658     num_options = cupsAddOption(CUPS_MEDIA, CUPS_MEDIA_LETTER,
    659                                 num_options, &options);
    660     num_options = cupsAddOption(CUPS_SIDES,
    661                                 CUPS_SIDES_TWO_SIDED_PORTRAIT,
    662                                 num_options, &options);
    663 
    664     if (cupsCreateDestJob(CUPS_HTTP_DEFAULT, dest, info,
    665                           &job_id, "My Document", num_options,
    666                           options) == IPP_STATUS_OK)
    667       printf("Created job: %d\n", job_id);
    668     else
    669       printf("Unable to create job: %s\n",
    670              cupsLastErrorString());
    671 
    672 Once the job is created, you submit documents for the job using the
    673 `cupsStartDestDocument`, `cupsWriteRequestData`, and `cupsFinishDestDocument`
    674 functions:
    675 
    676     http_status_t
    677     cupsStartDestDocument(http_t *http, cups_dest_t *dest,
    678                           cups_dinfo_t *info, int job_id,
    679                           const char *docname,
    680                           const char *format,
    681                           int num_options,
    682                           cups_option_t *options,
    683                           int last_document);
    684 
    685     http_status_t
    686     cupsWriteRequestData(http_t *http, const char *buffer,
    687                          size_t length);
    688 
    689     ipp_status_t
    690     cupsFinishDestDocument(http_t *http, cups_dest_t *dest,
    691                            cups_dinfo_t *info);
    692 
    693 The `docname` argument specifies the name of the document, typically the
    694 original filename.  The `format` argument specifies the MIME media type of the
    695 document, including the following constants:
    696 
    697 - `CUPS_FORMAT_JPEG`: "image/jpeg"
    698 - `CUPS_FORMAT_PDF`: "application/pdf"
    699 - `CUPS_FORMAT_POSTSCRIPT`: "application/postscript"
    700 - `CUPS_FORMAT_TEXT`: "text/plain"
    701 
    702 The `num_options` and `options` arguments specify per-document print options,
    703 which at present must be 0 and `NULL`.  The `last_document` argument specifies
    704 whether this is the last document in the job.
    705 
    706 For example, the following code submits a PDF file to the job that was just
    707 created:
    708 
    709     FILE *fp = fopen("filename.pdf", "rb");
    710     size_t bytes;
    711     char buffer[65536];
    712 
    713     if (cupsStartDestDocument(CUPS_HTTP_DEFAULT, dest, info,
    714                               job_id, "filename.pdf", 0, NULL,
    715                               1) == HTTP_STATUS_CONTINUE)
    716     {
    717       while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
    718         if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer,
    719                                  bytes) != HTTP_STATUS_CONTINUE)
    720           break;
    721 
    722       if (cupsFinishDestDocument(CUPS_HTTP_DEFAULT, dest,
    723                                  info) == IPP_STATUS_OK)
    724         puts("Document send succeeded.");
    725       else
    726         printf("Document send failed: %s\n",
    727                cupsLastErrorString());
    728     }
    729 
    730     fclose(fp);
    731 
    732 
    733 # Sending IPP Requests
    734 
    735 CUPS provides a rich API for sending IPP requests to the scheduler or printers,
    736 typically from management or utility applications whose primary purpose is not
    737 to send print jobs.
    738 
    739 
    740 ## Connecting to the Scheduler or Printer
    741 
    742 The connection to the scheduler or printer is represented by the HTTP connection
    743 type `http_t`.  The `cupsConnectDest` function connects to the scheduler or
    744 printer associated with the destination:
    745 
    746     http_t *
    747     cupsConnectDest(cups_dest_t *dest, unsigned flags, int msec,
    748                     int *cancel, char *resource,
    749                     size_t resourcesize, cups_dest_cb_t cb,
    750                     void *user_data);
    751 
    752 The `dest` argument specifies the destination to connect to.
    753 
    754 The `flags` argument specifies whether you want to connect to the scheduler
    755 (`CUPS_DEST_FLAGS_NONE`) or device/printer (`CUPS_DEST_FLAGS_DEVICE`) associated
    756 with the destination.
    757 
    758 The `msec` argument specifies how long you are willing to wait for the
    759 connection to be established in milliseconds.  Specify a value of `-1` to wait
    760 indefinitely.
    761 
    762 The `cancel` argument specifies the address of an integer variable that can be
    763 set to a non-zero value to cancel the connection.  Specify a value of `NULL`
    764 to not provide a cancel variable.
    765 
    766 The `resource` and `resourcesize` arguments specify the address and size of a
    767 character string array to hold the path to use when sending an IPP request.
    768 
    769 The `cb` and `user_data` arguments specify a destination callback function that
    770 returns 1 to continue connecting or 0 to stop.  The destination callback work
    771 the same way as the one used for the `cupsEnumDests` function.
    772 
    773 On success, a HTTP connection is returned that can be used to send IPP requests
    774 and get IPP responses.
    775 
    776 For example, the following code connects to the printer associated with a
    777 destination with a 30 second timeout:
    778 
    779     char resource[256];
    780     http_t *http = cupsConnectDest(dest, CUPS_DEST_FLAGS_DEVICE,
    781                                    30000, NULL, resource,
    782                                    sizeof(resource), NULL, NULL);
    783 
    784 
    785 ## Creating an IPP Request
    786 
    787 IPP requests are represented by the IPP message type `ipp_t` and each IPP
    788 attribute in the request is representing using the type `ipp_attribute_t`.  Each
    789 IPP request includes an operation code (`IPP_OP_CREATE_JOB`,
    790 `IPP_OP_GET_PRINTER_ATTRIBUTES`, etc.) and a 32-bit integer identifier.
    791 
    792 The `ippNewRequest` function creates a new IPP request:
    793 
    794     ipp_t *
    795     ippNewRequest(ipp_op_t op);
    796 
    797 The `op` argument specifies the IPP operation code for the request.  For
    798 example, the following code creates an IPP Get-Printer-Attributes request:
    799 
    800     ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
    801 
    802 The request identifier is automatically set to a unique value for the current
    803 process.
    804 
    805 Each IPP request starts with two IPP attributes, "attributes-charset" and
    806 "attributes-natural-language", followed by IPP attribute(s) that specify the
    807 target of the operation.  The `ippNewRequest` automatically adds the correct
    808 "attributes-charset" and "attributes-natural-language" attributes, but you must
    809 add the target attribute(s).  For example, the following code adds the
    810 "printer-uri" attribute to the IPP Get-Printer-Attributes request to specify
    811 which printer is being queried:
    812 
    813     const char *printer_uri = cupsGetOption("device-uri",
    814                                             dest->num_options,
    815                                             dest->options);
    816 
    817     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
    818                  "printer-uri", NULL, printer_uri);
    819 
    820 > Note: If we wanted to query the scheduler instead of the device, we would look
    821 > up the "printer-uri-supported" option instead of the "device-uri" value.
    822 
    823 The `ippAddString` function adds the "printer-uri" attribute the the IPP
    824 request.  The `IPP_TAG_OPERATION` argument specifies that the attribute is part
    825 of the operation.  The `IPP_TAG_URI` argument specifies that the value is a
    826 Universal Resource Identifier (URI) string.  The `NULL` argument specifies there
    827 is no language (English, French, Japanese, etc.) associated with the string, and
    828 the `printer_uri` argument specifies the string value.
    829 
    830 The IPP Get-Printer-Attributes request also supports an IPP attribute called
    831 "requested-attributes" that lists the attributes and values you are interested
    832 in.  For example, the following code requests the printer state attributes:
    833 
    834     static const char * const requested_attributes[] =
    835     {
    836       "printer-state",
    837       "printer-state-message",
    838       "printer-state-reasons"
    839     };
    840 
    841     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
    842                   "requested-attributes", 3, NULL,
    843                   requested_attributes);
    844 
    845 The `ippAddStrings` function adds an attribute with one or more strings, in this
    846 case three.  The `IPP_TAG_KEYWORD` argument specifies that the strings are
    847 keyword values, which are used for attribute names.  All strings use the same
    848 language (`NULL`), and the attribute will contain the three strings in the
    849 array `requested_attributes`.
    850 
    851 CUPS provides many functions to adding attributes of different types:
    852 
    853 - `ippAddBoolean` adds a boolean (`IPP_TAG_BOOLEAN`) attribute with one value.
    854 - `ippAddInteger` adds an enum (`IPP_TAG_ENUM`) or integer (`IPP_TAG_INTEGER`)
    855   attribute with one value.
    856 - `ippAddIntegers` adds an enum or integer attribute with one or more values.
    857 - `ippAddOctetString` adds an octetString attribute with one value.
    858 - `ippAddOutOfBand` adds a admin-defined (`IPP_TAG_ADMINDEFINE`), default
    859   (`IPP_TAG_DEFAULT`), delete-attribute (`IPP_TAG_DELETEATTR`), no-value
    860   (`IPP_TAG_NOVALUE`), not-settable (`IPP_TAG_NOTSETTABLE`), unknown
    861   (`IPP_TAG_UNKNOWN`), or unsupported (`IPP_TAG_UNSUPPORTED_VALUE`) out-of-band
    862   attribute.
    863 - `ippAddRange` adds a rangeOfInteger attribute with one range.
    864 - `ippAddRanges` adds a rangeOfInteger attribute with one or more ranges.
    865 - `ippAddResolution` adds a resolution attribute with one resolution.
    866 - `ippAddResolutions` adds a resolution attribute with one or more resolutions.
    867 - `ippAddString` adds a charset (`IPP_TAG_CHARSET`), keyword (`IPP_TAG_KEYWORD`),
    868   mimeMediaType (`IPP_TAG_MIMETYPE`), name (`IPP_TAG_NAME` and
    869   `IPP_TAG_NAMELANG`), naturalLanguage (`IPP_TAG_NATURAL_LANGUAGE`), text
    870   (`IPP_TAG_TEXT` and `IPP_TAG_TEXTLANG`), uri (`IPP_TAG_URI`), or uriScheme
    871   (`IPP_TAG_URISCHEME`) attribute with one value.
    872 - `ippAddStrings` adds a charset, keyword, mimeMediaType, name, naturalLanguage,
    873   text, uri, or uriScheme attribute with one or more values.
    874 
    875 
    876 ## Sending the IPP Request
    877 
    878 Once you have created the IPP request, you can send it using the
    879 `cupsDoRequest` function.  For example, the following code sends the IPP
    880 Get-Printer-Attributes request to the destination and saves the response:
    881 
    882     ipp_t *response = cupsDoRequest(http, request, resource);
    883 
    884 For requests like Send-Document that include a file, the `cupsDoFileRequest`
    885 function should be used:
    886 
    887     ipp_t *response = cupsDoFileRequest(http, request, resource,
    888                                         filename);
    889 
    890 Both `cupsDoRequest` and `cupsDoFileRequest` free the IPP request.  If a valid
    891 IPP response is received, it is stored in a new IPP message (`ipp_t`) and
    892 returned to the caller.  Otherwise `NULL` is returned.
    893 
    894 The status from the most recent request can be queried using the `cupsLastError`
    895 function, for example:
    896 
    897     if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
    898     {
    899       /* request failed */
    900     }
    901 
    902 A human-readable error message is also available using the `cupsLastErrorString`
    903 function:
    904 
    905     if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
    906     {
    907       /* request failed */
    908       printf("Request failed: %s\n", cupsLastErrorString());
    909     }
    910 
    911 
    912 ## Processing the IPP Response
    913 
    914 Each response to an IPP request is also an IPP message (`ipp_t`) with its own
    915 IPP attributes (`ipp_attribute_t`) that includes a status code (`IPP_STATUS_OK`,
    916 `IPP_STATUS_ERROR_BAD_REQUEST`, etc.) and the corresponding 32-bit integer
    917 identifier from the request.
    918 
    919 For example, the following code finds the printer state attributes and prints
    920 their values:
    921 
    922     ipp_attribute_t *attr;
    923 
    924     if ((attr = ippFindAttribute(response, "printer-state",
    925                                  IPP_TAG_ENUM)) != NULL)
    926     {
    927       printf("printer-state=%s\n",
    928              ippEnumString("printer-state", ippGetInteger(attr, 0)));
    929     }
    930     else
    931       puts("printer-state=unknown");
    932 
    933     if ((attr = ippFindAttribute(response, "printer-state-message",
    934                                  IPP_TAG_TEXT)) != NULL)
    935     {
    936       printf("printer-state-message=\"%s\"\n",
    937              ippGetString(attr, 0, NULL)));
    938     }
    939 
    940     if ((attr = ippFindAttribute(response, "printer-state-reasons",
    941                                  IPP_TAG_KEYWORD)) != NULL)
    942     {
    943       int i, count = ippGetCount(attr);
    944 
    945       puts("printer-state-reasons=");
    946       for (i = 0; i < count; i ++)
    947         printf("    %s\n", ippGetString(attr, i, NULL)));
    948     }
    949 
    950 The `ippGetCount` function returns the number of values in an attribute.
    951 
    952 The `ippGetInteger` and `ippGetString` functions return a single integer or
    953 string value from an attribute.
    954 
    955 The `ippEnumString` function converts a enum value to its keyword (string)
    956 equivalent.
    957 
    958 Once you are done using the IPP response message, free it using the `ippDelete`
    959 function:
    960 
    961     ippDelete(response);
    962 
    963 
    964 ## Authentication
    965 
    966 CUPS normally handles authentication through the console.  GUI applications
    967 should set a password callback using the `cupsSetPasswordCB2` function:
    968 
    969     void
    970     cupsSetPasswordCB2(cups_password_cb2_t cb, void *user_data);
    971 
    972 The password callback will be called when needed and is responsible for setting
    973 the current user name using `cupsSetUser` and returning a string:
    974 
    975     const char *
    976     cups_password_cb2(const char *prompt, http_t *http,
    977                       const char *method, const char *resource,
    978                       void *user_data);
    979 
    980 The `prompt` argument is a string from CUPS that should be displayed to the
    981 user.
    982 
    983 The `http` argument is the connection hosting the request that is being
    984 authenticated.  The password callback can call the `httpGetField` and
    985 `httpGetSubField` functions to look for additional details concerning the
    986 authentication challenge.
    987 
    988 The `method` argument specifies the HTTP method used for the request and is
    989 typically "POST".
    990 
    991 The `resource` argument specifies the path used for the request.
    992 
    993 The `user_data` argument provides the user data pointer from the
    994 `cupsSetPasswordCB2` call.
    995