all: remove yggdrasil_rt dependency

This commit is contained in:
Mark Poliakov 2023-11-24 13:29:53 +02:00
parent 6c8ae720d0
commit 6da1dbecc7
15 changed files with 362 additions and 203 deletions

119
Cargo.lock generated
View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "anstyle"
version = "1.0.1"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "autocfg"
@ -34,20 +34,19 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.3.19"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
dependencies = [
"clap_builder",
"clap_derive",
"once_cell",
]
[[package]]
name = "clap_builder"
version = "4.3.19"
version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
dependencies = [
"anstyle",
"clap_lex",
@ -55,9 +54,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.3.12"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck",
"proc-macro2",
@ -67,9 +66,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "crossterm"
@ -114,6 +113,43 @@ dependencies = [
"version_check",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-core",
"futures-macro",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "heck"
version = "0.4.1"
@ -230,12 +266,6 @@ dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "parking_lot"
version = "0.12.1"
@ -259,6 +289,18 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -267,18 +309,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.32"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
@ -311,18 +353,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.192"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.192"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
@ -369,6 +411,15 @@ dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.11.2"
@ -377,9 +428,9 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "syn"
version = "2.0.32"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
@ -405,7 +456,6 @@ version = "0.1.0"
dependencies = [
"clap",
"humansize",
"yggdrasil-rt",
]
[[package]]
@ -461,9 +511,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
@ -571,13 +621,22 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "yasync"
version = "0.1.0"
dependencies = [
"futures-util",
]
[[package]]
name = "yggdrasil-abi"
version = "0.1.0"
source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-abi.git#c957a433c73bd704ca0c64c16477638ababe2432"
[[package]]
name = "yggdrasil-rt"
version = "0.1.0"
source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-rt.git#f00ecdb926c2f912d658589f9f631100e41ad6c5"
dependencies = [
"yggdrasil-abi",
]

View File

@ -6,9 +6,3 @@ members = [
"sysutils",
"red"
]
[patch.'https://git.alnyan.me/yggdrasil/yggdrasil-abi.git']
yggdrasil-abi = { path = "../abi" }
[patch.'https://git.alnyan.me/yggdrasil/yggdrasil-rt.git']
yggdrasil-rt = { path = "rt" }

View File

@ -1,3 +1,3 @@
init:1:wait:/sbin/rc default
user:1:once:/sbin/login /dev/tty0
user:1:once:/sbin/login /dev/ttyS0

View File

@ -1,7 +1,7 @@
use crate::{
buffer::Mode,
command::Action,
keymap::{bind, KeyMap, PrefixNode},
keymap::{bindn, bind1, KeyMap, KeySeq, PrefixNode},
};
pub struct Config {
@ -18,30 +18,30 @@ impl Default for Config {
use Action::*;
let nmap = KeyMap::from_iter([
bind('i', [InsertBefore]),
bind('a', [InsertAfter]),
bind('h', [MoveCharPrev]),
bind('l', [MoveCharNext]),
bind('j', [MoveLineForward(1)]),
bind("J", [MoveLineForward(25)]),
bind('k', [MoveLineBack(1)]),
bind("K", [MoveLineBack(25)]),
bind("gg", [MoveFirstLine]),
bind("G", [MoveLastLine]),
bind('I', [MoveLineStart, InsertBefore]),
bind('A', [MoveLineEnd, InsertAfter]),
bind('o', [NewlineAfter, MoveLineForward(1), InsertBefore]),
bind('O', [NewlineBefore, MoveLineBack(1), InsertBefore]),
bind("dd", [KillLine]),
bind1('i', [InsertBefore]),
bind1('a', [InsertAfter]),
bind1('h', [MoveCharPrev]),
bind1('l', [MoveCharNext]),
bind1('j', [MoveLineForward(1)]),
bind1('J', [MoveLineForward(25)]),
bind1('k', [MoveLineBack(1)]),
bind1('K', [MoveLineBack(25)]),
bindn(['g', 'g'], [MoveFirstLine]),
bind1('G', [MoveLastLine]),
bind1('I', [MoveLineStart, InsertBefore]),
bind1('A', [MoveLineEnd, InsertAfter]),
bind1('o', [NewlineAfter, MoveLineForward(1), InsertBefore]),
bind1('O', [NewlineBefore, MoveLineBack(1), InsertBefore]),
bindn(['d', 'd'], [KillLine]),
]);
let imap = KeyMap::from_iter([
bind('\x7F', [EraseBackward]),
bind(
bind1('\x7F', [EraseBackward]),
bind1(
'\n',
[BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore],
),
bind(
bind1(
'\x0D',
[BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore],
),
@ -57,10 +57,10 @@ impl Default for Config {
}
impl Config {
pub fn key(&self, mode: Mode, key: &str) -> Option<&PrefixNode<String, Vec<Action>>> {
pub fn key_seq(&self, mode: Mode, seq: &KeySeq) -> Option<&PrefixNode<KeySeq, Vec<Action>>> {
match mode {
Mode::Normal => self.nmap.get(key),
Mode::Insert => self.imap.get(key),
Mode::Normal => self.nmap.get(seq),
Mode::Insert => self.imap.get(seq),
}
}
}

76
red/src/keymap/key.rs Normal file
View File

@ -0,0 +1,76 @@
use std::fmt::{self, Write};
use super::map::Prefix;
#[derive(Clone, Copy, PartialEq, Debug, Hash, Eq)]
pub enum Key {
Char(char),
Escape,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct KeySeq(Vec<Key>);
impl KeySeq {
pub fn one<I: Into<Key>>(k: I) -> Self {
Self(vec![k.into()])
}
pub fn empty() -> Self {
Self(vec![])
}
pub fn push<I: Into<Key>>(&mut self, k: I) {
self.0.push(k.into());
}
pub fn clear(&mut self) {
self.0.clear();
}
}
impl Prefix for KeySeq {
fn prefix(&self) -> Option<Self> {
self.0.split_last().map(|(_, vs)| vs.iter().copied().collect()).map(Self)
}
}
impl<K: Into<Key>, I: IntoIterator<Item = K>> From<I> for KeySeq {
fn from(value: I) -> Self {
Self(value.into_iter().map(Into::into).collect())
}
}
impl From<Key> for KeySeq {
fn from(value: Key) -> Self {
Self::one(value)
}
}
impl fmt::Display for KeySeq {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, key) in self.0.iter().enumerate() {
if i != 0 {
f.write_char('+')?;
}
fmt::Display::fmt(key, f)?;
}
Ok(())
}
}
impl From<char> for Key {
fn from(value: char) -> Self {
Self::Char(value)
}
}
impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Char('\t') => f.write_str("<tab>"),
Self::Char(key) => fmt::Display::fmt(key, f),
Self::Escape => f.write_str("<esc>"),
}
}
}

View File

@ -1,18 +1,18 @@
use std::{
borrow::Borrow,
hash::Hash,
};
use std::{borrow::Borrow, hash::Hash};
use crate::command::Action;
use self::map::{PrefixMap, Prefix};
use self::map::PrefixMap;
pub use self::map::PrefixNode;
mod key;
mod map;
#[derive(Debug, Default)]
pub use key::{Key, KeySeq};
#[derive(Debug)]
pub struct KeyMap {
map: PrefixMap<String, Vec<Action>>,
map: PrefixMap<KeySeq, Vec<Action>>,
}
impl KeyMap {
@ -22,64 +22,37 @@ impl KeyMap {
}
}
pub fn get<N>(&self, key: &N) -> Option<&PrefixNode<String, Vec<Action>>>
pub fn get<N>(&self, key: &N) -> Option<&PrefixNode<KeySeq, Vec<Action>>>
where
String: Borrow<N>,
KeySeq: Borrow<N>,
N: Eq + Hash + ?Sized,
{
self.map.get(key)
}
}
impl FromIterator<(String, Vec<Action>)> for KeyMap {
fn from_iter<T: IntoIterator<Item = (String, Vec<Action>)>>(iter: T) -> Self {
impl FromIterator<(KeySeq, Vec<Action>)> for KeyMap {
fn from_iter<T: IntoIterator<Item = (KeySeq, Vec<Action>)>>(iter: T) -> Self {
Self {
map: PrefixMap::from_iter(iter),
}
}
}
impl Prefix for String {
fn prefix(&self) -> Option<Self> {
if self.is_empty() {
None
} else {
let mut res = self.clone();
res.remove(res.len() - 1);
Some(res)
}
}
}
pub fn bind<I: Into<String>, V: IntoIterator<Item = Action>>(
pub fn bindn<I: Into<KeySeq>, V: IntoIterator<Item = Action>>(
key: I,
actions: V,
) -> (String, Vec<Action>) {
) -> (KeySeq, Vec<Action>) {
(key.into(), actions.into_iter().collect())
}
pub fn bind1<I: Into<Key>, V: IntoIterator<Item = Action>>(key: I, actions: V) -> (KeySeq, Vec<Action>) {
(KeySeq::one(key), actions.into_iter().collect())
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use crate::{command::Action, keymap::PrefixNode};
use super::{bind, KeyMap};
#[test]
fn from_iter() {
let map = KeyMap::from_iter([
bind("aa", [Action::InsertBefore, Action::MoveLineEnd]),
]);
assert_eq!(
map.get("a"),
Some(&PrefixNode::Prefix(HashSet::from_iter(["aa".to_owned()])))
);
assert_eq!(
map.get("aa"),
Some(&PrefixNode::Leaf([Action::InsertBefore, Action::MoveLineEnd].to_vec()))
);
}
}

View File

@ -1,4 +1,4 @@
#![feature(let_chains, rustc_private)]
#![feature(let_chains, rustc_private, async_fn_in_trait)]
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_raw_fd, yggdrasil_os))]
use std::{env, fmt::Write, path::Path};
@ -6,7 +6,7 @@ use std::{env, fmt::Write, path::Path};
use buffer::{Buffer, Mode, SetMode};
use config::Config;
use error::Error;
use keymap::PrefixNode;
use keymap::{PrefixNode, KeySeq, Key};
use term::{Clear, Color, Term};
pub mod buffer;
@ -29,7 +29,7 @@ pub struct State {
command: String,
message: Option<String>,
status: Option<String>,
key: String,
key_seq: KeySeq,
top_mode: TopMode,
config: Config,
running: bool,
@ -59,7 +59,7 @@ impl State {
message: None,
status: None,
command: String::new(),
key: String::new(),
key_seq: KeySeq::empty(),
running: true,
buffer,
term,
@ -157,7 +157,7 @@ impl State {
self.term
.set_cursor_position(self.buffer.height(), self.buffer.width() - 10)?;
self.term.set_foreground(Color::White)?;
write!(self.term, "{}", self.key).map_err(Error::TerminalFmtError)?;
write!(self.term, "{}", self.key_seq).map_err(Error::TerminalFmtError)?;
self.term.reset_style()?;
@ -213,38 +213,37 @@ impl State {
command::execute(self, cmd)
}
fn handle_command_key(&mut self, key: char) -> Result<(), Error> {
fn handle_command_key(&mut self, key: Key) -> Result<(), Error> {
match key {
'\n' | '\x0D' => {
Key::Char('\n') | Key::Char('\x0D') => {
self.top_mode = TopMode::Normal;
self.handle_command()?;
}
'\x7F' => {
Key::Char('\x7F') => {
if self.command.is_empty() {
self.top_mode = TopMode::Normal;
} else {
self.command.pop();
}
}
'\x1B' => {
Key::Escape => {
self.top_mode = TopMode::Normal;
}
c if c.is_ascii_graphic() => self.command.push(c),
' ' => self.command.push(' '),
Key::Char(c) if c.is_ascii_graphic() || c == ' ' => self.command.push(c),
_ => (),
}
Ok(())
}
fn handle_mode_key(&mut self, mode: Mode, key: char) -> Result<(), Error> {
fn handle_mode_key(&mut self, mode: Mode, key: Key) -> Result<(), Error> {
let buffer = &mut self.buffer;
self.key.push(key);
self.key_seq.push(key);
match self.config.key(mode, &self.key) {
match self.config.key_seq(mode, &self.key_seq) {
Some(PrefixNode::Leaf(actions)) => {
self.key.clear();
self.key_seq.clear();
for &action in actions {
command::perform(buffer, &self.config, action)?;
@ -252,7 +251,7 @@ impl State {
}
Some(PrefixNode::Prefix(_)) => {}
None => {
self.key.clear();
self.key_seq.clear();
}
}
@ -263,15 +262,15 @@ impl State {
Ok(())
}
fn handle_normal_key(&mut self, key: char) -> Result<(), Error> {
fn handle_normal_key(&mut self, key: Key) -> Result<(), Error> {
match key {
'\x1B' => {
self.key.clear();
Key::Escape => {
self.key_seq.clear();
self.buffer.set_mode(&self.config, SetMode::Normal);
Ok(())
}
':' => {
self.key.clear();
Key::Char(':') => {
self.key_seq.clear();
self.command.clear();
self.status = None;
self.top_mode = TopMode::Command;
@ -281,13 +280,13 @@ impl State {
}
}
fn handle_insert_key(&mut self, key: char) -> Result<(), Error> {
fn handle_insert_key(&mut self, key: Key) -> Result<(), Error> {
match key {
'\x1B' => {
Key::Escape => {
self.buffer.set_mode(&self.config, SetMode::Normal);
Ok(())
}
key if !key.is_ascii() || key == ' ' || key == '\t' || key.is_ascii_graphic() => {
Key::Char(key) if !key.is_ascii() || key == ' ' || key == '\t' || key.is_ascii_graphic() => {
self.buffer.insert(&self.config, key);
Ok(())
}
@ -312,7 +311,7 @@ impl State {
if self.message.is_some() {
self.message = None;
if key != ':' {
if key != Key::Char(':') {
return Ok(());
}
}

View File

@ -1,9 +1,10 @@
use std::io::{Read, Stdin};
use std::{io::{Read, Stdin}, future::{Future, self}};
use crate::error::InputError;
pub trait ReadChar {
fn read_char(&mut self) -> Result<char, InputError>;
async fn read_byte_delay(&mut self);
}
impl ReadChar for Stdin {
@ -23,6 +24,10 @@ impl ReadChar for Stdin {
let s = core::str::from_utf8(&buf[..len + 1]).map_err(InputError::DecodeError)?;
Ok(s.chars().next().unwrap())
}
async fn read_byte_delay(&mut self) {
todo!();
}
}
const fn utf8_len_prefix(l: u8) -> Option<usize> {

View File

@ -1,6 +1,6 @@
use std::{io::{Stdout, Write, Stdin, stdin, stdout, self}, fmt};
use crate::{error::Error, term::input::ReadChar};
use crate::{error::Error, term::input::ReadChar, keymap::Key};
use self::sys::RawMode;
@ -161,8 +161,14 @@ impl Term {
}.map_err(Error::TerminalError)
}
pub fn read_key(&mut self) -> Result<char, Error> {
self.stdin.read_char().map_err(Error::InputError)
pub fn read_key(&mut self) -> Result<Key, Error> {
let ch = self.stdin.read_char().map_err(Error::InputError)?;
if ch == '\x1B' {
return Ok(Key::Escape);
}
Ok(Key::Char(ch))
}
pub fn flush(&mut self) -> Result<(), Error> {

View File

@ -9,7 +9,6 @@ edition = "2021"
clap = { version = "4.3.19", features = ["std", "derive"], default-features = false }
# TODO own impl
humansize = { version = "2.1.3", features = ["impl_style"] }
yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git" }
[lib]
path = "src/lib.rs"

View File

@ -1,11 +1,12 @@
fn main() {
for bg in 40..=49 {
if bg == 48 { continue; }
for fg in 30..=39 {
if fg == 48 { continue; }
print!("\x1B[{}m\x1B[{}m@\x1B[0m", bg, fg);
}
println!();
}
loop {}
// for bg in 40..=49 {
// if bg == 48 { continue; }
// for fg in 30..=39 {
// if fg == 48 { continue; }
// print!("\x1B[{}m\x1B[{}m@\x1B[0m", bg, fg);
// }
// println!();
// }
}

View File

@ -1,4 +1,50 @@
use std::{io::{self, Read}, fs::File};
use std::{
fs::File,
io::{self, Read},
};
#[cfg(unix)]
pub mod unix {
use std::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct FileMode(u32);
impl From<u32> for FileMode {
fn from(value: u32) -> Self {
Self(value)
}
}
impl fmt::Display for FileMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
macro_rules! print_bit {
($res:expr, $val:expr, $self:expr, $bit:expr) => {
if $self.0 & $bit == $bit {
$res = $val;
}
};
}
let mut buf = ['-'; 9];
print_bit!(buf[0], 'r', self, 0o400);
print_bit!(buf[1], 'w', self, 0o200);
print_bit!(buf[2], 'x', self, 0o100);
print_bit!(buf[3], 'r', self, 0o040);
print_bit!(buf[4], 'w', self, 0o020);
print_bit!(buf[5], 'x', self, 0o010);
print_bit!(buf[6], 'r', self, 0o004);
print_bit!(buf[7], 'w', self, 0o002);
print_bit!(buf[8], 'x', self, 0o001);
for ch in buf.iter() {
fmt::Display::fmt(ch, f)?;
}
Ok(())
}
}
}
// TODO replace this
pub trait ToExitCode {
@ -9,14 +55,14 @@ impl<T> ToExitCode for io::Result<T> {
fn to_exit_code(&self) -> i32 {
match self {
Ok(_) => 0,
_ => 1
_ => 1,
}
}
}
pub enum Input {
Stdin(io::Stdin),
File(io::BufReader<File>)
File(io::BufReader<File>),
}
impl Input {
@ -47,7 +93,7 @@ impl Read for Input {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Self::Stdin(value) => value.read(buf),
Self::File(value) => value.read(buf)
Self::File(value) => value.read(buf),
}
}
}

View File

@ -2,18 +2,15 @@
use std::{
env,
io::{stdin, stdout, BufRead, Write},
io::{self, stdin, stdout, BufRead, Write},
os::{
fd::AsRawFd,
yggdrasil::signal::{set_signal_handler, Signal, SignalHandler},
yggdrasil::{
io::{start_terminal_session, DeviceRequest, FdDeviceRequest},
signal::{set_signal_handler, Signal, SignalHandler},
},
process::{ExitCode, Command},
};
use yggdrasil_rt::{
debug_trace,
io::{DeviceRequest, FileMode, OpenOptions, RawFd},
sys,
},
process::{self, Command, ExitCode},
};
fn handler(_signal: Signal) {}
@ -22,18 +19,18 @@ fn login_readline<R: BufRead + AsRawFd>(
reader: &mut R,
buf: &mut String,
_secret: bool,
) -> Result<usize, std::io::Error> {
) -> Result<usize, io::Error> {
reader.read_line(buf)
}
fn login_as(username: &str, _password: &str) -> Result<(), std::io::Error> {
fn login_as(username: &str, _password: &str) -> Result<(), io::Error> {
let mut shell = Command::new("/bin/sh").arg("-l").spawn()?;
println!("Hello {:?}", username);
shell.wait()?;
Ok(())
}
fn login_attempt(erase: bool) -> Result<(), std::io::Error> {
fn login_attempt(erase: bool) -> Result<(), io::Error> {
let mut stdin = stdin().lock();
let mut stdout = stdout();
@ -53,20 +50,6 @@ fn login_attempt(erase: bool) -> Result<(), std::io::Error> {
login_as(username.trim(), "")
}
fn setup_session(terminal: &str) -> Result<(), yggdrasil_rt::Error> {
// This will close the file descriptors associated with the old terminal
unsafe { sys::start_session()? };
unsafe {
// File descriptors 0, 1, 2 are now free, need to reopen them with a new terminal
sys::open(None, terminal, OpenOptions::READ, FileMode::empty())?;
sys::open(None, terminal, OpenOptions::WRITE, FileMode::empty())?;
sys::open(None, terminal, OpenOptions::WRITE, FileMode::empty())?;
}
Ok(())
}
fn main() -> ExitCode {
let args: Vec<_> = env::args().skip(1).collect();
if args.len() != 1 {
@ -76,21 +59,22 @@ fn main() -> ExitCode {
let terminal = args[0].as_str();
// TODO check that `terminal` is a terminal
debug_trace!("Starting a session at {}", terminal);
if let Err(err) = setup_session(terminal) {
debug_trace!("Failed: {:?}", err);
eprintln!("Could not setup session at {}: {:?}", terminal, err);
if let Err(err) = unsafe { start_terminal_session(terminal) } {
debug_trace!("Error: {:?}", err);
eprintln!("Could not setup a session at {}: {:?}", terminal, err);
return ExitCode::FAILURE;
}
let mut attempt_number = 0;
loop {
debug_trace!("Login attempt {}", attempt_number);
// "Attach" the terminal
unsafe {
let mut req = DeviceRequest::SetTerminalGroup(sys::get_pid());
sys::device_request(RawFd::STDIN, &mut req).unwrap();
stdin()
.device_request(&mut DeviceRequest::SetTerminalGroup(process::id()))
.expect("Could not attach the terminal");
}
if let Err(err) = login_attempt(attempt_number % 3 == 0) {

View File

@ -1,14 +1,20 @@
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os))]
use std::{
fmt,
fs::{read_dir, FileType},
fs::{read_dir, FileType, Metadata},
io,
mem::MaybeUninit,
path::Path,
};
#[cfg(target_os = "yggdrasil")]
use std::os::yggdrasil::fs::MetadataExt;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use clap::Parser;
use humansize::{FormatSize, BINARY};
use yggdrasil_rt::io::FileAttr;
#[derive(Parser)]
pub struct Args {
@ -74,7 +80,7 @@ impl<T: DisplaySizeBit + Copy> fmt::Display for DisplaySizeWith<'_, T> {
struct Entry {
name: String,
ty: Option<FileType>,
attrs: Option<FileAttr>,
attrs: Option<Metadata>,
}
impl DisplayBit for Option<FileType> {
@ -93,13 +99,29 @@ impl DisplayBit for Option<FileType> {
}
}
impl DisplayBit for Option<FileAttr> {
#[cfg(target_os = "yggdrasil")]
impl DisplayBit for Option<Metadata> {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Some(attrs) = self else {
return write!(f, "--------- {:<8}", "???");
};
write!(f, "{} {:>8}", attrs.mode, attrs.size.display_size_with(opts))
let mode = attrs.mode_ext();
write!(f, "{} {:>8}", mode, attrs.len().display_size_with(opts))
}
}
#[cfg(unix)]
impl DisplayBit for Option<Metadata> {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use sysutils::unix::FileMode;
let Some(attrs) = self else {
return write!(f, "--------- {:<8}", "???");
};
let mode = FileMode::from(attrs.mode());
write!(f, "{} {:>8}", mode, attrs.len().display_size_with(opts))
}
}
@ -119,15 +141,6 @@ impl DisplayBit for Entry {
}
}
fn fetch_entry<P: AsRef<Path>>(path: P) -> Option<FileAttr> {
let mut attrs = MaybeUninit::uninit();
let attrs = unsafe {
yggdrasil_rt::sys::get_metadata(None, path.as_ref().to_str()?, &mut attrs, false).ok()?;
attrs.assume_init()
};
Some(attrs)
}
impl Entry {
fn invalid() -> Self {
Self {
@ -148,7 +161,7 @@ fn list_directory(path: &Path) -> io::Result<Vec<Entry>> {
let os_filename = entry.file_name();
let ty = entry.file_type().ok();
let attrs = fetch_entry(entry.path());
let attrs = entry.path().metadata().ok();
entries.push(Entry {
name: os_filename.to_string_lossy().to_string(),

View File

@ -1,7 +1,7 @@
use std::process::ExitCode;
#![feature(rustc_private, yggdrasil_os)]
use std::{process::ExitCode, os::yggdrasil::io::{MountOptions, mount_raw}};
use clap::Parser;
use yggdrasil_rt::{io::MountOptions, sys::mount};
#[derive(Parser, Debug)]
struct Args {
@ -14,7 +14,11 @@ struct Args {
fn main() -> ExitCode {
let args = Args::parse();
let source = if args.target.is_some() { Some(args.source.as_str()) } else { None };
let source = if args.target.is_some() {
Some(args.source.as_str())
} else {
None
};
let target = args.target.as_deref().unwrap_or(args.source.as_str());
let filesystem = args.ty.as_deref();
@ -23,10 +27,10 @@ fn main() -> ExitCode {
let options = MountOptions {
source,
filesystem,
target
target,
};
mount(&options)
mount_raw(&options)
};
match result {