1/* 2 * "$Id: usb-darwin.c 11668 2014-03-03 20:58:58Z duyk $" 3 * 4 * Copyright 2005-2014 Apple Inc. All rights reserved. 5 * 6 * IMPORTANT: This Apple software is supplied to you by Apple Computer, 7 * Inc. ("Apple") in consideration of your agreement to the following 8 * terms, and your use, installation, modification or redistribution of 9 * this Apple software constitutes acceptance of these terms. If you do 10 * not agree with these terms, please do not use, install, modify or 11 * redistribute this Apple software. 12 * 13 * In consideration of your agreement to abide by the following terms, and 14 * subject to these terms, Apple grants you a personal, non-exclusive 15 * license, under Apple's copyrights in this original Apple software (the 16 * "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 * Software, with or without modifications, in source and/or binary forms; 18 * provided that if you redistribute the Apple Software in its entirety and 19 * without modifications, you must retain this notice and the following 20 * text and disclaimers in all such redistributions of the Apple Software. 21 * Neither the name, trademarks, service marks or logos of Apple Computer, 22 * Inc. may be used to endorse or promote products derived from the Apple 23 * Software without specific prior written permission from Apple. Except 24 * as expressly stated in this notice, no other rights or licenses, express 25 * or implied, are granted by Apple herein, including but not limited to 26 * any patent rights that may be infringed by your derivative works or by 27 * other works in which the Apple Software may be incorporated. 28 * 29 * The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 * THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 * FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 * OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 * 35 * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 * MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 * AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 * STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGE. 43 */ 44 45/* 46 * Include necessary headers. 47 */ 48 49#include <stdio.h> 50#include <stdlib.h> 51#include <errno.h> 52#include <signal.h> 53#include <fcntl.h> 54#include <termios.h> 55#include <unistd.h> 56#include <sys/stat.h> 57#include <sys/sysctl.h> 58#include <libgen.h> 59#include <mach/mach.h> 60#include <mach/mach_error.h> 61#include <mach/mach_time.h> 62#include <cups/debug-private.h> 63#include <cups/file-private.h> 64#include <cups/sidechannel.h> 65#include <cups/language-private.h> 66#include "backend-private.h" 67#include <CoreFoundation/CoreFoundation.h> 68#include <IOKit/usb/IOUSBLib.h> 69#include <IOKit/IOCFPlugIn.h> 70#include <libproc.h> 71#include <asl.h> 72#include <spawn.h> 73#include <pthread.h> 74 75extern char **environ; 76 77 78/* 79 * DEBUG_WRITES, if defined, causes the backend to write data to the printer in 80 * 512 byte increments, up to 8192 bytes, to make debugging with a USB bus 81 * analyzer easier. 82 */ 83 84#define DEBUG_WRITES 0 85 86/* 87 * WAIT_EOF_DELAY is number of seconds we'll wait for responses from 88 * the printer after we've finished sending all the data 89 */ 90#define WAIT_EOF_DELAY 7 91#define WAIT_SIDE_DELAY 3 92#define DEFAULT_TIMEOUT 5000L 93 94#define USB_INTERFACE_KIND CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID190) 95#define kUSBLanguageEnglish 0x409 96 97#define PRINTER_POLLING_INTERVAL 5 /* seconds */ 98#define INITIAL_LOG_INTERVAL PRINTER_POLLING_INTERVAL 99#define SUBSEQUENT_LOG_INTERVAL 3 * INITIAL_LOG_INTERVAL 100 101#define kUSBPrinterClassTypeID CFUUIDGetConstantUUIDWithBytes(NULL, 0x06, 0x04, 0x7D, 0x16, 0x53, 0xA2, 0x11, 0xD6, 0x92, 0x06, 0x00, 0x30, 0x65, 0x52, 0x45, 0x92) 102#define kUSBPrinterClassInterfaceID CFUUIDGetConstantUUIDWithBytes(NULL, 0x03, 0x34, 0x6D, 0x74, 0x53, 0xA3, 0x11, 0xD6, 0x9E, 0xA1, 0x76, 0x30, 0x65, 0x52, 0x45, 0x92) 103 104#define kUSBClassDriverProperty CFSTR("USB Printing Class") 105 106#define kUSBGenericTOPrinterClassDriver CFSTR("/System/Library/Printers/Libraries/USBGenericPrintingClass.plugin") 107#define kUSBPrinterClassDeviceNotOpen -9664 /*kPMInvalidIOMContext*/ 108 109#define CRSetCrashLogMessage(m) _crc_make_setter(message, m) 110#define _crc_make_setter(attr, arg) (gCRAnnotations.attr = (uint64_t)(unsigned long)(arg)) 111#define CRASH_REPORTER_CLIENT_HIDDEN __attribute__((visibility("hidden"))) 112#define CRASHREPORTER_ANNOTATIONS_VERSION 4 113#define CRASHREPORTER_ANNOTATIONS_SECTION "__crash_info" 114 115struct crashreporter_annotations_t { 116 uint64_t version; // unsigned long 117 uint64_t message; // char * 118 uint64_t signature_string; // char * 119 uint64_t backtrace; // char * 120 uint64_t message2; // char * 121 uint64_t thread; // uint64_t 122 uint64_t dialog_mode; // unsigned int 123}; 124 125CRASH_REPORTER_CLIENT_HIDDEN 126struct crashreporter_annotations_t gCRAnnotations 127 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 128 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; 129 130/* 131 * Section 5.3 USB Printing Class spec 132 */ 133#define kUSBPrintingSubclass 1 134#define kUSBPrintingProtocolNoOpen 0 135#define kUSBPrintingProtocolUnidirectional 1 136#define kUSBPrintingProtocolBidirectional 2 137 138typedef IOUSBInterfaceInterface190 **printer_interface_t; 139 140typedef struct iodevice_request_s /**** Device request ****/ 141{ 142 UInt8 requestType; 143 UInt8 request; 144 UInt16 value; 145 UInt16 index; 146 UInt16 length; 147 void *buffer; 148} iodevice_request_t; 149 150typedef union /**** Centronics status byte ****/ 151{ 152 char b; 153 struct 154 { 155 unsigned reserved0:2; 156 unsigned paperError:1; 157 unsigned select:1; 158 unsigned notError:1; 159 unsigned reserved1:3; 160 } status; 161} centronics_status_t; 162 163typedef struct classdriver_s /**** g.classdriver context ****/ 164{ 165 IUNKNOWN_C_GUTS; 166 CFPlugInRef plugin; /* release plugin */ 167 IUnknownVTbl **factory; /* Factory */ 168 void *vendorReference; /* vendor class specific usage */ 169 UInt32 location; /* unique location in bus topology */ 170 UInt8 interfaceNumber; /* Interface number */ 171 UInt16 vendorID; /* Vendor id */ 172 UInt16 productID; /* Product id */ 173 printer_interface_t interface; /* identify the device to IOKit */ 174 UInt8 outpipe; /* mandatory bulkOut pipe */ 175 UInt8 inpipe; /* optional bulkIn pipe */ 176 177 /* general class requests */ 178 kern_return_t (*DeviceRequest)(struct classdriver_s **printer, iodevice_request_t *iorequest, UInt16 timeout); 179 kern_return_t (*GetString)(struct classdriver_s **printer, UInt8 whichString, UInt16 language, UInt16 timeout, CFStringRef *result); 180 181 /* standard printer class requests */ 182 kern_return_t (*SoftReset)(struct classdriver_s **printer, UInt16 timeout); 183 kern_return_t (*GetCentronicsStatus)(struct classdriver_s **printer, centronics_status_t *result, UInt16 timeout); 184 kern_return_t (*GetDeviceID)(struct classdriver_s **printer, CFStringRef *devid, UInt16 timeout); 185 186 /* standard bulk device requests */ 187 kern_return_t (*ReadPipe)(struct classdriver_s **printer, UInt8 *buffer, UInt32 *count); 188 kern_return_t (*WritePipe)(struct classdriver_s **printer, UInt8 *buffer, UInt32 *count, Boolean eoj); 189 190 /* interface requests */ 191 kern_return_t (*Open)(struct classdriver_s **printer, UInt32 location, UInt8 protocol); 192 kern_return_t (*Abort)(struct classdriver_s **printer); 193 kern_return_t (*Close)(struct classdriver_s **printer); 194 195 /* initialize and terminate */ 196 kern_return_t (*Initialize)(struct classdriver_s **printer, struct classdriver_s **baseclass); 197 kern_return_t (*Terminate)(struct classdriver_s **printer); 198 199} classdriver_t; 200 201typedef Boolean (*iterator_callback_t)(void *refcon, io_service_t obj); 202 203typedef struct iterator_reference_s /**** Iterator reference data */ 204{ 205 iterator_callback_t callback; 206 void *userdata; 207 Boolean keepRunning; 208} iterator_reference_t; 209 210typedef struct globals_s 211{ 212 io_service_t printer_obj; 213 classdriver_t **classdriver; 214 215 pthread_mutex_t read_thread_mutex; 216 pthread_cond_t read_thread_cond; 217 int read_thread_stop; 218 int read_thread_done; 219 220 pthread_mutex_t readwrite_lock_mutex; 221 pthread_cond_t readwrite_lock_cond; 222 int readwrite_lock; 223 224 CFStringRef make; 225 CFStringRef model; 226 CFStringRef serial; 227 UInt32 location; 228 UInt8 interfaceNum; 229 230 CFRunLoopTimerRef status_timer; 231 232 int print_fd; /* File descriptor to print */ 233 ssize_t print_bytes; /* Print bytes read */ 234#if DEBUG_WRITES 235 ssize_t debug_bytes; /* Current bytes to read */ 236#endif /* DEBUG_WRITES */ 237 238 Boolean wait_eof; 239 int drain_output; /* Drain all pending output */ 240 int bidi_flag; /* 0=unidirectional, 1=bidirectional */ 241 242 pthread_mutex_t sidechannel_thread_mutex; 243 pthread_cond_t sidechannel_thread_cond; 244 int sidechannel_thread_stop; 245 int sidechannel_thread_done; 246} globals_t; 247 248 249/* 250 * Globals... 251 */ 252 253globals_t g = { 0 }; /* Globals */ 254int Iterating = 0; /* Are we iterating the bus? */ 255 256 257/* 258 * Local functions... 259 */ 260 261static Boolean find_device_cb(void *refcon, io_service_t obj); 262static Boolean list_device_cb(void *refcon, io_service_t obj); 263static CFStringRef cfstr_create_trim(const char *cstr); 264static CFStringRef copy_value_for_key(CFStringRef deviceID, CFStringRef *keys); 265static kern_return_t load_classdriver(CFStringRef driverPath, printer_interface_t interface, classdriver_t ***printerDriver); 266static kern_return_t load_printerdriver(CFStringRef *driverBundlePath); 267static kern_return_t registry_close(void); 268static kern_return_t registry_open(CFStringRef *driverBundlePath); 269static kern_return_t unload_classdriver(classdriver_t ***classdriver); 270static OSStatus copy_deviceid(classdriver_t **printer, CFStringRef *deviceID); 271static void *read_thread(void *reference); 272static void *sidechannel_thread(void *reference); 273static void copy_deviceinfo(CFStringRef deviceIDString, CFStringRef *make, CFStringRef *model, CFStringRef *serial); 274static void copy_devicestring(io_service_t usbInterface, CFStringRef *deviceID, UInt32 *deviceLocation, UInt8 *interfaceNum); 275static void device_added(void *userdata, io_iterator_t iterator); 276static void get_device_id(cups_sc_status_t *status, char *data, int *datalen); 277static void iterate_printers(iterator_callback_t callBack, void *userdata); 278static void parse_options(char *options, char *serial, int serial_size, UInt32 *location, Boolean *wait_eof); 279static void release_deviceinfo(CFStringRef *make, CFStringRef *model, CFStringRef *serial); 280static void setup_cfLanguage(void); 281static void soft_reset(void); 282static void status_timer_cb(CFRunLoopTimerRef timer, void *info); 283static void log_usb_class_driver(int is_64bit); 284#define IS_64BIT 1 285#define IS_NOT_64BIT 0 286 287#if defined(__i386__) || defined(__x86_64__) 288static pid_t child_pid; /* Child PID */ 289static void run_legacy_backend(int argc, char *argv[], int fd) __attribute__((noreturn)); /* Starts child backend process running as a ppc executable */ 290#endif /* __i386__ || __x86_64__ */ 291static void sigterm_handler(int sig); /* SIGTERM handler */ 292static void sigquit_handler(int sig, siginfo_t *si, void *unused) __attribute__((noreturn)); 293 294#ifdef PARSE_PS_ERRORS 295static const char *next_line (const char *buffer); 296static void parse_pserror (char *sockBuffer, int len); 297#endif /* PARSE_PS_ERRORS */ 298 299#pragma mark - 300 301/* 302 * 'list_devices()' - List all USB devices. 303 */ 304 305void list_devices() 306{ 307 iterate_printers(list_device_cb, NULL); 308} 309 310 311/* 312 * 'print_device()' - Print a file to a USB device. 313 */ 314 315int /* O - Exit status */ 316print_device(const char *uri, /* I - Device URI */ 317 const char *hostname, /* I - Hostname/manufacturer */ 318 const char *resource, /* I - Resource/modelname */ 319 char *options, /* I - Device options/serial number */ 320 int print_fd, /* I - File descriptor to print */ 321 int copies, /* I - Copies to print */ 322 int argc, /* I - Number of command-line arguments (6 or 7) */ 323 char *argv[]) /* I - Command-line arguments */ 324{ 325 char serial[1024]; /* Serial number buffer */ 326 OSStatus status; /* Function results */ 327 IOReturn iostatus; /* Current IO status */ 328 pthread_t read_thread_id, /* Read thread */ 329 sidechannel_thread_id;/* Side-channel thread */ 330 int have_sidechannel = 0; /* Was the side-channel thread started? */ 331 struct stat sidechannel_info; /* Side-channel file descriptor info */ 332 char print_buffer[8192], /* Print data buffer */ 333 *print_ptr; /* Pointer into print data buffer */ 334 UInt32 location; /* Unique location in bus topology */ 335 fd_set input_set; /* Input set for select() */ 336 CFStringRef driverBundlePath; /* Class driver path */ 337 int countdown, /* Logging interval */ 338 nfds; /* Number of file descriptors */ 339 ssize_t total_bytes; /* Total bytes written */ 340 UInt32 bytes; /* Bytes written */ 341 struct timeval *timeout, /* Timeout pointer */ 342 tv; /* Time value */ 343 struct timespec cond_timeout; /* pthread condition timeout */ 344 struct sigaction action; /* Actions for POSIX signals */ 345 346 347 (void)uri; 348 349 /* 350 * Catch SIGQUIT to determine who is sending it... 351 */ 352 353 memset(&action, 0, sizeof(action)); 354 action.sa_sigaction = sigquit_handler; 355 action.sa_flags = SA_SIGINFO; 356 sigaction(SIGQUIT, &action, NULL); 357 358 /* 359 * See if the side-channel descriptor is valid... 360 */ 361 362 have_sidechannel = !fstat(CUPS_SC_FD, &sidechannel_info) && 363 S_ISSOCK(sidechannel_info.st_mode); 364 365 /* 366 * Localize using CoreFoundation... 367 */ 368 369 setup_cfLanguage(); 370 371 parse_options(options, serial, sizeof(serial), &location, &g.wait_eof); 372 373 if (resource[0] == '/') 374 resource++; 375 376 g.print_fd = print_fd; 377 g.make = cfstr_create_trim(hostname); 378 g.model = cfstr_create_trim(resource); 379 g.serial = cfstr_create_trim(serial); 380 g.location = location; 381 382 if (!g.make || !g.model) 383 { 384 fprintf(stderr, "DEBUG: Fatal USB error.\n"); 385 _cupsLangPrintFilter(stderr, "ERROR", 386 _("There was an unrecoverable USB error.")); 387 388 if (!g.make) 389 fputs("DEBUG: USB make string is NULL\n", stderr); 390 if (!g.model) 391 fputs("DEBUG: USB model string is NULL\n", stderr); 392 393 return (CUPS_BACKEND_STOP); 394 } 395 396 fputs("STATE: +connecting-to-device\n", stderr); 397 398 countdown = INITIAL_LOG_INTERVAL; 399 400 do 401 { 402 if (g.printer_obj) 403 { 404 IOObjectRelease(g.printer_obj); 405 unload_classdriver(&g.classdriver); 406 g.printer_obj = 0x0; 407 g.classdriver = 0x0; 408 } 409 410 fprintf(stderr, "DEBUG: Looking for '%s %s'\n", hostname, resource); 411 412 iterate_printers(find_device_cb, NULL); 413 414 fputs("DEBUG: Opening connection\n", stderr); 415 416 driverBundlePath = NULL; 417 418 status = registry_open(&driverBundlePath); 419 420#if defined(__i386__) || defined(__x86_64__) 421 /* 422 * If we were unable to load the class drivers for this printer it's 423 * probably because they're ppc or i386. In this case try to run this 424 * backend as i386 or ppc executables so we can use them... 425 */ 426 if (status == -2) 427 { 428 run_legacy_backend(argc, argv, print_fd); 429 /* Never returns here */ 430 } 431#endif /* __i386__ || __x86_64__ */ 432 433 if (status == -2) 434 { 435 /* 436 * If we still were unable to load the class drivers for this printer log 437 * the error and stop the queue... 438 */ 439 440 if (driverBundlePath == NULL || !CFStringGetCString(driverBundlePath, print_buffer, sizeof(print_buffer), kCFStringEncodingUTF8)) 441 strlcpy(print_buffer, "USB class driver", sizeof(print_buffer)); 442 443 fputs("STATE: +apple-missing-usbclassdriver-error\n", stderr); 444 _cupsLangPrintFilter(stderr, "ERROR", 445 _("There was an unrecoverable USB error.")); 446 fprintf(stderr, "DEBUG: Could not load %s\n", print_buffer); 447 448 if (driverBundlePath) 449 CFRelease(driverBundlePath); 450 451 return (CUPS_BACKEND_STOP); 452 } 453 454#ifdef __x86_64__ 455 if (status == noErr && driverBundlePath != NULL && CFStringCompare(driverBundlePath, kUSBGenericTOPrinterClassDriver, 0) != kCFCompareEqualTo) 456 log_usb_class_driver(IS_64BIT); 457#endif /* __x86_64__ */ 458 459 if (driverBundlePath) 460 CFRelease(driverBundlePath); 461 462 if (status != noErr) 463 { 464 sleep(PRINTER_POLLING_INTERVAL); 465 countdown -= PRINTER_POLLING_INTERVAL; 466 if (countdown <= 0) 467 { 468 _cupsLangPrintFilter(stderr, "INFO", 469 _("Waiting for printer to become available.")); 470 fprintf(stderr, "DEBUG: USB printer status: 0x%08x\n", (int)status); 471 countdown = SUBSEQUENT_LOG_INTERVAL; /* subsequent log entries, every 15 seconds */ 472 } 473 } 474 } while (status != noErr); 475 476 fputs("STATE: -connecting-to-device\n", stderr); 477 478 /* 479 * Now that we are "connected" to the port, ignore SIGTERM so that we 480 * can finish out any page data the driver sends (e.g. to eject the 481 * current page... Only ignore SIGTERM if we are printing data from 482 * stdin (otherwise you can't cancel raw jobs...) 483 */ 484 485 if (!print_fd) 486 { 487 memset(&action, 0, sizeof(action)); 488 489 sigemptyset(&action.sa_mask); 490 action.sa_handler = SIG_IGN; 491 sigaction(SIGTERM, &action, NULL); 492 } 493 494 /* 495 * Start the side channel thread if the descriptor is valid... 496 */ 497 498 pthread_mutex_init(&g.readwrite_lock_mutex, NULL); 499 pthread_cond_init(&g.readwrite_lock_cond, NULL); 500 g.readwrite_lock = 1; 501 502 if (have_sidechannel) 503 { 504 g.sidechannel_thread_stop = 0; 505 g.sidechannel_thread_done = 0; 506 507 pthread_cond_init(&g.sidechannel_thread_cond, NULL); 508 pthread_mutex_init(&g.sidechannel_thread_mutex, NULL); 509 510 if (pthread_create(&sidechannel_thread_id, NULL, sidechannel_thread, NULL)) 511 { 512 fprintf(stderr, "DEBUG: Fatal USB error.\n"); 513 _cupsLangPrintFilter(stderr, "ERROR", 514 _("There was an unrecoverable USB error.")); 515 fputs("DEBUG: Couldn't create side-channel thread\n", stderr); 516 registry_close(); 517 return (CUPS_BACKEND_STOP); 518 } 519 } 520 521 /* 522 * Get the read thread going... 523 */ 524 525 g.read_thread_stop = 0; 526 g.read_thread_done = 0; 527 528 pthread_cond_init(&g.read_thread_cond, NULL); 529 pthread_mutex_init(&g.read_thread_mutex, NULL); 530 531 if (pthread_create(&read_thread_id, NULL, read_thread, NULL)) 532 { 533 fprintf(stderr, "DEBUG: Fatal USB error.\n"); 534 _cupsLangPrintFilter(stderr, "ERROR", 535 _("There was an unrecoverable USB error.")); 536 fputs("DEBUG: Couldn't create read thread\n", stderr); 537 registry_close(); 538 return (CUPS_BACKEND_STOP); 539 } 540 541 /* 542 * The main thread sends the print file... 543 */ 544 545 g.drain_output = 0; 546 g.print_bytes = 0; 547 total_bytes = 0; 548 print_ptr = print_buffer; 549 550 while (status == noErr && copies-- > 0) 551 { 552 _cupsLangPrintFilter(stderr, "INFO", _("Sending data to printer.")); 553 554 if (print_fd != STDIN_FILENO) 555 { 556 fputs("PAGE: 1 1\n", stderr); 557 lseek(print_fd, 0, SEEK_SET); 558 } 559 560 while (status == noErr) 561 { 562 FD_ZERO(&input_set); 563 564 if (!g.print_bytes) 565 FD_SET(print_fd, &input_set); 566 567 /* 568 * Calculate select timeout... 569 * If we have data waiting to send timeout is 100ms. 570 * else if we're draining print_fd timeout is 0. 571 * else we're waiting forever... 572 */ 573 574 if (g.print_bytes) 575 { 576 tv.tv_sec = 0; 577 tv.tv_usec = 100000; /* 100ms */ 578 timeout = &tv; 579 } 580 else if (g.drain_output) 581 { 582 tv.tv_sec = 0; 583 tv.tv_usec = 0; 584 timeout = &tv; 585 } 586 else 587 timeout = NULL; 588 589 /* 590 * I/O is unlocked around select... 591 */ 592 593 pthread_mutex_lock(&g.readwrite_lock_mutex); 594 g.readwrite_lock = 0; 595 pthread_cond_signal(&g.readwrite_lock_cond); 596 pthread_mutex_unlock(&g.readwrite_lock_mutex); 597 598 nfds = select(print_fd + 1, &input_set, NULL, NULL, timeout); 599 600 /* 601 * Reacquire the lock... 602 */ 603 604 pthread_mutex_lock(&g.readwrite_lock_mutex); 605 while (g.readwrite_lock) 606 pthread_cond_wait(&g.readwrite_lock_cond, &g.readwrite_lock_mutex); 607 g.readwrite_lock = 1; 608 pthread_mutex_unlock(&g.readwrite_lock_mutex); 609 610 if (nfds < 0) 611 { 612 if (errno == EINTR && total_bytes == 0) 613 { 614 fputs("DEBUG: Received an interrupt before any bytes were " 615 "written, aborting\n", stderr); 616 registry_close(); 617 return (CUPS_BACKEND_OK); 618 } 619 else if (errno != EAGAIN && errno != EINTR) 620 { 621 _cupsLangPrintFilter(stderr, "ERROR", 622 _("Unable to read print data.")); 623 perror("DEBUG: select"); 624 registry_close(); 625 return (CUPS_BACKEND_FAILED); 626 } 627 } 628 629 /* 630 * If drain output has finished send a response... 631 */ 632 633 if (g.drain_output && !nfds && !g.print_bytes) 634 { 635 /* Send a response... */ 636 cupsSideChannelWrite(CUPS_SC_CMD_DRAIN_OUTPUT, CUPS_SC_STATUS_OK, NULL, 0, 1.0); 637 g.drain_output = 0; 638 } 639 640 /* 641 * Check if we have print data ready... 642 */ 643 644 if (FD_ISSET(print_fd, &input_set)) 645 { 646#if DEBUG_WRITES 647 g.debug_bytes += 512; 648 if (g.debug_bytes > sizeof(print_buffer)) 649 g.debug_bytes = 512; 650 651 g.print_bytes = read(print_fd, print_buffer, g.debug_bytes); 652 653#else 654 g.print_bytes = read(print_fd, print_buffer, sizeof(print_buffer)); 655#endif /* DEBUG_WRITES */ 656 657 if (g.print_bytes < 0) 658 { 659 /* 660 * Read error - bail if we don't see EAGAIN or EINTR... 661 */ 662 663 if (errno != EAGAIN && errno != EINTR) 664 { 665 _cupsLangPrintFilter(stderr, "ERROR", 666 _("Unable to read print data.")); 667 perror("DEBUG: read"); 668 registry_close(); 669 return (CUPS_BACKEND_FAILED); 670 } 671 672 g.print_bytes = 0; 673 } 674 else if (g.print_bytes == 0) 675 { 676 /* 677 * End of file, break out of the loop... 678 */ 679 680 break; 681 } 682 683 print_ptr = print_buffer; 684 685 fprintf(stderr, "DEBUG: Read %d bytes of print data...\n", 686 (int)g.print_bytes); 687 } 688 689 if (g.print_bytes) 690 { 691 bytes = (UInt32)g.print_bytes; 692 iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0); 693 694 /* 695 * Ignore timeout errors, but retain the number of bytes written to 696 * avoid sending duplicate data... 697 */ 698 699 if (iostatus == kIOUSBTransactionTimeout) 700 { 701 fputs("DEBUG: Got USB transaction timeout during write\n", stderr); 702 iostatus = 0; 703 } 704 705 /* 706 * If we've stalled, retry the write... 707 */ 708 709 else if (iostatus == kIOUSBPipeStalled) 710 { 711 fputs("DEBUG: Got USB pipe stalled during write\n", stderr); 712 713 bytes = (UInt32)g.print_bytes; 714 iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0); 715 } 716 717 /* 718 * Retry a write after an aborted write since we probably just got 719 * SIGTERM... 720 */ 721 722 else if (iostatus == kIOReturnAborted) 723 { 724 fputs("DEBUG: Got USB return aborted during write\n", stderr); 725 726 IOReturn err = (*g.classdriver)->Abort(g.classdriver); 727 fprintf(stderr, "DEBUG: USB class driver Abort returned %x\n", err); 728 729#if DEBUG_WRITES 730 sleep(5); 731#endif /* DEBUG_WRITES */ 732 733 bytes = (UInt32)g.print_bytes; 734 iostatus = (*g.classdriver)->WritePipe(g.classdriver, (UInt8*)print_ptr, &bytes, 0); 735 } 736 737 if (iostatus) 738 { 739 /* 740 * Write error - bail if we don't see an error we can retry... 741 */ 742 743 _cupsLangPrintFilter(stderr, "ERROR", 744 _("Unable to send data to printer.")); 745 fprintf(stderr, "DEBUG: USB class driver WritePipe returned %x\n", 746 iostatus); 747 748 IOReturn err = (*g.classdriver)->Abort(g.classdriver); 749 fprintf(stderr, "DEBUG: USB class driver Abort returned %x\n", 750 err); 751 752 status = CUPS_BACKEND_FAILED; 753 break; 754 } 755 else if (bytes > 0) 756 { 757 fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes); 758 759 g.print_bytes -= bytes; 760 print_ptr += bytes; 761 total_bytes += bytes; 762 } 763 } 764 765 if (print_fd != 0 && status == noErr) 766 fprintf(stderr, "DEBUG: Sending print file, %lld bytes...\n", 767 (off_t)total_bytes); 768 } 769 } 770 771 fprintf(stderr, "DEBUG: Sent %lld bytes...\n", (off_t)total_bytes); 772 fputs("STATE: +cups-waiting-for-job-completed\n", stderr); 773 774 /* 775 * Signal the side channel thread to exit... 776 */ 777 778 if (have_sidechannel) 779 { 780 close(CUPS_SC_FD); 781 pthread_mutex_lock(&g.readwrite_lock_mutex); 782 g.readwrite_lock = 0; 783 pthread_cond_signal(&g.readwrite_lock_cond); 784 pthread_mutex_unlock(&g.readwrite_lock_mutex); 785 786 g.sidechannel_thread_stop = 1; 787 pthread_mutex_lock(&g.sidechannel_thread_mutex); 788 789 if (!g.sidechannel_thread_done) 790 { 791 gettimeofday(&tv, NULL); 792 cond_timeout.tv_sec = tv.tv_sec + WAIT_SIDE_DELAY; 793 cond_timeout.tv_nsec = tv.tv_usec * 1000; 794 795 while (!g.sidechannel_thread_done) 796 { 797 if (pthread_cond_timedwait(&g.sidechannel_thread_cond, 798 &g.sidechannel_thread_mutex, 799 &cond_timeout) != 0) 800 break; 801 } 802 } 803 804 pthread_mutex_unlock(&g.sidechannel_thread_mutex); 805 } 806 807 /* 808 * Signal the read thread to exit then wait 7 seconds for it to complete... 809 */ 810 811 g.read_thread_stop = 1; 812 813 pthread_mutex_lock(&g.read_thread_mutex); 814 815 if (!g.read_thread_done) 816 { 817 fputs("DEBUG: Waiting for read thread to exit...\n", stderr); 818 819 gettimeofday(&tv, NULL); 820 cond_timeout.tv_sec = tv.tv_sec + WAIT_EOF_DELAY; 821 cond_timeout.tv_nsec = tv.tv_usec * 1000; 822 823 while (!g.read_thread_done) 824 { 825 if (pthread_cond_timedwait(&g.read_thread_cond, &g.read_thread_mutex, 826 &cond_timeout) != 0) 827 break; 828 } 829 830 /* 831 * If it didn't exit abort the pending read and wait an additional second... 832 */ 833 834 if (!g.read_thread_done) 835 { 836 fputs("DEBUG: Read thread still active, aborting the pending read...\n", 837 stderr); 838 839 g.wait_eof = 0; 840 841 (*g.classdriver)->Abort(g.classdriver); 842 843 gettimeofday(&tv, NULL); 844 cond_timeout.tv_sec = tv.tv_sec + 1; 845 cond_timeout.tv_nsec = tv.tv_usec * 1000; 846 847 while (!g.read_thread_done) 848 { 849 if (pthread_cond_timedwait(&g.read_thread_cond, &g.read_thread_mutex, 850 &cond_timeout) != 0) 851 break; 852 } 853 } 854 } 855 856 pthread_mutex_unlock(&g.read_thread_mutex); 857 858 /* 859 * Close the connection and input file and general clean up... 860 */ 861 862 registry_close(); 863 864 if (print_fd != STDIN_FILENO) 865 close(print_fd); 866 867 if (g.make != NULL) 868 CFRelease(g.make); 869 870 if (g.model != NULL) 871 CFRelease(g.model); 872 873 if (g.serial != NULL) 874 CFRelease(g.serial); 875 876 if (g.printer_obj != 0x0) 877 IOObjectRelease(g.printer_obj); 878 879 return status; 880} 881 882 883/* 884 * 'read_thread()' - Thread to read the backchannel data on. 885 */ 886 887static void *read_thread(void *reference) 888{ 889 UInt8 readbuffer[512]; 890 UInt32 rbytes; 891 kern_return_t readstatus; 892 struct mach_timebase_info timeBaseInfo; 893 uint64_t start, 894 delay; 895 896 897 (void)reference; 898 899 /* Calculate what 250 milliSeconds are in mach absolute time... 900 */ 901 mach_timebase_info(&timeBaseInfo); 902 delay = ((uint64_t)250000000 * (uint64_t)timeBaseInfo.denom) / (uint64_t)timeBaseInfo.numer; 903 904 do 905 { 906 /* 907 * Remember when we started so we can throttle the loop after the read call... 908 */ 909 910 start = mach_absolute_time(); 911 912 rbytes = sizeof(readbuffer); 913 readstatus = (*g.classdriver)->ReadPipe(g.classdriver, readbuffer, &rbytes); 914 if (readstatus == kIOReturnSuccess && rbytes > 0) 915 { 916 fprintf(stderr, "DEBUG: Read %d bytes of back-channel data...\n", 917 (int)rbytes); 918 cupsBackChannelWrite((char*)readbuffer, rbytes, 1.0); 919 920 /* cntrl-d is echoed by the printer. 921 * NOTES: 922 * Xerox Phaser 6250D doesn't echo the cntrl-d. 923 * Xerox Phaser 6250D doesn't always send the product query. 924 */ 925 if (g.wait_eof && readbuffer[rbytes-1] == 0x4) 926 break; 927 928#ifdef PARSE_PS_ERRORS 929 parse_pserror(readbuffer, rbytes); 930#endif 931 } 932 else if (readstatus == kIOUSBTransactionTimeout) 933 fputs("DEBUG: Got USB transaction timeout during read\n", stderr); 934 else if (readstatus == kIOUSBPipeStalled) 935 fputs("DEBUG: Got USB pipe stalled during read\n", stderr); 936 else if (readstatus == kIOReturnAborted) 937 fputs("DEBUG: Got USB return aborted during read\n", stderr); 938 939 /* 940 * Make sure this loop executes no more than once every 250 miliseconds... 941 */ 942 943 if ((readstatus != kIOReturnSuccess || rbytes == 0) && (g.wait_eof || !g.read_thread_stop)) 944 mach_wait_until(start + delay); 945 946 } while (g.wait_eof || !g.read_thread_stop); /* Abort from main thread tests error here */ 947 948 /* 949 * Let the main thread know that we have completed the read thread... 950 */ 951 952 pthread_mutex_lock(&g.read_thread_mutex); 953 g.read_thread_done = 1; 954 pthread_cond_signal(&g.read_thread_cond); 955 pthread_mutex_unlock(&g.read_thread_mutex); 956 957 return NULL; 958} 959 960 961/* 962 * 'sidechannel_thread()' - Handle side-channel requests. 963 */ 964 965static void* 966sidechannel_thread(void *reference) 967{ 968 cups_sc_command_t command; /* Request command */ 969 cups_sc_status_t status; /* Request/response status */ 970 char data[2048]; /* Request/response data */ 971 int datalen; /* Request/response data size */ 972 973 974 (void)reference; 975 976 do 977 { 978 datalen = sizeof(data); 979 980 if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0)) 981 { 982 if (status == CUPS_SC_STATUS_TIMEOUT) 983 continue; 984 else 985 break; 986 } 987 988 switch (command) 989 { 990 case CUPS_SC_CMD_SOFT_RESET: /* Do a soft reset */ 991 fputs("DEBUG: CUPS_SC_CMD_SOFT_RESET received from driver...\n", 992 stderr); 993 994 if ((*g.classdriver)->SoftReset != NULL) 995 { 996 soft_reset(); 997 cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, NULL, 0, 1.0); 998 fputs("DEBUG: Returning status CUPS_STATUS_OK with no bytes...\n", 999 stderr); 1000 } 1001 else 1002 { 1003 cupsSideChannelWrite(command, CUPS_SC_STATUS_NOT_IMPLEMENTED, 1004 NULL, 0, 1.0); 1005 fputs("DEBUG: Returning status CUPS_STATUS_NOT_IMPLEMENTED with " 1006 "no bytes...\n", stderr); 1007 } 1008 break; 1009 1010 case CUPS_SC_CMD_DRAIN_OUTPUT: /* Drain all pending output */ 1011 fputs("DEBUG: CUPS_SC_CMD_DRAIN_OUTPUT received from driver...\n", 1012 stderr); 1013 1014 g.drain_output = 1; 1015 break; 1016 1017 case CUPS_SC_CMD_GET_BIDI: /* Is the connection bidirectional? */ 1018 fputs("DEBUG: CUPS_SC_CMD_GET_BIDI received from driver...\n", 1019 stderr); 1020 1021 data[0] = (char)g.bidi_flag; 1022 cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0); 1023 1024 fprintf(stderr, 1025 "DEBUG: Returned CUPS_SC_STATUS_OK with 1 byte (%02X)...\n", 1026 data[0]); 1027 break; 1028 1029 case CUPS_SC_CMD_GET_DEVICE_ID: /* Return IEEE-1284 device ID */ 1030 fputs("DEBUG: CUPS_SC_CMD_GET_DEVICE_ID received from driver...\n", 1031 stderr); 1032 1033 datalen = sizeof(data); 1034 get_device_id(&status, data, &datalen); 1035 cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, datalen, 1.0); 1036 1037 if ((size_t)datalen < sizeof(data)) 1038 data[datalen] = '\0'; 1039 else 1040 data[sizeof(data) - 1] = '\0'; 1041 1042 fprintf(stderr, 1043 "DEBUG: Returning CUPS_SC_STATUS_OK with %d bytes (%s)...\n", 1044 datalen, data); 1045 break; 1046 1047 case CUPS_SC_CMD_GET_STATE: /* Return device state */ 1048 fputs("DEBUG: CUPS_SC_CMD_GET_STATE received from driver...\n", 1049 stderr); 1050 1051 data[0] = CUPS_SC_STATE_ONLINE; 1052 cupsSideChannelWrite(command, CUPS_SC_STATUS_OK, data, 1, 1.0); 1053 1054 fprintf(stderr, 1055 "DEBUG: Returned CUPS_SC_STATUS_OK with 1 byte (%02X)...\n", 1056 data[0]); 1057 break; 1058 1059 default: 1060 fprintf(stderr, "DEBUG: Unknown side-channel command (%d) received " 1061 "from driver...\n", command); 1062 1063 cupsSideChannelWrite(command, CUPS_SC_STATUS_NOT_IMPLEMENTED, 1064 NULL, 0, 1.0); 1065 1066 fputs("DEBUG: Returned CUPS_SC_STATUS_NOT_IMPLEMENTED with no bytes...\n", 1067 stderr); 1068 break; 1069 } 1070 } 1071 while (!g.sidechannel_thread_stop); 1072 1073 pthread_mutex_lock(&g.sidechannel_thread_mutex); 1074 g.sidechannel_thread_done = 1; 1075 pthread_cond_signal(&g.sidechannel_thread_cond); 1076 pthread_mutex_unlock(&g.sidechannel_thread_mutex); 1077 1078 return NULL; 1079} 1080 1081 1082#pragma mark - 1083/* 1084 * 'iterate_printers()' - Iterate over all the printers. 1085 */ 1086 1087static void iterate_printers(iterator_callback_t callBack, 1088 void *userdata) 1089{ 1090 Iterating = 1; 1091 1092 mach_port_t masterPort = 0x0; 1093 kern_return_t kr = IOMasterPort (bootstrap_port, &masterPort); 1094 1095 if (kr == kIOReturnSuccess && masterPort != 0x0) 1096 { 1097 io_iterator_t addIterator = 0x0; 1098 1099 iterator_reference_t reference = { callBack, userdata, true }; 1100 IONotificationPortRef addNotification = IONotificationPortCreate(masterPort); 1101 1102 int klass = kUSBPrintingClass; 1103 int subklass = kUSBPrintingSubclass; 1104 1105 CFNumberRef usb_klass = CFNumberCreate(NULL, kCFNumberIntType, &klass); 1106 CFNumberRef usb_subklass = CFNumberCreate(NULL, kCFNumberIntType, &subklass); 1107 CFMutableDictionaryRef usbPrinterMatchDictionary = IOServiceMatching(kIOUSBInterfaceClassName); 1108 1109 CFDictionaryAddValue(usbPrinterMatchDictionary, CFSTR("bInterfaceClass"), usb_klass); 1110 CFDictionaryAddValue(usbPrinterMatchDictionary, CFSTR("bInterfaceSubClass"), usb_subklass); 1111 1112 CFRelease(usb_klass); 1113 CFRelease(usb_subklass); 1114 1115 IOServiceAddMatchingNotification(addNotification, kIOMatchedNotification, usbPrinterMatchDictionary, &device_added, &reference, &addIterator); 1116 if (addIterator != 0x0) 1117 { 1118 device_added (&reference, addIterator); 1119 1120 if (reference.keepRunning) 1121 { 1122 CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(addNotification), kCFRunLoopDefaultMode); 1123 CFRunLoopRun(); 1124 } 1125 IOObjectRelease(addIterator); 1126 } 1127 mach_port_deallocate(mach_task_self(), masterPort); 1128 } 1129 1130 Iterating = 0; 1131} 1132 1133 1134/* 1135 * 'device_added()' - Device added notifier. 1136 */ 1137 1138static void device_added(void *userdata, 1139 io_iterator_t iterator) 1140{ 1141 iterator_reference_t *reference = userdata; 1142 1143 io_service_t obj; 1144 while (reference->keepRunning && (obj = IOIteratorNext(iterator)) != 0x0) 1145 { 1146 if (reference->callback != NULL) 1147 reference->keepRunning = reference->callback(reference->userdata, obj); 1148 1149 IOObjectRelease(obj); 1150 } 1151 1152 /* One last call to the call back now that we are not longer have printers left to iterate... 1153 */ 1154 if (reference->keepRunning && reference->callback) 1155 reference->keepRunning = reference->callback(reference->userdata, 0x0); 1156 1157 if (!reference->keepRunning) 1158 CFRunLoopStop(CFRunLoopGetCurrent()); 1159} 1160 1161 1162/* 1163 * 'list_device_cb()' - list_device iterator callback. 1164 */ 1165 1166static Boolean list_device_cb(void *refcon, 1167 io_service_t obj) 1168{ 1169 Boolean keepRunning = (obj != 0x0); 1170 1171 1172 (void)refcon; 1173 1174 if (keepRunning) 1175 { 1176 CFStringRef deviceIDString = NULL; 1177 UInt32 deviceLocation = 0; 1178 UInt8 interfaceNum = 0; 1179 1180 copy_devicestring(obj, &deviceIDString, &deviceLocation, &interfaceNum); 1181 if (deviceIDString != NULL) 1182 { 1183 CFStringRef make = NULL, model = NULL, serial = NULL; 1184 char uristr[1024], makestr[1024], modelstr[1024], serialstr[1024]; 1185 char optionsstr[1024], idstr[1024], make_modelstr[1024]; 1186 1187 copy_deviceinfo(deviceIDString, &make, &model, &serial); 1188 CFStringGetCString(deviceIDString, idstr, sizeof(idstr), 1189 kCFStringEncodingUTF8); 1190 backendGetMakeModel(idstr, make_modelstr, sizeof(make_modelstr)); 1191 1192 modelstr[0] = '/'; 1193 1194 if (!make || 1195 !CFStringGetCString(make, makestr, sizeof(makestr), 1196 kCFStringEncodingUTF8)) 1197 strlcpy(makestr, "Unknown", sizeof(makestr)); 1198 1199 if (!model || 1200 !CFStringGetCString(model, &modelstr[1], sizeof(modelstr)-1, 1201 kCFStringEncodingUTF8)) 1202 strlcpy(modelstr + 1, "Printer", sizeof(modelstr) - 1); 1203 1204 optionsstr[0] = '\0'; 1205 if (serial != NULL) 1206 { 1207 CFStringGetCString(serial, serialstr, sizeof(serialstr), kCFStringEncodingUTF8); 1208 snprintf(optionsstr, sizeof(optionsstr), "?serial=%s", serialstr); 1209 } 1210 else if (deviceLocation != 0) 1211 snprintf(optionsstr, sizeof(optionsstr), "?location=%x", (unsigned)deviceLocation); 1212 1213 httpAssembleURI(HTTP_URI_CODING_ALL, uristr, sizeof(uristr), "usb", NULL, makestr, 0, modelstr); 1214 strlcat(uristr, optionsstr, sizeof(uristr)); 1215 1216 cupsBackendReport("direct", uristr, make_modelstr, make_modelstr, idstr, 1217 NULL); 1218 1219 release_deviceinfo(&make, &model, &serial); 1220 CFRelease(deviceIDString); 1221 } 1222 } 1223 1224 return keepRunning; 1225} 1226 1227 1228/* 1229 * 'find_device_cb()' - print_device iterator callback. 1230 */ 1231 1232static Boolean find_device_cb(void *refcon, 1233 io_service_t obj) 1234{ 1235 Boolean keepLooking = true; 1236 1237 if (obj != 0x0) 1238 { 1239 CFStringRef idString = NULL; 1240 UInt32 location = ~0U; 1241 UInt8 interfaceNum = 0; 1242 1243 copy_devicestring(obj, &idString, &location, &interfaceNum); 1244 if (idString != NULL) 1245 { 1246 CFStringRef make = NULL, model = NULL, serial = NULL; 1247 1248 copy_deviceinfo(idString, &make, &model, &serial); 1249 if (make && CFStringCompare(make, g.make, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 1250 { 1251 if (model && CFStringCompare(model, g.model, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 1252 { 1253 if (g.serial != NULL && CFStringGetLength(g.serial) > 0) 1254 { 1255 if (serial != NULL && CFStringCompare(serial, g.serial, kCFCompareCaseInsensitive) == kCFCompareEqualTo) 1256 { 1257 IOObjectRetain(obj); 1258 g.printer_obj = obj; 1259 keepLooking = false; 1260 } 1261 } 1262 else 1263 { 1264 if (g.printer_obj != 0) 1265 IOObjectRelease(g.printer_obj); 1266 1267 g.printer_obj = obj; 1268 IOObjectRetain(obj); 1269 1270 if (g.location == 0 || g.location == location) 1271 keepLooking = false; 1272 } 1273 if ( !keepLooking ) 1274 g.interfaceNum = interfaceNum; 1275 } 1276 } 1277 1278 release_deviceinfo(&make, &model, &serial); 1279 CFRelease(idString); 1280 } 1281 } 1282 else 1283 { 1284 keepLooking = (g.printer_obj == 0); 1285 if (obj == 0x0 && keepLooking) 1286 { 1287 CFRunLoopTimerContext context = { 0, refcon, NULL, NULL, NULL }; 1288 CFRunLoopTimerRef timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + 1.0, 10, 0x0, 0x0, status_timer_cb, &context); 1289 if (timer != NULL) 1290 { 1291 CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); 1292 g.status_timer = timer; 1293 } 1294 } 1295 } 1296 1297 if (!keepLooking && g.status_timer != NULL) 1298 { 1299 fputs("STATE: -offline-report\n", stderr); 1300 _cupsLangPrintFilter(stderr, "INFO", _("The printer is now online.")); 1301 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), g.status_timer, kCFRunLoopDefaultMode); 1302 CFRelease(g.status_timer); 1303 g.status_timer = NULL; 1304 } 1305 1306 return keepLooking; 1307} 1308 1309 1310/* 1311 * 'status_timer_cb()' - Status timer callback. 1312 */ 1313 1314static void status_timer_cb(CFRunLoopTimerRef timer, 1315 void *info) 1316{ 1317 (void)timer; 1318 (void)info; 1319 1320 fputs("STATE: +offline-report\n", stderr); 1321 _cupsLangPrintFilter(stderr, "INFO", _("The printer is offline.")); 1322 1323 if (getenv("CLASS") != NULL) 1324 { 1325 /* 1326 * If the CLASS environment variable is set, the job was submitted 1327 * to a class and not to a specific queue. In this case, we want 1328 * to abort immediately so that the job can be requeued on the next 1329 * available printer in the class. 1330 * 1331 * Sleep 5 seconds to keep the job from requeuing too rapidly... 1332 */ 1333 1334 sleep(5); 1335 1336 exit(CUPS_BACKEND_FAILED); 1337 } 1338} 1339 1340 1341#pragma mark - 1342/* 1343 * 'copy_deviceinfo()' - Copy strings from the 1284 device ID. 1344 */ 1345 1346static void copy_deviceinfo(CFStringRef deviceIDString, 1347 CFStringRef *make, 1348 CFStringRef *model, 1349 CFStringRef *serial) 1350{ 1351 CFStringRef modelKeys[] = { CFSTR("MDL:"), CFSTR("MODEL:"), NULL }; 1352 CFStringRef makeKeys[] = { CFSTR("MFG:"), CFSTR("MANUFACTURER:"), NULL }; 1353 CFStringRef serialKeys[] = { CFSTR("SN:"), CFSTR("SERN:"), NULL }; 1354 1355 if (make != NULL) 1356 *make = copy_value_for_key(deviceIDString, makeKeys); 1357 1358 if (model != NULL) 1359 *model = copy_value_for_key(deviceIDString, modelKeys); 1360 1361 if (serial != NULL) 1362 *serial = copy_value_for_key(deviceIDString, serialKeys); 1363} 1364 1365 1366/* 1367 * 'release_deviceinfo()' - Release deviceinfo strings. 1368 */ 1369 1370static void release_deviceinfo(CFStringRef *make, 1371 CFStringRef *model, 1372 CFStringRef *serial) 1373{ 1374 if (make != NULL && *make != NULL) 1375 { 1376 CFRelease(*make); 1377 *make = NULL; 1378 } 1379 1380 if (model != NULL && *model != NULL) 1381 { 1382 CFRelease(*model); 1383 *model = NULL; 1384 } 1385 1386 if (serial != NULL && *serial != NULL) 1387 { 1388 CFRelease(*serial); 1389 *serial = NULL; 1390 } 1391} 1392 1393 1394#pragma mark - 1395/* 1396 * 'load_classdriver()' - Load a classdriver. 1397 */ 1398 1399static kern_return_t load_classdriver(CFStringRef driverPath, 1400 printer_interface_t interface, 1401 classdriver_t ***printerDriver) 1402{ 1403 kern_return_t kr = kUSBPrinterClassDeviceNotOpen; 1404 classdriver_t **driver = NULL; 1405 CFStringRef bundle = driverPath ? driverPath : kUSBGenericTOPrinterClassDriver; 1406 char bundlestr[1024]; /* Bundle path */ 1407 CFURLRef url; /* URL for driver */ 1408 CFPlugInRef plugin = NULL; /* Plug-in address */ 1409 1410 1411 CFStringGetCString(bundle, bundlestr, sizeof(bundlestr), kCFStringEncodingUTF8); 1412 1413 /* 1414 * Validate permissions for the class driver... 1415 */ 1416 1417 _cups_fc_result_t result = _cupsFileCheck(bundlestr, 1418 _CUPS_FILE_CHECK_DIRECTORY, 1, 1419 Iterating ? NULL : _cupsFileCheckFilter, NULL); 1420 1421 if (result && driverPath) 1422 return (load_classdriver(NULL, interface, printerDriver)); 1423 else if (result) 1424 return (kr); 1425 1426 /* 1427 * Try loading the class driver... 1428 */ 1429 1430 url = CFURLCreateWithFileSystemPath(NULL, bundle, kCFURLPOSIXPathStyle, true); 1431 1432 if (url) 1433 { 1434 plugin = CFPlugInCreate(NULL, url); 1435 CFRelease(url); 1436 } 1437 else 1438 plugin = NULL; 1439 1440 if (plugin) 1441 { 1442 CFArrayRef factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn(kUSBPrinterClassTypeID, plugin); 1443 if (factories != NULL && CFArrayGetCount(factories) > 0) 1444 { 1445 CFUUIDRef factoryID = CFArrayGetValueAtIndex(factories, 0); 1446 IUnknownVTbl **iunknown = CFPlugInInstanceCreate(NULL, factoryID, kUSBPrinterClassTypeID); 1447 if (iunknown != NULL) 1448 { 1449 kr = (*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(kUSBPrinterClassInterfaceID), (LPVOID *)&driver); 1450 if (kr == kIOReturnSuccess && driver != NULL) 1451 { 1452 classdriver_t **genericDriver = NULL; 1453 if (driverPath != NULL && CFStringCompare(driverPath, kUSBGenericTOPrinterClassDriver, 0) != kCFCompareEqualTo) 1454 kr = load_classdriver(NULL, interface, &genericDriver); 1455 1456 if (kr == kIOReturnSuccess) 1457 { 1458 (*driver)->interface = interface; 1459 (*driver)->Initialize(driver, genericDriver); 1460 1461 (*driver)->plugin = plugin; 1462 (*driver)->interface = interface; 1463 *printerDriver = driver; 1464 } 1465 } 1466 (*iunknown)->Release(iunknown); 1467 } 1468 CFRelease(factories); 1469 } 1470 } 1471 1472 fprintf(stderr, "DEBUG: load_classdriver(%s) (kr:0x%08x)\n", bundlestr, (int)kr); 1473 1474 return (kr); 1475} 1476 1477 1478/* 1479 * 'unload_classdriver()' - Unload a classdriver. 1480 */ 1481 1482static kern_return_t unload_classdriver(classdriver_t ***classdriver) 1483{ 1484 if (*classdriver != NULL) 1485 { 1486 (**classdriver)->Release(*classdriver); 1487 *classdriver = NULL; 1488 } 1489 1490 return kIOReturnSuccess; 1491} 1492 1493 1494/* 1495 * 'load_printerdriver()' - Load vendor's classdriver. 1496 * 1497 * If driverBundlePath is not NULL on return it is the callers responsbility to release it! 1498 */ 1499 1500static kern_return_t load_printerdriver(CFStringRef *driverBundlePath) 1501{ 1502 IOCFPlugInInterface **iodev = NULL; 1503 SInt32 score; 1504 kern_return_t kr; 1505 printer_interface_t interface; 1506 HRESULT res; 1507 1508 kr = IOCreatePlugInInterfaceForService(g.printer_obj, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score); 1509 if (kr == kIOReturnSuccess) 1510 { 1511 if ((res = (*iodev)->QueryInterface(iodev, USB_INTERFACE_KIND, (LPVOID *) &interface)) == noErr) 1512 { 1513 *driverBundlePath = IORegistryEntryCreateCFProperty(g.printer_obj, kUSBClassDriverProperty, NULL, kNilOptions); 1514 1515 kr = load_classdriver(*driverBundlePath, interface, &g.classdriver); 1516 1517 if (kr != kIOReturnSuccess) 1518 (*interface)->Release(interface); 1519 } 1520 IODestroyPlugInInterface(iodev); 1521 } 1522 return kr; 1523} 1524 1525 1526/* 1527 * 'registry_open()' - Open a connection to the printer. 1528 */ 1529 1530static kern_return_t registry_open(CFStringRef *driverBundlePath) 1531{ 1532 g.bidi_flag = 0; /* 0=unidirectional */ 1533 1534 kern_return_t kr = load_printerdriver(driverBundlePath); 1535 if (kr != kIOReturnSuccess) 1536 kr = -2; 1537 1538 if (g.classdriver != NULL) 1539 { 1540 (*g.classdriver)->interfaceNumber = g.interfaceNum; 1541 kr = (*g.classdriver)->Open(g.classdriver, g.location, kUSBPrintingProtocolBidirectional); 1542 if (kr != kIOReturnSuccess || (*g.classdriver)->interface == NULL) 1543 { 1544 kr = (*g.classdriver)->Open(g.classdriver, g.location, kUSBPrintingProtocolUnidirectional); 1545 if (kr == kIOReturnSuccess) 1546 { 1547 if ((*g.classdriver)->interface == NULL) 1548 { 1549 (*g.classdriver)->Close(g.classdriver); 1550 kr = -1; 1551 } 1552 } 1553 } 1554 else 1555 g.bidi_flag = 1; /* 1=bidirectional */ 1556 } 1557 1558 if (kr != kIOReturnSuccess) 1559 unload_classdriver(&g.classdriver); 1560 1561 return kr; 1562} 1563 1564 1565/* 1566 * 'registry_close()' - Close the connection to the printer. 1567 */ 1568 1569static kern_return_t registry_close(void) 1570{ 1571 if (g.classdriver != NULL) 1572 (*g.classdriver)->Close(g.classdriver); 1573 1574 unload_classdriver(&g.classdriver); 1575 return kIOReturnSuccess; 1576} 1577 1578 1579/* 1580 * 'copy_deviceid()' - Copy the 1284 device id string. 1581 */ 1582 1583static OSStatus copy_deviceid(classdriver_t **classdriver, 1584 CFStringRef *deviceID) 1585{ 1586 CFStringRef devID = NULL; 1587 CFStringRef deviceMake = NULL; 1588 CFStringRef deviceModel = NULL; 1589 CFStringRef deviceSerial = NULL; 1590 1591 *deviceID = NULL; 1592 1593 OSStatus err = (*classdriver)->GetDeviceID(classdriver, &devID, DEFAULT_TIMEOUT); 1594 1595 copy_deviceinfo(devID, &deviceMake, &deviceModel, &deviceSerial); 1596 1597 if (deviceMake == NULL || deviceModel == NULL || deviceSerial == NULL) 1598 { 1599 IOUSBDeviceDescriptor desc; 1600 iodevice_request_t request; 1601 1602 request.requestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); 1603 request.request = kUSBRqGetDescriptor; 1604 request.value = (kUSBDeviceDesc << 8) | 0; 1605 request.index = 0; 1606 request.length = sizeof(desc); 1607 request.buffer = &desc; 1608 err = (*classdriver)->DeviceRequest(classdriver, &request, DEFAULT_TIMEOUT); 1609 if (err == kIOReturnSuccess) 1610 { 1611 CFMutableStringRef newDevID = CFStringCreateMutable(NULL, 0); 1612 1613 if (deviceMake == NULL) 1614 { 1615 CFStringRef data = NULL; 1616 err = (*classdriver)->GetString(classdriver, desc.iManufacturer, kUSBLanguageEnglish, DEFAULT_TIMEOUT, &data); 1617 if (data != NULL) 1618 { 1619 CFStringAppendFormat(newDevID, NULL, CFSTR("MFG:%@;"), data); 1620 CFRelease(data); 1621 } 1622 } 1623 1624 if (deviceModel == NULL) 1625 { 1626 CFStringRef data = NULL; 1627 err = (*classdriver)->GetString(classdriver, desc.iProduct, kUSBLanguageEnglish, DEFAULT_TIMEOUT, &data); 1628 if (data != NULL) 1629 { 1630 CFStringAppendFormat(newDevID, NULL, CFSTR("MDL:%@;"), data); 1631 CFRelease(data); 1632 } 1633 } 1634 1635 if (deviceSerial == NULL && desc.iSerialNumber != 0) 1636 { 1637 err = (*classdriver)->GetString(classdriver, desc.iSerialNumber, kUSBLanguageEnglish, DEFAULT_TIMEOUT, &deviceSerial); 1638 if (deviceSerial != NULL) 1639 { 1640 CFStringAppendFormat(newDevID, NULL, CFSTR("SERN:%@;"), deviceSerial); 1641 } 1642 } 1643 1644 if (devID != NULL) 1645 { 1646 CFStringAppend(newDevID, devID); 1647 CFRelease(devID); 1648 } 1649 1650 *deviceID = newDevID; 1651 } 1652 } 1653 else 1654 { 1655 *deviceID = devID; 1656 } 1657 1658 if (*deviceID == NULL) 1659 return err; 1660 1661 /* Remove special characters from the serial number */ 1662 CFRange range = (deviceSerial != NULL ? CFStringFind(deviceSerial, CFSTR("+"), 0) : CFRangeMake(0, 0)); 1663 if (range.length == 1) { 1664 range = CFStringFind(*deviceID, deviceSerial, 0); 1665 1666 CFMutableStringRef deviceIDString = CFStringCreateMutableCopy(NULL, 0, *deviceID); 1667 CFStringFindAndReplace(deviceIDString, CFSTR("+"), CFSTR(""), range, 0); 1668 CFRelease(*deviceID); 1669 *deviceID = deviceIDString; 1670 } 1671 1672 release_deviceinfo(&deviceMake, &deviceModel, &deviceSerial); 1673 1674 return err; 1675} 1676 1677 1678/* 1679 * 'copy_devicestring()' - Copy the 1284 device id string. 1680 */ 1681 1682static void copy_devicestring(io_service_t usbInterface, 1683 CFStringRef *deviceID, 1684 UInt32 *deviceLocation, 1685 UInt8 *interfaceNumber ) 1686{ 1687 IOCFPlugInInterface **iodev = NULL; 1688 SInt32 score; 1689 kern_return_t kr; 1690 printer_interface_t interface; 1691 HRESULT res; 1692 classdriver_t **klassDriver = NULL; 1693 CFStringRef driverBundlePath; 1694 1695 if ((kr = IOCreatePlugInInterfaceForService(usbInterface, 1696 kIOUSBInterfaceUserClientTypeID, 1697 kIOCFPlugInInterfaceID, 1698 &iodev, &score)) == kIOReturnSuccess) 1699 { 1700 if ((res = (*iodev)->QueryInterface(iodev, USB_INTERFACE_KIND, (LPVOID *) 1701 &interface)) == noErr) 1702 { 1703 (*interface)->GetLocationID(interface, deviceLocation); 1704 (*interface)->GetInterfaceNumber(interface, interfaceNumber); 1705 1706 driverBundlePath = IORegistryEntryCreateCFProperty(usbInterface, 1707 kUSBClassDriverProperty, 1708 NULL, kNilOptions); 1709 1710 kr = load_classdriver(driverBundlePath, interface, &klassDriver); 1711 1712 if (kr != kIOReturnSuccess && driverBundlePath != NULL) 1713 kr = load_classdriver(NULL, interface, &klassDriver); 1714 1715 if (kr == kIOReturnSuccess && klassDriver != NULL) 1716 copy_deviceid(klassDriver, deviceID); 1717 1718 unload_classdriver(&klassDriver); 1719 1720 if (driverBundlePath != NULL) 1721 CFRelease(driverBundlePath); 1722 1723 /* (*interface)->Release(interface); */ 1724 } 1725 IODestroyPlugInInterface(iodev); 1726 } 1727} 1728 1729 1730#pragma mark - 1731/* 1732 * 'copy_value_for_key()' - Copy value string associated with a key. 1733 */ 1734 1735static CFStringRef copy_value_for_key(CFStringRef deviceID, 1736 CFStringRef *keys) 1737{ 1738 CFStringRef value = NULL; 1739 CFArrayRef kvPairs = deviceID != NULL ? CFStringCreateArrayBySeparatingStrings(NULL, deviceID, CFSTR(";")) : NULL; 1740 CFIndex max = kvPairs != NULL ? CFArrayGetCount(kvPairs) : 0; 1741 CFIndex idx = 0; 1742 1743 while (idx < max && value == NULL) 1744 { 1745 CFStringRef kvpair = CFArrayGetValueAtIndex(kvPairs, idx); 1746 CFIndex idxx = 0; 1747 while (keys[idxx] != NULL && value == NULL) 1748 { 1749 CFRange range = CFStringFind(kvpair, keys[idxx], kCFCompareCaseInsensitive); 1750 if (range.length != -1) 1751 { 1752 if (range.location != 0) 1753 { 1754 CFMutableStringRef theString = CFStringCreateMutableCopy(NULL, 0, kvpair); 1755 CFStringTrimWhitespace(theString); 1756 range = CFStringFind(theString, keys[idxx], kCFCompareCaseInsensitive); 1757 if (range.location == 0) 1758 value = CFStringCreateWithSubstring(NULL, theString, CFRangeMake(range.length, CFStringGetLength(theString) - range.length)); 1759 1760 CFRelease(theString); 1761 } 1762 else 1763 { 1764 CFStringRef theString = CFStringCreateWithSubstring(NULL, kvpair, CFRangeMake(range.length, CFStringGetLength(kvpair) - range.length)); 1765 CFMutableStringRef theString2 = CFStringCreateMutableCopy(NULL, 0, theString); 1766 CFRelease(theString); 1767 1768 CFStringTrimWhitespace(theString2); 1769 value = theString2; 1770 } 1771 } 1772 idxx++; 1773 } 1774 idx++; 1775 } 1776 1777 if (kvPairs != NULL) 1778 CFRelease(kvPairs); 1779 return value; 1780} 1781 1782 1783/* 1784 * 'cfstr_create_trim()' - Create CFString and trim whitespace characters. 1785 */ 1786 1787CFStringRef cfstr_create_trim(const char *cstr) 1788{ 1789 CFStringRef cfstr; 1790 CFMutableStringRef cfmutablestr = NULL; 1791 1792 if ((cfstr = CFStringCreateWithCString(NULL, cstr, kCFStringEncodingUTF8)) != NULL) 1793 { 1794 if ((cfmutablestr = CFStringCreateMutableCopy(NULL, 1024, cfstr)) != NULL) 1795 CFStringTrimWhitespace(cfmutablestr); 1796 1797 CFRelease(cfstr); 1798 } 1799 return (CFStringRef) cfmutablestr; 1800} 1801 1802 1803#pragma mark - 1804/* 1805 * 'parse_options()' - Parse URI options. 1806 */ 1807 1808static void parse_options(char *options, 1809 char *serial, 1810 int serial_size, 1811 UInt32 *location, 1812 Boolean *wait_eof) 1813{ 1814 char sep, /* Separator character */ 1815 *name, /* Name of option */ 1816 *value; /* Value of option */ 1817 1818 1819 if (serial) 1820 *serial = '\0'; 1821 if (location) 1822 *location = 0; 1823 1824 if (!options) 1825 return; 1826 1827 while (*options) 1828 { 1829 /* 1830 * Get the name... 1831 */ 1832 1833 name = options; 1834 1835 while (*options && *options != '=' && *options != '+' && *options != '&') 1836 options ++; 1837 1838 if ((sep = *options) != '\0') 1839 *options++ = '\0'; 1840 1841 if (sep == '=') 1842 { 1843 /* 1844 * Get the value... 1845 */ 1846 1847 value = options; 1848 1849 while (*options && *options != '+' && *options != '&') 1850 options ++; 1851 1852 if (*options) 1853 *options++ = '\0'; 1854 } 1855 else 1856 value = (char *)""; 1857 1858 /* 1859 * Process the option... 1860 */ 1861 1862 if (!_cups_strcasecmp(name, "waiteof")) 1863 { 1864 if (!_cups_strcasecmp(value, "on") || 1865 !_cups_strcasecmp(value, "yes") || 1866 !_cups_strcasecmp(value, "true")) 1867 *wait_eof = true; 1868 else if (!_cups_strcasecmp(value, "off") || 1869 !_cups_strcasecmp(value, "no") || 1870 !_cups_strcasecmp(value, "false")) 1871 *wait_eof = false; 1872 else 1873 _cupsLangPrintFilter(stderr, "WARNING", 1874 _("Boolean expected for waiteof option \"%s\"."), 1875 value); 1876 } 1877 else if (!_cups_strcasecmp(name, "serial")) 1878 strlcpy(serial, value, serial_size); 1879 else if (!_cups_strcasecmp(name, "location") && location) 1880 *location = (UInt32)strtoul(value, NULL, 16); 1881 } 1882} 1883 1884 1885/*! 1886 * @function setup_cfLanguage 1887 * @abstract Convert the contents of the CUPS 'APPLE_LANGUAGE' environment 1888 * variable into a one element CF array of languages. 1889 * 1890 * @discussion Each submitted job comes with a natural language. CUPS passes 1891 * that language in an environment variable. We take that language 1892 * and jam it into the AppleLanguages array so that CF will use 1893 * it when reading localized resources. We need to do this before 1894 * any CF code reads and caches the languages array, so this function 1895 * should be called early in main() 1896 */ 1897static void setup_cfLanguage(void) 1898{ 1899 CFStringRef lang[1] = {NULL}; 1900 CFArrayRef langArray = NULL; 1901 const char *requestedLang = NULL; 1902 1903 if ((requestedLang = getenv("APPLE_LANGUAGE")) == NULL) 1904 requestedLang = getenv("LANG"); 1905 1906 if (requestedLang != NULL) 1907 { 1908 lang[0] = CFStringCreateWithCString(kCFAllocatorDefault, requestedLang, kCFStringEncodingUTF8); 1909 langArray = CFArrayCreate(kCFAllocatorDefault, (const void **)lang, sizeof(lang) / sizeof(lang[0]), &kCFTypeArrayCallBacks); 1910 1911 CFPreferencesSetValue(CFSTR("AppleLanguages"), langArray, kCFPreferencesCurrentApplication, kCFPreferencesAnyUser, kCFPreferencesAnyHost); 1912 fprintf(stderr, "DEBUG: usb: AppleLanguages=\"%s\"\n", requestedLang); 1913 1914 CFRelease(lang[0]); 1915 CFRelease(langArray); 1916 } 1917 else 1918 fputs("DEBUG: usb: LANG and APPLE_LANGUAGE environment variables missing.\n", stderr); 1919} 1920 1921#pragma mark - 1922#if defined(__i386__) || defined(__x86_64__) 1923/*! 1924 * @function run_legacy_backend 1925 * 1926 * @abstract Starts child backend process running as a ppc or i386 executable. 1927 * 1928 * @result Never returns; always calls exit(). 1929 * 1930 * @discussion 1931 */ 1932static void run_legacy_backend(int argc, 1933 char *argv[], 1934 int fd) 1935{ 1936 int i; 1937 int exitstatus = 0; 1938 int childstatus; 1939 pid_t waitpid_status; 1940 char *my_argv[32]; 1941 char *usb_legacy_status; 1942 1943 1944 /* 1945 * If we're running as x86_64 or i386 and couldn't load the class driver 1946 * (because it's ppc or i386), then try to re-exec ourselves in ppc or i386 1947 * mode to try again. If we don't have a ppc or i386 architecture we may be 1948 * running with the same architecture again so guard against this by setting 1949 * and testing an environment variable... 1950 */ 1951 1952# ifdef __x86_64__ 1953 usb_legacy_status = getenv("USB_I386_STATUS"); 1954# else 1955 usb_legacy_status = getenv("USB_PPC_STATUS"); 1956# endif /* __x86_64__ */ 1957 1958 if (!usb_legacy_status) 1959 { 1960 log_usb_class_driver(IS_NOT_64BIT); 1961 1962 /* 1963 * Setup a SIGTERM handler then block it before forking... 1964 */ 1965 1966 int err; /* posix_spawn result */ 1967 struct sigaction action; /* POSIX signal action */ 1968 sigset_t newmask, /* New signal mask */ 1969 oldmask; /* Old signal mask */ 1970 char usbpath[1024]; /* Path to USB backend */ 1971 const char *cups_serverbin;/* Path to CUPS binaries */ 1972 1973 1974 memset(&action, 0, sizeof(action)); 1975 sigaddset(&action.sa_mask, SIGTERM); 1976 action.sa_handler = sigterm_handler; 1977 sigaction(SIGTERM, &action, NULL); 1978 1979 sigemptyset(&newmask); 1980 sigaddset(&newmask, SIGTERM); 1981 sigprocmask(SIG_BLOCK, &newmask, &oldmask); 1982 1983 /* 1984 * Set the environment variable... 1985 */ 1986 1987# ifdef __x86_64__ 1988 setenv("USB_I386_STATUS", "1", false); 1989# else 1990 setenv("USB_PPC_STATUS", "1", false); 1991# endif /* __x86_64__ */ 1992 1993 /* 1994 * Tell the kernel to use the specified CPU architecture... 1995 */ 1996 1997# ifdef __x86_64__ 1998 cpu_type_t cpu = CPU_TYPE_I386; 1999# else 2000 cpu_type_t cpu = CPU_TYPE_POWERPC; 2001# endif /* __x86_64__ */ 2002 size_t ocount = 1; 2003 posix_spawnattr_t attrs; 2004 2005 if (!posix_spawnattr_init(&attrs)) 2006 { 2007 posix_spawnattr_setsigdefault(&attrs, &oldmask); 2008 if (posix_spawnattr_setbinpref_np(&attrs, 1, &cpu, &ocount) || ocount != 1) 2009 { 2010# ifdef __x86_64__ 2011 perror("DEBUG: Unable to set binary preference to i386"); 2012# else 2013 perror("DEBUG: Unable to set binary preference to ppc"); 2014# endif /* __x86_64__ */ 2015 _cupsLangPrintFilter(stderr, "ERROR", 2016 _("Unable to use legacy USB class driver.")); 2017 exit(CUPS_BACKEND_STOP); 2018 } 2019 } 2020 2021 /* 2022 * Set up the arguments and call posix_spawn... 2023 */ 2024 2025 if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL) 2026 cups_serverbin = CUPS_SERVERBIN; 2027 snprintf(usbpath, sizeof(usbpath), "%s/backend/usb", cups_serverbin); 2028 2029 for (i = 0; i < argc && i < (int)(sizeof(my_argv) / sizeof(my_argv[0])) - 1; i ++) 2030 my_argv[i] = argv[i]; 2031 2032 my_argv[i] = NULL; 2033 2034 if ((err = posix_spawn(&child_pid, usbpath, NULL, &attrs, my_argv, 2035 environ)) != 0) 2036 { 2037 fprintf(stderr, "DEBUG: Unable to exec %s: %s\n", usbpath, 2038 strerror(err)); 2039 _cupsLangPrintFilter(stderr, "ERROR", 2040 _("Unable to use legacy USB class driver.")); 2041 exit(CUPS_BACKEND_STOP); 2042 } 2043 2044 /* 2045 * Unblock signals... 2046 */ 2047 2048 sigprocmask(SIG_SETMASK, &oldmask, NULL); 2049 2050 /* 2051 * Close the fds we won't be using then wait for the child backend to exit. 2052 */ 2053 2054 close(fd); 2055 close(1); 2056 2057 fprintf(stderr, "DEBUG: Started usb(legacy) backend (PID %d)\n", 2058 (int)child_pid); 2059 2060 while ((waitpid_status = waitpid(child_pid, &childstatus, 0)) == (pid_t)-1 && errno == EINTR) 2061 usleep(1000); 2062 2063 if (WIFSIGNALED(childstatus)) 2064 { 2065 exitstatus = CUPS_BACKEND_STOP; 2066 fprintf(stderr, "DEBUG: usb(legacy) backend %d crashed on signal %d\n", 2067 child_pid, WTERMSIG(childstatus)); 2068 } 2069 else 2070 { 2071 if ((exitstatus = WEXITSTATUS(childstatus)) != 0) 2072 fprintf(stderr, 2073 "DEBUG: usb(legacy) backend %d stopped with status %d\n", 2074 child_pid, exitstatus); 2075 else 2076 fprintf(stderr, "DEBUG: usb(legacy) backend %d exited with no errors\n", 2077 child_pid); 2078 } 2079 } 2080 else 2081 { 2082 fputs("DEBUG: usb(legacy) backend running native again\n", stderr); 2083 exitstatus = CUPS_BACKEND_STOP; 2084 } 2085 2086 exit(exitstatus); 2087} 2088#endif /* __i386__ || __x86_64__ */ 2089 2090 2091/* 2092 * 'sigterm_handler()' - SIGTERM handler. 2093 */ 2094 2095static void 2096sigterm_handler(int sig) /* I - Signal */ 2097{ 2098#if defined(__i386__) || defined(__x86_64__) 2099 /* 2100 * If we started a child process pass the signal on to it... 2101 */ 2102 2103 if (child_pid) 2104 { 2105 /* 2106 * If we started a child process pass the signal on to it... 2107 */ 2108 2109 int status; 2110 2111 kill(child_pid, sig); 2112 while (waitpid(child_pid, &status, 0) < 0 && errno == EINTR); 2113 2114 if (WIFEXITED(status)) 2115 exit(WEXITSTATUS(status)); 2116 else if (status == SIGTERM || status == SIGKILL) 2117 exit(0); 2118 else 2119 { 2120 fprintf(stderr, "DEBUG: Child crashed on signal %d\n", status); 2121 exit(CUPS_BACKEND_STOP); 2122 } 2123 } 2124#endif /* __i386__ || __x86_64__ */ 2125} 2126 2127 2128/* 2129 * 'sigquit_handler()' - SIGQUIT handler. 2130 */ 2131 2132static void sigquit_handler(int sig, siginfo_t *si, void *unused) 2133{ 2134 char *path; 2135 char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; 2136 static char msgbuf[256] = ""; 2137 2138 2139 (void)sig; 2140 (void)unused; 2141 2142 if (proc_pidpath(si->si_pid, pathbuf, sizeof(pathbuf)) > 0 && 2143 (path = basename(pathbuf)) != NULL) 2144 snprintf(msgbuf, sizeof(msgbuf), "SIGQUIT sent by %s(%d)", path, (int)si->si_pid); 2145 else 2146 snprintf(msgbuf, sizeof(msgbuf), "SIGQUIT sent by PID %d", (int)si->si_pid); 2147 2148 CRSetCrashLogMessage(msgbuf); 2149 2150 abort(); 2151} 2152 2153 2154#ifdef PARSE_PS_ERRORS 2155/* 2156 * 'next_line()' - Find the next line in a buffer. 2157 */ 2158 2159static const char *next_line (const char *buffer) 2160{ 2161 const char *cptr, *lptr = NULL; 2162 2163 for (cptr = buffer; *cptr && lptr == NULL; cptr++) 2164 if (*cptr == '\n' || *cptr == '\r') 2165 lptr = cptr; 2166 return lptr; 2167} 2168 2169 2170/* 2171 * 'parse_pserror()' - Scan the backchannel data for postscript errors. 2172 */ 2173 2174static void parse_pserror(char *sockBuffer, 2175 int len) 2176{ 2177 static char gErrorBuffer[1024] = ""; 2178 static char *gErrorBufferPtr = gErrorBuffer; 2179 static char *gErrorBufferEndPtr = gErrorBuffer + sizeof(gErrorBuffer); 2180 2181 char *pCommentBegin, *pCommentEnd, *pLineEnd; 2182 char *logLevel; 2183 char logstr[1024]; 2184 int logstrlen; 2185 2186 if (gErrorBufferPtr + len > gErrorBufferEndPtr - 1) 2187 gErrorBufferPtr = gErrorBuffer; 2188 if (len > sizeof(gErrorBuffer) - 1) 2189 len = sizeof(gErrorBuffer) - 1; 2190 2191 memcpy(gErrorBufferPtr, (const void *)sockBuffer, len); 2192 gErrorBufferPtr += len; 2193 *(gErrorBufferPtr + 1) = '\0'; 2194 2195 pLineEnd = (char *)next_line((const char *)gErrorBuffer); 2196 while (pLineEnd != NULL) 2197 { 2198 *pLineEnd++ = '\0'; 2199 2200 pCommentBegin = strstr(gErrorBuffer,"%%["); 2201 pCommentEnd = strstr(gErrorBuffer, "]%%"); 2202 if (pCommentBegin != gErrorBuffer && pCommentEnd != NULL) 2203 { 2204 pCommentEnd += 3; /* Skip past "]%%" */ 2205 *pCommentEnd = '\0'; /* There's always room for the nul */ 2206 2207 if (_cups_strncasecmp(pCommentBegin, "%%[ Error:", 10) == 0) 2208 logLevel = "DEBUG"; 2209 else if (_cups_strncasecmp(pCommentBegin, "%%[ Flushing", 12) == 0) 2210 logLevel = "DEBUG"; 2211 else 2212 logLevel = "INFO"; 2213 2214 if ((logstrlen = snprintf(logstr, sizeof(logstr), "%s: %s\n", logLevel, pCommentBegin)) >= sizeof(logstr)) 2215 { 2216 /* If the string was trucnated make sure it has a linefeed before the nul */ 2217 logstrlen = sizeof(logstr) - 1; 2218 logstr[logstrlen - 1] = '\n'; 2219 } 2220 write(STDERR_FILENO, logstr, logstrlen); 2221 } 2222 2223 /* move everything over... */ 2224 strlcpy(gErrorBuffer, pLineEnd, sizeof(gErrorBuffer)); 2225 gErrorBufferPtr = gErrorBuffer; 2226 pLineEnd = (char *)next_line((const char *)gErrorBuffer); 2227 } 2228} 2229#endif /* PARSE_PS_ERRORS */ 2230 2231 2232/* 2233 * 'soft_reset()' - Send a soft reset to the device. 2234 */ 2235 2236static void soft_reset(void) 2237{ 2238 fd_set input_set; /* Input set for select() */ 2239 struct timeval tv; /* Time value */ 2240 char buffer[2048]; /* Buffer */ 2241 struct timespec cond_timeout; /* pthread condition timeout */ 2242 2243 /* 2244 * Send an abort once a second until the I/O lock is released by the main thread... 2245 */ 2246 2247 pthread_mutex_lock(&g.readwrite_lock_mutex); 2248 while (g.readwrite_lock) 2249 { 2250 (*g.classdriver)->Abort(g.classdriver); 2251 2252 gettimeofday(&tv, NULL); 2253 cond_timeout.tv_sec = tv.tv_sec + 1; 2254 cond_timeout.tv_nsec = tv.tv_usec * 1000; 2255 2256 while (g.readwrite_lock) 2257 { 2258 if (pthread_cond_timedwait(&g.readwrite_lock_cond, 2259 &g.readwrite_lock_mutex, 2260 &cond_timeout) != 0) 2261 break; 2262 } 2263 } 2264 2265 g.readwrite_lock = 1; 2266 pthread_mutex_unlock(&g.readwrite_lock_mutex); 2267 2268 /* 2269 * Flush bytes waiting on print_fd... 2270 */ 2271 2272 g.print_bytes = 0; 2273 2274 FD_ZERO(&input_set); 2275 FD_SET(g.print_fd, &input_set); 2276 2277 tv.tv_sec = 0; 2278 tv.tv_usec = 0; 2279 2280 while (select(g.print_fd+1, &input_set, NULL, NULL, &tv) > 0) 2281 if (read(g.print_fd, buffer, sizeof(buffer)) <= 0) 2282 break; 2283 2284 /* 2285 * Send the reset... 2286 */ 2287 2288 (*g.classdriver)->SoftReset(g.classdriver, DEFAULT_TIMEOUT); 2289 2290 /* 2291 * Release the I/O lock... 2292 */ 2293 2294 pthread_mutex_lock(&g.readwrite_lock_mutex); 2295 g.readwrite_lock = 0; 2296 pthread_cond_signal(&g.readwrite_lock_cond); 2297 pthread_mutex_unlock(&g.readwrite_lock_mutex); 2298} 2299 2300 2301/* 2302 * 'get_device_id()' - Return IEEE-1284 device ID. 2303 */ 2304 2305static void get_device_id(cups_sc_status_t *status, 2306 char *data, 2307 int *datalen) 2308{ 2309 CFStringRef deviceIDString = NULL; 2310 2311 /* GetDeviceID */ 2312 copy_deviceid(g.classdriver, &deviceIDString); 2313 2314 if (deviceIDString) 2315 { 2316 CFStringGetCString(deviceIDString, data, *datalen, kCFStringEncodingUTF8); 2317 *datalen = (int)strlen(data); 2318 CFRelease(deviceIDString); 2319 } 2320 *status = CUPS_SC_STATUS_OK; 2321} 2322 2323 2324static void 2325log_usb_class_driver(int is_64bit) /* I - Is the USB class driver 64-bit? */ 2326{ 2327 /* 2328 * Report the usage of legacy USB class drivers to Apple if the user opts into providing 2329 * feedback to Apple... 2330 */ 2331 2332 aslmsg aslm = asl_new(ASL_TYPE_MSG); 2333 if (aslm) 2334 { 2335 ppd_file_t *ppd = ppdOpenFile(getenv("PPD")); 2336 const char *make_model = ppd ? ppd->nickname : NULL; 2337 ppd_attr_t *version = ppdFindAttr(ppd, "FileVersion", ""); 2338 2339 asl_set(aslm, "com.apple.message.domain", "com.apple.printing.usb.64bit"); 2340 asl_set(aslm, "com.apple.message.result", is_64bit ? "yes" : "no"); 2341 asl_set(aslm, "com.apple.message.signature", make_model ? make_model : "Unknown"); 2342 asl_set(aslm, "com.apple.message.signature2", version ? version->value : "?.?"); 2343 asl_set(aslm, "com.apple.message.summarize", "YES"); 2344 asl_log(NULL, aslm, ASL_LEVEL_NOTICE, ""); 2345 asl_free(aslm); 2346 } 2347} 2348 2349 2350/* 2351 * End of "$Id: usb-darwin.c 11668 2014-03-03 20:58:58Z duyk $". 2352 */ 2353