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
This commit is contained in:
parent
bc39b73969
commit
b08432b2c3
17 changed files with 994 additions and 21 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include "lwip/netif.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/ip4_addr.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
// Wait until the next timer tick. `ticks` advances at 100 Hz, so this is a
|
||||
// sleep of up to 10 ms -- and, more importantly, it is the kernel's only timed
|
||||
|
|
@ -414,6 +415,48 @@ put_field(char *out, const char *name)
|
|||
// can parse one can parse any number, which is the whole reason it is not a
|
||||
// single flat list of values: with two NICs a flat list has no way to say which
|
||||
// address belongs to which.
|
||||
// /proc/resolv.conf -- the nameservers, in the format a resolver expects.
|
||||
//
|
||||
// SchOS has no DNS client of its own and does not need one: musl contains a
|
||||
// complete resolver, and it works over ordinary UDP sockets, which this system
|
||||
// has. The only thing it was missing was the one fact a process cannot find
|
||||
// out for itself -- *which* nameserver -- because that arrives in a DHCP reply
|
||||
// the kernel handled.
|
||||
//
|
||||
// So this is the mechanism and nothing more. It renders resolv.conf's exact
|
||||
// syntax so that putting it where the resolver looks is a copy rather than a
|
||||
// translation, and deciding whether to do that is userspace's business; see
|
||||
// cmd/resolvconf.
|
||||
//
|
||||
// Empty until DHCP answers, which is the honest report: a file saying nothing
|
||||
// is right, and a file naming a server that does not exist is not.
|
||||
int
|
||||
net_resolv(char *buf, int cap)
|
||||
{
|
||||
int len = 0, i;
|
||||
|
||||
if (cap < 64 * DNS_MAX_SERVERS)
|
||||
return 0;
|
||||
if (!net_started)
|
||||
return 0;
|
||||
|
||||
lwip_sys_lock();
|
||||
for (i = 0; i < DNS_MAX_SERVERS; i++) {
|
||||
const ip_addr_t *a = dns_getserver(i);
|
||||
|
||||
if (a == 0 || ip4_addr_isany_val(*ip_2_ip4(a)))
|
||||
continue;
|
||||
// put_field pads to a column, which is right for /proc/netif and
|
||||
// wrong here: this file is not for looking at, it is for copying to
|
||||
// where a resolver reads it.
|
||||
len += put_str(buf + len, "nameserver ");
|
||||
len += put_ip4(buf + len, ip_2_ip4(a));
|
||||
buf[len++] = '\n';
|
||||
}
|
||||
lwip_sys_unlock();
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
net_info(char *buf, int cap)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue