39 lines
1.2 KiB
C
39 lines
1.2 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "../internal/syscall.h"
|
|
|
|
/*
|
|
* select: plain POSIX select over SYS_pselect6. The kernel wants a struct
|
|
* timespec, so the struct timeval timeout is converted here (NULL passes
|
|
* through as "block indefinitely") and the sigset pair stays NULL: select
|
|
* never changes the signal mask. select() and pselect() share this syscall
|
|
* on Linux; the 6th argument of pselect6 is a { sigset_t *, size_t } pair
|
|
* pointer that is NULL when the mask is left alone.
|
|
*/
|
|
int
|
|
select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
|
{
|
|
struct timespec ts;
|
|
struct timespec *tsp = NULL;
|
|
|
|
if (timeout != NULL)
|
|
{
|
|
if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec >= 1000000L)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
ts.tv_sec = timeout->tv_sec;
|
|
ts.tv_nsec = (long)timeout->tv_usec * 1000;
|
|
tsp = &ts;
|
|
}
|
|
return syscall_ret(__syscall6(SYS_pselect6, (long)nfds, (long)readfds, (long)writefds,
|
|
(long)exceptfds, (long)tsp, 0L));
|
|
}
|