about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Darwin.mk4
-rw-r--r--Makefile17
-rw-r--r--sandman.134
-rw-r--r--sandman.m72
4 files changed, 119 insertions, 8 deletions
diff --git a/Darwin.mk b/Darwin.mk
index 7ef8901..d1f26cc 100644
--- a/Darwin.mk
+++ b/Darwin.mk
@@ -1,2 +1,4 @@
 LIBRESSL_PREFIX = /usr/local/opt/libressl
-LDLIBS = -lcurses -ltls
+LDLIBS = -lcurses -ltls -framework Cocoa
+BINS += sandman
+MANS += sandman.1
diff --git a/Makefile b/Makefile
index 14a4a37..e09be8b 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,9 @@ CFLAGS += -I$(LIBRESSL_PREFIX)/include
 LDFLAGS += -L$(LIBRESSL_PREFIX)/lib
 LDLIBS = -lcursesw -ltls
 
+BINS = catgirl
+MANS = catgirl.1
+
 -include config.mk
 
 OBJS += chat.o
@@ -29,7 +32,7 @@ OBJS += url.o
 TESTS += format.t
 TESTS += term.t
 
-all: tags catgirl test
+all: tags $(BINS) test
 
 $(OBJS): chat.h
 
@@ -47,14 +50,14 @@ test: $(TESTS)
 tags: *.h *.c
 	ctags -w *.h *.c
 
-install: catgirl catgirl.1
+install: $(BINS) $(MANS)
 	install -d $(PREFIX)/bin $(MANDIR)1
-	install catgirl $(PREFIX)/bin/catgirl
-	install -m 644 catgirl.1 $(MANDIR)1/catgirl.1
+	install $(BINS) $(PREFIX)/bin
+	install -m 644 $(MANS) $(MANDIR)1
 
 uninstall:
-	rm -f $(PREFIX)/bin/catgirl
-	rm -f $(MANDIR)1/catgirl.1
+	rm -f $(BINS:%=$(PREFIX)/bin/%)
+	rm -f $(MAN:%=%(MANDIR)1/%)
 
 chroot.tar: catgirl catgirl.1 man.sh
 	install -d -o root -g wheel \
@@ -92,7 +95,7 @@ install-chroot: chroot.tar
 	tar -xf chroot.tar -C /home/$(CHROOT_USER)
 
 clean:
-	rm -fr $(OBJS) catgirl $(TESTS) tags root chroot.tar
+	rm -fr $(OBJS) $(BINS) $(TESTS) tags root chroot.tar
 
 README: catgirl.7
 	mandoc catgirl.7 | col -bx > README
diff --git a/sandman.1 b/sandman.1
new file mode 100644
index 0000000..1cd0583
--- /dev/null
+++ b/sandman.1
@@ -0,0 +1,34 @@
+.Dd November 30, 2018
+.Dt SANDMAN 1
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm sandman
+.Nd signal sleep
+.
+.Sh SYNOPSIS
+.Nm
+.Ar command ...
+.
+.Sh DESCRIPTION
+.Nm
+is a utility for Darwin systems.
+.Nm
+runs the
+.Ar command
+in a child process
+and sends it
+.Dv SIGTSTP
+and
+.Dv SIGCONT
+signals
+when the computer goes to sleep
+and wakes from sleep,
+respectively.
+.
+.Sh EXIT STATUS
+.Nm
+exits with the exit status of the child process.
+.
+.Sh SEE ALSO
+.Xr signal 3
diff --git a/sandman.m b/sandman.m
new file mode 100644
index 0000000..12a4817
--- /dev/null
+++ b/sandman.m
@@ -0,0 +1,72 @@
+/* Copyright (C) 2018  Curtis McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <err.h>
+#import <signal.h>
+#import <stdlib.h>
+#import <sysexits.h>
+#import <unistd.h>
+
+void sigchld(int sig) {
+	(void)sig;
+	int status;
+	pid_t pid = wait(&status);
+	if (pid < 0) err(EX_OSERR, "wait");
+	if (WIFSIGNALED(status)) {
+		_exit(128 + WTERMSIG(status));
+	} else {
+		_exit(WEXITSTATUS(status));
+	}
+}
+
+int main(int argc, char *argv[]) {
+	if (argc < 2) return EX_USAGE;
+
+	signal(SIGCHLD, sigchld);
+
+	pid_t pid = fork();
+	if (pid < 0) err(EX_OSERR, "fork");
+
+	if (!pid) {
+		execvp(argv[1], &argv[1]);
+		err(EX_NOINPUT, "%s", argv[1]);
+	}
+
+	NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
+	NSNotificationCenter *center = [workspace notificationCenter];
+	NSOperationQueue *main = [NSOperationQueue mainQueue];
+
+	[center addObserverForName:NSWorkspaceWillSleepNotification
+						object:nil
+						 queue:main
+					usingBlock:^(NSNotification *note) {
+						(void)note;
+						int error = kill(pid, SIGTSTP);
+						if (error) err(EX_UNAVAILABLE, "kill %d", pid);
+					}];
+
+	[center addObserverForName:NSWorkspaceDidWakeNotification
+						object:nil
+						 queue:main
+					usingBlock:^(NSNotification *note) {
+						(void)note;
+						int error = kill(pid, SIGCONT);
+						if (error) err(EX_UNAVAILABLE, "kill %d", pid);
+					}];
+
+	[[NSApplication sharedApplication] run];
+}