Chapter 41 — Dynamic /programs from the Program Registry

This entry is part 4 of 4 in the series AI for Software Development

Post Stastics

  • This post has 730 words.
  • Estimated read time is 3.48 minute(s).

Chapter 40 closed the loop on shell-visible background jobs by giving them local %N references.

That matters here because it gave us a stable chapter boundary:
the shell can now be scripted without hardcoding fragile PIDs, so the filesystem work that follows can focus on the namespace itself instead of fighting the test harness.

The next problem is still the same one we have been circling for a while:
the current /programs directory knows too much about embedded programs in two separate places:

kernel/program.c
kernel/vfs.c

That duplication is the real problem.

If the embedded registry already knows the available user programs, the VFS should not also keep a second hand-written list of the same names.

This chapter removes that duplication.

After this change, /programs is generated from the embedded program registry.

That means the VFS only needs to know how to expose a registry-backed directory and synthesize a read-only pseudo-file for each registered program:

/programs/demo
/programs/counter
/programs/shell
/programs/fstest

The shell output does not change:

ush> ls /programs
file demo
file counter
file shell
file fstest

But the implementation becomes simpler and easier to extend.

If a future chapter adds another embedded program, /programs will pick it up automatically instead of requiring a second filesystem edit.


1. What this chapter adds

Modify:

include/kernel/program.h
kernel/program.c
kernel/vfs.c
tests/smoke.py
README.md
CHANGELOG.md
index.md
docs/roadmap.md

No new syscall is needed.

No shell syntax changes are needed.

This is a filesystem and documentation cleanup built on top of the embedded-program registry that already exists.


2. Why this matters

The program registry already answers one important question:

Which embedded programs exist?

The VFS should reuse that answer instead of repeating it.

Before this chapter, the kernel had two separate sources of truth:

kernel/program.c  -> program registry
kernel/vfs.c      -> manual /programs directory table

That duplication works until the next program lands.

Then the registry changes, the filesystem changes, and the tests have to be updated in lockstep.

That is the kind of drift that causes stale tutorials and misleading logs.

This chapter removes the drift by making the VFS ask the registry for the live program list.


3. What we implement

The change is small but structural.

First, kernel/program.c exposes safe registry iteration helpers:

uint32_t program_registry_count(void);
const embedded_program_t *program_registry_get(uint32_t index);

That lets other kernel code iterate the registry without reaching into the raw array.

Then kernel/vfs.c uses those helpers in three places:

vfs_readdir()
vfs_stat()
vfs_read()

/programs becomes a synthetic directory view over the registry.

/programs/<name> becomes a synthetic read-only file that reports the program name and description.

The user-visible result is still the same simple workflow:

toyix> run shell
ush> ls /programs
ush> stat /programs/demo
ush> cat /programs/demo

But the filesystem is now derived from the registry instead of being copied by hand.


4. How the code works

The VFS keeps static nodes for /, /README, and /programs.

It no longer stores individual /programs/<name> entries in RAMFS tables.

Instead, when the kernel sees a path like /programs/demo, it:

1. checks the path prefix
2. looks up the program in the registry
3. exposes a file object backed by generated text

That lets stat, read, and ls keep working without a second copy of the program list.

The generated file text is intentionally simple:

Toyix embedded program: demo
Description: interactive stdin/stdout demo

The important part is not the prose in the file.

The important part is that the file exists because the registry says it exists.


5. What to verify

After this chapter, these checks should still pass:

VFS: initialized RAMFS with 3 node(s)
VFS test: /programs entries=4 type=directory
VFS test: /programs/demo size=
fstest: /programs type=directory size=4
fstest: first /programs entry: demo

And the shell should still behave the same way:

ush> ls /programs
ush> cat /programs/demo
ush> run /programs/counter alpha beta

That is the real point of the chapter.

The layout becomes less brittle, but the user workflow stays stable.


Resources

Closure

Chapter 41 replaces a hand-maintained filesystem mirror with a registry-backed view of the same embedded programs.
The next chapter can build on this without having to keep two copies of the program list in sync.

Happy Coding!

AI for Software Development

Leveraging AI for the Complete Software Development Cycle as a Lone Developer

Leave a Reply

Your email address will not be published. Required fields are marked *