/* read_wait.c - Wait for data to read on a fd. * * Copyright (C) 2011, Darren Besler (dbesler@beehive.mb.ca) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program - see the file COPYING. * * See `CHANGES' file for revision history. */ #include #include #include #include #include "libtac.h" /* FIONREAD support for sun */ #ifdef sun #include #endif static int delta_msecs(struct timeval *newer, struct timeval *older) { long deltasecs, deltausecs; struct timeval now; if (newer == NULL) { gettimeofday(&now, NULL); newer = &now; } deltasecs = newer->tv_sec - older->tv_sec; deltausecs = newer->tv_usec - older->tv_usec; if ( newer->tv_usec < older->tv_usec ) { deltasecs--; deltausecs = (1000000+newer->tv_usec) - older->tv_usec; } else { deltausecs = newer->tv_usec - older->tv_usec; } return (deltasecs*1000)+(deltausecs/1000); } /* * tac_read_wait * * Parms: * fd - open fd to wait on till data avail, or timeout * timeout - maximum time to wait in milliseconds * size - amount of data to wait for * 0 : any amount of data * >0 : amount of data to wait for * timeleft - return of time left from timeout * * Returns: * 0 - data avail, no timeout * -1 - timeout * n - errno */ int tac_read_wait(int fd, int timeout, int size, int *time_left) { int retval = 0; int remaining; struct pollfd fds[1]; struct timeval start; gettimeofday(&start, NULL); /* setup for read timeout. * will use poll() as it provides greatest compatibility * vs setsockopt(SO_RCVTIMEO) which isn't supported on Solaris */ remaining = timeout; /* in msecs */ fds[0].fd = fd; fds[0].events = POLLIN; while (remaining > 0) { int rc; int avail = 0; rc = poll(fds, 1, remaining); remaining -= delta_msecs(NULL, &start); if ( time_left != NULL ) { *time_left = remaining > 0 ? remaining : 0; } /* why did poll return */ if (rc == 0) { /* Receive timeout */ retval = -1; break; } if (rc > 0) { /* there is data available */ if (size > 0 && /* check for enuf available? */ ioctl(fd,FIONREAD,(char*)&avail) == 0 && avail < size) { continue; /* not enuf yet, wait for more */ } else { break; } } if (rc < 0 && errno == EINTR) { /* interrupt */ continue; } /* all other conditions is an error */ retval = errno; break; } return retval; } /* read_wait */