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