/* netio/fget_netio_timeout.c. Generated from netio_timeout.c.in by configure. */
/*
** Copyright 2000-2004 University of Illinois Board of Trustees
** Copyright 2000-2004 Mark D. Roth
** All rights reserved.
**
** fget_netio_timeout.c - NETIO timeout code
**
** Mark D. Roth <roth@feep.net>
*/
#include <fget_netio_internal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#else
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# endif
#endif
/*
** wait for an I/O operation to complete.
** arguments:
** file descriptor
** write flag (boolean - true for write, false for read)
** timeout value:
** -1 infinite wait
** 0 immediate return (0 second wait)
** (positive) number of seconds to wait
** Returns:
** 0 success
** -1 error
** 1 timed out
*/
int
fget_netio_wait(NETIO *nio, int write_mode, time_t timeout)
{
int i;
#ifdef HAVE_POLL
struct pollfd pfd[1];
int ito;
#else /* ! HAVE_POLL */
fd_set rfds, wfds, efds;
struct timeval tv;
#endif /* HAVE_POLL */
#ifdef DEBUG
printf("==> fget_netio_wait(nio=0x%lx { nio->n_fd=%d }, "
"write_mode=%d, timeout=%lu)\n",
nio, nio->n_fd, write_mode, (unsigned long)timeout);
#endif
#ifdef HAVE_POLL
/*
** if the system supports poll(2), use it
*/
pfd[0].fd = nio->n_fd;
pfd[0].events = (write_mode ? POLLOUT : POLLIN);
pfd[0].revents = 0;
if (timeout == (time_t)-1)
ito = -1;
else
ito = timeout * 1000;
i = poll(pfd, 1, ito);
# ifdef DEBUG
printf(" fget_netio_wait(): poll() returned %d\n", i);
printf(" fget_netio_wait(): pfd[0].revents = %d\n",
pfd[0].revents);
# endif
if (i == -1)
return -1;
if (BIT_ISSET(pfd[0].revents, POLLERR))
{
errno = EIO;
return -1;
}
if (BIT_ISSET(pfd[0].revents, POLLHUP))
{
errno = ECONNRESET;
return -1;
}
if (i == 0)
return 1;
#else /* ! HAVE_POLL */
/*
** if poll(2) is not available, use select(2) instead
*/
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
if (write_mode)
FD_SET(nio->n_fd, &wfds);
else
FD_SET(nio->n_fd, &rfds);
FD_SET(nio->n_fd, &efds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
i = select(FD_SETSIZE, &rfds, &wfds, &efds,
(timeout == (time_t)-1 ? NULL : &tv));
# ifdef DEBUG
printf(" fget_netio_wait(): select() returned %d\n", i);
# endif
if (i == -1)
return -1;
if (FD_ISSET(nio->n_fd, &efds))
{
errno = EIO;
return -1;
}
if (i == 0)
return 1;
#endif /* HAVE_POLL */
#ifdef DEBUG
puts("<== fget_netio_wait(): success");
#endif
return 0;
}
int
fget_netio_eof(NETIO *nio)
{
int i;
char buf[NETIOBUFSIZE];
/* if the EOF flag is set, return true immediately */
if (nio->n_eof)
return 1;
/* otherwise, we need to try poll() */
i = fget_netio_wait(nio, 0, 0);
#ifdef DEBUG
printf(" fget_netio_eof(): "
"fget_netio_wait() returned %d\n", i);
#endif
if (i == -1)
/* error means EOF */
return 1;
if (i == 1)
/* timed out means idle, not EOF */
return 0;
/*
** otherwise, _netio_wait() returned 0, which means there's data
** to be read. however, this is true even when read() would
** return 0, indicating an EOF. so, to distinguish between
** these two cases, we use recv() with MSG_PEEK to see how
** much data is available to be read.
*/
#ifdef DEBUG
printf(" fget_netio_eof(): calling recv()\n");
#endif
i = recv(nio->n_fd, buf, sizeof(buf), MSG_PEEK);
if (i == 0)
/* no data to be read - must be EOF */
return 1;
/*
** either there's data to be read, or it's an error.
** either way, not EOF
*/
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1