# /.bashrc — brintOS fbcon console shell rc for BASH-init machines (HWJS-C-1 # console-shell wiring, extended to the demo distros 2026-07-03). # # WHY: the framebuffer console (fbcon on /dev/tty1, rendered to the browser # canvas) only accepts typed text if SOMETHING is reading /dev/tty1. The # dev-machine dual-console wiring used busybox ash's $ENV rc # (distros/linux-6.12-musl-busybox/tools/fbcon-rc) with setsid+cttyhack; a # bash-init machine has NEITHER (bash ignores $ENV outside POSIX mode, and # coreutils ships no setsid). This rc is the bash-native equivalent: pid 1 is # `/init -i` (interactive, non-login) with HOME=/ from the host initEnvp, so # bash reads THIS file at startup. # # It spawns ONE additional interactive bash with stdio on /dev/tty1, in its # OWN session with tty1 as the CONTROLLING terminal: /bin/setsid (first-party # packages/custom/setsid, staged via this rig's DISTRO_PACKAGES manifest) # forks off pid 1's session, setsid(2)s, and -c acquires stdin (tty1) via # TIOCSCTTY before exec'ing bash — the bash-machine equivalent of the busybox # machine's `setsid cttyhack sh`. This is what gives the canvas shell real # job control: bash's tcsetpgrp succeeds (no more "cannot set terminal # process group (1): Not a tty" / "no job control in this shell" at startup — # issue linux-in-the-browser#28) and canvas Ctrl-C (VT ISIG -> fg pgrp of # tty1's session) has a target. # # HISTORY: until 2026-07-06 the spawn line was a bare # `bash -i 0<>/dev/tty1 ... &` — no setsid existed for bash machines, the # tty1 shell stayed in pid 1's session, tty1 never became its controlling # terminal, and bash printed the two #28 startup errors (job control off; # typing/echo/commands still worked). packages/custom/setsid closed that # documented limitation. # # Guards: fire exactly once, in pid 1 only, only when the kernel actually # has a /dev/tty1 (a display-less boot skips silently — the rc is inert), # and NEVER under wasm_user_pin (see below). # # wasm_user_pin note (HISTORY): the glibc machine originally did NOT stage # this rc — under its wasm_user_pin cmdline fallback every blocking tty read # PINNED its pool Worker's JS thread, so a second idle console shell would # exhaust a cpu=2 pool and wedge the first fork(). CLOSED (HWJS-C-1, # 2026-07-03): glibc now decodes the -517 coro-park, the glibc machine runs # the cooperative default (wasm_user_pin removed from its MachineSpec) and # stages its own adapted copy of this rc — see # distros/linux-6.12-glibc-bash-coreutils/tools/fbcon-bashrc. if [ -z "${BRINTOS_FBCON_STARTED-}" ] && [ "$$" = 1 ] && [ -c /dev/tty1 ]; then export BRINTOS_FBCON_STARTED=1 TERM=linux PS1='fb$ ' setsid -c bash -i 0<>/dev/tty1 1>&0 2>&0 & fi # One-shot network bring-up (issue #51; HWJS-C-2.b shape). This image has no # busybox init / /etc/init.d/rcS — pid 1 is interactive bash reading THIS rc — # so the static config the busybox machine runs from its rcS lives here, same # pid-1-once guard pattern as the fbcon block above. Loopback is NOT # configured here (issue #76): the wasm32 kernel boot path # (arch_kernel_init_pre_run_init) brings lo UP itself — devinet auto-assigns # 127.0.0.1/8 — because images with no network init at all (user dev # machines) had an unaddressed lo; ownership moved from this rc (#51) to the # kernel, one point for ALL images. eth0 is guarded on the interface existing # so a boot without virtio-net degrades loudly, not with an `ip` error # cascade. `ip` here is the REAL iproute2 staged in /bin (HWJS-C-2 userland). if [ -z "${BRINTOS_NET_STARTED-}" ] && [ "$$" = 1 ]; then export BRINTOS_NET_STARTED=1 if ip link show eth0 > /dev/null 2>&1; then # ONLY CONFIGURE WHAT NOBODY CONFIGURED ALREADY. This rc is not # always the first thing to touch eth0: on a guestroot boot the # initramfs /init (packages/custom/guestroot-init) has already # brought eth0 up with 10.0.2.15/24 and a default route via the # gateway from the kernel cmdline, before it execs the distro # init that reads this file. The unconditional `add`s below then # returned EEXIST and printed # # RTNETLINK answers: File exists # RTNETLINK answers: File exists # # on EVERY boot of such an image, one per add — a machine that is # perfectly configured greeting the user with two errors. # # The test is for ANY address / ANY default route, deliberately # NOT for these specific values: whoever configured first wins. # guestroot-init takes its gateway from `prestrike.gw=`, so a # machine may legitimately be on a different one, and `ip route # replace default via 10.0.2.2` — the obvious one-line fix — # would silently CLOBBER that machine's real gateway. Likewise a # static image that already has an address must not gain a # second one. # # `add` is kept rather than `replace` so a genuine failure (no # permission, device vanished mid-boot) is still LOUD; what is # removed is only the case where there was nothing to do. ip link set eth0 up [ -n "$(ip -o -4 addr show dev eth0)" ] \ || ip addr add 10.0.2.15/24 dev eth0 [ -n "$(ip -o -4 route show default)" ] \ || ip route add default via 10.0.2.2 else echo "brintos bashrc: no eth0 (virtio-net absent) — network not configured" fi fi