mirror of
https://github.com/st3fan/ewm.git
synced 2026-10-25 02:02:15 +00:00
* --tty-telnet: proactive echo negotiation (fix telnet double-echo) The telnet echo suppression was reactive — the server only announced WILL ECHO / WILL SGA after the client sent an IAC first. But a classic telnet client sits in line-mode-with-local-echo and waits for the server to negotiate, so the announcement never went out, the client kept echoing locally, and every line appeared twice (its echo plus the machine's own authentic echo). A telnet server that wants remote echo has to offer it proactively on connect. The new --tty-telnet flag (implies --tty) does exactly that: it writes WILL ECHO + WILL SGA before the banner and marks the filter active so the reactive path doesn't double-announce. Bare --tty stays byte-clean for local terminals and nc (kickoff option B); the reactive fallback still helps a plain --tty client that does negotiate first. The systemd @.service switches its ExecStart to --tty-telnet. The growing session-behavior params (throttle, banner, telnet) fold into a TtyConfig struct. Tests: proactive announce leads the stream (before the banner) and doesn't double-announce when the client then sends its own IAC; the flag implies --tty and parses. Verified live: `ewm one --tty-telnet | xxd` shows FF FB 01 FF FB 03 then the prompt. Docs: scripts/systemd/README.md and notes/APPLE1.md explain proactive --tty-telnet vs byte-clean --tty, with troubleshooting for the double-echo and the nc negotiation bytes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Disk images over HTTP, downloaded once into a cache A floppy, hard-drive or 3.5" image path may now be an http(s):// URL: ewm two --set 'machine:slots:6:drive1=https://example.com/Frogger.dsk' ewm/src/fetch.rs downloads it into $XDG_CACHE_HOME/ewm (else ~/.cache/ewm) / <sha1 of the URL> / <file name from the URL>, beside a meta.json holding the ETag and Last-Modified. The digest keys the directory because URLs are not filesystem-safe; the file keeps its own name so the cache is browsable and errors read normally. The hash is the crate's own SHA-1 (ws::sha1) — no dependency for that. Freshness is one *conditional* GET (If-None-Match / If-Modified-Since) rather than HEAD-then-GET: a 304 costs a single round trip. If the request fails and a copy is cached, the cached copy is used, so a machine assembled from URLs still boots offline; a cold cache with no server is a loud error instead. A URL is a source, not a path: resolve_paths leaves it alone (like builtin:), while referenced_files still counts it, so a built-in config may not carry one — builtins must run offline. Downloaded hard drives mount memory-only. This needed a real change, not just leaving the file handle unopened: in hdd.rs an unopenable file means WRITE PROTECTED, which is a different (and still supported) state for a local image. Hdd now carries an explicit `writeback` flag — false for downloads, so ProDOS writes update the in-memory image and never reach the cached file, and revalidating a download cannot destroy them. Floppies already behaved this way. Dependency: ureq (blocking + rustls), owner's decision — the one place the tiny-dependency budget gives way, because TLS is not something to hand-roll. It brings ~25 transitive crates including ring, so the headless server build now compiles native crypto too. Tests: the cache round trip against a real local HTTP server (cold download, conditional revalidation with a 304, offline fallback, and a cold cache with nothing listening failing loudly); URL naming and digest stability including degenerate URLs; memory-only vs write-back block writes at the register level; URLs surviving path resolution; and the wiring gate — a machine builds with DOS 3.3 served over HTTP into drive 1, which only passes if the mount path really fetched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>