summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--www/git.causal.agency/.gitignore5
-rw-r--r--www/git.causal.agency/Makefile26
-rw-r--r--www/git.causal.agency/about-filter.sh16
-rw-r--r--www/git.causal.agency/email-filter.sh6
-rw-r--r--www/git.causal.agency/filter.c156
-rw-r--r--www/git.causal.agency/owner-filter.sh6
-rw-r--r--www/git.causal.agency/source-filter.sh20
7 files changed, 169 insertions, 66 deletions
diff --git a/www/git.causal.agency/.gitignore b/www/git.causal.agency/.gitignore
index 40b3dcbf..25e26cc8 100644
--- a/www/git.causal.agency/.gitignore
+++ b/www/git.causal.agency/.gitignore
@@ -1,15 +1,12 @@
 about-filter
-cat
 compress
 ctags
 email-filter
+filter
 gzip
 hilex
 htagml
 mandoc
-mktemp
 mtags
 owner-filter
-rm
-sh
 source-filter
diff --git a/www/git.causal.agency/Makefile b/www/git.causal.agency/Makefile
index 76c93d3a..f05d4a4a 100644
--- a/www/git.causal.agency/Makefile
+++ b/www/git.causal.agency/Makefile
@@ -3,46 +3,44 @@ CONFDIR = ${PREFIX}/conf
 DATADIR = ${PREFIX}/cgit
 BINDIR = ${PREFIX}/bin
 
+CFLAGS += -Wall -Wextra
+LDFLAGS = -static -pie
+
 BINS += about-filter
-BINS += cat
-BINS += compress
 BINS += ctags
 BINS += email-filter
 BINS += gzip
 BINS += hilex
 BINS += htagml
 BINS += mandoc
-BINS += mktemp
 BINS += mtags
 BINS += owner-filter
-BINS += rm
-BINS += sh
 BINS += source-filter
 
 all: ${BINS}
 
-cat rm sh:
-	cp /bin/$@ $@
-
-compress ctags mandoc mktemp:
-	${MAKE} -C /usr/src/usr.bin/$@ LDFLAGS='-static -pie'
+compress ctags mandoc:
+	${MAKE} -C /usr/src/usr.bin/$@ LDFLAGS='${LDFLAGS}'
 	mv /usr/src/usr.bin/$@/$@ $@
 	${MAKE} -C /usr/src/usr.bin/$@ clean
 
 gzip: compress
-	cp compress $@
+	ln -f compress $@
 
 hilex htagml mtags:
 	rm -f ../../bin/$@
-	${MAKE} -C ../../bin $@ LDFLAGS='-static -pie'
+	${MAKE} -C ../../bin $@ LDFLAGS='${LDFLAGS}'
 	mv ../../bin/$@ $@
 
+about-filter email-filter owner-filter source-filter: filter
+	ln -f filter $@
+
 install: cgitrc custom.css ${BINS}
 	install -m 644 cgitrc ${CONFDIR}
 	install -m 644 custom.css ${DATADIR}
 	install -d -o www -g daemon ${PREFIX}/cache/cgit
 	install -d -m 1700 -o www -g daemon ${PREFIX}/tmp
-	install ${BINS} ${BINDIR}
+	install -s ${BINS} ${BINDIR}
 
 clean:
