feat(users): per-user sealed folders users/<id>/{home,apps,data,permissions}; storage SET_USER/LOCK/PURGE; init sign-in/sign-out loop (purge fresh/removed/guest, seed from factory, session start/stop); shell logout; pm user+system app shelves; terminal SIGNED_OUT; per-program stack (gatekeeper 12p); 128K load scratch

This commit is contained in:
2026-10-28 01:08:50 +01:00
parent 29a25bd8c2
commit 91f7d28834
38 changed files with 1156 additions and 378 deletions

View File

@@ -103,6 +103,10 @@ impl server::Console for Screen {
fn interrupt(&mut self, notification: CapSlot) {
let _ = syscall::signal(notification);
}
fn forget(&mut self, notification: CapSlot) {
syscall::drop_cap(notification);
}
}
pub fn run() -> ! {

View File

@@ -24,6 +24,8 @@ pub trait Console {
/// Takes input focus back from whoever took it, and clears the screen.
fn take_focus(&mut self);
fn interrupt(&mut self, notification: CapSlot);
/// Lets go of a notification it was given.
fn forget(&mut self, notification: CapSlot);
}
pub const BACKSPACE: u8 = 8;
@@ -232,7 +234,7 @@ impl<C: Console> Server for TerminalServer<C> {
Done
}
fn handle_call(&mut self, _badge: usize, words: [usize; 4], cap: Option<CapSlot>) -> ([usize; 4], Option<libkos::syscall::Give>) {
fn handle_call(&mut self, badge: usize, words: [usize; 4], cap: Option<CapSlot>) -> ([usize; 4], Option<libkos::syscall::Give>) {
let reply = match words[0] {
types::terminal::READ => self.read(false),
types::terminal::READ_SECRET => self.read(true),
@@ -252,6 +254,13 @@ impl<C: Console> Server for TerminalServer<C> {
}
_ => [MALFORMED, 0, 0, 0],
},
types::terminal::SIGNED_OUT if badge == 0 => {
if let Some(n) = self.on_interrupt.take() {
self.console.forget(n);
}
[0; 4]
}
types::terminal::SIGNED_OUT => [MALFORMED, 0, 0, 0],
types::terminal::CLEAR => {
self.handle(Request::Clear);
[0; 4]

View File

@@ -20,6 +20,7 @@ struct Fake {
/// Every row drawn, with how many cells.
rows_drawn: Vec<(usize, usize)>,
interrupted: Vec<CapSlot>,
forgotten: Vec<CapSlot>,
}
impl Console for Fake {
@@ -48,6 +49,9 @@ impl Console for Fake {
fn interrupt(&mut self, notification: CapSlot) {
self.interrupted.push(notification);
}
fn forget(&mut self, notification: CapSlot) {
self.forgotten.push(notification);
}
}
fn term(keys: &[u8]) -> TerminalServer<Fake> {
@@ -186,3 +190,17 @@ fn a_secret_line_shows_stars_and_is_forgotten() {
assert_eq!(&t.grid().row(0)[..8], b"*******\x20");
assert!(!t.grid().row(0).windows(7).any(|w| w == b"hunter2"));
}
#[test]
fn only_init_lets_the_next_session_register_for_ctrl_c() {
use server_framework::MALFORMED;
let mut t = term(&[]);
assert_eq!(on_interrupt(&mut t, 7), 0);
assert_eq!(on_interrupt(&mut t, 8), MALFORMED, "an app cannot take Ctrl+C over");
let signed_out = |t: &mut TerminalServer<Fake>, badge| t.handle_call(badge, [types::terminal::SIGNED_OUT, 0, 0, 0], None).0[0];
assert_eq!(signed_out(&mut t, 1), MALFORMED, "nor say the user signed out");
assert_eq!(on_interrupt(&mut t, 8), MALFORMED);
assert_eq!(signed_out(&mut t, 0), 0);
assert_eq!(t.console().forgotten, [CapSlot::new(7).unwrap()]);
assert_eq!(on_interrupt(&mut t, 9), 0, "the next shell may");
}