SchOS/ports/kilo/Makefile
Nexoniarz b08432b2c3 userland: 268 applets, an editor, names that resolve, and a web server
Four complaints, and only one of them was the thing it looked like.

**"toybox is too small."** Half true, and the fix cost no licensing at all:
236 of toybox's applets are what defconfig builds, and the rest live in
toys/pending/ -- awk, bc, diff, more, expr, tr, hexdump, stty among them. Same
0BSD tarball, switched off by a config default. 26 of them are on now, 236 ->
268. Not everything: strace wants ptrace, syslogd wants BSD's facilitynames[],
git wants OpenSSL, and those three break the link.

The toybox build also works again on this machine. Its scripts start
#!/bin/bash, which does not exist on NixOS, so the binary in the tree was one
nobody could reproduce; the shebangs are rewritten to /usr/bin/env bash on the
way in. Pending applets are enabled by editing .config directly, because
`make oldconfig` is the obvious way and undoes it -- every pending symbol is
`default n`.

**BusyBox was asked for and is not here.** It is GPL-2.0-only, and `make
ramroot` links the root image *into the kernel binary*, so it would put GPLv2
inside an Apache-2.0 executable -- which is the exact case ports/Makefile's
NOTPORTS filter and docs/licensing.md §4 exist for. nano is the same answer one
version later. Both recorded in licensing.md with what was done instead, since
"no" without an alternative is how a rule gets quietly broken later.

**An editor that is not vi.** kilo, BSD-2-Clause, one 1300-line file, no
dependencies beyond termios and TIOCGWINSZ, both of which zsh already needed.
Installed as /bin/edit as well as /bin/kilo, because somebody with a file to
fix will type `edit`.

**"wget doesn't work."** Not a userland problem, and BusyBox's wget would have
failed identically: nothing on this system could turn a name into an address,
so every program taking a hostname failed in its own way and each looked like
a separate bug. There is still no DNS client in SchOS and there does not need
to be -- musl has a complete resolver and it works over ordinary UDP sockets.
The one missing fact was which nameserver, which the kernel has had all along
from DHCP and never published. /proc/resolv.conf publishes it in resolv.conf's
exact syntax; cmd/resolvconf decides whether it becomes /etc/resolv.conf, and
will not overwrite a hand-written one without -f.

  # wget -O - http://example.com/ | head -1
  <!doctype html><html lang="en"><head><title>Example Domain</title>

**Something to host with.** cmd/httpd: GET and HEAD, static files, index.html
for a directory and a listing otherwise, a child per connection. No CGI, no
keep-alive, no TLS, no config file. The path check is the only
security-relevant code in it and it refuses rather than normalises -- no
component may be `..`, and percent-decoding happens first, because %2e%2e is
`..` and a check before decoding does not see it. Both forms answer 403.

And the disk is 100 MB, from 32. It is sparse, so the image is 21 MB on the
host. RAMDISK_BLOCKS went 6000 -> 8000 with it: the ramdisk was at 86% and the
next thing added would have broken `make ramroot`, which nobody would have
noticed until they used it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
2026-09-14 19:24:55 +02:00

84 lines
3.4 KiB
Makefile

# SPDX-License-Identifier: Apache-2.0
# kilo — BSD-2-Clause: https://github.com/antirez/kilo
#
# SchOS's text editor, installed as sysroot/bin/kilo with `edit` beside it.
#
# It is here because the alternative every small system reaches for is vi, and
# vi is a program you have to be taught before you can use it to fix the file
# that is stopping the machine booting. kilo is the other kind: the arrow keys
# move the cursor, typing inserts, Ctrl-S saves, Ctrl-Q quits, Ctrl-F finds,
# and the bottom line says so while you work. Nobody has to be told any of it.
#
# The whole editor is one 1,300-line C file with no dependencies beyond libc --
# termios and TIOCGWINSZ, both of which SchOS already has because zsh needs
# them. That is the entire reason it was chosen over nano: nano is GPLv3 and
# wants ncurses at runtime, and GPLv3 cannot be combined with Apache-2.0 any
# more than GPLv2 can. See ../../docs/licensing.md.
#
# What it does not do: no undo, no multiple buffers, no configuration, no
# mouse, no UTF-8 beyond passing bytes through. It edits one file.
include ../mk/port.mk
# Pinned to a commit rather than a release, because kilo has never had one --
# it was written as the worked example for a tutorial and has been finished
# ever since. A commit is at least an exact thing to name.
#
# The checksum is of GitHub's generated archive. Those are reproducible for a
# given commit, but they are generated rather than uploaded, so if this ever
# fails to verify check that upstream still has the commit before assuming the
# tarball was tampered with.
KILO_COMMIT := 323d93b29bd89a2cb446de90c4ed4fea1764176e
KILO_URL := https://github.com/antirez/kilo/archive/$(KILO_COMMIT).tar.gz
KILO_SHA256 := 79e62c23fdf369fa0cbbeaab9fd8ae2848dcc0156faf6efc89ea274528b39723
TARBALL := $(DISTDIR)/kilo-$(KILO_COMMIT).tar.gz
CFLAGS := -static -Os -D__SCHOS__ -I$(MUSL)/include $(CFLAGS_BT) \
-D_BSD_SOURCE -std=c99 -Wall
LDFLAGS := -static -L$(MUSL)/lib -lc
$(TARBALL): | $(DISTDIR)
curl -fsSL -o $@ $(KILO_URL)
sh $(SHA256CHECK) "$(KILO_SHA256)" "$@"
download: $(TARBALL)
$(SRCDIR): $(TARBALL)
mkdir -p $(PORTDIR)
rm -rf $(PORTDIR)/kilo-$(KILO_COMMIT)
tar -xzf $< -C $(PORTDIR)
mv $(PORTDIR)/kilo-$(KILO_COMMIT) $@
# One file, so its own Makefile is not worth invoking -- it hardcodes flags
# that assume a hosted glibc and would link against the build host's libc.
$(BUILDDIR)/kilo: | $(SRCDIR)
mkdir -p $(BUILDDIR)
$(CC) $(CFLAGS) -o $@ $(SRCDIR)/kilo.c $(LDFLAGS)
build: $(BUILDDIR)/kilo
# `edit` as well as `kilo`.
#
# Two real copies rather than a link, for the reason ports/toybox/Makefile
# gives at length: mkschfs deduplicates by content, so the image holds one copy
# with two names either way, and this needs nothing from the host filesystem.
#
# The second name is not decoration. Somebody who has just arrived at a SchOS
# prompt with a file to fix will type `edit`; they will not guess `kilo`.
$(PORTDIR)/.installed: $(BUILDDIR)/kilo | $(SYSROOT)/bin
cp $(BUILDDIR)/kilo $(SYSROOT)/bin/kilo
cp $(BUILDDIR)/kilo $(SYSROOT)/bin/edit
chmod 755 $(SYSROOT)/bin/kilo $(SYSROOT)/bin/edit
@mkdir -p $(SYSROOT)/usr/share/licenses/kilo
cp $(SRCDIR)/LICENSE $(SYSROOT)/usr/share/licenses/kilo/LICENSE
@touch $@
@echo "kilo: installed as /bin/kilo and /bin/edit"
install: $(PORTDIR)/.installed
clean:
rm -rf $(BUILDDIR) $(PORTDIR)/.installed
distclean: clean
rm -rf $(PORTDIR)