mirror of https://gitee.com/openkylin/cups.git
247 lines
5.6 KiB
C
247 lines
5.6 KiB
C
/*
|
||
* 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 <ApplicationServices/ApplicationServices.h>
|
||
#endif /* __APPLE__ */
|
||
|
||
#include "backend-private.h"
|
||
|
||
#ifdef _WIN32
|
||
# include <io.h>
|
||
#else
|
||
# include <unistd.h>
|
||
# include <fcntl.h>
|
||
# include <termios.h>
|
||
#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);
|
||
}
|