This commit is contained in:
Raven Scott
2026-04-03 18:46:37 -04:00
parent c02ffc6021
commit 7c9c9ae83c
19 changed files with 675 additions and 52 deletions
+3 -2
View File
@@ -14,12 +14,13 @@ Files in this directory are **read from disk by the seeder** (or copied into `pa
## Contents
- **`init.js`** — Kernel entry: must define `async function start(ctx)`. Reads `/etc/os-release`, optional **`/etc/motd`**, runs non-comment lines from **`/etc/bare-os/rc`** via **`execLine`**, prints a short banner, then loops on `readLine` / `execLine` (with error handling so user mistakes do not tear down the session). Custom kernels may call **`ctx.registerKernelShutdownHook(fn)`** to run teardown when the session ends (before initd disposers); see [`developer-guide/02-the-context-object.md`](../developer-guide/02-the-context-object.md).
- **`init.js`** — Kernel entry: must define `async function start(ctx)`. Boot order: **`/etc/os-release`** → **`/etc/motd`** **`/etc/bare-os/rc`** **`/etc/bare-os/rc.d/*`** (sorted; skips dotfiles and `*~`) → banner → **`readLine` / `execLine`** loop (boot snippet errors are logged, not fatal). Custom kernels may call **`ctx.registerKernelShutdownHook(fn)`** before initd disposers; see [`developer-guide/02-the-context-object.md`](../developer-guide/02-the-context-object.md).
- **`bin/`** — **Tier-1 utilities** built by [bare-os-coreutils](../packages/bare-os-coreutils/README.md). Each file is **`runtime.js`** + optional **`lib/*-engine.js`** (**`sed`**, **`awk`**) or **`lib/man-render.js`** (**`man`**) + **`async function run(ctx, argv)`** (no ESM **`import`** in **`src/`**).
- **`share/man/man.json`** — Merged manual database for **`/bin/man`** (built by **`bare-os-coreutils`**; see [handbook ch.10](../handbook/10-manpages-and-online-help.md)).
- **`etc/os-release`** — Static OS metadata (`NAME`, `VERSION`, …).
- **`etc/motd`** — Optional message printed after **`os-release`** (distributors can customize).
- **`etc/bare-os/rc`** — Optional boot snippet: non-comment, non-blank lines are passed to **`execLine`** one at a time (same power as the interactive shell—keep lines minimal and trusted).
- **`etc/bare-os/rc`** — Optional boot snippet: one **`execLine`** per non-comment line (trusted).
- **`etc/bare-os/rc.d/`** — Optional extra snippets, same line rules, run after **`rc`** in filename order.
## Editing workflow
+1 -1
View File
@@ -1,4 +1,4 @@
# Optional boot-time shell lines (one command per non-comment line).
# Executed by /boot/init.js after /etc/os-release and this motd, before the main banner.
# Executed by /boot/init.js after /etc/os-release and /etc/motd, then /etc/bare-os/rc.d/*, before the main banner.
# Example (uncomment to use):
# export BARE_OS_SHOW_RC=1
+11
View File
@@ -0,0 +1,11 @@
# Optional boot snippets (trusted)
Files in this directory are executed after `/etc/bare-os/rc`, in **lexicographic
order** by filename. Use numeric prefixes (e.g. `10-local`, `20-proxy`) to
control order. Each file is treated like `rc`: one shell command per non-empty,
non-comment line.
Lines starting with `#` and blank lines are ignored. Dotfiles and names ending
in `~` are skipped.
Only ship snippets you trust — they run with full `execLine` power.
+91 -18
View File
@@ -1,31 +1,96 @@
/**
* Hyperdrive-resident kernel (staged as /boot/init.js).
* Loaded by the booter with an injected ctx object (trusted replication source).
*
* Boot order: /etc/os-release → /etc/motd → /etc/bare-os/rc → /etc/bare-os/rc.d/*
* (sorted by filename) → session banner → interactive loop.
* Use ctx.registerKernelShutdownHook(fn) for teardown before initd disposers.
*/
/**
* Print /etc/motd and run /etc/bare-os/rc lines (comments and blank lines skipped).
* @param {Record<string, unknown>} ctx
* @param {string} text
*/
async function runRcLines(ctx, text) {
const { execLine, console } = ctx
for (const line of text.split(/\r?\n/)) {
const t = line.trim()
if (!t || t.startsWith('#')) continue
try {
await execLine(t)
} catch (e) {
console.error((e && e.message) || String(e))
}
}
}
/**
* @param {Record<string, unknown>} ctx
*/
async function runEtcSnippets(ctx) {
const { drive, execLine, b4a, console } = ctx
async function printOsRelease(ctx) {
const { drive, b4a, console } = ctx
try {
const rel = await drive.get('/etc/os-release')
if (rel) console.log(b4a.toString(rel))
} catch (e) {
console.error((e && e.message) || String(e))
}
}
/**
* @param {Record<string, unknown>} ctx
*/
async function printMotd(ctx) {
const { drive, b4a, console } = ctx
try {
const motd = await drive.get('/etc/motd')
if (motd) console.log(b4a.toString(motd).trimEnd())
} catch (e) {
console.error((e && e.message) || String(e))
}
}
/**
* @param {Record<string, unknown>} ctx
* @param {string} drivePath absolute path on system drive
* @param {string} label for errors
*/
async function runRcFileAt(ctx, drivePath, label) {
const { drive, b4a, console } = ctx
try {
const rc = await drive.get('/etc/bare-os/rc')
if (!rc) return
const text = b4a.toString(rc)
for (const line of text.split(/\r?\n/)) {
const t = line.trim()
if (!t || t.startsWith('#')) continue
const buf = await drive.get(drivePath)
if (!buf) return
await runRcLines(ctx, b4a.toString(buf))
} catch (e) {
console.error(`${label}: ` + ((e && e.message) || String(e)))
}
}
/**
* Optional snippets under /etc/bare-os/rc.d/ — executed in lexicographic order.
* Skips dotfiles and names ending in ~.
* @param {Record<string, unknown>} ctx
*/
async function runBareOsRcDir(ctx) {
const { drive, b4a, console } = ctx
try {
/** @type {string[]} */
const names = []
try {
for await (const n of drive.readdir('/etc/bare-os/rc.d')) names.push(n)
} catch {
return
}
names.sort()
for (const name of names) {
if (!name || name.startsWith('.') || name.endsWith('~')) continue
const p = `/etc/bare-os/rc.d/${name}`
try {
await execLine(t)
const buf = await drive.get(p)
if (!buf) continue
await runRcLines(ctx, b4a.toString(buf))
} catch (e) {
console.error((e && e.message) || String(e))
console.error(`rc.d/${name}: ` + ((e && e.message) || String(e)))
}
}
} catch (e) {
@@ -33,14 +98,22 @@ async function runEtcSnippets(ctx) {
}
}
async function start(ctx) {
const { console, drive, readLine, execLine, b4a } = ctx
const rel = await drive.get('/etc/os-release')
if (rel) console.log(b4a.toString(rel))
await runEtcSnippets(ctx)
console.log(
'Bare operating system — session: guest (login [--new] <passphrase> to unlock identity) | shell: cd, export, && || ;, exit, login, logout | try: help, getconf PATH_MAX, ls /bin, pwd, crontab -l'
/**
* @param {Record<string, unknown>} ctx
*/
function printSessionBanner(ctx) {
ctx.console.log(
'Bare operating system — guest session (login [--new] <passphrase> to unlock) | shell: cd, export, if/fi, && || ;, |, exit | services: systemctl list-units, journalctl -u UNIT | try: help, ls /bin, crontab -l'
)
}
async function start(ctx) {
const { readLine, execLine, console } = ctx
await printOsRelease(ctx)
await printMotd(ctx)
await runRcFileAt(ctx, '/etc/bare-os/rc', 'rc')
await runBareOsRcDir(ctx)
printSessionBanner(ctx)
while (true) {
const line = await readLine('')
if (line == null) break
File diff suppressed because one or more lines are too long