X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=blobdiff_plain;f=backend%2Fparallel.c;h=125aa8141bdd131284f9bd3021cffabfeeb72a24;hp=d80f8e21460edd9e308d52d1d46bcd04cd5fefd3;hb=771bd8cbffe1ffb06d90b2c7f00191830e6b738c;hpb=ef416fc25c4af449e930416117bedb12fc9924ba diff --git a/backend/parallel.c b/backend/parallel.c index d80f8e214..125aa8141 100644 --- a/backend/parallel.c +++ b/backend/parallel.c @@ -1,25 +1,16 @@ /* - * "$Id: parallel.c 4906 2006-01-10 20:53:28Z mike $" + * "$Id: parallel.c 7810 2008-07-29 01:11:15Z mike $" * - * Parallel port backend for the Common UNIX Printing System (CUPS). + * Parallel port backend for CUPS. * - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2011 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" * "LICENSE" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org + * file is missing or damaged, see the license at "http://www.cups.org/". * * This file is subject to the Apple OS-Developed Software exception. * @@ -27,21 +18,20 @@ * * main() - Send a file to the specified parallel port. * list_devices() - List all parallel devices. + * side_cb() - Handle side-channel requests... */ /* * Include necessary headers. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ieee1284.c" +#include "backend-private.h" + +#ifdef __hpux +# include +#else +# include +#endif /* __hpux */ #ifdef WIN32 # include @@ -68,7 +58,9 @@ * Local functions... */ -void list_devices(void); +static void list_devices(void); +static int side_cb(int print_fd, int device_fd, int snmp_fd, + http_addr_t *addr, int use_bc); /* @@ -89,25 +81,15 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ resource[1024], /* Resource info (device and options) */ *options; /* Pointer to options */ int port; /* Port number (not used) */ - int fp; /* Print file */ + int print_fd, /* Print file */ + device_fd, /* Parallel device */ + use_bc; /* Read back-channel data? */ int copies; /* Number of copies to print */ - int fd; /* Parallel device */ - int rbytes; /* Number of bytes read */ - int wbytes; /* Number of bytes written */ - size_t nbytes, /* Number of bytes read */ - tbytes; /* Total number of bytes written */ - char buffer[8192], /* Output buffer */ - *bufptr; /* Pointer into buffer */ + ssize_t tbytes; /* Total number of bytes written */ struct termios opts; /* Parallel port options */ - fd_set input, /* Input set for select() */ - output; /* Output set for select() */ - int paperout; /* Paper out? */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ -#ifdef __linux - unsigned int status; /* Port status (off-line, out-of-paper, etc.) */ -#endif /* __linux */ /* @@ -141,7 +123,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ } else if (argc < 6 || argc > 7) { - fputs("Usage: parallel job-id user title copies options [file]\n", stderr); + _cupsLangPrintf(stderr, + _("Usage: %s job-id user title copies options [file]"), + argv[0]); return (CUPS_BACKEND_FAILED); } @@ -152,8 +136,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if (argc == 6) { - fp = 0; - copies = 1; + print_fd = 0; + copies = 1; } else { @@ -161,9 +145,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Try to open the print file... */ - if ((fp = open(argv[6], O_RDONLY)) < 0) + if ((print_fd = open(argv[6], O_RDONLY)) < 0) { - perror("ERROR: unable to open print file"); + _cupsLangPrintError("ERROR", _("Unable to open print file")); return (CUPS_BACKEND_FAILED); } @@ -174,8 +158,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Extract the device name and options from the URI... */ - httpSeparateURI(argv[0], method, sizeof(method), username, sizeof(username), - hostname, sizeof(hostname), &port, + httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv), + method, sizeof(method), username, sizeof(username), + hostname, sizeof(hostname), &port, resource, sizeof(resource)); /* @@ -196,9 +181,30 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Open the parallel port device... */ + fputs("STATE: +connecting-to-device\n", stderr); + do { - if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1) +#if defined(__linux) || defined(__FreeBSD__) + /* + * The Linux and FreeBSD parallel port drivers currently are broken WRT + * select() and bidirection I/O... + */ + + device_fd = open(resource, O_WRONLY | O_EXCL); + use_bc = 0; + +#else + if ((device_fd = open(resource, O_RDWR | O_EXCL)) < 0) + { + device_fd = open(resource, O_WRONLY | O_EXCL); + use_bc = 0; + } + else + use_bc = 1; +#endif /* __linux || __FreeBSD__ */ + + if (device_fd == -1) { if (getenv("CLASS") != NULL) { @@ -209,8 +215,9 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * available printer in the class. */ - fputs("INFO: Unable to open parallel port, queuing on next printer in class...\n", - stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("Unable to contact printer, queuing on next " + "printer in class.")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... @@ -223,211 +230,72 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if (errno == EBUSY) { - fputs("INFO: Parallel port busy; will retry in 30 seconds...\n", stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("Printer busy; will retry in 30 seconds.")); sleep(30); } else if (errno == ENXIO || errno == EIO || errno == ENOENT) { - fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("Printer not connected; will retry in 30 " + "seconds.")); sleep(30); } else { - fprintf(stderr, "ERROR: Unable to open parallel port device file \"%s\": %s\n", - resource, strerror(errno)); + _cupsLangPrintError("ERROR", _("Unable to open device file")); return (CUPS_BACKEND_FAILED); } } } - while (fd < 0); + while (device_fd < 0); + + fputs("STATE: -connecting-to-device\n", stderr); /* * Set any options provided... */ - tcgetattr(fd, &opts); + tcgetattr(device_fd, &opts); opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ /**** No options supported yet ****/ - tcsetattr(fd, TCSANOW, &opts); - - /* - * Check printer status... - */ - - paperout = 0; - -#if defined(__linux) && defined(LP_POUTPA) - /* - * Show the printer status before we send the file... - */ - - while (!ioctl(fd, LPGETSTATUS, &status)) - { - fprintf(stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status); - - if (status & LP_POUTPA) - { - fputs("WARNING: Media tray empty!\n", stderr); - fputs("STATUS: +media-tray-empty-error\n", stderr); - - paperout = 1; - } - - if (!(status & LP_PERRORP)) - fputs("WARNING: Printer fault!\n", stderr); - else if (!(status & LP_PSELECD)) - fputs("WARNING: Printer off-line.\n", stderr); - else - break; - - sleep(5); - } -#endif /* __linux && LP_POUTPA */ - - /* - * Now that we are "connected" to the port, ignore SIGTERM so that we - * can finish out any page data the driver sends (e.g. to eject the - * current page... Only ignore SIGTERM if we are printing data from - * stdin (otherwise you can't cancel raw jobs...) - */ - - if (argc < 7) - { -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, SIG_IGN); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, SIG_IGN); -#endif /* HAVE_SIGSET */ - } + tcsetattr(device_fd, TCSANOW, &opts); /* * Finally, send the print file... */ - wbytes = 0; + tbytes = 0; - while (copies > 0) + while (copies > 0 && tbytes >= 0) { copies --; - if (fp != 0) + if (print_fd != 0) { fputs("PAGE: 1 1\n", stderr); - lseek(fp, 0, SEEK_SET); + lseek(print_fd, 0, SEEK_SET); } - tbytes = 0; - while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0) - { - /* - * Write the print data to the printer... - */ - - tbytes += nbytes; - bufptr = buffer; - - while (nbytes > 0) - { - /* - * See if we are ready to read or write... - */ - - do - { - FD_ZERO(&input); - FD_SET(fd, &input); - FD_ZERO(&output); - FD_SET(fd, &output); - } - while (select(fd + 1, &input, &output, NULL, NULL) < 0); - - if (FD_ISSET(fd, &input)) - { - /* - * Read backchannel data... - */ - - if ((rbytes = read(fd, resource, sizeof(resource))) > 0) - { - fprintf(stderr, "DEBUG: Received %d bytes of back-channel data!\n", - rbytes); - cupsBackchannelWrite(resource, rbytes, 1.0); - } - } + tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb); - if (FD_ISSET(fd, &output)) - { - /* - * Write print data... - */ - - if ((wbytes = write(fd, bufptr, nbytes)) < 0) - if (errno == ENOTTY) - wbytes = write(fd, bufptr, nbytes); - - if (wbytes < 0) - { - /* - * Check for retryable errors... - */ - - if (errno == ENOSPC) - { - paperout = 1; - fputs("ERROR: Out of paper!\n", stderr); - fputs("STATUS: +media-tray-empty-error\n", stderr); - } - else if (errno != EAGAIN && errno != EINTR) - { - perror("ERROR: Unable to send print file to printer"); - break; - } - } - else - { - /* - * Update count and pointer... - */ - - if (paperout) - { - fputs("STATUS: -media-tray-empty-error\n", stderr); - paperout = 0; - } - - nbytes -= wbytes; - bufptr += wbytes; - } - } - } - - if (wbytes < 0) - break; - - if (argc > 6) - fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", - (unsigned long)tbytes); - } + if (print_fd != 0 && tbytes >= 0) + _cupsLangPrintFilter(stderr, "INFO", _("Print file sent.")); } /* * Close the socket connection and input file and return... */ - close(fd); - if (fp != 0) - close(fp); + close(device_fd); + + if (print_fd != 0) + close(print_fd); - return (wbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK); + return (CUPS_BACKEND_OK); } @@ -435,7 +303,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * 'list_devices()' - List all parallel devices. */ -void +static void list_devices(void) { #if defined(__hpux) || defined(__sgi) || defined(__sun) @@ -449,15 +317,15 @@ list_devices(void) char device[255], /* Device filename */ basedevice[255], /* Base device filename for ports */ device_id[1024], /* Device ID string */ - make_model[1024]; /* Make and model */ + make_model[1024], /* Make and model */ + info[1024], /* Info string */ + uri[1024]; /* Device URI */ if (!access("/dev/parallel/", 0)) strcpy(basedevice, "/dev/parallel/"); else if (!access("/dev/printers/", 0)) strcpy(basedevice, "/dev/printers/"); - else if (!access("/dev/par0", 0)) - strcpy(basedevice, "/dev/par"); else strcpy(basedevice, "/dev/lp"); @@ -477,13 +345,20 @@ list_devices(void) * Now grab the IEEE 1284 device ID string... */ - if (!get_device_id(fd, device_id, sizeof(device_id), - make_model, sizeof(make_model), - NULL, NULL, 0)) - printf("direct parallel:%s \"%s\" \"%s LPT #%d\" \"%s\"\n", device, - make_model, make_model, i + 1, device_id); + snprintf(uri, sizeof(uri), "parallel:%s", device); + + if (!backendGetDeviceID(fd, device_id, sizeof(device_id), + make_model, sizeof(make_model), + NULL, uri, sizeof(uri))) + { + snprintf(info, sizeof(info), "%s LPT #%d", make_model, i + 1); + cupsBackendReport("direct", uri, make_model, info, device_id, NULL); + } else - printf("direct parallel:%s \"Unknown\" \"LPT #%d\"\n", device, i + 1); + { + snprintf(info, sizeof(info), "LPT #%d", i + 1); + cupsBackendReport("direct", uri, NULL, info, NULL, NULL); + } close(fd); } @@ -685,7 +560,7 @@ list_devices(void) printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1); } } -#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) int i; /* Looping var */ int fd; /* File descriptor */ char device[255]; /* Device filename */ @@ -727,5 +602,75 @@ list_devices(void) /* - * End of "$Id: parallel.c 4906 2006-01-10 20:53:28Z mike $". + * 'side_cb()' - Handle side-channel requests... + */ + +static int /* O - 0 on success, -1 on error */ +side_cb(int print_fd, /* I - Print file */ + int device_fd, /* I - Device file */ + int snmp_fd, /* I - SNMP socket (unused) */ + http_addr_t *addr, /* I - Device address (unused) */ + int use_bc) /* I - Using back-channel? */ +{ + cups_sc_command_t command; /* Request command */ + cups_sc_status_t status; /* Request/response status */ + char data[2048]; /* Request/response data */ + int datalen; /* Request/response data size */ + + + (void)snmp_fd; + (void)addr; + + datalen = sizeof(data); + + if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0)) + return (-1); + + switch (command) + { + case CUPS_SC_CMD_DRAIN_OUTPUT : + if (backendDrainOutput(print_fd, device_fd)) + status = CUPS_SC_STATUS_IO_ERROR; + else if (tcdrain(device_fd)) + status = CUPS_SC_STATUS_IO_ERROR; + else + status = CUPS_SC_STATUS_OK; + + datalen = 0; + break; + + case CUPS_SC_CMD_GET_BIDI : + status = CUPS_SC_STATUS_OK; + data[0] = use_bc; + datalen = 1; + break; + + case CUPS_SC_CMD_GET_DEVICE_ID : + memset(data, 0, sizeof(data)); + + if (backendGetDeviceID(device_fd, data, sizeof(data) - 1, + NULL, 0, NULL, NULL, 0)) + { + status = CUPS_SC_STATUS_NOT_IMPLEMENTED; + datalen = 0; + } + else + { + status = CUPS_SC_STATUS_OK; + datalen = strlen(data); + } + break; + + default : + status = CUPS_SC_STATUS_NOT_IMPLEMENTED; + datalen = 0; + break; + } + + return (cupsSideChannelWrite(command, status, data, datalen, 1.0)); +} + + +/* + * End of "$Id: parallel.c 7810 2008-07-29 01:11:15Z mike $". */