diff --git a/Userland/Libraries/LibC/sys/select.cpp b/Userland/Libraries/LibC/sys/select.cpp index be306ec868..186fb845cd 100644 --- a/Userland/Libraries/LibC/sys/select.cpp +++ b/Userland/Libraries/LibC/sys/select.cpp @@ -6,10 +6,13 @@ #include #include +#include #include #include #include +#include + extern "C" { int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout_tv) @@ -25,8 +28,53 @@ int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timev int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const timespec* timeout, const sigset_t* sigmask) { - Syscall::SC_select_params params { nfds, readfds, writefds, exceptfds, timeout, sigmask }; - int rc = syscall(SC_select, ¶ms); - __RETURN_WITH_ERRNO(rc, rc, -1); + Vector fds; + + if (nfds < 0 || static_cast(nfds) >= fds.capacity()) + return EINVAL; + + for (int fd = 0; fd < nfds; fd++) { + short events = 0; + if (readfds && FD_ISSET(fd, readfds)) + events |= POLLIN; + if (writefds && FD_ISSET(fd, writefds)) + events |= POLLOUT; + if (exceptfds && FD_ISSET(fd, exceptfds)) + events |= POLLPRI; + if (!events) + continue; + + fds.unchecked_append({ fd, events, 0 }); + } + + if (ppoll(fds.data(), fds.size(), timeout, sigmask) < 0) + return -1; + + if (readfds) + FD_ZERO(readfds); + if (writefds) + FD_ZERO(writefds); + if (exceptfds) + FD_ZERO(exceptfds); + + int marked_fd_count = 0; + for (auto& fd_entry : fds) { + if (fd_entry.revents == 0) + continue; + if (readfds && (fd_entry.revents & POLLIN)) { + FD_SET(fd_entry.fd, readfds); + marked_fd_count++; + } + if (writefds && (fd_entry.revents & POLLOUT)) { + FD_SET(fd_entry.fd, writefds); + marked_fd_count++; + } + if (exceptfds && (fd_entry.revents & (POLLPRI | POLLERR | POLLHUP))) { + FD_SET(fd_entry.fd, exceptfds); + marked_fd_count++; + } + } + + return marked_fd_count; } }