diff --git a/kernel/include/starkernel/v4/sk_v4_identity.h b/kernel/include/starkernel/v4/sk_v4_identity.h index dcbde69c..aef23de9 100644 --- a/kernel/include/starkernel/v4/sk_v4_identity.h +++ b/kernel/include/starkernel/v4/sk_v4_identity.h @@ -20,8 +20,13 @@ int sk_v4_identity_present(void); * with nothing typed. */ void sk_v4_identity_beat(void); -/* Headless: no prompt, no input, until Zuse's session begins (v3's - * sk_repl_headless_wait()). */ +/* The USB drives that have arrived or left, now, not waiting for the next + * beat: before each prompt, so that a drive pulled while the last line ran + * is seen before a prompt is shown. */ +void sk_v4_identity_check_now(void); + +/* Headless: no prompt, and what is typed is read and dropped, until Zuse's + * session begins (v3's sk_repl_headless_wait()). */ void sk_v4_identity_wait(void); #endif /* STARKERNEL_V4_SK_V4_IDENTITY_H */ diff --git a/kernel/src/v4/sk_v4.c b/kernel/src/v4/sk_v4.c index d4df370c..71c8a8df 100644 --- a/kernel/src/v4/sk_v4.c +++ b/kernel/src/v4/sk_v4.c @@ -77,8 +77,10 @@ static void sk_v4_serve(v4_node *node, unsigned request) /* Read a line from the keyboard: characters are echoed, backspace rubs one * out, Enter ends it. Returns its length; or -1 when, with nothing typed, - * Zuse's session has ended (her drive was pulled): the caller goes headless. - * While nothing is typed the idle beat runs, as v3's sk_console_readline(). */ + * Zuse's session has ended (her drive was pulled): the caller goes headless + * (not in a build with EMERGENCY_CONSOLE_ENABLED, whose console needs no + * login: v3's sk_console_readline() the same). While nothing is typed the + * idle beat runs, as v3's. */ static int sk_v4_readline(void) { int len = 0; @@ -87,7 +89,9 @@ static int sk_v4_readline(void) if (c < 0) { if (len == 0) { sk_v4_identity_beat(); +#if !EMERGENCY_CONSOLE_ENABLED if (!sk_v4_identity_present()) return -1; +#endif } else { heartbeat_service(); } @@ -134,9 +138,18 @@ void sk_v4_run(void (*chain)(void)) for (;;) { int len; int how; + int logged_out = 0; - /* no identity, no console: headless until Zuse's drive is checked */ +#if !EMERGENCY_CONSOLE_ENABLED + /* no identity, no console: headless until Zuse's drive is checked. + * The drives are looked at first, now: one pulled while the last + * line ran is seen before a prompt is shown (the identity gate's + * final review, item 1). Not in a build with + * EMERGENCY_CONSOLE_ENABLED, whose console needs no login (v3's + * kernel_main.c and repl.c the same; item 3). */ + sk_v4_identity_check_now(); if (!sk_v4_identity_present()) sk_v4_identity_wait(); +#endif console_puts(SK_V4_PROMPT); len = sk_v4_readline(); if (len < 0) continue; @@ -146,13 +159,26 @@ void sk_v4_run(void (*chain)(void)) * error, and then the line just typed is done (v4/boot.h). */ while (how == V4_BOOT_LINE_WAITING) { len = sk_v4_readline(); - if (len < 0) { sk_v4_identity_wait(); continue; } + if (len < 0) { + /* Zuse's session ended while the line waited: its wait is + * ended now, by an empty line, and not carried into the + * next session (Captain Bob, 2026-10-26: "end the waiting + * line at logout"). How it ended is shown; the empty line + * is then done, and shows nothing. */ + how = v4_boot_line(&boot, "", 0u); + if (how == V4_TEXT_ERROR) console_puts(" ERROR\n"); + else if (how == V4_TEXT_COMPLETED) console_puts(" ok\n"); + if (how == V4_TEXT_ERROR || how == V4_TEXT_COMPLETED) how = v4_boot_line(&boot, 0, 0); + logged_out = 1; + break; + } how = v4_boot_line(&boot, sk_v4_text, (unsigned)len); if (how == V4_TEXT_ERROR) console_puts(" ERROR\n" SK_V4_PROMPT); else if (how == V4_TEXT_COMPLETED) console_puts(" ok\n" SK_V4_PROMPT); else break; how = v4_boot_line(&boot, 0, 0); } + if (logged_out && (how == V4_TEXT_ERROR || how == V4_TEXT_COMPLETED)) continue; if (how == V4_TEXT_COMPLETED) console_puts(" ok\n"); else if (how == V4_TEXT_ERROR) console_puts(" ERROR\n"); else if (how == V4_BOOT_LINE_REFUSED) console_puts("Message refused\n ERROR\n"); /* the node's wire is full: error 19's words */ diff --git a/kernel/src/v4/sk_v4_identity.c b/kernel/src/v4/sk_v4_identity.c index 5de513aa..4619a518 100644 --- a/kernel/src/v4/sk_v4_identity.c +++ b/kernel/src/v4/sk_v4_identity.c @@ -191,10 +191,26 @@ void sk_v4_identity_beat(void) } } +void sk_v4_identity_check_now(void) +{ + g_last_beat = heartbeat_ticks(); + sk_v4_idle(); +} + +/* What was typed at a headless machine is no one's: it is read and dropped, + * so that it does not run as whoever logs in next (the identity gate's + * final review, item 4, 2026-10-26). */ +static void sk_v4_discard_input(void) +{ + while (console_getc() >= 0) { } +} + void sk_v4_identity_wait(void) { while (!g_zuse_session) { + sk_v4_discard_input(); sk_v4_identity_beat(); arch_relax(); } + sk_v4_discard_input(); }