#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/select.h>
#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
ipaddr_t addr, Udpport_t port ));
static int udp_receive _ARGS(( int fd, char *buf, unsigned buflen,
time_t timeout ));
-static void alarm_handler _ARGS(( int sig ));
#endif /* !_MINIX */
return r;
}
-static void alarm_handler(sig)
-int sig;
-{
- signal(SIGALRM, alarm_handler);
- alarm(1);
-}
-
static int udp_receive(fd, buf, buflen, timeout)
int fd;
char *buf;
char *newbuf;
udp_io_hdr_t *udp_io_hdr;
int r, terrno;
- void (*u_handler) _ARGS(( int sig ));
- time_t u_timeout;
-
- newbuf= malloc(sizeof(*udp_io_hdr) + buflen);
+ fd_set readfds;
+ struct timeval timeval;
+
+ /* allocate buffer for packet */
+ newbuf = malloc(sizeof(*udp_io_hdr) + buflen);
if (newbuf == NULL)
{
- errno= ENOMEM;
+ errno = ENOMEM;
return -1;
}
+
+ /* only read if there is something to be read within timeout seconds */
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+ timeval.tv_sec = timeout;
+ timeval.tv_usec = 0;
+ r = select(fd + 1, &readfds, NULL, NULL, &timeval);
+ if (r >= 0 && !FD_ISSET(fd, &readfds))
+ {
+ errno = EINTR;
+ r = -1;
+ }
- u_handler= signal(SIGALRM, alarm_handler);
- u_timeout= alarm(timeout);
-
- r= read(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
- terrno= errno;
+ if (r >= 0)
+ r = read(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
+ /* clean up in case of failure */
+ terrno = errno;
if (r < 0 || r <= sizeof(*udp_io_hdr))
{
if (r > 0)
- r= 0;
- free(newbuf);
-
-
- alarm(0);
- signal(SIGALRM, u_handler);
- alarm(u_timeout);
+ r = 0;
- errno= terrno;
+ free(newbuf);
+ errno = terrno;
return r;
}
+ /* copy packet body to caller-provided buffer */
memcpy(buf, newbuf + sizeof(*udp_io_hdr), r - sizeof(*udp_io_hdr));
free(newbuf);
- alarm(0);
- signal(SIGALRM, u_handler);
- alarm(u_timeout);
-
- return r-sizeof(*udp_io_hdr);
+ return r - sizeof(*udp_io_hdr);
}
#endif