#include "backend-private.h"
#include <limits.h>
#ifdef __hpux
# include <sys/time.h>
#else
# include <sys/select.h>
#endif
int
backendDrainOutput(int print_fd,
int device_fd)
{
int nfds;
fd_set input;
ssize_t print_bytes,
bytes;
char print_buffer[8192],
*print_ptr;
struct timeval timeout;
fprintf(stderr, "DEBUG: backendDrainOutput(print_fd=%d, device_fd=%d)\n",
print_fd, device_fd);
nfds = (print_fd > device_fd ? print_fd : device_fd) + 1;
for (;;)
{
FD_ZERO(&input);
FD_SET(print_fd, &input);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (select(nfds, &input, NULL, NULL, &timeout) < 0)
return (-1);
if (!FD_ISSET(print_fd, &input))
return (0);
if ((print_bytes = read(print_fd, print_buffer,
sizeof(print_buffer))) < 0)
{
if (errno != EAGAIN || errno != EINTR)
{
fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno));
_cupsLangPrintFilter(stderr, "ERROR", _("Unable to read print data."));
return (-1);
}
print_bytes = 0;
}
else if (print_bytes == 0)
{
return (0);
}
fprintf(stderr, "DEBUG: Read %d bytes of print data...\n",
(int)print_bytes);
for (print_ptr = print_buffer; print_bytes > 0;)
{
if ((bytes = write(device_fd, print_ptr, print_bytes)) < 0)
{
if (errno != ENOSPC && errno != ENXIO && errno != EAGAIN &&
errno != EINTR && errno != ENOTTY)
{
_cupsLangPrintError("ERROR", _("Unable to write print data"));
return (-1);
}
}
else
{
fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
print_bytes -= bytes;
print_ptr += bytes;
}
}
}
}
ssize_t
backendRunLoop(
int print_fd,
int device_fd,
int snmp_fd,
http_addr_t *addr,
int use_bc,
int update_state,
_cups_sccb_t side_cb)
{
int nfds;
fd_set input,
output;
ssize_t print_bytes,
bc_bytes,
total_bytes,
bytes;
int paperout;
int offline;
char print_buffer[8192],
*print_ptr,
bc_buffer[1024];
struct timeval timeout;
time_t curtime,
snmp_update = 0;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
fprintf(stderr,
"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 (!print_fd)
{
#ifdef HAVE_SIGSET
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
}
else if (print_fd < 0)
{
print_fd = 0;
}
nfds = (print_fd > device_fd ? print_fd : device_fd) + 1;
for (print_bytes = 0, print_ptr = print_buffer, offline = -1,
paperout = -1, total_bytes = 0;;)
{
FD_ZERO(&input);
if (!print_bytes)
FD_SET(print_fd, &input);
if (use_bc)
FD_SET(device_fd, &input);
if (!print_bytes && side_cb)
FD_SET(CUPS_SC_FD, &input);
FD_ZERO(&output);
if (print_bytes || (!use_bc && !side_cb))
FD_SET(device_fd, &output);
if (use_bc || side_cb)
{
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (select(nfds, &input, &output, NULL, &timeout) < 0)
{
if (errno == ENXIO && offline != 1 && update_state)
{
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);
return (0);
}
sleep(1);
continue;
}
}
if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
{
if ((*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc))
side_cb = NULL;
continue;
}
if (FD_ISSET(device_fd, &input))
{
if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
{
fprintf(stderr,
"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;
}
if (FD_ISSET(print_fd, &input))
{
if ((print_bytes = read(print_fd, print_buffer,
sizeof(print_buffer))) < 0)
{
if (errno != EAGAIN || errno != EINTR)
{
fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno));
_cupsLangPrintFilter(stderr, "ERROR",
_("Unable to read print data."));
return (-1);
}
print_bytes = 0;
}
else if (print_bytes == 0)
{
break;
}
print_ptr = print_buffer;
fprintf(stderr, "DEBUG: Read %d bytes of print data...\n",
(int)print_bytes);
}
if (print_bytes && FD_ISSET(device_fd, &output))
{
if ((bytes = write(device_fd, print_ptr, print_bytes)) < 0)
{
if (errno == ENOSPC)
{
if (paperout != 1 && update_state)
{
fputs("STATE: +media-empty-warning\n", stderr);
fputs("DEBUG: Out of paper\n", stderr);
paperout = 1;
}
}
else if (errno == ENXIO)
{
if (offline != 1 && update_state)
{
fputs("STATE: +offline-report\n", stderr);
_cupsLangPrintFilter(stderr, "INFO",
_("The printer is not connected."));
offline = 1;
}
}
else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
{
_cupsLangPrintError("ERROR", _("Unable to write print data"));
return (-1);
}
}
else
{
if (paperout && update_state)
{
fputs("STATE: -media-empty-warning\n", stderr);
paperout = 0;
}
if (offline && update_state)
{
fputs("STATE: -offline-report\n", stderr);
_cupsLangPrintFilter(stderr, "INFO",
_("The printer is now connected."));
offline = 0;
}
fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
print_bytes -= bytes;
print_ptr += bytes;
total_bytes += bytes;
}
}
if (snmp_fd >= 0 && time(&curtime) >= snmp_update)
{
if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
snmp_update = INT_MAX;
else
snmp_update = curtime + 5;
}
}
return (total_bytes);
}
int
backendWaitLoop(
int snmp_fd,
http_addr_t *addr,
int use_bc,
_cups_sccb_t side_cb)
{
int nfds;
fd_set input;
time_t curtime = 0,
snmp_update = 0;
struct timeval timeout;
fprintf(stderr, "DEBUG: backendWaitLoop(snmp_fd=%d, addr=%p, side_cb=%p)\n",
snmp_fd, addr, side_cb);
if (snmp_fd >= 0)
snmp_update = time(NULL) + 5;
for (;;)
{
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)
{
if (errno == EINTR)
{
fputs("DEBUG: Received an interrupt before any bytes were "
"written, aborting.\n", stderr);
return (0);
}
sleep(1);
continue;
}
if (FD_ISSET(0, &input))
break;
if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
{
if ((*side_cb)(0, -1, snmp_fd, addr, use_bc))
side_cb = NULL;
continue;
}
if (snmp_fd >= 0 && curtime >= snmp_update)
{
if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
snmp_fd = -1;
else
snmp_update = curtime + 5;
}
}
return (1);
}