X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=backend%2Frunloop.c;h=0b3f65f7864a55a80304a3b16f24eb6ba348e839;hb=23ef1cac65a36f01e78a88f4d987e6350b441990;hp=647c794889a39e1c060d5a184e25d09078025c1e;hpb=09a101d671d39312a756c325d8463a1a02f582a6;p=thirdparty%2Fcups.git diff --git a/backend/runloop.c b/backend/runloop.c index 647c79488..0b3f65f78 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -1,25 +1,16 @@ /* - * "$Id: runloop.c 6591 2007-06-21 20:35:28Z mike $" + * "$Id: runloop.c 9565 2011-02-23 00:08:08Z mike $" * - * Common run loop APIs for the Common UNIX Printing System (CUPS). + * Common run loop APIs for CUPS backends. * + * Copyright 2007-2012 by Apple Inc. * Copyright 2006-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,6 +18,8 @@ * * backendDrainOutput() - Drain pending print data to the device. * backendRunLoop() - Read and write print and back-channel data. + * backendWaitLoop() - Wait for input from stdin while handling + * side-channel queries. */ /* @@ -34,6 +27,7 @@ */ #include "backend-private.h" +#include #ifdef __hpux # include #else @@ -98,7 +92,8 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */ if (errno != EAGAIN || errno != EINTR) { - perror("ERROR: Unable to read print data"); + fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno)); + _cupsLangPrintFilter(stderr, "ERROR", _("Unable to read print data.")); return (-1); } @@ -127,8 +122,7 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */ if (errno != ENOSPC && errno != ENXIO && errno != EAGAIN && errno != EINTR && errno != ENOTTY) { - fprintf(stderr, _("ERROR: Unable to write print data: %s\n"), - strerror(errno)); + _cupsLangPrintError("ERROR", _("Unable to write print data")); return (-1); } } @@ -150,10 +144,13 @@ backendDrainOutput(int print_fd, /* I - Print file descriptor */ ssize_t /* O - Total bytes on success, -1 on error */ backendRunLoop( - int print_fd, /* I - Print file descriptor */ - int device_fd, /* I - Device file descriptor */ - int use_bc, /* I - Use back-channel? */ - void (*side_cb)(int, int, int)) /* I - Side-channel callback */ + int print_fd, /* I - Print file descriptor */ + int device_fd, /* I - Device file descriptor */ + int snmp_fd, /* I - SNMP socket or -1 if none */ + http_addr_t *addr, /* I - Address of device */ + int use_bc, /* I - Use back-channel? */ + int update_state, /* I - Update printer-state-reasons? */ + _cups_sccb_t side_cb) /* I - Side-channel callback */ { int nfds; /* Maximum file descriptor value + 1 */ fd_set input, /* Input set for reading */ @@ -167,15 +164,18 @@ backendRunLoop( char print_buffer[8192], /* Print data buffer */ *print_ptr, /* Pointer into print data buffer */ bc_buffer[1024]; /* Back-channel data buffer */ + struct timeval timeout; /* Timeout for select() */ + time_t curtime, /* Current time */ + snmp_update = 0; #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ fprintf(stderr, - "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, use_bc=%d, " - "side_cb=%p)\n", - print_fd, device_fd, use_bc, side_cb); + "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, snmp_fd=%d, " + "addr=%p, use_bc=%d, side_cb=%p)\n", + print_fd, device_fd, snmp_fd, addr, use_bc, side_cb); /* * If we are printing data from a print driver on stdin, ignore SIGTERM @@ -198,6 +198,14 @@ backendRunLoop( signal(SIGTERM, SIG_IGN); #endif /* HAVE_SIGSET */ } + else if (print_fd < 0) + { + /* + * Copy print data from stdin, but don't mess with the signal handlers... + */ + + print_fd = 0; + } /* * Figure out the maximum file descriptor value to use with select()... @@ -221,31 +229,35 @@ backendRunLoop( FD_SET(print_fd, &input); if (use_bc) FD_SET(device_fd, &input); - if (side_cb) + if (!print_bytes && side_cb) FD_SET(CUPS_SC_FD, &input); FD_ZERO(&output); - if (print_bytes || !use_bc) + if (print_bytes || (!use_bc && !side_cb)) FD_SET(device_fd, &output); if (use_bc || side_cb) { - if (select(nfds, &input, &output, NULL, NULL) < 0) + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + if (select(nfds, &input, &output, NULL, &timeout) < 0) { /* * Pause printing to clear any pending errors... */ - if (errno == ENXIO && offline != 1) + if (errno == ENXIO && offline != 1 && update_state) { - fputs("STATE: +offline-error\n", stderr); - fputs(_("INFO: Printer is currently off-line.\n"), stderr); + fputs("STATE: +offline-report\n", stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("The printer is not connected.")); offline = 1; } else if (errno == EINTR && total_bytes == 0) { fputs("DEBUG: Received an interrupt before any bytes were " - "written, aborting!\n", stderr); + "written, aborting.\n", stderr); return (0); } @@ -259,7 +271,16 @@ backendRunLoop( */ if (side_cb && FD_ISSET(CUPS_SC_FD, &input)) - (*side_cb)(print_fd, device_fd, use_bc); + { + /* + * Do the side-channel request, then start back over in the select + * loop since it may have read from print_fd... + */ + + if ((*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc)) + side_cb = NULL; + continue; + } /* * Check if we have back-channel data ready... @@ -270,10 +291,18 @@ backendRunLoop( if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0) { fprintf(stderr, - "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n", + "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n", CUPS_LLCAST bc_bytes); cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0); } + else if (bc_bytes < 0 && errno != EAGAIN && errno != EINTR) + { + fprintf(stderr, "DEBUG: Error reading back-channel data: %s\n", + strerror(errno)); + use_bc = 0; + } + else if (bc_bytes == 0) + use_bc = 0; } /* @@ -291,7 +320,9 @@ backendRunLoop( if (errno != EAGAIN || errno != EINTR) { - perror("ERROR: Unable to read print data"); + fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno)); + _cupsLangPrintFilter(stderr, "ERROR", + _("Unable to read print data.")); return (-1); } @@ -327,41 +358,42 @@ backendRunLoop( if (errno == ENOSPC) { - if (paperout != 1) + if (paperout != 1 && update_state) { - fputs("STATE: +media-empty-error\n", stderr); - fputs(_("ERROR: Out of paper!\n"), stderr); + fputs("STATE: +media-empty-warning\n", stderr); + fputs("DEBUG: Out of paper\n", stderr); paperout = 1; } } else if (errno == ENXIO) { - if (offline != 1) + if (offline != 1 && update_state) { - fputs("STATE: +offline-error\n", stderr); - fputs(_("INFO: Printer is currently off-line.\n"), stderr); + fputs("STATE: +offline-report\n", stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("The printer is not connected.")); offline = 1; } } else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY) { - fprintf(stderr, _("ERROR: Unable to write print data: %s\n"), - strerror(errno)); + _cupsLangPrintError("ERROR", _("Unable to write print data")); return (-1); } } else { - if (paperout) + if (paperout && update_state) { - fputs("STATE: -media-empty-error\n", stderr); + fputs("STATE: -media-empty-warning\n", stderr); paperout = 0; } - if (offline) + if (offline && update_state) { - fputs("STATE: -offline-error\n", stderr); - fputs(_("INFO: Printer is now on-line.\n"), stderr); + fputs("STATE: -offline-report\n", stderr); + _cupsLangPrintFilter(stderr, "INFO", + _("The printer is now connected.")); offline = 0; } @@ -372,6 +404,18 @@ backendRunLoop( total_bytes += bytes; } } + + /* + * Do SNMP updates periodically... + */ + + if (snmp_fd >= 0 && time(&curtime) >= snmp_update) + { + if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL)) + snmp_update = INT_MAX; + else + snmp_update = curtime + 5; + } } /* @@ -383,5 +427,117 @@ backendRunLoop( /* - * End of "$Id: runloop.c 6591 2007-06-21 20:35:28Z mike $". + * 'backendWaitLoop()' - Wait for input from stdin while handling side-channel + * queries. + */ + +int /* O - 1 if data is ready, 0 if not */ +backendWaitLoop( + int snmp_fd, /* I - SNMP socket or -1 if none */ + http_addr_t *addr, /* I - Address of device */ + int use_bc, /* I - Use back-channel? */ + _cups_sccb_t side_cb) /* I - Side-channel callback */ +{ + int nfds; /* Number of file descriptors */ + fd_set input; /* Input set for reading */ + time_t curtime = 0, /* Current time */ + snmp_update = 0;/* Last SNMP status update */ + struct timeval timeout; /* Timeout for select() */ + + + fprintf(stderr, "DEBUG: backendWaitLoop(snmp_fd=%d, addr=%p, side_cb=%p)\n", + snmp_fd, addr, side_cb); + + /* + * Now loop until we receive data from stdin... + */ + + if (snmp_fd >= 0) + snmp_update = time(NULL) + 5; + + for (;;) + { + /* + * Use select() to determine whether we have data to copy around... + */ + + FD_ZERO(&input); + FD_SET(0, &input); + if (side_cb) + FD_SET(CUPS_SC_FD, &input); + + if (snmp_fd >= 0) + { + curtime = time(NULL); + timeout.tv_sec = curtime >= snmp_update ? 0 : snmp_update - curtime; + timeout.tv_usec = 0; + + nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout); + } + else + nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, NULL); + + if (nfds < 0) + { + /* + * Pause printing to clear any pending errors... + */ + + if (errno == EINTR) + { + fputs("DEBUG: Received an interrupt before any bytes were " + "written, aborting.\n", stderr); + return (0); + } + + sleep(1); + continue; + } + + /* + * Check for input on stdin... + */ + + if (FD_ISSET(0, &input)) + break; + + /* + * Check if we have a side-channel request ready... + */ + + if (side_cb && FD_ISSET(CUPS_SC_FD, &input)) + { + /* + * Do the side-channel request, then start back over in the select + * loop since it may have read from print_fd... + */ + + if ((*side_cb)(0, -1, snmp_fd, addr, use_bc)) + side_cb = NULL; + continue; + } + + /* + * Do SNMP updates periodically... + */ + + if (snmp_fd >= 0 && curtime >= snmp_update) + { + if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL)) + snmp_fd = -1; + else + snmp_update = curtime + 5; + } + } + + /* + * Return with success... + */ + + return (1); +} + + +/* + * End of "$Id: runloop.c 9565 2011-02-23 00:08:08Z mike $". */