mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Serve VT1200 font files over TFTP.
|
|
|
|
The terminal's "TFTP Font Path" is ``<host>:<filename>``; it requests that exact
|
|
filename over TFTP and (if it parses) loads it as a font. This serves several
|
|
plausible names so we catch whatever it asks for.
|
|
|
|
sudo python3 -u harness/serve.py [host] [port]
|
|
"""
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.dirname(HERE)
|
|
sys.path.insert(0, os.path.join(ROOT, "tools"))
|
|
|
|
import fontgen
|
|
|
|
FONTS = os.path.join(ROOT, "reference", "fonts")
|
|
|
|
|
|
def load(name):
|
|
with open(os.path.join(FONTS, name), "rb") as fh:
|
|
return fh.read()
|
|
|
|
|
|
def main():
|
|
baseline = load("baseline.pcf")
|
|
evil = load("evil-real.pcf")
|
|
probe = load("probe-uniq.pcf")
|
|
probe_snf = load("probe.snf")
|
|
probe_dec = load("probe-dec.snf")
|
|
probe_dec2 = load("probe-dec2.snf")
|
|
real = load("system-10x20.pcf")
|
|
fonts_dir = load("fonts.dir")
|
|
files = {}
|
|
# The font path value is <host>:<fontdir>. The terminal fetches
|
|
# "<fontdir>/fonts.dir" (the directory index), then the font files it names.
|
|
for d in ("69", "font", "fonts", "misc", "X11"):
|
|
files[f"{d}/fonts.dir"] = fonts_dir
|
|
files[f"{d}/baseline.pcf"] = baseline
|
|
files[f"{d}/v1200a.pcf"] = baseline
|
|
files[f"{d}/evil.pcf"] = evil
|
|
# also serve the plain names, in case it asks for those first
|
|
for n in ("69", "fonts.dir", "font", "fonts", "ROM", "rom", "real.pcf"):
|
|
files[n] = real
|
|
files["baseline.pcf"] = baseline
|
|
files["evil.pcf"] = evil
|
|
if os.path.exists(os.path.join(FONTS, "fonts.dir")):
|
|
files["fonts.dir"] = load("fonts.dir")
|
|
|
|
host = sys.argv[1] if len(sys.argv) > 1 else "100.103.255.254"
|
|
port = int(sys.argv[2]) if len(sys.argv) > 2 else 69
|
|
def resolve(name):
|
|
# The terminal first fetches the bare path, then "<dir>/fonts.dir".
|
|
# Accept ANY name: the index for fonts.dir, the payload otherwise.
|
|
if name == "fonts.dir" or name.endswith("/fonts.dir"):
|
|
return fonts_dir
|
|
if name.endswith(".snf"):
|
|
if "dec2" in name:
|
|
return probe_dec2
|
|
return probe_dec if "dec" in name else probe_snf
|
|
if name.endswith((".pcf", ".DECW$FONT")):
|
|
if "evil" in name:
|
|
return evil
|
|
if "probe" in name:
|
|
return probe
|
|
return baseline
|
|
return baseline # bare directory name: give it data, not an error
|
|
|
|
srv = fontgen.TFTPServer((host, port), files, timeout=60.0, retries=10,
|
|
resolver=resolve).start()
|
|
print(f"serving {len(files)} names on {srv.address}", flush=True)
|
|
print(" names: " + ", ".join(sorted(files)), flush=True)
|
|
try:
|
|
while True:
|
|
time.sleep(0.5)
|
|
while srv.log:
|
|
ts, name, addr = srv.log.pop(0)
|
|
stamp = time.strftime("%H:%M:%S", time.localtime(ts))
|
|
print(f"{stamp} {addr[0]}:{addr[1]} requested {name!r}", flush=True)
|
|
except KeyboardInterrupt:
|
|
pass
|
|
finally:
|
|
srv.stop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|