/*
* "$Id: sidechannel.c 7720 2008-07-11 22:46:21Z mike $"
*
- * Side-channel API code for the Common UNIX Printing System (CUPS).
+ * Side-channel API code for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
*/
#include "sidechannel.h"
-#include "string.h"
-#include "debug.h"
-#include <unistd.h>
-#include <errno.h>
+#include "string-private.h"
+#include "debug-private.h"
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 */
#ifdef __hpux
# include <sys/time.h>
-#else
+#elif !defined(WIN32)
# include <sys/select.h>
#endif /* __hpux */
#ifndef WIN32
char buffer[16388]; /* Message buffer */
int bytes; /* Bytes read */
int templen; /* Data length from message */
+ int nfds; /* Number of file descriptors */
#ifdef HAVE_POLL
struct pollfd pfd; /* Poll structure for poll() */
#else /* select() */
pfd.fd = CUPS_SC_FD;
pfd.events = POLLIN;
- if (timeout < 0.0)
- {
- if (poll(&pfd, 1, -1) < 1)
- return (-1);
- }
- else if (poll(&pfd, 1, (long)(timeout * 1000)) < 1)
- return (-1);
+ while ((nfds = poll(&pfd, 1,
+ timeout < 0.0 ? -1 : (long)(timeout * 1000))) < 0 &&
+ (errno == EINTR || errno == EAGAIN))
+ ;
#else /* select() */
FD_ZERO(&input_set);
FD_SET(CUPS_SC_FD, &input_set);
- if (timeout < 0.0)
- {
- if (select(CUPS_SC_FD + 1, &input_set, NULL, NULL, NULL) < 1)
- {
- DEBUG_printf(("1cupsSideChannelRead: Select error: %s", strerror(errno)));
- return (-1);
- }
- }
- else
- {
- stimeout.tv_sec = (int)timeout;
- stimeout.tv_usec = (int)(timeout * 1000000) % 1000000;
+ stimeout.tv_sec = (int)timeout;
+ stimeout.tv_usec = (int)(timeout * 1000000) % 1000000;
+
+ while ((nfds = select(CUPS_SC_FD + 1, &input_set, NULL, NULL,
+ timeout < 0.0 ? NULL : &stimeout)) < 0 &&
+ (errno == EINTR || errno == EAGAIN))
+ ;
- if (select(CUPS_SC_FD + 1, &input_set, NULL, NULL, &stimeout) < 1)
- {
- DEBUG_puts("1cupsSideChannelRead: Select timeout");
- return (-1);
- }
- }
#endif /* HAVE_POLL */
+ if (nfds < 1)
+ {
+ *status = nfds==0 ? CUPS_SC_STATUS_TIMEOUT : CUPS_SC_STATUS_IO_ERROR;
+ return (-1);
+ }
+
/*
* Read a side-channel message for the format:
*
if (errno != EINTR && errno != EAGAIN)
{
DEBUG_printf(("1cupsSideChannelRead: Read error: %s", strerror(errno)));
+ *command = CUPS_SC_CMD_NONE;
+ *status = CUPS_SC_STATUS_IO_ERROR;
return (-1);
}
+ /*
+ * Watch for EOF or too few bytes...
+ */
+
+ if (bytes < 4)
+ {
+ DEBUG_printf(("1cupsSideChannelRead: Short read of %d bytes", bytes));
+ *command = CUPS_SC_CMD_NONE;
+ *status = CUPS_SC_STATUS_BAD_MESSAGE;
+ return (-1);
+ }
+
/*
* Validate the command code in the message...
*/
buffer[0] > CUPS_SC_CMD_SNMP_GET_NEXT)
{
DEBUG_printf(("1cupsSideChannelRead: Bad command %d!", buffer[0]));
+ *command = CUPS_SC_CMD_NONE;
+ *status = CUPS_SC_STATUS_BAD_MESSAGE;
return (-1);
}
real_oidlen, /* Length of returned OID string */
oidlen; /* Length of first OID */
const char *current_oid; /* Current OID */
+ char last_oid[2048]; /* Last OID */
DEBUG_printf(("cupsSideChannelSNMPWalk(oid=\"%s\", timeout=%.3f, cb=%p, "
current_oid = oid;
oidlen = (int)strlen(oid);
+ last_oid[0] = '\0';
do
{
* Parse the response of the form "oid\0value"...
*/
- if (strncmp(real_data, oid, oidlen) || real_data[oidlen] != '.')
+ if (strncmp(real_data, oid, oidlen) || real_data[oidlen] != '.' ||
+ !strcmp(real_data, last_oid))
{
/*
* Done with this set of OIDs...
*/
current_oid = real_data;
+ strlcpy(last_oid, current_oid, sizeof(last_oid));
}
}
while (status == CUPS_SC_STATUS_OK);