-	rm -f ${BINS}
+	rm -f compress filter ${BINS}
diff --git a/www/git.causal.agency/about-filter.sh b/www/git.causal.agency/about-filter.sh
deleted file mode 100644
index 7a93d471..00000000
--- a/www/git.causal.agency/about-filter.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-set -eu
-
-options=fragment,man=%N.%S,includes=../tree/%I
-
-case "$1" in
-	(README.[1-9])
-		exec mandoc -T html -O $options
-		;;
-	(*.[1-9])
-		exec mandoc -T html -O $options,toc
-		;;
-	(*)
-		exec hilex -l text -f html -o pre
-		;;
-esac
diff --git a/www/git.causal.agency/email-filter.sh b/www/git.causal.agency/email-filter.sh
deleted file mode 100644
index ca778d69..00000000
--- a/www/git.causal.agency/email-filter.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-
-read -r first rest || :
-[ "${first}" != "${first#C}" ] && first='C.'
-echo "${first}" "${rest}"
diff --git a/www/git.causal.agency/filter.c b/www/git.causal.agency/filter.c
new file mode 100644
index 00000000..b9e7f4cd
--- /dev/null
+++ b/www/git.causal.agency/filter.c
@@ -0,0 +1,156 @@
+#include <err.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define Q(...) #__VA_ARGS__
+
+#define MANDOC_OPTIONS "fragment,man=%N.%S,includes=../tree/%I"
+
+static int about(int argc, char *argv[]) {
+	if (argc < 2) return 1;
+	if (!fnmatch("README.[1-9]", argv[1], 0)) {
+		execlp("mandoc", "mandoc", "-T", "html", "-O", MANDOC_OPTIONS, NULL);
+		err(127, "mandoc");
+	} else if (!fnmatch("*.[1-9]", argv[1], 0)) {
+		execlp(
+			"mandoc", "mandoc", "-T", "html", "-O", "toc," MANDOC_OPTIONS, NULL
+		);
+		err(127, "mandoc");
+	} else {
+		execlp("hilex", "hilex", "-l", "text", "-f", "html", "-o", "pre", NULL);
+		err(127, "hilex");
+	}
+}
+
+static int email(void) {
+	size_t cap = 0;
+	char *buf = NULL;
+	if (getline(&buf, &cap, stdin) < 0) err(1, "getline");
+	if (buf[0] == 'C') {
+		printf("C.%s", buf + strcspn(buf, " "));
+	} else {
+		printf("%s", buf);
+	}
+	return 0;
+}
+
+static int owner(void) {
+	printf(Q(<a href="https://liberapay.com/june/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>));
+	return 0;
+}
+
+#define CTAGS_PATTERN "*.[chlmy]"
+#define TEMPLATE "/tmp/filter.XXXXXXXXXX"
+
+static char tmp[PATH_MAX];
+static char tags[] = TEMPLATE;
+static void cleanup(void) {
+	unlink(tmp);
+	unlink(tags);
+}
+
+static int source(int argc, char *argv[]) {
+	if (argc < 2) return 1;
+	if (
+		strcmp("Makefile", argv[1]) &&
+		strcmp(".profile", argv[1]) &&
+		strcmp(".shrc", argv[1]) &&
+		fnmatch(CTAGS_PATTERN, argv[1], 0) &&
+		fnmatch("*.mk", argv[1], 0) &&
+		fnmatch("*.[1-9]", argv[1], 0) &&
+		fnmatch("*.sh", argv[1], 0)
+	) {
+		execlp("hilex", "hilex", "-t", "-n", argv[1], "-f", "html", NULL);
+		err(127, "hilex");
+	}
+
+	const char *ext = strrchr(argv[1], '.');
+	if (!strcmp(argv[1], ".profile") || !strcmp(argv[1], ".shrc")) {
+		ext = ".sh";
+	} else if (!strcmp(argv[1], "Makefile")) {
+		ext = ".mk";
+	} else if (!ext) {
+		ext = "";
+	}
+
+	snprintf(tmp, sizeof(tmp), TEMPLATE "%s", ext);
+	int fd = mkstemps(tmp, strlen(ext));
+	if (fd < 0) err(1, "%s", tmp);
+	atexit(cleanup);
+
+	char buf[4096];
+	for (ssize_t len; 0 < (len = read(STDIN_FILENO, buf, sizeof(buf)));) {
+		if (write(fd, buf, len) < 0) err(1, "%s", tmp);
+	}
+	if (close(fd) < 0) err(1, "%s", tmp);
+
+	fd = mkstemp(tags);
+	if (fd < 0) err(1, "%s", tags);
+	close(fd);
+	pid_t pid = fork();
+	if (pid < 0) err(1, "fork");
+	if (!pid) {
+		if (!fnmatch(CTAGS_PATTERN, argv[1], 0)) {
+			execlp("ctags", "ctags", "-w", "-f", tags, tmp, NULL);
+			warn("ctags");
+		} else {
+			execlp("mtags", "mtags", "-f", tags, tmp, NULL);
+			warn("mtags");
+		}
+		_exit(127);
+	}
+	int status;
+	if (wait(&status) < 0) err(1, "wait");
+
+	int rw[2];
+	if (pipe(rw) < 0) err(1, "pipe");
+	pid = fork();
+	if (pid < 0) err(1, "fork");
+	if (!pid) {
+		dup2(rw[1], STDOUT_FILENO);
+		close(rw[0]);
+		close(rw[1]);
+		execlp("hilex", "hilex", "-f", "html", tmp, NULL);
+		warn("hilex");
+		_exit(127);
+	}
+	pid = fork();
+	if (pid < 0) err(1, "fork");
+	if (!pid) {
+		dup2(rw[0], STDIN_FILENO);
+		close(rw[0]);
+		close(rw[1]);
+		execlp("htagml", "htagml", "-im", "-f", tags, tmp, NULL);
+		warn("htagml");
+		_exit(127);
+	}
+	close(rw[0]);
+	close(rw[1]);
+
+	if (wait(&status) < 0) err(1, "wait");
+	if (wait(&status) < 0) err(1, "wait");
+	return status;
+}
+
+int main(int argc, char *argv[]) {
+	int error;
+	switch (getprogname()[0]) {
+		break; case 'a': error = pledge("stdio exec", NULL);
+		break; case 's': error = pledge("stdio tmppath proc exec", NULL);
+		break; default:  error = pledge("stdio", NULL);
+	}
+	if (error) err(1, "pledge");
+	switch (getprogname()[0]) {
+		case 'a': return about(argc, argv);
+		case 'e': return email();
+		case 'o': return owner();
+		case 's': return source(argc, argv);
+		default: return 1;
+	}
+}
diff --git a/www/git.causal.agency/owner-filter.sh b/www/git.causal.agency/owner-filter.sh
deleted file mode 100644
index 1997e97b..00000000
--- a/www/git.causal.agency/owner-filter.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-
-echo '
-<a href="https://liberapay.com/june/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
-'
diff --git a/www/git.causal.agency/source-filter.sh b/www/git.causal.agency/source-filter.sh
deleted file mode 100644
index 8782e266..00000000
--- a/www/git.causal.agency/source-filter.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-set -eu
-
-case "$1" in
-	(*.[chlmy]|Makefile|*.mk|*.[1-9]|.profile|.shrc|*.sh)
-		tmp=$(mktemp -d)
-		trap 'rm -fr "${tmp}"' EXIT
-		cd "${tmp}"
-		cat >"$1"
-		: >tags
-		case "$1" in
-			(*.[chlmy]) ctags -w "$1";;
-			(*) mtags "$1";;
-		esac
-		hilex -f html "$1" | htagml -i "$1"
-		;;
-	(*)
-		exec hilex -t -n "$1" -f html
-		;;
-esac