/* 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 */ #include #include #include #include #include #ifdef HAVE_SYS_POLL_H # include #else # ifdef HAVE_SYS_SELECT_H # include # 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; }