feat(userspace): programs in /bin w/o .elf; bin manifests (needs = display) so shell runs snake; Ctrl+C kills foreground via terminal interrupt notification; ctrl keys; sleep
This commit is contained in:
@@ -55,18 +55,21 @@ pub const CELL_HEIGHT: usize = 16;
|
||||
/// arrive; read them with `poll_input`.
|
||||
pub fn subscribe_input(ep: CapSlot) -> Option<CapSlot> {
|
||||
use types::badge::Badge;
|
||||
use types::permission::{Permission, PermissionSet};
|
||||
let notify = syscall::create_notification().ok()?;
|
||||
subscribe(ep, notify, Badge::NONE).then_some(notify)
|
||||
}
|
||||
|
||||
/// Takes input focus, to be told through `notify` with `badge`'s bits.
|
||||
pub fn subscribe(ep: CapSlot, notify: CapSlot, badge: types::badge::Badge) -> bool {
|
||||
use types::permission::{Permission, PermissionSet};
|
||||
// Signal only (Delegate just to send it; the transfer strips it).
|
||||
let signal = PermissionSet::empty().with(Permission::Write).with(Permission::Delegate);
|
||||
let copy = syscall::mint(notify, Badge::NONE, signal).ok()?;
|
||||
let sent = syscall::call(
|
||||
ep,
|
||||
[types::display::input::SUBSCRIBE, 0, 0, 0],
|
||||
Some(copy.into()),
|
||||
);
|
||||
let Ok(copy) = syscall::mint(notify, badge, signal) else {
|
||||
return false;
|
||||
};
|
||||
let sent = syscall::call(ep, [types::display::input::SUBSCRIBE, 0, 0, 0], Some(copy.into()));
|
||||
syscall::drop_cap(copy);
|
||||
(sent.ok()?.words()[0] == 0).then_some(notify)
|
||||
sent.is_ok_and(|r| r.words()[0] == 0)
|
||||
}
|
||||
|
||||
/// The next input event, if this process has focus and one is waiting.
|
||||
|
||||
@@ -57,6 +57,12 @@ impl Spawned {
|
||||
syscall::delegate(cap, self.process, perms.without(Permission::Delegate))
|
||||
}
|
||||
|
||||
/// Like `give`, but an endpoint the program may send capabilities
|
||||
/// through (which takes Delegate, so it could pass the endpoint on too).
|
||||
pub fn give_sending(&self, endpoint: CapSlot, perms: PermissionSet) -> Option<CapSlot> {
|
||||
syscall::delegate(endpoint, self.process, perms.with(Permission::Delegate))
|
||||
}
|
||||
|
||||
/// Puts `args` (its name first) where the program finds them: a page
|
||||
/// this process fills and then moves into the program, which owns it.
|
||||
pub fn set_args(&self, args: &[&str]) -> bool {
|
||||
|
||||
@@ -38,6 +38,11 @@ pub fn storage() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).storage
|
||||
}
|
||||
|
||||
/// The display server endpoint this process was given, if any.
|
||||
pub fn display() -> Option<CapSlot> {
|
||||
StartArg::decode(arg()).display
|
||||
}
|
||||
|
||||
/// This program's arguments, its name first; none without an args page.
|
||||
pub fn args() -> impl Iterator<Item = &'static str> {
|
||||
let page: &'static [u8] = if StartArg::decode(arg()).args {
|
||||
|
||||
@@ -27,3 +27,22 @@ pub fn read_line(terminal: CapSlot, buf: &mut [u8]) -> usize {
|
||||
pub fn clear(terminal: CapSlot) {
|
||||
let _ = syscall::request(terminal, [types::terminal::CLEAR, 0, 0, 0]);
|
||||
}
|
||||
|
||||
/// Repaints the terminal and gives it input focus again, after a program
|
||||
/// that drew on the screen.
|
||||
pub fn redraw(terminal: CapSlot) {
|
||||
let _ = syscall::request(terminal, [types::terminal::REDRAW, 0, 0, 0]);
|
||||
}
|
||||
|
||||
/// Has the terminal signal `notify` with `badge`'s bits when Ctrl+C is
|
||||
/// typed while no line is being read. Only the first caller is heard.
|
||||
pub fn on_interrupt(terminal: CapSlot, notify: CapSlot, badge: types::badge::Badge) -> bool {
|
||||
use types::permission::{Permission, PermissionSet};
|
||||
let signal = PermissionSet::empty().with(Permission::Write).with(Permission::Delegate);
|
||||
let Ok(copy) = syscall::mint(notify, badge, signal) else {
|
||||
return false;
|
||||
};
|
||||
let sent = syscall::call(terminal, [types::terminal::ON_INTERRUPT, 0, 0, 0], Some(copy.into()));
|
||||
syscall::drop_cap(copy);
|
||||
sent.is_ok_and(|r| r.words()[0] == 0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user