• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2title: CUPS Programming Manual
3author: Michael R Sweet
4copyright: Copyright © 2007-2017 by Apple Inc. All Rights Reserved.
5version: 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
14CUPS provides the "cups" library to talk to the different parts of CUPS and with
15Internet Printing Protocol (IPP) printers. The "cups" library functions are
16accessed by including the `<cups/cups.h>` header.
17
18CUPS is based on the Internet Printing Protocol ("IPP"), which allows clients
19(applications) to communicate with a server (the scheduler, printers, etc.) to
20get a list of destinations, send print jobs, and so forth.  You identify which
21server 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
23the CUPS scheduler.
24
25
26## Guidelines
27
28When 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
35CUPS is designed to insulate users and developers from the implementation
36details of printers and file formats.  The goal is to allow an application to
37supply a print file in a standard format with the user intent ("print four
38copies, two-sided on A4 media, and staple each copy") and have the printing
39system manage the printer communication and format conversion needed.
40
41Similarly, printer and job management applications can use standard query
42operations to obtain the status information in a common, generic form and use
43standard management operations to control the state of those printers and jobs.
44
45
46## Terms Used in This Document
47
48A *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
50using options supplied when creating the job.  A *Document* is a file (JPEG
51image, PDF file, etc.) suitable for printing.  An *Option* controls some aspect
52of printing, such as the media used. *Media* is the sheets or roll that is
53printed on.  An *Attribute* is an option encoded for an Internet Printing
54Protocol (IPP) request.
55
56
57## Compiling Programs That Use the CUPS API
58
59The CUPS libraries can be used from any C, C++, or Objective C program.
60The method of compiling against the libraries varies depending on the
61operating system and installation of CUPS. The following sections show how
62to compile a simple program (shown below) in two common environments.
63
64The 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
89In Xcode, choose *New Project...* from the *File* menu (or press SHIFT+CMD+N),
90then select the *Command Line Tool* under the macOS Application project type.
91Click *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
94In the project window, click on the *Build Phases* group and expand the
95*Link Binary with Libraries* section. Click *+*, type "libcups" to show the
96library, and then double-click on `libcups.tbd`.
97
98Finally, click on the `main.c` file in the sidebar and copy the example program
99to the file.  Build and run (CMD+R) to see the list of destinations.
100
101
102### Compiling with GCC
103
104From the command-line, create a file called `sample.c` using your favorite
105editor, copy the example to this file, and save.  Then run the following command
106to compile it with GCC and run it:
107
108    gcc -o simple `cups-config --cflags` simple.c `cups-config --libs`
109    ./simple
110
111The `cups-config` command provides the compiler flags (`cups-config --cflags`)
112and libraries (`cups-config --libs`) needed for the local system.
113
114
115# Working with Destinations
116
117Destinations, which in CUPS represent individual printers or classes
118(collections or pools) of printers, are represented by the `cups_dest_t`
119structure which includes the name \(`name`), instance \(`instance`, saved
120options/settings), whether the destination is the default for the user
121\(`is_default`), and the options and basic information associated with that
122destination \(`num_options` and `options`).
123
124Historically destinations have been manually maintained by the administrator of
125a system or network, but CUPS also supports dynamic discovery of destinations on
126the current network.
127
128
129## Finding Available Destinations
130
131The `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
138The `flags` argument specifies enumeration options, which at present must be
139`CUPS_DEST_FLAGS_NONE`.
140
141The `msec` argument specifies the maximum amount of time that should be used for
142enumeration in milliseconds - interactive applications should keep this value to
1435000 or less when run on the main thread.
144
145The `cancel` argument points to an integer variable that, when set to a non-zero
146value, will cause enumeration to stop as soon as possible.  It can be `NULL` if
147not needed.
148
149The `type` and `mask` arguments are bitfields that allow the caller to filter
150the 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`
152value when filtering.  For example, to only enumerate destinations that are
153hosted on the local system, pass `CUPS_PRINTER_LOCAL` for the `type` argument
154and `CUPS_PRINTER_DISCOVERED` for the `mask` argument.  The following constants
155can 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
179The `cb` argument specifies a function to call for every destination that is
180found:
181
182    typedef int (*cups_dest_cb_t)(void *user_data,
183                                  unsigned flags,
184                                  cups_dest_t *dest);
185
186The callback function receives a copy of the `user_data` argument along with a
187bitfield \(`flags`) and the destination that was found.  The `flags` argument
188can 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
196The 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
202The following example shows how to use `cupsEnumDests` to get a filtered array
203of 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
274The `num_options` and `options` members of the `cups_dest_t` structure provide
275basic attributes about the destination in addition to the user default options
276and values for that destination.  The following names are predefined for various
277destination 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
302Use the `cupsGetOption` function to retrieve the value.  For example, the
303following 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
312Once a destination has been chosen, the `cupsCopyDestInfo` function can be used
313to gather detailed information about the destination:
314
315    cups_dinfo_t *
316    cupsCopyDestInfo(http_t *http, cups_dest_t *dest);
317
318The `http` argument specifies a connection to the CUPS scheduler and is
319typically the constant `CUPS_HTTP_DEFAULT`.  The `dest` argument specifies the
320destination to query.
321
322The `cups_dinfo_t` structure that is returned contains a snapshot of the
323supported options and their supported, ready, and default values.  It also can
324report constraints between different options and values, and recommend changes
325to resolve those constraints.
326
327
328### Getting Supported Options and Values
329
330The `cupsCheckDestSupported` function can be used to test whether a particular
331option 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
339The `option` argument specifies the name of the option to check.  The following
340constants 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
375If the `value` argument is `NULL`, the `cupsCheckDestSupported` function returns
376whether the option is supported by the destination.  Otherwise, the function
377returns whether the specified value of the option is supported.
378
379The `cupsFindDestSupported` function returns the IPP attribute containing the
380supported 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
387For example, the following code prints the supported finishing processes for a
388destination, 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
408The "job-creation-attributes" option can be queried to get a list of supported
409options.  For example, the following code prints the list of supported options
410to 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
423There 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
425destination defaults that available via the `cups_dinfo_t` structure and the
426`cupsFindDestDefault` function which returns the IPP attribute containing the
427default 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
434The user defaults from `cupsGetOption` should always take preference over the
435destination defaults.  For example, the following code prints the default
436finishings 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
463The finishings and media options also support queries for the ready, or loaded,
464values.  For example, a printer may have punch and staple finishers installed
465but be out of staples - the supported values will list both punch and staple
466finishing processes but the ready values will only list the punch processes.
467Similarly, a printer may support hundreds of different sizes of media but only
468have a single size loaded at any given time - the ready values are limited to
469the media that is actually in the printer.
470
471The `cupsFindDestReady` function finds the IPP attribute containing the ready
472values 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
478For 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
498CUPS provides functions for querying the dimensions and margins for each of the
499supported media size options.  The `cups_size_t` structure is used to describe a
500media 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
509The `width` and `length` members specify the dimensions of the media in
510hundredths of millimeters (1/2540th of an inch).  The `bottom`, `left`, `right`,
511and `top` members specify the margins of the printable area, also in hundredths
512of millimeters.
513
514The `cupsGetDestMediaByName` and `cupsGetDestMediaBySize` functions lookup the
515media size information using a standard media size name or dimensions in
516hundredths 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
530The `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
541If a matching size is found for the destination, the size information is stored
542in the structure pointed to by the `size` argument and 1 is returned.  Otherwise
5430 is returned.
544
545For example, the following code prints the margins for two-sided printing on US
546Letter 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
563You can also enumerate all of the sizes that match a given `flags` value using
564the `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
575For example, the following code prints the list of ready media and corresponding
576margins:
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
600Finally, 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
610CUPS provides three functions to get localized, human-readable strings in the
611user'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
632Once 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
641The `title` argument specifies a name for the print job such as "My Document".
642The `num_options` and `options` arguments specify the options for the print
643job which are allocated using the `cupsAddOption` function.
644
645When successful, the job's numeric identifier is stored in the integer pointed
646to by the `job_id` argument and `IPP_STATUS_OK` is returned.  Otherwise, an IPP
647error status is returned.
648
649For example, the following code creates a new job that will print 42 copies of a
650two-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
672Once the job is created, you submit documents for the job using the
673`cupsStartDestDocument`, `cupsWriteRequestData`, and `cupsFinishDestDocument`
674functions:
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
693The `docname` argument specifies the name of the document, typically the
694original filename.  The `format` argument specifies the MIME media type of the
695document, 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
702The `num_options` and `options` arguments specify per-document print options,
703which at present must be 0 and `NULL`.  The `last_document` argument specifies
704whether this is the last document in the job.
705
706For example, the following code submits a PDF file to the job that was just
707created:
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
735CUPS provides a rich API for sending IPP requests to the scheduler or printers,
736typically from management or utility applications whose primary purpose is not
737to send print jobs.
738
739
740## Connecting to the Scheduler or Printer
741
742The connection to the scheduler or printer is represented by the HTTP connection
743type `http_t`.  The `cupsConnectDest` function connects to the scheduler or
744printer 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
752The `dest` argument specifies the destination to connect to.
753
754The `flags` argument specifies whether you want to connect to the scheduler
755(`CUPS_DEST_FLAGS_NONE`) or device/printer (`CUPS_DEST_FLAGS_DEVICE`) associated
756with the destination.
757
758The `msec` argument specifies how long you are willing to wait for the
759connection to be established in milliseconds.  Specify a value of `-1` to wait
760indefinitely.
761
762The `cancel` argument specifies the address of an integer variable that can be
763set to a non-zero value to cancel the connection.  Specify a value of `NULL`
764to not provide a cancel variable.
765
766The `resource` and `resourcesize` arguments specify the address and size of a
767character string array to hold the path to use when sending an IPP request.
768
769The `cb` and `user_data` arguments specify a destination callback function that
770returns 1 to continue connecting or 0 to stop.  The destination callback work
771the same way as the one used for the `cupsEnumDests` function.
772
773On success, a HTTP connection is returned that can be used to send IPP requests
774and get IPP responses.
775
776For example, the following code connects to the printer associated with a
777destination 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
787IPP requests are represented by the IPP message type `ipp_t` and each IPP
788attribute in the request is representing using the type `ipp_attribute_t`.  Each
789IPP request includes an operation code (`IPP_OP_CREATE_JOB`,
790`IPP_OP_GET_PRINTER_ATTRIBUTES`, etc.) and a 32-bit integer identifier.
791
792The `ippNewRequest` function creates a new IPP request:
793
794    ipp_t *
795    ippNewRequest(ipp_op_t op);
796
797The `op` argument specifies the IPP operation code for the request.  For
798example, the following code creates an IPP Get-Printer-Attributes request:
799
800    ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
801
802The request identifier is automatically set to a unique value for the current
803process.
804
805Each IPP request starts with two IPP attributes, "attributes-charset" and
806"attributes-natural-language", followed by IPP attribute(s) that specify the
807target of the operation.  The `ippNewRequest` automatically adds the correct
808"attributes-charset" and "attributes-natural-language" attributes, but you must
809add the target attribute(s).  For example, the following code adds the
810"printer-uri" attribute to the IPP Get-Printer-Attributes request to specify
811which 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
823The `ippAddString` function adds the "printer-uri" attribute the the IPP
824request.  The `IPP_TAG_OPERATION` argument specifies that the attribute is part
825of the operation.  The `IPP_TAG_URI` argument specifies that the value is a
826Universal Resource Identifier (URI) string.  The `NULL` argument specifies there
827is no language (English, French, Japanese, etc.) associated with the string, and
828the `printer_uri` argument specifies the string value.
829
830The IPP Get-Printer-Attributes request also supports an IPP attribute called
831"requested-attributes" that lists the attributes and values you are interested
832in.  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
845The `ippAddStrings` function adds an attribute with one or more strings, in this
846case three.  The `IPP_TAG_KEYWORD` argument specifies that the strings are
847keyword values, which are used for attribute names.  All strings use the same
848language (`NULL`), and the attribute will contain the three strings in the
849array `requested_attributes`.
850
851CUPS 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
878Once you have created the IPP request, you can send it using the
879`cupsDoRequest` function.  For example, the following code sends the IPP
880Get-Printer-Attributes request to the destination and saves the response:
881
882    ipp_t *response = cupsDoRequest(http, request, resource);
883
884For requests like Send-Document that include a file, the `cupsDoFileRequest`
885function should be used:
886
887    ipp_t *response = cupsDoFileRequest(http, request, resource,
888                                        filename);
889
890Both `cupsDoRequest` and `cupsDoFileRequest` free the IPP request.  If a valid
891IPP response is received, it is stored in a new IPP message (`ipp_t`) and
892returned to the caller.  Otherwise `NULL` is returned.
893
894The status from the most recent request can be queried using the `cupsLastError`
895function, for example:
896
897    if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
898    {
899      /* request failed */
900    }
901
902A human-readable error message is also available using the `cupsLastErrorString`
903function:
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
914Each response to an IPP request is also an IPP message (`ipp_t`) with its own
915IPP 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
917identifier from the request.
918
919For example, the following code finds the printer state attributes and prints
920their 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
950The `ippGetCount` function returns the number of values in an attribute.
951
952The `ippGetInteger` and `ippGetString` functions return a single integer or
953string value from an attribute.
954
955The `ippEnumString` function converts a enum value to its keyword (string)
956equivalent.
957
958Once you are done using the IPP response message, free it using the `ippDelete`
959function:
960
961    ippDelete(response);
962
963
964## Authentication
965
966CUPS normally handles authentication through the console.  GUI applications
967should set a password callback using the `cupsSetPasswordCB2` function:
968
969    void
970    cupsSetPasswordCB2(cups_password_cb2_t cb, void *user_data);
971
972The password callback will be called when needed and is responsible for setting
973the 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
980The `prompt` argument is a string from CUPS that should be displayed to the
981user.
982
983The `http` argument is the connection hosting the request that is being
984authenticated.  The password callback can call the `httpGetField` and
985`httpGetSubField` functions to look for additional details concerning the
986authentication challenge.
987
988The `method` argument specifies the HTTP method used for the request and is
989typically "POST".
990
991The `resource` argument specifies the path used for the request.
992
993The `user_data` argument provides the user data pointer from the
994`cupsSetPasswordCB2` call.
995