From 5447306fa69b335a14a82bfbaf06987a7774f731 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Tue, 14 Nov 2023 17:31:30 +0200 Subject: [PATCH] shell: set tty control for spawned processes --- Cargo.toml | 2 +- abi | 1 - build.sh | 1 + shell/src/main.rs | 30 ++++++++++++++--- sysutils/Cargo.toml | 6 ++++ sysutils/src/display.rs | 0 sysutils/src/hexd.rs | 73 +++++++++++++++++++++++++++++++++++++++++ sysutils/src/lib.rs | 54 +++++++++++++++++++++++++++++- 8 files changed, 159 insertions(+), 8 deletions(-) delete mode 120000 abi delete mode 100644 sysutils/src/display.rs create mode 100644 sysutils/src/hexd.rs diff --git a/Cargo.toml b/Cargo.toml index 2b8de832..572ca10e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ ] [patch.'https://git.alnyan.me/yggdrasil/yggdrasil-abi.git'] -yggdrasil-abi = { path = "abi" } +yggdrasil-abi = { path = "../abi" } [patch.'https://git.alnyan.me/yggdrasil/yggdrasil-rt.git'] yggdrasil-rt = { path = "rt" } diff --git a/abi b/abi deleted file mode 120000 index 56d6bf5f..00000000 --- a/abi +++ /dev/null @@ -1 +0,0 @@ -../abi \ No newline at end of file diff --git a/build.sh b/build.sh index f9305aa6..8c953d24 100755 --- a/build.sh +++ b/build.sh @@ -53,6 +53,7 @@ pack_initrd() { cp ${build_dir}/mount ${root_dir}/sbin/ cp ${build_dir}/login ${root_dir}/sbin/ cp ${build_dir}/ls ${root_dir}/bin/ + cp ${build_dir}/hexd ${root_dir}/bin/ cp -r ${workspace_dir}/etc ${root_dir}/ diff --git a/shell/src/main.rs b/shell/src/main.rs index 30789472..9f23fd90 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -1,3 +1,4 @@ +#![feature(yggdrasil_os)] use std::{ collections::HashMap, env, @@ -22,7 +23,7 @@ pub struct Args { #[arg(short)] login: bool, script: Option, - args: Vec + args: Vec, } pub enum Outcome { @@ -93,8 +94,28 @@ impl From for Outcome { } } +#[cfg(target_os = "yggdrasil")] +fn exec_binary( + interactive: bool, + binary: &str, + args: &[String], + env: &HashMap, +) -> Result { + use std::os::yggdrasil::process::CommandExt; + let mut command = Command::new(binary); + let mut command = command.args(args).envs(env.iter()); + + if interactive { + unsafe { + command = command.process_group(0).gain_terminal(0); + } + } + + command.status() +} + // TODO this has one flaw: it needs to somehow fork() (?) to set the created process' process group -pub fn exec(cmd: &[String], env: &mut HashMap) -> Result { +pub fn exec(interactive: bool, cmd: &[String], env: &mut HashMap) -> Result { let Some((cmd, args)) = cmd.split_first() else { return Ok(Outcome::ok()); }; @@ -102,8 +123,7 @@ pub fn exec(cmd: &[String], env: &mut HashMap) -> Result) -> io::Result { if input.is_interactive() { match status { diff --git a/sysutils/Cargo.toml b/sysutils/Cargo.toml index 829cdb59..26c25139 100644 --- a/sysutils/Cargo.toml +++ b/sysutils/Cargo.toml @@ -14,6 +14,7 @@ yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git" } [lib] path = "src/lib.rs" +# /sbin [[bin]] name = "mount" path = "src/mount.rs" @@ -22,6 +23,11 @@ path = "src/mount.rs" name = "login" path = "src/login.rs" +# /bin [[bin]] name = "ls" path = "src/ls.rs" + +[[bin]] +name = "hexd" +path = "src/hexd.rs" diff --git a/sysutils/src/display.rs b/sysutils/src/display.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/sysutils/src/hexd.rs b/sysutils/src/hexd.rs new file mode 100644 index 00000000..d97d0b90 --- /dev/null +++ b/sysutils/src/hexd.rs @@ -0,0 +1,73 @@ +use std::{env, io::{self, Read}, process::ExitCode}; + +use sysutils::{ToExitCode, Input}; + +const WINDOW_SIZE: usize = 16; + +fn do_line(offset: usize, line: &[u8]) { + print!("{:08x} |", offset); + + for i in 0..WINDOW_SIZE { + if i % 2 == 0 { + print!(" "); + } + if i < line.len() { + print!("{:02X}", line[i]); + } else { + print!(" "); + } + } + + print!(" | "); + + for &ch in line { + let ch = if ch.is_ascii_control() { b'.' } else { ch }; + print!("{}", ch as char); + } + + println!(); +} + +fn do_file(path: &str) -> io::Result<()> { + let mut input = Input::open_str(path)?; + let mut buf = [0; WINDOW_SIZE]; + let mut offset = 0; + + loop { + let len = input.read(&mut buf)?; + + if len == 0 { + break; + } + + do_line(offset, &buf[..len]); + offset += len; + } + + Ok(()) +} + +pub fn main() -> ExitCode { + let args = env::args().collect::>(); + + let result = if args.len() < 2 { + do_file("-").to_exit_code() + } else if args.len() == 2 { + do_file(&args[1]).to_exit_code() + } else { + let mut result = 0; + for arg in args[1..].iter() { + println!("{}:", arg); + if do_file(arg).to_exit_code() != 0 { + result = 1; + } + } + result + }; + + if result == 0 { + ExitCode::SUCCESS + } else { + ExitCode::FAILURE + } +} diff --git a/sysutils/src/lib.rs b/sysutils/src/lib.rs index 8754563b..c7585dbc 100644 --- a/sysutils/src/lib.rs +++ b/sysutils/src/lib.rs @@ -1 +1,53 @@ -pub mod display; +use std::{io::{self, Read}, fs::File}; + +// TODO replace this +pub trait ToExitCode { + fn to_exit_code(&self) -> i32; +} + +impl ToExitCode for io::Result { + fn to_exit_code(&self) -> i32 { + match self { + Ok(_) => 0, + _ => 1 + } + } +} + +pub enum Input { + Stdin(io::Stdin), + File(io::BufReader) +} + +impl Input { + pub fn open_str(arg: &str) -> io::Result { + if arg == "-" { + Ok(Self::Stdin(io::stdin())) + } else { + let file = File::open(arg)?; + let reader = io::BufReader::new(file); + Ok(Self::File(reader)) + } + } +} + +impl From for Input { + fn from(value: io::Stdin) -> Self { + Self::Stdin(value) + } +} + +impl From for Input { + fn from(value: File) -> Self { + Self::File(io::BufReader::new(value)) + } +} + +impl Read for Input { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self { + Self::Stdin(value) => value.read(buf), + Self::File(value) => value.read(buf) + } + } +}