/* * USB printer backend for CUPS. * * Copyright © 2007-2012 by Apple Inc. * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * Licensed under Apache License v2.0. See the file "LICENSE" for more * information. */ /* * Include necessary headers. */ #ifdef __APPLE__ /* A header order dependency requires this be first */ # include #endif /* __APPLE__ */ #include "backend-private.h" #ifdef _WIN32 # include #else # include # include # include #endif /* _WIN32 */ /* * Local functions... */ void list_devices(void); int print_device(const char *uri, const char *hostname, const char *resource, char *options, int print_fd, int copies, int argc, char *argv[]); /* * Include the vendor-specific USB implementation... */ #ifdef HAVE_LIBUSB # include "usb-libusb.c" #elif defined(__APPLE__) # include "usb-darwin.c" #elif defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) # include "usb-unix.c" #else /* * Use dummy functions that do nothing on unsupported platforms... * These can be used as templates for implementing USB printing on new * platforms... */ /* * 'list_devices()' - List all available USB devices to stdout. */ void list_devices(void) { /* * Don't have any devices to list... Use output of the form: * * direct usb:/make/model?serial=foo "Make Model" "USB Printer" * * Note that "Hewlett Packard" or any other variation MUST be mapped to * "HP" for compatibility with the PPD and ICC specs. */ } /* * 'print_device()' - Print a file to a USB device. */ int /* O - Exit status */ print_device(const char *uri, /* I - Device URI */ const char *hostname, /* I - Hostname/manufacturer */ const char *resource, /* I - Resource/modelname */ char *options, /* I - Device options/serial number */ int print_fd, /* I - File descriptor to print */ int copies, /* I - Copies to print */ int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { /* * Can't print, so just reference the arguments to eliminate compiler * warnings and return and exit status of 1. Normally you would use the * arguments to send a file to the printer and return 0 if everything * worked OK and non-zero if there was an error. */ (void)uri; (void)hostname; (void)resource; (void)options; (void)print_fd; (void)copies; (void)argc; (void)argv; return (CUPS_BACKEND_FAILED); } #endif /* HAVE_LIBUSB */ /* * 'main()' - Send a file to the specified USB port. * * Usage: * * printer-uri job-id user title copies options [file] */ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { int print_fd; /* Print file */ int copies; /* Number of copies to print */ int status; /* Exit status */ int port; /* Port number (not used) */ const char *uri; /* Device URI */ char method[255], /* Method in URI */ hostname[1024], /* Hostname */ username[255], /* Username info (not used) */ resource[1024], /* Resource info (device and options) */ *options; /* Pointer to options */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE signals... */ #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); #else signal(SIGPIPE, SIG_IGN); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc == 1) { list_devices(); return (CUPS_BACKEND_OK); } else if (argc != 6 && argc != 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (CUPS_BACKEND_FAILED); } /* * Extract the device name and options from the URI... */ uri = cupsBackendDeviceURI(argv); if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)) < HTTP_URI_OK) { _cupsLangPrintFilter(stderr, "ERROR", _("No device URI found in argv[0] or in DEVICE_URI " "environment variable.")); return (1); } /* * See if there are any options... */ if ((options = strchr(resource, '?')) != NULL) { /* * Yup, terminate the device name string and move to the first * character of the options... */ *options++ = '\0'; } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, send stdin instead... */ if (argc == 6) { print_fd = 0; copies = 1; } else { /* * Try to open the print file... */ if ((print_fd = open(argv[6], O_RDONLY)) < 0) { _cupsLangPrintError("ERROR", _("Unable to open print file")); return (CUPS_BACKEND_FAILED); } copies = atoi(argv[4]); } /* * Finally, send the print file... */ status = print_device(uri, hostname, resource, options, print_fd, copies, argc, argv); /* * Close the input file and return... */ if (print_fd != 0) close(print_fd); return (status); }