2 title: CUPS Programming Manual
3 author: Michael R Sweet
4 copyright: Copyright © 2007-2017 by Apple Inc. All Rights Reserved.
8 > Note: This document is under active development and is incomplete, with a goal
9 > completing it prior to releasing CUPS 2.2.4. Please
10 > [file issues on Github](https://github.com/apple/cups/issues)
11 > to provide any feedback.
16 CUPS provides the "cups" library to talk to the different parts of CUPS and with
17 Internet Printing Protocol (IPP) printers. The "cups" library functions are
18 accessed by including the `<cups/cups.h>` header.
20 CUPS is based on the Internet Printing Protocol ("IPP"), which allows clients
21 (applications) to communicate with a server (the scheduler, printers, etc.) to
22 get a list of destinations, send print jobs, and so forth. You identify which
23 server you want to communicate with using a pointer to the opaque structure
24 `http_t`. The `CUPS_HTTP_DEFAULT` constant can be used when you want to talk to
30 When writing software that uses the "cups" library:
32 - Do not use undocumented or deprecated APIs,
33 - Do not rely on pre-configured printers,
34 - Do not assume that printers support specific features or formats, and
35 - Do not rely on implementation details (PPDs, etc.)
37 CUPS is designed to insulate users and developers from the implementation
38 details of printers and file formats. The goal is to allow an application to
39 supply a print file in a standard format with the user intent ("print four
40 copies, two-sided on A4 media, and staple each copy") and have the printing
41 system manage the printer communication and format conversion needed.
43 Similarly, printer and job management applications can use standard query
44 operations to obtain the status information in a common, generic form and use
45 standard management operations to control the state of those printers and jobs.
48 ## Terms Used in This Document
50 A *Destination* is a printer or print queue that accepts print jobs. A
51 *Print Job* is one or more documents that are processed by a destination
52 using options supplied when creating the job. A *Document* is a file (JPEG
53 image, PDF file, etc.) suitable for printing. An *Option* controls some aspect
54 of printing, such as the media used. *Media* is the sheets or roll that is
55 printed on. An *Attribute* is an option encoded for an Internet Printing
56 Protocol (IPP) request.
59 ## Compiling Programs That Use the CUPS API
61 The CUPS libraries can be used from any C, C++, or Objective C program.
62 The method of compiling against the libraries varies depending on the
63 operating system and installation of CUPS. The following sections show how
64 to compile a simple program (shown below) in two common environments.
66 The following simple program lists the available destinations:
69 #include <cups/cups.h>
71 int print_dest(void *user_data, unsigned flags, cups_dest_t *dest)
74 printf("%s/%s\n", dest->name, dest->instance);
83 cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, 0, 0, print_dest, NULL);
89 ### Compiling with Xcode
91 In Xcode, choose *New Project...* from the *File* menu (or press SHIFT+CMD+N),
92 then select the *Command Line Tool* under the macOS Application project type.
93 Click *Next* and enter a name for the project, for example "firstcups". Click
94 *Next* and choose a project directory. The click *Next* to create the project.
96 In the project window, click on the *Build Phases* group and expand the
97 *Link Binary with Libraries* section. Click *+*, type "libcups" to show the
98 library, and then double-click on `libcups.tbd`.
100 Finally, click on the `main.c` file in the sidebar and copy the example program
101 to the file. Build and run (CMD+R) to see the list of destinations.
104 ### Compiling with GCC
106 From the command-line, create a file called `sample.c` using your favorite
107 editor, copy the example to this file, and save. Then run the following command
108 to compile it with GCC and run it:
110 gcc -o simple `cups-config --cflags` simple.c `cups-config --libs`
113 The `cups-config` command provides the compiler flags (`cups-config --cflags`)
114 and libraries (`cups-config --libs`) needed for the local system.
117 # Working with Destinations
119 Destinations, which in CUPS represent individual printers or classes
120 (collections or pools) of printers, are represented by the `cups_dest_t`
121 structure which includes the name \(`name`), instance \(`instance`, saved
122 options/settings), whether the destination is the default for the user
123 \(`is_default`), and the options and basic information associated with that
124 destination \(`num_options` and `options`).
126 Historically destinations have been manually maintained by the administrator of
127 a system or network, but CUPS also supports dynamic discovery of destinations on
131 ## Finding Available Destinations
133 The `cupsEnumDests` function finds all of the available destinations:
136 cupsEnumDests(unsigned flags, int msec, int *cancel,
137 cups_ptype_t type, cups_ptype_t mask,
138 cups_dest_cb_t cb, void *user_data)
140 The `flags` argument specifies enumeration options, which at present must be
141 `CUPS_DEST_FLAGS_NONE`.
143 The `msec` argument specifies the maximum amount of time that should be used for
144 enumeration in milliseconds - interactive applications should keep this value to
145 5000 or less when run on the main thread.
147 The `cancel` argument points to an integer variable that, when set to a non-zero
148 value, will cause enumeration to stop as soon as possible. It can be `NULL` if
151 The `type` and `mask` arguments are bitfields that allow the caller to filter
152 the destinations based on categories and/or capabilities. The destination's
153 "printer-type" value is masked by the `mask` value and compared to the `type`
154 value when filtering. For example, to only enumerate destinations that are
155 hosted on the local system, pass `CUPS_PRINTER_LOCAL` for the `type` argument
156 and `CUPS_PRINTER_DISCOVERED` for the `mask` argument. The following constants
157 can be used for filtering:
159 - `CUPS_PRINTER_CLASS`: A collection of destinations.
160 - `CUPS_PRINTER_FAX`: A facsimile device.
161 - `CUPS_PRINTER_LOCAL`: A local printer or class. This constant has the value 0
162 (no bits set) and is only used for the `type` argument and is paired with the
163 `CUPS_PRINTER_REMOTE` or `CUPS_PRINTER_DISCOVERED` constant passed in the
165 - `CUPS_PRINTER_REMOTE`: A remote (shared) printer or class.
166 - `CUPS_PRINTER_DISCOVERED`: An available network printer or class.
167 - `CUPS_PRINTER_BW`: Can do B&W printing.
168 - `CUPS_PRINTER_COLOR`: Can do color printing.
169 - `CUPS_PRINTER_DUPLEX`: Can do two-sided printing.
170 - `CUPS_PRINTER_STAPLE`: Can staple output.
171 - `CUPS_PRINTER_COLLATE`: Can quickly collate copies.
172 - `CUPS_PRINTER_PUNCH`: Can punch output.
173 - `CUPS_PRINTER_COVER`: Can cover output.
174 - `CUPS_PRINTER_BIND`: Can bind output.
175 - `CUPS_PRINTER_SORT`: Can sort output (mailboxes, etc.)
176 - `CUPS_PRINTER_SMALL`: Can print on Letter/Legal/A4-size media.
177 - `CUPS_PRINTER_MEDIUM`: Can print on Tabloid/B/C/A3/A2-size media.
178 - `CUPS_PRINTER_LARGE`: Can print on D/E/A1/A0-size media.
179 - `CUPS_PRINTER_VARIABLE`: Can print on rolls and custom-size media.
181 The `cb` argument specifies a function to call for every destination that is
184 typedef int (*cups_dest_cb_t)(void *user_data,
188 The callback function receives a copy of the `user_data` argument along with a
189 bitfield \(`flags`) and the destination that was found. The `flags` argument
190 can have any of the following constant (bit) values set:
192 - `CUPS_DEST_FLAGS_MORE`: There are more destinations coming.
193 - `CUPS_DEST_FLAGS_REMOVED`: The destination has gone away and should be removed
194 from the list of destinations a user can select.
195 - `CUPS_DEST_FLAGS_ERROR`: An error occurred. The reason for the error can be
196 found by calling the `cupsLastError` and/or `cupsLastErrorString` functions.
198 The callback function returns 0 to stop enumeration or 1 to continue.
200 The following example shows how to use `cupsEnumDests` to get a filtered array
210 my_dest_cb(my_user_data_t *user_data, unsigned flags,
213 if (flags & CUPS_DEST_FLAGS_REMOVED)
216 * Remove destination from array...
219 user_data->num_dests =
220 cupsRemoveDest(dest->name, dest->instance,
221 user_data->num_dests,
222 &(user_data->dests));
227 * Add destination to array...
230 user_data->num_dests =
231 cupsCopyDest(dest, user_data->num_dests,
232 &(user_data->dests));
239 my_get_dests(cups_ptype_t type, cups_ptype_t mask,
242 my_user_data_t user_data = { 0, NULL };
244 if (!cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, type,
245 mask, (cups_dest_cb_t)my_dest_cb,
249 * An error occurred, free all of the destinations and
253 cupsFreeDests(user_data.num_dests, user_dasta.dests);
261 * Return the destination array...
264 *dests = user_data.dests;
266 return (user_data.num_dests);
270 ## Basic Destination Information
272 The `num_options` and `options` members of the `cups_dest_t` structure provide
273 basic attributes about the destination in addition to the user default options
274 and values for that destination. The following names are predefined for various
275 destination attributes:
277 - "auth-info-required": The type of authentication required for printing to this
278 destination: "none", "username,password", "domain,username,password", or
279 "negotiate" (Kerberos).
280 - "printer-info": The human-readable description of the destination such as "My
282 - "printer-is-accepting-jobs": "true" if the destination is accepting new jobs,
284 - "printer-is-shared": "true" if the destination is being shared with other
285 computers, "false" otherwise.
286 - "printer-location": The human-readable location of the destination such as
288 - "printer-make-and-model": The human-readable make and model of the destination
289 such as "ExampleCorp LaserPrinter 4000 Series".
290 - "printer-state": "3" if the destination is idle, "4" if the destination is
291 printing a job, and "5" if the destination is stopped.
292 - "printer-state-change-time": The UNIX time when the destination entered the
294 - "printer-state-reasons": Additional comma-delimited state keywords for the
295 destination such as "media-tray-empty-error" and "toner-low-warning".
296 - "printer-type": The `cups_ptype_t` value associated with the destination.
297 - "printer-uri": The URI associated with the destination; if not set, this
298 destination was discovered but is not yet setup as a local printer.
300 Use the `cupsGetOption` function to retrieve the value. For example, the
301 following code gets the make and model of a destination:
303 const char *model = cupsGetOption("printer-make-and-model",
307 ## Detailed Destination Information
309 Once a destination has been chosen, the `cupsCopyDestInfo` function can be used
310 to gather detailed information about the destination:
313 cupsCopyDestInfo(http_t *http, cups_dest_t *dest);
315 The `http` argument specifies a connection to the CUPS scheduler and is
316 typically the constant `CUPS_HTTP_DEFAULT`. The `dest` argument specifies the
317 destination to query.
319 The `cups_dinfo_t` structure that is returned contains a snapshot of the
320 supported options and their supported, ready, and default values. It also can
321 report constraints between different options and values, and recommend changes
322 to resolve those constraints.
324 ### Getting Supported Options and Values
326 The `cupsCheckDestSupported` function can be used to test whether a particular
327 option or option and value is supported:
330 cupsCheckDestSupported(http_t *http, cups_dest_t *dest,
335 The `option` argument specifies the name of the option to check. The following
336 constants can be used to check the various standard options:
338 - `CUPS_COPIES`: Controls the number of copies that are produced.
339 - `CUPS_FINISHINGS`: A comma-delimited list of integer constants that control
340 the finishing processes that are applied to the job, including stapling,
341 punching, and folding.
342 - `CUPS_MEDIA`: Controls the media size that is used, typically one of the
343 following: `CUPS_MEDIA_3X5`, `CUPS_MEDIA_4X6`, `CUPS_MEDIA_5X7`,
344 `CUPS_MEDIA_8X10`, `CUPS_MEDIA_A3`, `CUPS_MEDIA_A4`, `CUPS_MEDIA_A5`,
345 `CUPS_MEDIA_A6`, `CUPS_MEDIA_ENV10`, `CUPS_MEDIA_ENVDL`, `CUPS_MEDIA_LEGAL`,
346 `CUPS_MEDIA_LETTER`, `CUPS_MEDIA_PHOTO_L`, `CUPS_MEDIA_SUPERBA3`, or
347 `CUPS_MEDIA_TABLOID`.
348 - `CUPS_MEDIA_SOURCE`: Controls where the media is pulled from, typically either
349 `CUPS_MEDIA_SOURCE_AUTO` or `CUPS_MEDIA_SOURCE_MANUAL`.
350 - `CUPS_MEDIA_TYPE`: Controls the type of media that is used, typically one of
351 the following: `CUPS_MEDIA_TYPE_AUTO`, `CUPS_MEDIA_TYPE_ENVELOPE`,
352 `CUPS_MEDIA_TYPE_LABELS`, `CUPS_MEDIA_TYPE_LETTERHEAD`,
353 `CUPS_MEDIA_TYPE_PHOTO`, `CUPS_MEDIA_TYPE_PHOTO_GLOSSY`,
354 `CUPS_MEDIA_TYPE_PHOTO_MATTE`, `CUPS_MEDIA_TYPE_PLAIN`, or
355 `CUPS_MEDIA_TYPE_TRANSPARENCY`.
356 - `CUPS_NUMBER_UP`: Controls the number of document pages that are placed on
358 - `CUPS_ORIENTATION`: Controls the orientation of document pages placed on the
359 media: `CUPS_ORIENTATION_PORTRAIT` or `CUPS_ORIENTATION_LANDSCAPE`.
360 - `CUPS_PRINT_COLOR_MODE`: Controls whether the output is in color
361 \(`CUPS_PRINT_COLOR_MODE_COLOR`), grayscale
362 \(`CUPS_PRINT_COLOR_MODE_MONOCHROME`), or either
363 \(`CUPS_PRINT_COLOR_MODE_AUTO`).
364 - `CUPS_PRINT_QUALITY`: Controls the generate quality of the output:
365 `CUPS_PRINT_QUALITY_DRAFT`, `CUPS_PRINT_QUALITY_NORMAL`, or
366 `CUPS_PRINT_QUALITY_HIGH`.
367 - `CUPS_SIDES`: Controls whether prints are placed on one or both sides of the
368 media: `CUPS_SIDES_ONE_SIDED`, `CUPS_SIDES_TWO_SIDED_PORTRAIT`, or
369 `CUPS_SIDES_TWO_SIDED_LANDSCAPE`.
371 If the `value` argument is `NULL`, the `cupsCheckDestSupported` function returns
372 whether the option is supported by the destination. Otherwise, the function
373 returns whether the specified value of the option is supported.
375 The `cupsFindDestSupported` function returns the IPP attribute containing the
376 supported values for a given option:
379 cupsFindDestSupported(http_t *http, cups_dest_t *dest,
383 For example, the following code prints the supported finishing processes for a
384 destination, if any, to the standard output:
386 cups_dinfo_t *info = cupsCopyDestInfo(CUPS_HTTP_DEFAULT,
389 if (cupsCheckDestSupported(CUPS_HTTP_DEFAULT, dest, info,
390 CUPS_FINISHINGS, NULL))
392 ipp_attribute_t *finishings =
393 cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
395 int i, count = ippGetCount(finishings);
397 puts("finishings supported:");
398 for (i = 0; i < count; i ++)
399 printf(" %d\n", ippGetInteger(finishings, i));
402 puts("finishings not supported.");
404 The "job-creation-attributes" option can be queried to get a list of supported
405 options. For example, the following code prints the list of supported options
406 to the standard output:
408 ipp_attribute_t *attrs =
409 cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
410 "job-creation-attributes");
411 int i, count = ippGetCount(attrs);
413 for (i = 0; i < count; i ++)
414 puts(ippGetString(attrs, i, NULL));
417 ### Getting Default Values
419 There are two sets of default values - user defaults that are available via the
420 `num_options` and `options` members of the `cups_dest_t` structure, and
421 destination defaults that available via the `cups_dinfo_t` structure and the
422 `cupsFindDestDefault` function which returns the IPP attribute containing the
423 default value(s) for a given option:
426 cupsFindDestDefault(http_t *http, cups_dest_t *dest,
430 The user defaults from `cupsGetOption` should always take preference over the
431 destination defaults. For example, the following code prints the default
432 finishings value(s) to the standard output:
434 const char *def_value =
435 cupsGetOption(CUPS_FINISHINGS, dest->num_options,
437 ipp_attribute_t *def_attr =
438 cupsFindDestDefault(CUPS_HTTP_DEFAULT, dest, info,
441 if (def_value != NULL)
443 printf("Default finishings: %s\n", def_value);
447 int i, count = ippGetCount(def_attr);
449 printf("Default finishings: %d",
450 ippGetInteger(def_attr, 0));
451 for (i = 1; i < count; i ++)
452 printf(",%d", ippGetInteger(def_attr, i));
457 ### Getting Ready (Loaded) Values
459 The finishings and media options also support queries for the ready, or loaded,
460 values. For example, a printer may have punch and staple finishers installed
461 but be out of staples - the supported values will list both punch and staple
462 finishing processes but the ready values will only list the punch processes.
463 Similarly, a printer may support hundreds of different sizes of media but only
464 have a single size loaded at any given time - the ready values are limited to
465 the media that is actually in the printer.
467 The `cupsFindDestReady` function finds the IPP attribute containing the ready
468 values for a given option:
471 cupsFindDestReady(http_t *http, cups_dest_t *dest,
472 cups_dinfo_t *dinfo, const char *option);
474 For example, the following code lists the ready finishing processes:
476 ipp_attribute_t *ready_finishings =
477 cupsFindDestReady(CUPS_HTTP_DEFAULT, dest, info,
480 if (ready_finishings != NULL)
482 int i, count = ippGetCount(ready_finishings);
484 puts("finishings ready:");
485 for (i = 0; i < count; i ++)
486 printf(" %d\n", ippGetInteger(ready_finishings, i));
489 puts("no finishings are ready.");
492 ### Media Size Options
494 CUPS provides functions for querying the dimensions and margins for each of the
495 supported media size options. The `cups_size_t` structure is used to describe a
498 typedef struct cups_size_s
502 int bottom, left, right, top;
505 The `width` and `length` members specify the dimensions of the media in
506 hundredths of millimeters (1/2540th of an inch). The `bottom`, `left`, `right`,
507 and `top` members specify the margins of the printable area, also in hundredths
510 The `cupsGetDestMediaByName` and `cupsGetDestMediaBySize` functions lookup the
511 media size information using a standard media size name or dimensions in
512 hundredths of millimeters:
515 cupsGetDestMediaByName(http_t *http, cups_dest_t *dest,
518 unsigned flags, cups_size_t *size);
521 cupsGetDestMediaBySize(http_t *http, cups_dest_t *dest,
523 int width, int length,
524 unsigned flags, cups_size_t *size);
526 The `media`, `width`, and `length` arguments specify the size to lookup. The
527 `flags` argument specifies a bitfield controlling various lookup options:
529 - `CUPS_MEDIA_FLAGS_DEFAULT`: Find the closest size supported by the printer.
530 - `CUPS_MEDIA_FLAGS_BORDERLESS`: Find a borderless size.
531 - `CUPS_MEDIA_FLAGS_DUPLEX`: Find a size compatible with two-sided printing.
532 - `CUPS_MEDIA_FLAGS_EXACT`: Find an exact match for the size.
533 - `CUPS_MEDIA_FLAGS_READY`: If the printer supports media sensing or
534 configuration of the media in each tray/source, find the size amongst the
537 If a matching size is found for the destination, the size information is stored
538 in the structure pointed to by the `size` argument and 1 is returned. Otherwise
541 For example, the following code prints the margins for two-sided printing on US
546 if (cupsGetDestMediaByName(CUPS_HTTP_DEFAULT, dest, info,
548 CUPS_MEDIA_FLAGS_DUPLEX, &size))
550 puts("Margins for duplex US Letter:");
551 printf(" Bottom: %.2fin\n", size.bottom / 2540.0);
552 printf(" Left: %.2fin\n", size.left / 2540.0);
553 printf(" Right: %.2fin\n", size.right / 2540.0);
554 printf(" Top: %.2fin\n", size.top / 2540.0);
557 puts("Margins for duplex US Letter are not available.");
559 You can also enumerate all of the sizes that match a given `flags` value using
560 the `cupsGetDestMediaByIndex` and `cupsGetDestMediaCount` functions:
563 cupsGetDestMediaByIndex(http_t *http, cups_dest_t *dest,
564 cups_dinfo_t *dinfo, int n,
565 unsigned flags, cups_size_t *size);
568 cupsGetDestMediaCount(http_t *http, cups_dest_t *dest,
569 cups_dinfo_t *dinfo, unsigned flags);
571 For example, the following code prints the list of ready media and corresponding
576 int count = cupsGetDestMediaCount(CUPS_HTTP_DEFAULT,
578 CUPS_MEDIA_FLAGS_READY);
580 for (i = 0; i < count; i ++)
582 if (cupsGetDestMediaByIndex(CUPS_HTTP_DEFAULT, dest, info,
583 i, CUPS_MEDIA_FLAGS_READY,
586 printf("%s:\n", size.name);
587 printf(" Width: %.2fin\n", size.width / 2540.0);
588 printf(" Length: %.2fin\n", size.length / 2540.0);
589 printf(" Bottom: %.2fin\n", size.bottom / 2540.0);
590 printf(" Left: %.2fin\n", size.left / 2540.0);
591 printf(" Right: %.2fin\n", size.right / 2540.0);
592 printf(" Top: %.2fin\n", size.top / 2540.0);
596 Finally, the `cupsGetDestMediaDefault` function returns the default media size:
599 cupsGetDestMediaDefault(http_t *http, cups_dest_t *dest,
600 cups_dinfo_t *dinfo, unsigned flags,
604 ### Localizing Options and Values
606 CUPS provides three functions to get localized versions of options and values:
607 `cupsLocalizeDestMedia`, `cupsLocalizeDestOption`, and `cupsLocalizeDestValue`:
610 cupsLocalizeDestMedia(http_t *http, cups_dest_t *dest,
611 cups_dinfo_t *info, unsigned flags,
615 cupsLocalizeDestOption(http_t *http, cups_dest_t *dest,
620 cupsLocalizeDestValue(http_t *http, cups_dest_t *dest,
622 const char *option, const char *value);
625 ## Submitting a Print Job
627 Once you are ready to submit a print job, you create a job using the
628 `cupsCreateDestJob` function:
631 cupsCreateDestJob(http_t *http, cups_dest_t *dest,
632 cups_dinfo_t *info, int *job_id,
633 const char *title, int num_options,
634 cups_option_t *options);
636 The `title` argument specifies a name for the print job such as "My Document".
637 The `num_options` and `options` arguments specify the options for the print
638 job which are allocated using the `cupsAddOption` function.
640 When successful, the job's numeric identifier is stored in the integer pointed
641 to by the `job_id` argument and `IPP_STATUS_OK` is returned. Otherwise, an IPP
642 error status is returned.
644 For example, the following code creates a new job that will print 42 copies of a
645 two-sided US Letter document:
649 cups_option_t *options = NULL;
651 num_options = cupsAddOption(CUPS_COPIES, "42",
652 num_options, &options);
653 num_options = cupsAddOption(CUPS_MEDIA, CUPS_MEDIA_LETTER,
654 num_options, &options);
655 num_options = cupsAddOption(CUPS_SIDES,
656 CUPS_SIDES_TWO_SIDED_PORTRAIT,
657 num_options, &options);
659 if (cupsCreateDestJob(CUPS_HTTP_DEFAULT, dest, info,
660 &job_id, "My Document", num_options,
661 options) == IPP_STATUS_OK)
662 printf("Created job: %d\n", job_id);
664 printf("Unable to create job: %s\n",
665 cupsLastErrorString());
667 Once the job is created, you submit documents for the job using the
668 `cupsStartDestDocument`, `cupsWriteRequestData`, and `cupsFinishDestDocument`
672 cupsStartDestDocument(http_t *http, cups_dest_t *dest,
673 cups_dinfo_t *info, int job_id,
677 cups_option_t *options,
681 cupsWriteRequestData(http_t *http, const char *buffer,
685 cupsFinishDestDocument(http_t *http, cups_dest_t *dest,
688 The `docname` argument specifies the name of the document, typically the
689 original filename. The `format` argument specifies the MIME media type of the
690 document, including the following constants:
692 - `CUPS_FORMAT_JPEG`: "image/jpeg"
693 - `CUPS_FORMAT_PDF`: "application/pdf"
694 - `CUPS_FORMAT_POSTSCRIPT`: "application/postscript"
695 - `CUPS_FORMAT_TEXT`: "text/plain"
697 The `num_options` and `options` arguments specify per-document print options,
698 which at present must be 0 and `NULL`. The `last_document` argument specifies
699 whether this is the last document in the job.
701 For example, the following code submits a PDF file to the job that was just
704 FILE *fp = fopen("filename.pdf", "rb");
708 if (cupsStartDestDocument(CUPS_HTTP_DEFAULT, dest, info,
709 job_id, "filename.pdf", 0, NULL,
710 1) == HTTP_STATUS_CONTINUE)
712 while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
713 if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer,
714 bytes) != HTTP_STATUS_CONTINUE)
717 if (cupsFinishDestDocument(CUPS_HTTP_DEFAULT, dest,
718 info) == IPP_STATUS_OK)
719 puts("Document send succeeded.");
721 printf("Document send failed: %s\n",
722 cupsLastErrorString());