aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-06-08 16:56:25 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-06-08 16:56:25 -0700
commitf783a3d9b01b1214c3f928deddc86ae5a746ebd4 (patch)
tree5ad35446c17d0fc27798073699cd2ad04fd6751b
parentdd79082a94b62e0d8c398dcfad19449e72c542da (diff)
downloadpw-f783a3d9b01b1214c3f928deddc86ae5a746ebd4.tar.gz
pw-f783a3d9b01b1214c3f928deddc86ae5a746ebd4.tar.bz2
pw-f783a3d9b01b1214c3f928deddc86ae5a746ebd4.zip
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.
-rw-r--r--Makefile6
-rw-r--r--macpoll.c83
-rw-r--r--macpoll.h2
-rw-r--r--pw.c3
4 files changed, 92 insertions, 2 deletions
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 <kaz@kylheku.com>
+//
+// 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 <stddef.h>
+#include <sys/select.h>
+#include <poll.h>
+#include <limits.h>
+
+// 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 <errno.h>
#include <signal.h>
#include <regex.h>
+#ifdef _DARWIN_C_SOURCE
+#include "macpoll.h"
+#endif
#define ctrl(ch) ((ch) & 0x1f)
#define BS 8