From f783a3d9b01b1214c3f928deddc86ae5a746ebd4 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 8 Jun 2023 16:56:25 -0700 Subject: MacOS port. - The poll function is broken on Darwin (won't handle devices). We make a macpoll out of select and use that. - Makefile adds _D_DARWIN_C_SOURCE to CFLAGS. --- Makefile | 6 +++-- macpoll.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ macpoll.h | 2 ++ pw.c | 3 +++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 macpoll.c create mode 100644 macpoll.h diff --git a/Makefile b/Makefile index f85adbf..9b507f4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ PW_SHA256 := 7361c87eb5e55240a3afbf7f41bc2a08f93e392414103075d3929b5fd53e021c +DARWIN = $(findstring Darwin,$(shell uname)) NEEDED_CFLAGS := -std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ +NEEDED_CFLAGS += $(if $(DARWIN),-D_DARWIN_C_SOURCE) ifeq ($(shell sha256sum pw.c),$(PW_SHA256) pw.c) PW_VERSION := 3 else @@ -11,8 +13,8 @@ override CFLAGS += $(NEEDED_CFLAGS) -DCONFIG_PW_VER=\"$(PW_VERSION)\" DESTDIR ?= /usr/local .PHONY: all fixver all: pw fixver -pw: -clean:; rm -f pw +pw: $(if $(DARWIN),macpoll.o) +clean:; rm -f pw macpoll.o install:; install pw $(DESTDIR)/bin/pw; \ install -D pw.1 $(DESTDIR)/share/man/man1/pw.1; \ install -D pw-relnotes.5 $(DESTDIR)/share/man/man5/pw-relnotes.5 diff --git a/macpoll.c b/macpoll.c new file mode 100644 index 0000000..82e87ac --- /dev/null +++ b/macpoll.c @@ -0,0 +1,83 @@ +// Pipe Watch ("pw") +// Copyright 2022-2023 Kaz Kylheku +// +// BSD-2 License +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +// Would you believe it? MacOS poll() does not support devices, such as TTYs. +// Here we implement a lame poll using the inefficient select function. + +int macpoll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + fd_set readfds, writefds, exceptfds; + struct timeval tv; + int maxfd = 0; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + for (nfds_t i = 0; i < nfds; i++) { + int events = fds[i].events; + int fd = fds[i].fd; + if (fd < 0) + continue; + if (fd > maxfd) + maxfd = fd; + if (events & POLLIN) + FD_SET(fd, &readfds); + if (events & POLLOUT) + FD_SET(fd, &writefds); + if (events & POLLERR) + FD_SET(fd, &exceptfds); + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + int ret = select(maxfd + 1, &readfds, &writefds, &exceptfds, + timeout >= 0 ? &tv : NULL); + + if (ret >= 0) { + for (nfds_t i = 0; i < nfds; i++) { + int fd = fds[i].fd; + int revents = 0; + fds[i].revents = 0; + if (FD_ISSET(fd, &readfds)) + revents |= POLLIN; + if (FD_ISSET(fd, &writefds)) + revents |= POLLOUT; + if (FD_ISSET(fd, &exceptfds)) + revents |= POLLERR; + fds[i].revents = revents; + } + } + + return ret; +} diff --git a/macpoll.h b/macpoll.h new file mode 100644 index 0000000..95dfc04 --- /dev/null +++ b/macpoll.h @@ -0,0 +1,2 @@ +int macpoll(struct pollfd *fds, nfds_t nfds, int timeout); +#define poll macpoll diff --git a/pw.c b/pw.c index 68bf58c..23a7beb 100644 --- a/pw.c +++ b/pw.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef _DARWIN_C_SOURCE +#include "macpoll.h" +#endif #define ctrl(ch) ((ch) & 0x1f) #define BS 8 -- cgit v1.2.3