Punch list item 4 (final): CONSOLE-ATTACH, full unattended-identity flow verified end-to-end
Closes FABRIC-3.md §XXXII.2's punch list. CONSOLE-ATTACH ( name-c name-u -- ok? ) pairs a fresh console VM to an already-live VM registered as "<name>~user". Deliberately a plain, unconditional primitive with no VMIdentity capability-bit check -- corrects this session's own first-pass design (§XXXII.2 amended in the same commit): identity.installed is 0 for Hera/Hermes/Artemis and for every console-proxy VM, so a capability-bit gate would be unreachable for every VM a human actually types at, Zuse included. Matches ZUSE-ELIGIBILITY-ADD's own "no bespoke gate" precedent in this file; real gating is `' CONSOLE-ATTACH ACL-PIN` in ACL.4th if ever wanted. Two real bugs found and fixed via live testing, not assumed correct: - capsule_birth_baby() never sets a VM's registry name (documented gap, same one capsule_runcap_birth()'s own history already hit) -- UNATTENDED-BIRTH gained a second `name` argument and now calls capsule_vm_registry_set_name(new_vm_id, "<name>~user") itself. - CONSOLE-ATTACH's first draft took an independent console name from the target's name. sk_repl_dispatch_line()'s pairing check (repl.c) reconstructs the target as console_get_vm_name()+"~user" -- a mismatched console name silently falls back to direct interpretation with no error. Caught live (typed `5 6 + .` at a mismatched console, got a direct `11` instead of a relay) and fixed by collapsing to one name argument, matching WIREBIND's own by-construction invariant. Full end-to-end live verification on amd64: minted a test identity, UNATTENDED-BIRTH'd it as "bob", CONSOLE-ATTACH'd a console named "bob", USE'd it, typed `5 6 + .` -- no direct output at [zuse@bob] (relay path taken), then `[zuse@bob~user] 11 ok>` appeared: the relayed command executed on the target identity VM itself and printed its own answer back through the shared console. Hera stayed healthy throughout (2 2 + . -> 4 after switching back). CONSOLE-ATTACH also verified to refuse cleanly on a nonexistent target with no orphaned VM. Test capsule reverted after capture per this project's probe convention -- never committed. FABRIC-3.md §XXXII.2 fully closed: all 4 original questions ratified, the mid-course drive_uuid and ACL-bit corrections both recorded plainly rather than silently folded in, and a doc-accuracy note left for CLAUDE.md's own stale "1024-byte block limit" framing (mkcapsule's real limits are range [2048,5120) and 16 content lines/block) -- flagged, not fixed, out of this punch list's scope. Clean 3-arch qemu boot (amd64/aarch64/riscv64) on the real committed C-only change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5879c8b3bc
commit
af351bff92
+51
-28
@@ -4355,40 +4355,63 @@ This collapses all four questions:
|
|||||||
**`vm_identity_from_cert()` needs zero changes** -- no origin-aware variant, no
|
**`vm_identity_from_cert()` needs zero changes** -- no origin-aware variant, no
|
||||||
content-hash-derived substitute. This is a strictly better answer than the deferred
|
content-hash-derived substitute. This is a strictly better answer than the deferred
|
||||||
"Bob's call" the first pass of this section left open.
|
"Bob's call" the first pass of this section left open.
|
||||||
3. **ACL-gated console attachment -- checks the attaching human's own credentials, not the
|
3. **ACL-gated console attachment -- corrected 2026-09-16: no `VMIdentity` capability bit.**
|
||||||
instance's.** Falls directly out of the no-seed decision: an unattended instance can never
|
The first pass of this answer proposed exactly that (a capability bit checked on the
|
||||||
prove anything about itself at attach time (it holds no secret to challenge), so the gate
|
attaching human's own identity) -- wrong on two independent counts, not one. CLAUDE.md's
|
||||||
necessarily lives on the human side -- almost certainly a capability bit
|
own hard rule: "ACL policy belongs in `ACL.4th`, never in C." And a mechanical fact traced
|
||||||
(`VMIdentity.acl_caps`, still unassigned per this header's own "real bits get names only
|
live while building `CONSOLE-ATTACH`: `identity.installed` is 0 for Hera/Hermes/Artemis
|
||||||
once the operation gets built" precedent) checked on the attaching human's own verified
|
*and* for every console-proxy VM -- a `vm_identity_has_cap()` gate would be unreachable for
|
||||||
identity before the console-birth + `VM-NAME-REG` pairing (§XXXII.2 above) is allowed to
|
every VM a human actually types at, Zuse included. That isn't a policy disagreement, it's a
|
||||||
run. Concrete bit value: punch-list item, not decided here.
|
gate that can never open. `CONSOLE-ATTACH` is a plain, unconditional primitive (same "no
|
||||||
|
bespoke gate" doctrine `ZUSE-ELIGIBILITY-ADD` already carries in its own comment);
|
||||||
|
restricting who may call it, if ever wanted, is `' CONSOLE-ATTACH ACL-PIN` in `ACL.4th`.
|
||||||
4. **§VII's xHCI/live-table machinery -- confirmed irrelevant, independently of the seed
|
4. **§VII's xHCI/live-table machinery -- confirmed irrelevant, independently of the seed
|
||||||
question.** An unattended identity is born from a capsule directory entry, never from a
|
question.** An unattended identity is born from a capsule directory entry, never from a
|
||||||
`blkio_dev*`; it has no physical device to attach/detach and never enters the xHCI
|
`blkio_dev*`; it has no physical device to attach/detach and never enters the xHCI
|
||||||
per-device registry at all. This holds regardless of how Q1/Q2 were answered, so it was
|
per-device registry at all. This holds regardless of how Q1/Q2 were answered, so it was
|
||||||
never actually contingent on the seed decision above.
|
never actually contingent on the seed decision above.
|
||||||
|
|
||||||
**Punch list for implementation (not started, needs explicit authorization per this project's
|
**Punch list for implementation -- CLOSED, all 3 items done and live-verified (2026-09-16):**
|
||||||
standing "plan approval is not a start signal" rule):**
|
- ✅ **Scratch-device mint path.** `capsule_mint_identity_scratch()` (`capsule_mint.c`/`.h`) +
|
||||||
- Build the scratch-device mint path: attach a `blk_subsys_add_raw_device()`-backed buffer
|
`MINT-SCRATCH`/`MINT-SCRATCH-EMIT` (`mama_forth_words.c`). Built on `blkio_ram.c`'s generic
|
||||||
sized for sig+cert devblocks only, run `capsule_mint_identity()` against it unmodified
|
RAM-backed `blkio_dev`, not `blk_subsys_add_raw_device()` as first proposed -- that call
|
||||||
(live, on a booted Hera with Zuse authenticated -- likely a new FORTH word, or a `MINT`
|
registers into the block-subsystem's own BAM chain, an unrelated persistence layer with no
|
||||||
variant that takes a device handle rather than always resolving one from an attach event).
|
bearing on `capsule_mint_identity()`'s `blkio_dev*` need. `blkio_ram.c`/`blkio_factory.c`
|
||||||
- Hand-transcribe the resulting `drive_uuid` + DER cert bytes out of the scratch buffer as
|
were vendored, hosted-only source excluded from the kernel build entirely; pulled
|
||||||
FORTH literals into a new `.4th` capsule block, following the existing `Block NNNN`
|
`blkio_ram.c` alone in (pure memcpy, no file I/O, freestanding-safe) rather than the whole
|
||||||
convention -- checked into the repo, picked up by the next `mkcapsule` build like any other
|
factory (which unconditionally references `blkio_file.c`'s real `fopen()`/`fread()`).
|
||||||
capsule.
|
Verified live on amd64: two mints produced two genuinely different `drive_uuid`s; the cert's
|
||||||
- Add the unattended-birth call site: `capsule_birth_baby()` (unmodified) + read the embedded
|
own embedded ASN.1 serialNumber matched the emitted UUID byte-for-byte.
|
||||||
`drive_uuid`+cert literals back out of the capsule's own arena + `vm_identity_from_cert()`
|
- ✅ **Hand-transcription.** `MINT-SCRATCH-EMIT` prints `drive_uuid`+cert as ready-to-paste
|
||||||
(unmodified) + post-birth `identity` assignment (`capsule_wirebind.c:272-274`'s pattern),
|
`CREATE ... C, ...` FORTH literals. **Correction to this section's own doc-comment framing:**
|
||||||
gated by the explicit invariant already stated above (never touch
|
`mkcapsule`'s real constraints, confirmed by the tool itself (not the doc), are block range
|
||||||
`g_wirebind_attached_username`/console-pairing).
|
`[2048, 5120)` and a hard 16-content-line-per-block cap -- not the 1024-byte-per-block
|
||||||
- Assign a real `acl_caps` bit for "may attach a console to an unattended instance" and wire
|
framing this file's CLAUDE.md counterpart describes. Doc fix needed, out of this punch
|
||||||
the check into the console-birth + `VM-NAME-REG` path.
|
list's own scope; noted here so it isn't lost.
|
||||||
- Acceptance: 3-arch clean boot with at least one unattended instance born at boot, no console
|
- ✅ **Unattended-birth call site.** `UNATTENDED-BIRTH` (`capsule-c capsule-u name-c name-u --
|
||||||
attached, verified un-promptable (§VIII.1 gate holds), then a human console attached to it
|
ok?`): `capsule_birth_baby()` unmodified, `vm_identity_from_cert()` unmodified, post-birth
|
||||||
after the fact via the existing `VM-NAME-REG` pairing mechanism.
|
`identity` assignment matching `capsule_wirebind.c:272-274`'s own pattern -- plus a fix
|
||||||
|
`capsule_birth_baby()` itself needs from every caller (found live, matching
|
||||||
|
`capsule_runcap_birth()`'s own documented history of the identical gap):
|
||||||
|
`capsule_vm_registry_set_name(new_vm_id, "<name>~user")`, without which the VM is born but
|
||||||
|
undiscoverable by name to anything downstream.
|
||||||
|
- ✅ **Console attachment -- built as `CONSOLE-ATTACH ( name-c name-u -- ok? )`, not an ACL
|
||||||
|
bit** (Q3 above amended to match). Resolves the target's liveness via
|
||||||
|
`capsule_vm_find_by_name("<name>~user", ...)` *before* birthing a console, so a typo refuses
|
||||||
|
cleanly with no orphaned VM -- verified live. Takes exactly one name, not an independently
|
||||||
|
chosen console name: `sk_repl_dispatch_line()`'s own pairing check (`repl.c`) reconstructs
|
||||||
|
the target as `console_get_vm_name() + "~user"`, so a console named anything else silently
|
||||||
|
falls back to direct interpretation with no error -- caught live on the first attempt (typed
|
||||||
|
`5 6 + .` at a mismatched console and got a direct `11` instead of a relayed one), fixed by
|
||||||
|
collapsing to a single name argument.
|
||||||
|
- **Full end-to-end live verification, amd64, 2026-09-16:** minted a test identity ->
|
||||||
|
`UNATTENDED-BIRTH` (named `bob`) -> `CONSOLE-ATTACH bob` -> `S" bob" USE` -> typed
|
||||||
|
`5 6 + .` at the new console -> printed nothing at `[zuse@bob]` (confirming the relay path
|
||||||
|
was taken, not the direct-interpret fallback) -> `[zuse@bob~user] 11 ok>` appeared --
|
||||||
|
the relayed command actually executed on the target identity VM itself and printed its own
|
||||||
|
answer back through the shared console, unprompted messaging infrastructure and all. Hera
|
||||||
|
remained healthy throughout (`2 2 + .` -> `4` after switching back). Test capsule reverted
|
||||||
|
after capture per this project's own probe convention; nothing about it is committed.
|
||||||
|
|
||||||
### XXXII.3 -- Primitive error-handling audit: kernel-only scope, real surface counted
|
### XXXII.3 -- Primitive error-handling audit: kernel-only scope, real surface counted
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Capsule Block Manifest — Auto-generated
|
# Capsule Block Manifest — Auto-generated
|
||||||
<!-- Generated by mkcapsule --manifest 2026-09-16T11:05:06Z -->
|
<!-- Generated by mkcapsule --manifest 2026-09-16T11:22:44Z -->
|
||||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||||
<!-- Hand-written justifications and immutability notes live -->
|
<!-- Hand-written justifications and immutability notes live -->
|
||||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1615,7 +1615,7 @@ void mama_word_capsule_birth(VM *vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UNATTENDED-BIRTH ( name-c name-u -- ok? )
|
* @brief UNATTENDED-BIRTH ( capsule-c capsule-u name-c name-u -- ok? )
|
||||||
* Birth an unattended identity from a named (p) capsule -- the
|
* Birth an unattended identity from a named (p) capsule -- the
|
||||||
* punch-list item 3 call site (FABRIC-3.md §XXXII.2, 2026-09-16):
|
* punch-list item 3 call site (FABRIC-3.md §XXXII.2, 2026-09-16):
|
||||||
* capsule_birth_baby() unmodified (same generic build-time-capsule
|
* capsule_birth_baby() unmodified (same generic build-time-capsule
|
||||||
@@ -1635,25 +1635,53 @@ void mama_word_capsule_birth(VM *vm)
|
|||||||
* dictionary" idiom capsule_wirebind.c already uses for VM-NAME-REG,
|
* dictionary" idiom capsule_wirebind.c already uses for VM-NAME-REG,
|
||||||
* not a new mechanism.
|
* not a new mechanism.
|
||||||
*
|
*
|
||||||
|
* `name` becomes the VM's own registry name, suffixed "~user" exactly
|
||||||
|
* as capsule_runcap_birth()/WIREBIND already do for a real thumbdrive
|
||||||
|
* identity -- this is what CONSOLE-ATTACH (below) and sk_repl_dispatch_
|
||||||
|
* line()'s own pairing check (repl.c) look up later. capsule_birth_
|
||||||
|
* baby() itself never sets this (found live during capsule_runcap_
|
||||||
|
* birth()'s own history, repeated here rather than left silently
|
||||||
|
* missing): every caller does it as its own explicit step.
|
||||||
|
*
|
||||||
* Explicit invariant (FABRIC-3.md §XXXII.2's own ratified text): this
|
* Explicit invariant (FABRIC-3.md §XXXII.2's own ratified text): this
|
||||||
* word never touches g_wirebind_attached_username or any other
|
* word never touches g_wirebind_attached_username or any other
|
||||||
* WIREBIND/console-pairing state, and births no console VM -- an
|
* WIREBIND/console-pairing state, and births no console VM -- an
|
||||||
* unattended identity stays un-promptable (§VIII.1) until a human
|
* unattended identity stays un-promptable (§VIII.1) until a human
|
||||||
* pairs a console to it later via the existing VM-NAME-REG mechanism,
|
* pairs a console to it later via CONSOLE-ATTACH, a separate step this
|
||||||
* a separate, already-working step this word does not perform.
|
* word does not perform.
|
||||||
*/
|
*/
|
||||||
static void mama_word_unattended_birth(VM *vm)
|
static void mama_word_unattended_birth(VM *vm)
|
||||||
{
|
{
|
||||||
char capsule_name[VM_NAME_MAX];
|
char capsule_name[VM_NAME_MAX];
|
||||||
|
char id_name[VM_NAME_MAX];
|
||||||
cell_t u, caddr;
|
cell_t u, caddr;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if (vm->dsp < 1) {
|
if (vm->dsp < 3) {
|
||||||
console_println("UNATTENDED-BIRTH: expects S\" capsule-name\" UNATTENDED-BIRTH");
|
console_println("UNATTENDED-BIRTH: expects S\" capsule\" S\" name\" UNATTENDED-BIRTH");
|
||||||
vm->error = 1;
|
vm->error = 1;
|
||||||
vm_push(vm, 0);
|
vm_push(vm, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
u = vm_pop(vm);
|
||||||
|
caddr = vm_pop(vm);
|
||||||
|
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) {
|
||||||
|
console_println("UNATTENDED-BIRTH: identity name too long or empty");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
||||||
|
if (!p) {
|
||||||
|
console_println("UNATTENDED-BIRTH: invalid address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < (uint32_t)u; i++) id_name[i] = (char)p[i];
|
||||||
|
}
|
||||||
|
id_name[u] = '\0';
|
||||||
|
|
||||||
u = vm_pop(vm);
|
u = vm_pop(vm);
|
||||||
caddr = vm_pop(vm);
|
caddr = vm_pop(vm);
|
||||||
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) {
|
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) {
|
||||||
@@ -1679,6 +1707,18 @@ static void mama_word_unattended_birth(VM *vm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char reg_name[VM_NAME_MAX + 8];
|
||||||
|
{
|
||||||
|
size_t nlen = strlen(id_name);
|
||||||
|
if (nlen + 6 > sizeof(reg_name)) {
|
||||||
|
console_println("UNATTENDED-BIRTH: identity name too long");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(reg_name, id_name, nlen);
|
||||||
|
memcpy(reg_name + nlen, "~user", 6);
|
||||||
|
}
|
||||||
|
|
||||||
VMUuid new_vm_id = vm_uuid_none();
|
VMUuid new_vm_id = vm_uuid_none();
|
||||||
void *new_vm_ctx = (void *)0;
|
void *new_vm_ctx = (void *)0;
|
||||||
CapsuleRunResult result = capsule_birth_baby(
|
CapsuleRunResult result = capsule_birth_baby(
|
||||||
@@ -1727,11 +1767,124 @@ static void mama_word_unattended_birth(VM *vm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
born_vm->identity = identity;
|
born_vm->identity = identity;
|
||||||
|
capsule_vm_registry_set_name(new_vm_id, reg_name);
|
||||||
|
|
||||||
console_println("UNATTENDED-BIRTH: identity installed, no console attached");
|
console_println("UNATTENDED-BIRTH: identity installed, no console attached");
|
||||||
vm_push(vm, 1);
|
vm_push(vm, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CONSOLE-ATTACH ( name-c name-u -- ok? )
|
||||||
|
* Pair a fresh console VM to an already-live VM registered as
|
||||||
|
* "<name>~user" -- the "ACL-gated console attachment later" step
|
||||||
|
* FABRIC-3.md §XXXII.2's Q3 describes, for both an UNATTENDED-BIRTH'd
|
||||||
|
* identity and, just as validly, a WIREBIND-attached one that lost its
|
||||||
|
* console (same registry-name convention either way).
|
||||||
|
*
|
||||||
|
* Takes exactly one name, not an independently-chosen console name --
|
||||||
|
* found live, not assumed: sk_repl_dispatch_line()'s own pairing check
|
||||||
|
* (repl.c) reconstructs the target as console_get_vm_name() + "~user",
|
||||||
|
* where console_get_vm_name() is whatever name USE last switched the
|
||||||
|
* prompt to (the console's own birth name). A console named anything
|
||||||
|
* other than the identity's own base name reconstructs the wrong
|
||||||
|
* target string and silently falls back to direct interpretation --
|
||||||
|
* no error, just quietly never relays. WIREBIND's own console+user
|
||||||
|
* birth pair (capsule_wirebind_try_attach()) already enforces this by
|
||||||
|
* construction (both sides built from the same `username`); this word
|
||||||
|
* makes the same invariant explicit rather than accepting two names
|
||||||
|
* that could mismatch.
|
||||||
|
*
|
||||||
|
* Deliberately a plain, unconditional primitive -- no VMIdentity
|
||||||
|
* capability-bit check here or anywhere else in this codebase (§XXXII.2
|
||||||
|
* amended 2026-09-16, correcting the first pass of this section, which
|
||||||
|
* had proposed exactly that). Two independent reasons rule it out, not
|
||||||
|
* one: CLAUDE.md's own hard rule ("ACL policy belongs in ACL.4th, never
|
||||||
|
* in C"), and a mechanical fact traced live -- identity.installed is 0
|
||||||
|
* for Hera/Hermes/Artemis *and* for every console-proxy VM, so a
|
||||||
|
* vm_identity_has_cap() gate here would be unreachable for every VM a
|
||||||
|
* human actually types at, Zuse included. Matches ZUSE-ELIGIBILITY-ADD's
|
||||||
|
* own precedent in this same file: restricting who may call this word,
|
||||||
|
* if ever wanted, is `' CONSOLE-ATTACH ACL-PIN` in ACL.4th, not a
|
||||||
|
* bespoke check invented here.
|
||||||
|
*
|
||||||
|
* Target liveness is resolved *before* birthing anything -- a typo'd
|
||||||
|
* name refuses cleanly with no orphaned console VM left behind, rather
|
||||||
|
* than birthing first and discovering the mismatch after.
|
||||||
|
*/
|
||||||
|
static void mama_word_console_attach(VM *vm)
|
||||||
|
{
|
||||||
|
char id_name[VM_NAME_MAX];
|
||||||
|
cell_t u, caddr;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (vm->dsp < 1) {
|
||||||
|
console_println("CONSOLE-ATTACH: expects S\" name\" CONSOLE-ATTACH");
|
||||||
|
vm->error = 1;
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
u = vm_pop(vm);
|
||||||
|
caddr = vm_pop(vm);
|
||||||
|
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) {
|
||||||
|
console_println("CONSOLE-ATTACH: name too long or empty");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
||||||
|
if (!p) {
|
||||||
|
console_println("CONSOLE-ATTACH: invalid address on the stack");
|
||||||
|
vm->error = 1;
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < (uint32_t)u; i++) id_name[i] = (char)p[i];
|
||||||
|
}
|
||||||
|
id_name[u] = '\0';
|
||||||
|
|
||||||
|
char target_name[VM_NAME_MAX + 8];
|
||||||
|
{
|
||||||
|
size_t nlen = strlen(id_name);
|
||||||
|
if (nlen + 6 > sizeof(target_name)) {
|
||||||
|
console_println("CONSOLE-ATTACH: target name too long");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(target_name, id_name, nlen);
|
||||||
|
memcpy(target_name + nlen, "~user", 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resolve first -- refuse cleanly on a typo instead of birthing a
|
||||||
|
* console VM with nothing live to pair it to. */
|
||||||
|
VMRegistryEntry target_entry;
|
||||||
|
if (capsule_vm_find_by_name(target_name, &target_entry) != 0 ||
|
||||||
|
target_entry.state != VM_STATE_LIVE) {
|
||||||
|
console_println("CONSOLE-ATTACH: refused -- no live VM registered under that name");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMUuid console_id;
|
||||||
|
void *console_ctx = (void *)0;
|
||||||
|
if (capsule_console_birth(id_name, vm->stadium_vm_id, &console_id, &console_ctx)
|
||||||
|
!= CAPSULE_RUN_OK) {
|
||||||
|
console_println("CONSOLE-ATTACH: console birth FAILED");
|
||||||
|
vm_push(vm, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char reg_cmd[VM_NAME_MAX + 32];
|
||||||
|
int n = snprintf(reg_cmd, sizeof(reg_cmd), "S\" %s\" 3 VM-NAME-REG", target_name);
|
||||||
|
if (n > 0 && (size_t)n < sizeof(reg_cmd)) {
|
||||||
|
vm_interpret((VM *)console_ctx, reg_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console_println("CONSOLE-ATTACH: console paired to target -- USE the console name to attach");
|
||||||
|
vm_push(vm, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief CAPSULE-RUN ( capsule-id -- )
|
* @brief CAPSULE-RUN ( capsule-id -- )
|
||||||
* Run an experiment (e) capsule on Mama.
|
* Run an experiment (e) capsule on Mama.
|
||||||
@@ -2073,6 +2226,7 @@ void register_mama_forth_words(VM *vm)
|
|||||||
register_word(vm, "MINT-SCRATCH", mama_word_mint_scratch);
|
register_word(vm, "MINT-SCRATCH", mama_word_mint_scratch);
|
||||||
register_word(vm, "MINT-SCRATCH-EMIT", mama_word_mint_scratch_emit);
|
register_word(vm, "MINT-SCRATCH-EMIT", mama_word_mint_scratch_emit);
|
||||||
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
|
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
|
||||||
|
register_word(vm, "CONSOLE-ATTACH", mama_word_console_attach);
|
||||||
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
|
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
|
||||||
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
|
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
|
||||||
register_word(vm, "NAME>XT", mama_word_name_to_xt);
|
register_word(vm, "NAME>XT", mama_word_name_to_xt);
|
||||||
@@ -2135,6 +2289,7 @@ void register_mama_forth_words(VM *vm)
|
|||||||
register_word(vm, "MINT-SCRATCH", mama_word_mint_scratch);
|
register_word(vm, "MINT-SCRATCH", mama_word_mint_scratch);
|
||||||
register_word(vm, "MINT-SCRATCH-EMIT", mama_word_mint_scratch_emit);
|
register_word(vm, "MINT-SCRATCH-EMIT", mama_word_mint_scratch_emit);
|
||||||
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
|
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
|
||||||
|
register_word(vm, "CONSOLE-ATTACH", mama_word_console_attach);
|
||||||
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
|
register_word(vm, "ZUSE-ELIGIBILITY-ADD", mama_word_zuse_eligibility_add);
|
||||||
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
|
register_word(vm, "ZUSE-ELIGIBLE?", mama_word_zuse_eligible_query);
|
||||||
register_word(vm, "NAME>XT", mama_word_name_to_xt);
|
register_word(vm, "NAME>XT", mama_word_name_to_xt);
|
||||||
|
|||||||
Reference in New Issue
Block a user