commit 1d677530fbf909c75b248f9f891d2be8ede058aa (patch)
parent f9181c89c1897f2eac7d417ea3d67ea65324d508
Author: Alex Karle <alex@alexkarle.com>
Date: Wed, 8 Sep 2021 00:25:58 -0400
text: Goodbye kiosk and gengopher, hello text.alexkarle.com
I'll never feel fully comfortable rolling out kiosk(1) via SSH,
and gengopher was always a hack (with the setting of mtimes and
all that). Yet, I've always wanted my site to be available not
just as HTML but in a more man(1)-y format.
After reading text.causal.agency, I knew that a ascii dump was
the way to go. It took me quite a while to get it all working in
a gmake and OpenBSD-make way, but I'm really happy with the
results!
Diffstat:
8 files changed, 118 insertions(+), 189 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -7,6 +7,11 @@ atom.xml
# jam-tuesday hits generated by jam-tuesday/stats.sh
jam-tuesday/greatest-hits
-# kiosk binary and files
-bin/kiosk
-kiosk/
+# timestamp files
+*.ts
+
+# text files (gopher, text.alexkarle.com)
+text/
+
+# obj directory on OpenBSD for out-of-tree builds
+obj/
diff --git a/Makefile b/Makefile
@@ -1,46 +1,89 @@
# alexkarle.com makefile
+#
+# a tale of two builds
+#
+# This Makefile builds both text.alexkarle.com (text-only) and
+# alexkarle.com (html) from the same mdoc(7) by leveraging "timestamp"
+# (*.ts) files which indicate when the two for each *.7 file were made.
+# On OpenBSD, all artifacts are built into the obj/ dir (after make obj)
+# for an out-of-tree build, but care was taken to maintain gmake
+# compatibility.
+#
# targets:
-# build [default] -- generates HTML in current dir
-# clean -- deletes said HTML
-HTML != echo index.html *.[1-9] | sed 's/\.[1-9]/.html/g'
-SETS != find jam-tuesday -name '[0-9][0-9][0-9][0-9]-*'
-JAMGEN = jam-tuesday/index.html jam-tuesday/greatest-hits
+# build [default] -- generates html and text in obj (OpenBSD) or $PWD
+# obj -- makes the obj/ directory for out-of-tree build on OpenBSD
+# clean -- deletes html and text artifacts
-# Running with HIDE="" shows the full build command instead
-# of the abbreviated version (@ suppresses the command in make)
-HIDE = @
+# gmake defines CURDIR, OpenBSD defines .CURDIR -- one should work
+DIR = $(.CURDIR)$(CURDIR)
-CC = cc
-CFLAGS = -g -O2 -Wall -Wpedantic -Wextra
+#----------------------------------------------------------
+# Variables to store timestamp and setlist dependencies
+TS != echo $(DIR)/*.[1-9] | sed 's@$(DIR)/\([^\.]*\)\.[1-9]@\1.ts@g'
+SETS != find $(DIR)/jam-tuesday -name '[0-9][0-9][0-9][0-9]-*'
+
+#----------------------------------------------------------
+# Top Level Targets
.PHONY: build
-build: $(HTML) atom.xml $(JAMGEN) bin/kiosk
+build: $(TS) html/atom.xml jam-text.ts jam-html.ts \
+ html/index.html html/style.css html/logo.png text/000-welcome.txt
+
+obj:
+ mkdir -p obj
.PHONY: clean
clean:
- rm -f $(HTML) atom.xml $(JAMGEN)
+ rm -f *.ts
+ rm -rf text html obj
+
+#----------------------------------------------------------
+# jam-tuesday targets
+jam-text.ts: $(SETS) bin/jam-stats.sh
+ @mkdir -p text/jam-tuesday
+ (date; echo; $(DIR)/bin/jam-stats.sh) > text/jam-tuesday/stats
+ @cp $(SETS) text/jam-tuesday
+ @echo 'cp $$SETS html/jam-tuesday'
+ @touch $@
+
+jam-html.ts: $(SETS) bin/jam-index.sh bin/jam-stats.sh
+ @mkdir -p html/jam-tuesday
+ $(DIR)/bin/jam-index.sh > html/jam-tuesday/index.html
+ @cp $(SETS) html/jam-tuesday
+ @echo 'cp $$SETS html/jam-tuesday'
+ @touch $@
+
+
+#----------------------------------------------------------
+# Various files that just need to be copied into html/text
+html/index.html:
+ cd html && ln -sf intro.html index.html
-index.html:
- ln -sf intro.html $@
+html/style.css: style.css
+ cp $(DIR)/style.css $@
-atom.xml: blog.7 bin/genatom.sh
- ./bin/genatom.sh > $@
+html/logo.png: logo.png
+ cp $(DIR)/logo.png $@
-jam-tuesday/index.html: $(SETS) bin/jam-index.sh bin/jam-stats.sh
- ./bin/jam-index.sh > $@
+html/atom.xml: blog.7 bin/genatom.sh
+ $(DIR)/bin/genatom.sh > $@
-jam-tuesday/greatest-hits: $(SETS) bin/jam-stats.sh
- (date; echo; ./bin/jam-stats.sh) > $@
+text/000-welcome.txt: welcome.txt
+ cp $(DIR)/welcome.txt $@
-bin/kiosk: src/kiosk.c
- $(CC) $(CFLAGS) -DMANDIR="\"`pwd`/kiosk\"" src/kiosk.c -o $@
-$(HTML): bin/genpost.sh
+#----------------------------------------------------------------------
+# Finally, the actual meat -- generating *.html/*.txt from the mdoc(7)
+# The most egregious hack here is the live renaming of the files via
+# grepping through the ORDER file so that text.alexkarle.com presents
+# the files in a reasonable order for viewing
+$(TS): bin/genpost.sh
-.SUFFIXES: .7 .html
-.7.html:
+.SUFFIXES: .7 .ts
+.7.ts:
@echo "mandoc $<"
- $(HIDE)mandoc -Tlint -Werror $<
- $(HIDE)./bin/genpost.sh < $< > $@
- $(HIDE)mkdir -p kiosk
- $(HIDE)mandoc $< > kiosk/`basename $@ .html`
+ @mkdir -p text html
+ @mandoc -Tlint -Werror $<
+ @$(DIR)/bin/genpost.sh < $< > html/$$(basename $< .7).html
+ @mandoc -Tascii -Owidth=72 < $< | col -b > text/$$(grep $$(basename $< .7) $(DIR)/ORDER)
+ @touch $@
diff --git a/ORDER b/ORDER
@@ -0,0 +1,14 @@
+# file order for the text.alexkarle.com site
+001-intro.txt
+002-license.txt
+003-uses.txt
+004-jam-tuesday.txt
+101-blog.txt
+102-a-new-hope.txt
+103-domain-names.txt
+104-BLM.txt
+105-self-hosted.txt
+106-on-writing.txt
+107-my-old-man.txt
+108-use-feeds.txt
+109-creative-coding.txt
diff --git a/bin/genatom.sh b/bin/genatom.sh
@@ -2,10 +2,12 @@
# genatom.sh -- generate atom.xml
set -e
+REPO=$(dirname "$(dirname "$0")")
+
# All posts are a item (.It) in the list, and linked via .Xr
-POSTS=$(sed '/SEE ALSO/q' blog.7 | grep -A1 '\.It' | grep '\.Xr' | sed 's/^\.Xr \([^ ]*\) 7/\1/')
+POSTS=$(sed '/SEE ALSO/q' "$REPO/blog.7" | grep -A1 '\.It' | grep '\.Xr' | sed 's/^\.Xr \([^ ]*\) 7/\1/')
# Assume dates are 1-1
-DATES=$(grep -o '[0-9]\{1,2\}/[0-9]\{1,2\}/[0-9]\{4\}' blog.7 \
+DATES=$(grep -o '[0-9]\{1,2\}/[0-9]\{1,2\}/[0-9]\{4\}' "$REPO/blog.7" \
| sed -e 's#\([0-9]\{2\}\)/\([0-9]\{2\}\)/\([0-9]\{4\}\)#\3-\1-\2#')
cat <<HEADER
@@ -36,7 +38,7 @@ for p in $POSTS; do
<![CDATA[
ENTRY
# Print fragment (no need for escapes -- in CDATA
- mandoc -Thtml -O'fragment,man=%N.html;https://man.openbsd.org/%N.%S' $p.7 \
+ mandoc -Thtml -O'fragment,man=%N.html;https://man.openbsd.org/%N.%S' "$REPO/$p.7" \
| sed '/<td class="head-vol">Miscellaneous Information Manual<\/td>/d'
cat <<EOENTRY
]]>
diff --git a/bin/gengopher.sh b/bin/gengopher.sh
@@ -1,35 +0,0 @@
-#!/bin/sh
-# generates my gopherhole based on the checkout of the files
-# in the html area
-set -e
-
-WWW=/var/www/htdocs/akcom
-DEPLOY=/var/gopher
-PHLOG=$DEPLOY/phlog
-
-# First generate the content
-for f in $WWW/*.7; do
- # col -b to strip backspace underlines, see mandoc(1)
- mandoc -Tascii -Owidth=72 $f | col -b > $PHLOG/`basename $f .7`.txt
-done
-
-# Copy over jam-tuesday
-cp -a "$WWW/jam-tuesday" "$PHLOG"
-
-# Remove/move some non-phlog cruft
-mv $PHLOG/intro.txt $DEPLOY/intro.txt
-rm -f $PHLOG/template.txt
-
-# Set the mtimes so they show nicely in the directory listing
-# by parsing the .Dd lines using grep(1) and date(1)
-# TODO: create a real gophermap for this directory based on blog(7)
-for f in $PHLOG/*.txt; do
- grep '\.Dd' $WWW/`basename $f .txt`.7 \
- | grep -v Mdocdate \
- | sed "s#\.Dd #$f #"
-done > /tmp/mtimes
-
-IFS=" " # tab to split file/date for read (see ksh(1))
-while read f d; do
- touch -m -d `date -j -f "%b %d, %Y" "+%Y-%m-%dT%H:%M:%S" "$d"` "$f"
-done < /tmp/mtimes
diff --git a/bin/genpost.sh b/bin/genpost.sh
@@ -1,6 +1,9 @@
#!/bin/sh
# genpost.sh -- reads mdoc(7) from stdin, generates HTML to stdout
+REPO=$(dirname "$(dirname "$0")")
+# cd into $REPO so that the includes work!
+cd $REPO
# Command Explained
# -----------------
diff --git a/src/kiosk.c b/src/kiosk.c
@@ -1,119 +0,0 @@
-#include <dirent.h>
-#include <err.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-int list(void) {
- DIR *dirp = opendir(MANDIR);
- struct dirent *dp;
- int n = 0;
- while ((dp = readdir(dirp)) != NULL) {
- /* ignore hidden files (and, conveniently, . and ..) */
- if (dp->d_name[0] != '.') {
- printf("%2d: %s(7)\n", ++n, dp->d_name);
- }
- }
- closedir(dirp);
- printf(" l: list\n");
- printf(" h: help\n");
- printf(" q: quit\n");
- return n;
-}
-
-void help(void) {
- printf(
- "Welcome to alexkarle.com's SSH Kiosk!\n"
- "\n"
- "Here you'll find all the mdoc(7) contents of my blog, rendered\n"
- "in their original form via mandoc(1).\n"
- "\n"
- "Currently, due to security concerns, only the blog posts are\n"
- "browsable (and no shell access is given).\n"
- "\n"
- "If you think this is cool, I'd love to hear from you!\n"
- "Drop me a line at alex@alexkarle.com!\n"
- );
-
-}
-
-/* TODO: have list() read into memory so we don't readdir each time! */
-void mandoc(int choice) {
- DIR *dirp = opendir(MANDIR);
- struct dirent *dp;
- int i = 0;
- while ((dp = readdir(dirp)) != NULL) {
- if (dp->d_name[0] != '.' && ++i == choice) {
- char path[PATH_MAX];
- sprintf(path, "%s/%s", MANDIR, dp->d_name);
- FILE *fd = fopen(path, "r");
- if (fd == NULL)
- err(1, "open");
- char c;
- while ((c = getc(fd)) != EOF) {
- putc(c, stdout);
- }
- fclose(fd);
- break;
- }
- }
- closedir(dirp);
-}
-
-void prompt(int n) {
- printf("kiosk> ");
- fflush(stdout);
-
- /* NOTE: Read from /dev/tty instead of stdin to prevent
- * simple DDOS via < /dev/random */
-
- FILE *tty = fopen("/dev/tty", "r");
- if (tty == NULL)
- errx(1, "unable to open tty");
- char *line = NULL;
- size_t line_len;
- ssize_t nread = getline(&line, &line_len, tty);
- if (nread == -1 || strcmp(line, "q\n") == 0) {
- printf("Goodbye!\n");
- exit(0);
- }
- fclose(tty);
-
- int choice;
- if (strcmp(line, "l\n") == 0) {
- list();
- } else if (strcmp(line, "h\n") == 0) {
- help();
- } else if (nread == 1) {
- /* must be blank line... no-op */
- } else if (sscanf(line, "%d\n", &choice) == 0) {
- printf("Bad input: %s", line);
- } else if (choice > n || choice <= 0) {
- printf("Choice %d out of bounds\n", choice);
- } else {
- mandoc(choice);
- }
-
- free(line);
-}
-
-int main(void) {
-#ifdef __OpenBSD__
- /* All unveils for this proc only (not for less) */
- if (unveil(MANDIR, "r") == -1)
- err(1, "unveil");
- if (unveil("/dev/tty", "r") == -1)
- err(1, "unveil");
- /* no more unveil's past here! requires pledge*/
- if (pledge("stdio rpath", NULL) == -1)
- err(1, "pledge");
-#endif
- int n = list();
- setenv("LESSSECURE", "1", 1);
- for(;;)
- prompt(n);
- return 0;
-}
diff --git a/welcome.txt b/welcome.txt
@@ -0,0 +1,16 @@
+Welcome to text.alexkarle.com!
+
+This is an experimental version of my main site (alexkarle.com)
+in text-only format. For maximum retro effect, I serve up this
+directory over HTTP, HTTPS, and Gopher.
+
+I've been serving txt versions of my mdoc(7) for a while over
+Gopher, but decided to formalize the subtree generation and serve
+it over HTTP after reading text.causal.agency, which you should
+totally check out. (aside: I'd like to state that I've been doing
+the whole mdoc(7) thing before I knew about causal.agency and am
+not a complete copycat (much respect, great minds think alike and
+all that) :) )
+
+I hope you enjoy your stay! If you think this is cool, don't
+hesitate to reach out: text@alexkarle.com