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