1/* 2 * "$Id: lpd.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * Line Printer Daemon backend for CUPS. 5 * 6 * Copyright 2007-2012 by Apple Inc. 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * "LICENSE" which should have been included with this file. If this 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * This file is subject to the Apple OS-Developed Software exception. 16 * 17 * Contents: 18 * 19 * main() - Send a file to the printer or server. 20 * lpd_command() - Send an LPR command sequence and wait for a reply. 21 * lpd_queue() - Queue a file using the Line Printer Daemon protocol. 22 * lpd_write() - Write a buffer of data to an LPD server. 23 * rresvport_af() - A simple implementation of rresvport_af(). 24 * sigterm_handler() - Handle 'terminate' signals that stop the backend. 25 */ 26 27/* 28 * Include necessary headers. 29 */ 30 31#include <cups/http-private.h> 32#include "backend-private.h" 33#include <stdarg.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <stdio.h> 37 38#ifdef WIN32 39# include <winsock.h> 40#else 41# include <sys/socket.h> 42# include <netinet/in.h> 43# include <arpa/inet.h> 44# include <netdb.h> 45#endif /* WIN32 */ 46#ifdef __APPLE__ 47# include <CoreFoundation/CFNumber.h> 48# include <CoreFoundation/CFPreferences.h> 49#endif /* __APPLE__ */ 50 51 52/* 53 * Globals... 54 */ 55 56static char tmpfilename[1024] = ""; /* Temporary spool file name */ 57static int abort_job = 0; /* Non-zero if we get SIGTERM */ 58 59 60/* 61 * Print mode... 62 */ 63 64#define MODE_STANDARD 0 /* Queue a copy */ 65#define MODE_STREAM 1 /* Stream a copy */ 66 67 68/* 69 * The order for control and data files in LPD requests... 70 */ 71 72#define ORDER_CONTROL_DATA 0 /* Control file first, then data */ 73#define ORDER_DATA_CONTROL 1 /* Data file first, then control */ 74 75 76/* 77 * What to reserve... 78 */ 79 80#define RESERVE_NONE 0 /* Don't reserve a priviledged port */ 81#define RESERVE_RFC1179 1 /* Reserve port 721-731 */ 82#define RESERVE_ANY 2 /* Reserve port 1-1023 */ 83 84 85/* 86 * Local functions... 87 */ 88 89static int lpd_command(int lpd_fd, char *format, ...); 90static int lpd_queue(const char *hostname, http_addrlist_t *addrlist, 91 const char *printer, int print_fd, int snmp_fd, 92 int mode, const char *user, const char *title, 93 int copies, int banner, int format, int order, 94 int reserve, int manual_copies, int timeout, 95 int contimeout, const char *orighost); 96static int lpd_write(int lpd_fd, char *buffer, int length); 97#ifndef HAVE_RRESVPORT_AF 98static int rresvport_af(int *port, int family); 99#endif /* !HAVE_RRESVPORT_AF */ 100static void sigterm_handler(int sig); 101 102 103/* 104 * 'main()' - Send a file to the printer or server. 105 * 106 * Usage: 107 * 108 * printer-uri job-id user title copies options [file] 109 */ 110 111int /* O - Exit status */ 112main(int argc, /* I - Number of command-line arguments (6 or 7) */ 113 char *argv[]) /* I - Command-line arguments */ 114{ 115 const char *device_uri; /* Device URI */ 116 char scheme[255], /* Scheme in URI */ 117 hostname[1024], /* Hostname */ 118 username[255], /* Username info */ 119 resource[1024], /* Resource info (printer name) */ 120 *options, /* Pointer to options */ 121 *name, /* Name of option */ 122 *value, /* Value of option */ 123 sep, /* Separator character */ 124 *filename, /* File to print */ 125 title[256]; /* Title string */ 126 int port; /* Port number */ 127 char portname[256]; /* Port name (string) */ 128 http_addrlist_t *addrlist; /* List of addresses for printer */ 129 int snmp_enabled = 1; /* Is SNMP enabled? */ 130 int snmp_fd; /* SNMP socket */ 131 int fd; /* Print file */ 132 int status; /* Status of LPD job */ 133 int mode; /* Print mode */ 134 int banner; /* Print banner page? */ 135 int format; /* Print format */ 136 int order; /* Order of control/data files */ 137 int reserve; /* Reserve priviledged port? */ 138 int sanitize_title; /* Sanitize title string? */ 139 int manual_copies, /* Do manual copies? */ 140 timeout, /* Timeout */ 141 contimeout, /* Connection timeout */ 142 copies; /* Number of copies */ 143 ssize_t bytes = 0; /* Initial bytes read */ 144 char buffer[16384]; /* Initial print buffer */ 145#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) 146 struct sigaction action; /* Actions for POSIX signals */ 147#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ 148 int num_jobopts; /* Number of job options */ 149 cups_option_t *jobopts = NULL; /* Job options */ 150 151 152 /* 153 * Make sure status messages are not buffered... 154 */ 155 156 setbuf(stderr, NULL); 157 158 /* 159 * Ignore SIGPIPE and catch SIGTERM signals... 160 */ 161 162#ifdef HAVE_SIGSET 163 sigset(SIGPIPE, SIG_IGN); 164 sigset(SIGTERM, sigterm_handler); 165#elif defined(HAVE_SIGACTION) 166 memset(&action, 0, sizeof(action)); 167 action.sa_handler = SIG_IGN; 168 sigaction(SIGPIPE, &action, NULL); 169 170 sigemptyset(&action.sa_mask); 171 sigaddset(&action.sa_mask, SIGTERM); 172 action.sa_handler = sigterm_handler; 173 sigaction(SIGTERM, &action, NULL); 174#else 175 signal(SIGPIPE, SIG_IGN); 176 signal(SIGTERM, sigterm_handler); 177#endif /* HAVE_SIGSET */ 178 179 /* 180 * Check command-line... 181 */ 182 183 if (argc == 1) 184 { 185 printf("network lpd \"Unknown\" \"%s\"\n", 186 _cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer"))); 187 return (CUPS_BACKEND_OK); 188 } 189 else if (argc < 6 || argc > 7) 190 { 191 _cupsLangPrintf(stderr, 192 _("Usage: %s job-id user title copies options [file]"), 193 argv[0]); 194 return (CUPS_BACKEND_FAILED); 195 } 196 197 num_jobopts = cupsParseOptions(argv[5], 0, &jobopts); 198 199 /* 200 * Extract the hostname and printer name from the URI... 201 */ 202 203 while ((device_uri = cupsBackendDeviceURI(argv)) == NULL) 204 { 205 _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer.")); 206 sleep(10); 207 208 if (getenv("CLASS") != NULL) 209 return (CUPS_BACKEND_FAILED); 210 } 211 212 httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), 213 username, sizeof(username), hostname, sizeof(hostname), &port, 214 resource, sizeof(resource)); 215 216 if (!port) 217 port = 515; /* Default to port 515 */ 218 219 if (!username[0]) 220 { 221 /* 222 * If no username is in the device URI, then use the print job user... 223 */ 224 225 strlcpy(username, argv[2], sizeof(username)); 226 } 227 228 /* 229 * See if there are any options... 230 */ 231 232 mode = MODE_STANDARD; 233 banner = 0; 234 format = 'l'; 235 order = ORDER_CONTROL_DATA; 236 reserve = RESERVE_ANY; 237 manual_copies = 1; 238 timeout = 300; 239 contimeout = 7 * 24 * 60 * 60; 240 241#ifdef __APPLE__ 242 /* 243 * We want to pass UTF-8 characters by default, not re-map them (3071945) 244 */ 245 246 sanitize_title = 0; 247#else 248 /* 249 * Otherwise we want to re-map UTF-8 to "safe" characters by default... 250 */ 251 252 sanitize_title = 1; 253#endif /* __APPLE__ */ 254 255 if ((options = strchr(resource, '?')) != NULL) 256 { 257 /* 258 * Yup, terminate the device name string and move to the first 259 * character of the options... 260 */ 261 262 *options++ = '\0'; 263 264 /* 265 * Parse options... 266 */ 267 268 while (*options) 269 { 270 /* 271 * Get the name... 272 */ 273 274 name = options; 275 276 while (*options && *options != '=' && *options != '+' && *options != '&') 277 options ++; 278 279 if ((sep = *options) != '\0') 280 *options++ = '\0'; 281 282 if (sep == '=') 283 { 284 /* 285 * Get the value... 286 */ 287 288 value = options; 289 290 while (*options && *options != '+' && *options != '&') 291 options ++; 292 293 if (*options) 294 *options++ = '\0'; 295 } 296 else 297 value = (char *)""; 298 299 /* 300 * Process the option... 301 */ 302 303 if (!_cups_strcasecmp(name, "banner")) 304 { 305 /* 306 * Set the banner... 307 */ 308 309 banner = !value[0] || !_cups_strcasecmp(value, "on") || 310 !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); 311 } 312 else if (!_cups_strcasecmp(name, "format") && value[0]) 313 { 314 /* 315 * Set output format... 316 */ 317 318 if (strchr("cdfglnoprtv", value[0])) 319 format = value[0]; 320 else 321 _cupsLangPrintFilter(stderr, "ERROR", 322 _("Unknown format character: \"%c\"."), 323 value[0]); 324 } 325 else if (!_cups_strcasecmp(name, "mode") && value[0]) 326 { 327 /* 328 * Set control/data order... 329 */ 330 331 if (!_cups_strcasecmp(value, "standard")) 332 mode = MODE_STANDARD; 333 else if (!_cups_strcasecmp(value, "stream")) 334 mode = MODE_STREAM; 335 else 336 _cupsLangPrintFilter(stderr, "ERROR", 337 _("Unknown print mode: \"%s\"."), value); 338 } 339 else if (!_cups_strcasecmp(name, "order") && value[0]) 340 { 341 /* 342 * Set control/data order... 343 */ 344 345 if (!_cups_strcasecmp(value, "control,data")) 346 order = ORDER_CONTROL_DATA; 347 else if (!_cups_strcasecmp(value, "data,control")) 348 order = ORDER_DATA_CONTROL; 349 else 350 _cupsLangPrintFilter(stderr, "ERROR", 351 _("Unknown file order: \"%s\"."), value); 352 } 353 else if (!_cups_strcasecmp(name, "reserve")) 354 { 355 /* 356 * Set port reservation mode... 357 */ 358 359 if (!value[0] || !_cups_strcasecmp(value, "on") || 360 !_cups_strcasecmp(value, "yes") || 361 !_cups_strcasecmp(value, "true") || 362 !_cups_strcasecmp(value, "rfc1179")) 363 reserve = RESERVE_RFC1179; 364 else if (!_cups_strcasecmp(value, "any")) 365 reserve = RESERVE_ANY; 366 else 367 reserve = RESERVE_NONE; 368 } 369 else if (!_cups_strcasecmp(name, "manual_copies")) 370 { 371 /* 372 * Set manual copies... 373 */ 374 375 manual_copies = !value[0] || !_cups_strcasecmp(value, "on") || 376 !_cups_strcasecmp(value, "yes") || 377 !_cups_strcasecmp(value, "true"); 378 } 379 else if (!_cups_strcasecmp(name, "sanitize_title")) 380 { 381 /* 382 * Set sanitize title... 383 */ 384 385 sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") || 386 !_cups_strcasecmp(value, "yes") || 387 !_cups_strcasecmp(value, "true"); 388 } 389 else if (!_cups_strcasecmp(name, "snmp")) 390 { 391 /* 392 * Enable/disable SNMP stuff... 393 */ 394 395 snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || 396 _cups_strcasecmp(value, "yes") || 397 _cups_strcasecmp(value, "true"); 398 } 399 else if (!_cups_strcasecmp(name, "timeout")) 400 { 401 /* 402 * Set the timeout... 403 */ 404 405 if (atoi(value) > 0) 406 timeout = atoi(value); 407 } 408 else if (!_cups_strcasecmp(name, "contimeout")) 409 { 410 /* 411 * Set the connection timeout... 412 */ 413 414 if (atoi(value) > 0) 415 contimeout = atoi(value); 416 } 417 } 418 } 419 420 if (mode == MODE_STREAM) 421 order = ORDER_CONTROL_DATA; 422 423 /* 424 * Find the printer... 425 */ 426 427 snprintf(portname, sizeof(portname), "%d", port); 428 429 fputs("STATE: +connecting-to-device\n", stderr); 430 fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname); 431 432 while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL) 433 { 434 _cupsLangPrintFilter(stderr, "INFO", 435 _("Unable to locate printer \"%s\"."), hostname); 436 sleep(10); 437 438 if (getenv("CLASS") != NULL) 439 { 440 fputs("STATE: -connecting-to-device\n", stderr); 441 exit(CUPS_BACKEND_FAILED); 442 } 443 } 444 445 if (snmp_enabled) 446 snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); 447 else 448 snmp_fd = -1; 449 450 /* 451 * Wait for data from the filter... 452 */ 453 454 if (argc == 6) 455 { 456 if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB)) 457 return (CUPS_BACKEND_OK); 458 else if (mode == MODE_STANDARD && 459 (bytes = read(0, buffer, sizeof(buffer))) <= 0) 460 return (CUPS_BACKEND_OK); 461 } 462 463 /* 464 * If we have 7 arguments, print the file named on the command-line. 465 * Otherwise, copy stdin to a temporary file and print the temporary 466 * file. 467 */ 468 469 if (argc == 6 && mode == MODE_STANDARD) 470 { 471 /* 472 * Copy stdin to a temporary file... 473 */ 474 475 if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0) 476 { 477 perror("DEBUG: Unable to create temporary file"); 478 return (CUPS_BACKEND_FAILED); 479 } 480 481 _cupsLangPrintFilter(stderr, "INFO", _("Copying print data.")); 482 483 if (bytes > 0) 484 write(fd, buffer, bytes); 485 486 backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0, 487 backendNetworkSideCB); 488 } 489 else if (argc == 6) 490 { 491 /* 492 * Stream from stdin... 493 */ 494 495 filename = NULL; 496 fd = 0; 497 } 498 else 499 { 500 filename = argv[6]; 501 fd = open(filename, O_RDONLY); 502 503 if (fd == -1) 504 { 505 _cupsLangPrintError("ERROR", _("Unable to open print file")); 506 return (CUPS_BACKEND_FAILED); 507 } 508 } 509 510 /* 511 * Sanitize the document title... 512 */ 513 514 strlcpy(title, argv[3], sizeof(title)); 515 516 if (sanitize_title) 517 { 518 /* 519 * Sanitize the title string so that we don't cause problems on 520 * the remote end... 521 */ 522 523 char *ptr; 524 525 for (ptr = title; *ptr; ptr ++) 526 if (!isalnum(*ptr & 255) && !isspace(*ptr & 255)) 527 *ptr = '_'; 528 } 529 530 /* 531 * Queue the job... 532 */ 533 534 if (argc > 6) 535 { 536 if (manual_copies) 537 { 538 manual_copies = atoi(argv[4]); 539 copies = 1; 540 } 541 else 542 { 543 manual_copies = 1; 544 copies = atoi(argv[4]); 545 } 546 547 status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, 548 username, title, copies, banner, format, order, reserve, 549 manual_copies, timeout, contimeout, 550 cupsGetOption("job-originating-host-name", num_jobopts, 551 jobopts)); 552 553 if (!status) 554 fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); 555 } 556 else 557 status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, 558 username, title, 1, banner, format, order, reserve, 1, 559 timeout, contimeout, 560 cupsGetOption("job-originating-host-name", num_jobopts, 561 jobopts)); 562 563 /* 564 * Remove the temporary file if necessary... 565 */ 566 567 if (tmpfilename[0]) 568 unlink(tmpfilename); 569 570 if (fd) 571 close(fd); 572 573 if (snmp_fd >= 0) 574 _cupsSNMPClose(snmp_fd); 575 576 /* 577 * Return the queue status... 578 */ 579 580 return (status); 581} 582 583 584/* 585 * 'lpd_command()' - Send an LPR command sequence and wait for a reply. 586 */ 587 588static int /* O - Status of command */ 589lpd_command(int fd, /* I - Socket connection to LPD host */ 590 char *format, /* I - printf()-style format string */ 591 ...) /* I - Additional args as necessary */ 592{ 593 va_list ap; /* Argument pointer */ 594 char buf[1024]; /* Output buffer */ 595 int bytes; /* Number of bytes to output */ 596 char status; /* Status from command */ 597 598 599 /* 600 * Don't try to send commands if the job has been canceled... 601 */ 602 603 if (abort_job) 604 return (-1); 605 606 /* 607 * Format the string... 608 */ 609 610 va_start(ap, format); 611 bytes = vsnprintf(buf, sizeof(buf), format, ap); 612 va_end(ap); 613 614 fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1); 615 616 /* 617 * Send the command... 618 */ 619 620 fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes); 621 622 if (lpd_write(fd, buf, bytes) < bytes) 623 { 624 perror("DEBUG: Unable to send LPD command"); 625 return (-1); 626 } 627 628 /* 629 * Read back the status from the command and return it... 630 */ 631 632 fputs("DEBUG: Reading command status...\n", stderr); 633 634 if (recv(fd, &status, 1, 0) < 1) 635 { 636 _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond.")); 637 status = errno; 638 } 639 640 fprintf(stderr, "DEBUG: lpd_command returning %d\n", status); 641 642 return (status); 643} 644 645 646/* 647 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol. 648 */ 649 650static int /* O - Zero on success, non-zero on failure */ 651lpd_queue(const char *hostname, /* I - Host to connect to */ 652 http_addrlist_t *addrlist, /* I - List of host addresses */ 653 const char *printer, /* I - Printer/queue name */ 654 int print_fd, /* I - File to print */ 655 int snmp_fd, /* I - SNMP socket */ 656 int mode, /* I - Print mode */ 657 const char *user, /* I - Requesting user */ 658 const char *title, /* I - Job title */ 659 int copies, /* I - Number of copies */ 660 int banner, /* I - Print LPD banner? */ 661 int format, /* I - Format specifier */ 662 int order, /* I - Order of data/control files */ 663 int reserve, /* I - Reserve ports? */ 664 int manual_copies,/* I - Do copies by hand... */ 665 int timeout, /* I - Timeout... */ 666 int contimeout, /* I - Connection timeout */ 667 const char *orighost) /* I - job-originating-host-name */ 668{ 669 char localhost[255]; /* Local host name */ 670 int error; /* Error number */ 671 struct stat filestats; /* File statistics */ 672 int lport; /* LPD connection local port */ 673 int fd; /* LPD socket */ 674 char control[10240], /* LPD control 'file' */ 675 *cptr; /* Pointer into control file string */ 676 char status; /* Status byte from command */ 677 int delay; /* Delay for retries... */ 678 char addrname[256]; /* Address name */ 679 http_addrlist_t *addr; /* Socket address */ 680 int have_supplies; /* Printer supports supply levels? */ 681 int copy; /* Copies written */ 682 time_t start_time; /* Time of first connect */ 683 size_t nbytes; /* Number of bytes written */ 684 off_t tbytes; /* Total bytes written */ 685 char buffer[32768]; /* Output buffer */ 686#ifdef WIN32 687 DWORD tv; /* Timeout in milliseconds */ 688#else 689 struct timeval tv; /* Timeout in secs and usecs */ 690#endif /* WIN32 */ 691 692 693 /* 694 * Remember when we started trying to connect to the printer... 695 */ 696 697 start_time = time(NULL); 698 699 /* 700 * Loop forever trying to print the file... 701 */ 702 703 while (!abort_job) 704 { 705 /* 706 * First try to reserve a port for this connection... 707 */ 708 709 fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname, 710 httpAddrPort(&(addrlist->addr)), printer); 711 _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer.")); 712 713 for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist, 714 delay = 5;; 715 addr = addr->next) 716 { 717 /* 718 * Stop if this job has been canceled... 719 */ 720 721 if (abort_job) 722 return (CUPS_BACKEND_FAILED); 723 724 /* 725 * Choose the next priviledged port... 726 */ 727 728 if (!addr) 729 addr = addrlist; 730 731 lport --; 732 733 if (lport < 721 && reserve == RESERVE_RFC1179) 734 lport = 731; 735 else if (lport < 1) 736 lport = 1023; 737 738#ifdef HAVE_GETEUID 739 if (geteuid() || !reserve) 740#else 741 if (getuid() || !reserve) 742#endif /* HAVE_GETEUID */ 743 { 744 /* 745 * Just create a regular socket... 746 */ 747 748 if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0) 749 { 750 perror("DEBUG: Unable to create socket"); 751 sleep(1); 752 753 continue; 754 } 755 756 lport = 0; 757 } 758 else 759 { 760 /* 761 * We're running as root and want to comply with RFC 1179. Reserve a 762 * priviledged lport between 721 and 731... 763 */ 764 765 if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0) 766 { 767 perror("DEBUG: Unable to reserve port"); 768 sleep(1); 769 770 continue; 771 } 772 } 773 774 /* 775 * Connect to the printer or server... 776 */ 777 778 if (abort_job) 779 { 780 close(fd); 781 782 return (CUPS_BACKEND_FAILED); 783 } 784 785 if (!connect(fd, &(addr->addr.addr), httpAddrLength(&(addr->addr)))) 786 break; 787 788 error = errno; 789 close(fd); 790 791 if (addr->next) 792 continue; 793 794 if (getenv("CLASS") != NULL) 795 { 796 /* 797 * If the CLASS environment variable is set, the job was submitted 798 * to a class and not to a specific queue. In this case, we want 799 * to abort immediately so that the job can be requeued on the next 800 * available printer in the class. 801 */ 802 803 _cupsLangPrintFilter(stderr, "INFO", 804 _("Unable to contact printer, queuing on next " 805 "printer in class.")); 806 807 /* 808 * Sleep 5 seconds to keep the job from requeuing too rapidly... 809 */ 810 811 sleep(5); 812 813 return (CUPS_BACKEND_FAILED); 814 } 815 816 fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error)); 817 818 if (error == ECONNREFUSED || error == EHOSTDOWN || 819 error == EHOSTUNREACH) 820 { 821 if (contimeout && (time(NULL) - start_time) > contimeout) 822 { 823 _cupsLangPrintFilter(stderr, "ERROR", 824 _("The printer is not responding.")); 825 return (CUPS_BACKEND_FAILED); 826 } 827 828 switch (error) 829 { 830 case EHOSTDOWN : 831 _cupsLangPrintFilter(stderr, "WARNING", 832 _("The printer may not exist or " 833 "is unavailable at this time.")); 834 break; 835 836 case EHOSTUNREACH : 837 _cupsLangPrintFilter(stderr, "WARNING", 838 _("The printer is unreachable at " 839 "this time.")); 840 break; 841 842 case ECONNREFUSED : 843 default : 844 _cupsLangPrintFilter(stderr, "WARNING", 845 _("The printer is in use.")); 846 break; 847 } 848 849 sleep(delay); 850 851 if (delay < 30) 852 delay += 5; 853 } 854 else if (error == EADDRINUSE) 855 { 856 /* 857 * Try on another port... 858 */ 859 860 sleep(1); 861 } 862 else 863 { 864 _cupsLangPrintFilter(stderr, "ERROR", 865 _("The printer is not responding.")); 866 sleep(30); 867 } 868 } 869 870 /* 871 * Set the timeout... 872 */ 873 874#ifdef WIN32 875 tv = (DWORD)(timeout * 1000); 876 877 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); 878 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); 879#else 880 tv.tv_sec = timeout; 881 tv.tv_usec = 0; 882 883 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 884 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 885#endif /* WIN32 */ 886 887 fputs("STATE: -connecting-to-device\n", stderr); 888 _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer.")); 889 890 fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n", 891 httpAddrString(&(addr->addr), addrname, sizeof(addrname)), 892 httpAddrPort(&(addr->addr)), lport); 893 894 /* 895 * See if the printer supports SNMP... 896 */ 897 898 if (snmp_fd >= 0) 899 have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL, 900 NULL); 901 else 902 have_supplies = 0; 903 904 /* 905 * Check for side-channel requests... 906 */ 907 908 backendCheckSideChannel(snmp_fd, &(addrlist->addr)); 909 910 /* 911 * Next, open the print file and figure out its size... 912 */ 913 914 if (print_fd) 915 { 916 /* 917 * Use the size from the print file... 918 */ 919 920 if (fstat(print_fd, &filestats)) 921 { 922 close(fd); 923 924 perror("DEBUG: unable to stat print file"); 925 return (CUPS_BACKEND_FAILED); 926 } 927 928 filestats.st_size *= manual_copies; 929 } 930 else 931 { 932 /* 933 * Use a "very large value" for the size so that the printer will 934 * keep printing until we close the connection... 935 */ 936 937#ifdef _LARGEFILE_SOURCE 938 filestats.st_size = (size_t)(999999999999.0); 939#else 940 filestats.st_size = 2147483647; 941#endif /* _LARGEFILE_SOURCE */ 942 } 943 944 /* 945 * Send a job header to the printer, specifying no banner page and 946 * literal output... 947 */ 948 949 if (lpd_command(fd, "\002%s\n", 950 printer)) /* Receive print job(s) */ 951 { 952 close(fd); 953 return (CUPS_BACKEND_FAILED); 954 } 955 956 if (orighost && _cups_strcasecmp(orighost, "localhost")) 957 strlcpy(localhost, orighost, sizeof(localhost)); 958 else 959 httpGetHostname(NULL, localhost, sizeof(localhost)); 960 961 snprintf(control, sizeof(control), 962 "H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */ 963 "P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */ 964 "J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */ 965 localhost, user, title); 966 cptr = control + strlen(control); 967 968 if (banner) 969 { 970 snprintf(cptr, sizeof(control) - (cptr - control), 971 "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */ 972 "L%s\n", 973 localhost, user); 974 cptr += strlen(cptr); 975 } 976 977 while (copies > 0) 978 { 979 snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%.15s\n", 980 format, (int)getpid() % 1000, localhost); 981 cptr += strlen(cptr); 982 copies --; 983 } 984 985 snprintf(cptr, sizeof(control) - (cptr - control), 986 "UdfA%03d%.15s\n" 987 "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */ 988 (int)getpid() % 1000, localhost, title); 989 990 fprintf(stderr, "DEBUG: Control file is:\n%s", control); 991 992 if (order == ORDER_CONTROL_DATA) 993 { 994 /* 995 * Check for side-channel requests... 996 */ 997 998 backendCheckSideChannel(snmp_fd, &(addr->addr)); 999 1000 /* 1001 * Send the control file... 1002 */ 1003 1004 if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control), 1005 (int)getpid() % 1000, localhost)) 1006 { 1007 close(fd); 1008 1009 return (CUPS_BACKEND_FAILED); 1010 } 1011 1012 fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n", 1013 (unsigned)strlen(control)); 1014 1015 if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) 1016 { 1017 status = errno; 1018 perror("DEBUG: Unable to write control file"); 1019 1020 } 1021 else 1022 { 1023 if (read(fd, &status, 1) < 1) 1024 { 1025 _cupsLangPrintFilter(stderr, "WARNING", 1026 _("The printer did not respond.")); 1027 status = errno; 1028 } 1029 } 1030 1031 if (status != 0) 1032 _cupsLangPrintFilter(stderr, "ERROR", 1033 _("Remote host did not accept control file (%d)."), 1034 status); 1035 else 1036 _cupsLangPrintFilter(stderr, "INFO", 1037 _("Control file sent successfully.")); 1038 } 1039 else 1040 status = 0; 1041 1042 if (status == 0) 1043 { 1044 /* 1045 * Check for side-channel requests... 1046 */ 1047 1048 backendCheckSideChannel(snmp_fd, &(addr->addr)); 1049 1050 /* 1051 * Send the print file... 1052 */ 1053 1054 if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03.3d%.15s\n", 1055 CUPS_LLCAST filestats.st_size, (int)getpid() % 1000, 1056 localhost)) 1057 { 1058 close(fd); 1059 1060 return (CUPS_BACKEND_FAILED); 1061 } 1062 1063 fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n", 1064 CUPS_LLCAST filestats.st_size); 1065 1066 tbytes = 0; 1067 for (copy = 0; copy < manual_copies; copy ++) 1068 { 1069 lseek(print_fd, 0, SEEK_SET); 1070 1071 while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0) 1072 { 1073 _cupsLangPrintFilter(stderr, "INFO", 1074 _("Spooling job, %.0f%% complete."), 1075 100.0 * tbytes / filestats.st_size); 1076 1077 if (lpd_write(fd, buffer, nbytes) < nbytes) 1078 { 1079 perror("DEBUG: Unable to send print file to printer"); 1080 break; 1081 } 1082 else 1083 tbytes += nbytes; 1084 } 1085 } 1086 1087 if (mode == MODE_STANDARD) 1088 { 1089 if (tbytes < filestats.st_size) 1090 status = errno; 1091 else if (lpd_write(fd, "", 1) < 1) 1092 { 1093 perror("DEBUG: Unable to send trailing nul to printer"); 1094 status = errno; 1095 } 1096 else 1097 { 1098 /* 1099 * Read the status byte from the printer; if we can't read the byte 1100 * back now, we should set status to "errno", however at this point 1101 * we know the printer got the whole file and we don't necessarily 1102 * want to requeue it over and over... 1103 */ 1104 1105 if (recv(fd, &status, 1, 0) < 1) 1106 { 1107 _cupsLangPrintFilter(stderr, "WARNING", 1108 _("The printer did not respond.")); 1109 status = 0; 1110 } 1111 } 1112 } 1113 else 1114 status = 0; 1115 1116 if (status != 0) 1117 _cupsLangPrintFilter(stderr, "ERROR", 1118 _("Remote host did not accept data file (%d)."), 1119 status); 1120 else 1121 _cupsLangPrintFilter(stderr, "INFO", 1122 _("Data file sent successfully.")); 1123 } 1124 1125 if (status == 0 && order == ORDER_DATA_CONTROL) 1126 { 1127 /* 1128 * Check for side-channel requests... 1129 */ 1130 1131 backendCheckSideChannel(snmp_fd, &(addr->addr)); 1132 1133 /* 1134 * Send control file... 1135 */ 1136 1137 if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control), 1138 (int)getpid() % 1000, localhost)) 1139 { 1140 close(fd); 1141 1142 return (CUPS_BACKEND_FAILED); 1143 } 1144 1145 fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n", 1146 (unsigned long)strlen(control)); 1147 1148 if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) 1149 { 1150 status = errno; 1151 perror("DEBUG: Unable to write control file"); 1152 } 1153 else 1154 { 1155 if (read(fd, &status, 1) < 1) 1156 { 1157 _cupsLangPrintFilter(stderr, "WARNING", 1158 _("The printer did not respond.")); 1159 status = errno; 1160 } 1161 } 1162 1163 if (status != 0) 1164 _cupsLangPrintFilter(stderr, "ERROR", 1165 _("Remote host did not accept control file (%d)."), 1166 status); 1167 else 1168 _cupsLangPrintFilter(stderr, "INFO", 1169 _("Control file sent successfully.")); 1170 } 1171 1172 /* 1173 * Collect the final supply levels as needed... 1174 */ 1175 1176 if (have_supplies) 1177 backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL); 1178 1179 /* 1180 * Close the socket connection and input file... 1181 */ 1182 1183 close(fd); 1184 1185 if (status == 0) 1186 return (CUPS_BACKEND_OK); 1187 1188 /* 1189 * Waiting for a retry... 1190 */ 1191 1192 sleep(30); 1193 } 1194 1195 /* 1196 * If we get here, then the job has been canceled... 1197 */ 1198 1199 return (CUPS_BACKEND_FAILED); 1200} 1201 1202 1203/* 1204 * 'lpd_write()' - Write a buffer of data to an LPD server. 1205 */ 1206 1207static int /* O - Number of bytes written or -1 on error */ 1208lpd_write(int lpd_fd, /* I - LPD socket */ 1209 char *buffer, /* I - Buffer to write */ 1210 int length) /* I - Number of bytes to write */ 1211{ 1212 int bytes, /* Number of bytes written */ 1213 total; /* Total number of bytes written */ 1214 1215 1216 if (abort_job) 1217 return (-1); 1218 1219 total = 0; 1220 while ((bytes = send(lpd_fd, buffer, length - total, 0)) >= 0) 1221 { 1222 total += bytes; 1223 buffer += bytes; 1224 1225 if (total == length) 1226 break; 1227 } 1228 1229 if (bytes < 0) 1230 return (-1); 1231 else 1232 return (length); 1233} 1234 1235 1236#ifndef HAVE_RRESVPORT_AF 1237/* 1238 * 'rresvport_af()' - A simple implementation of rresvport_af(). 1239 */ 1240 1241static int /* O - Socket or -1 on error */ 1242rresvport_af(int *port, /* IO - Port number to bind to */ 1243 int family) /* I - Address family */ 1244{ 1245 http_addr_t addr; /* Socket address */ 1246 int fd; /* Socket file descriptor */ 1247 1248 1249 /* 1250 * Try to create an IPv4 socket... 1251 */ 1252 1253 if ((fd = socket(family, SOCK_STREAM, 0)) < 0) 1254 return (-1); 1255 1256 /* 1257 * Initialize the address buffer... 1258 */ 1259 1260 memset(&addr, 0, sizeof(addr)); 1261 addr.addr.sa_family = family; 1262 1263 /* 1264 * Try to bind the socket to a reserved port... 1265 */ 1266 1267 while (*port > 511) 1268 { 1269 /* 1270 * Set the port number... 1271 */ 1272 1273 _httpAddrSetPort(&addr, *port); 1274 1275 /* 1276 * Try binding the port to the socket; return if all is OK... 1277 */ 1278 1279 if (!bind(fd, (struct sockaddr *)&addr, sizeof(addr))) 1280 return (fd); 1281 1282 /* 1283 * Stop if we have any error other than "address already in use"... 1284 */ 1285 1286 if (errno != EADDRINUSE) 1287 { 1288# ifdef WIN32 1289 closesocket(fd); 1290# else 1291 close(fd); 1292# endif /* WIN32 */ 1293 1294 return (-1); 1295 } 1296 1297 /* 1298 * Try the next port... 1299 */ 1300 1301 (*port)--; 1302 } 1303 1304 /* 1305 * Wasn't able to bind to a reserved port, so close the socket and return 1306 * -1... 1307 */ 1308 1309# ifdef WIN32 1310 closesocket(fd); 1311# else 1312 close(fd); 1313# endif /* WIN32 */ 1314 1315 return (-1); 1316} 1317#endif /* !HAVE_RRESVPORT_AF */ 1318 1319 1320/* 1321 * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend. 1322 */ 1323 1324static void 1325sigterm_handler(int sig) /* I - Signal */ 1326{ 1327 (void)sig; /* remove compiler warnings... */ 1328 1329 abort_job = 1; 1330} 1331 1332 1333/* 1334 * End of "$Id: lpd.c 11093 2013-07-03 20:48:42Z msweet $". 1335 */ 1336