shell: set tty control for spawned processes
This commit is contained in:
parent
7e42999539
commit
5447306fa6
@ -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" }
|
||||
|
1
build.sh
1
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}/
|
||||
|
||||
|
@ -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<String>,
|
||||
args: Vec<String>
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
||||
pub enum Outcome {
|
||||
@ -93,8 +94,28 @@ impl From<ExitStatus> for Outcome {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "yggdrasil")]
|
||||
fn exec_binary(
|
||||
interactive: bool,
|
||||
binary: &str,
|
||||
args: &[String],
|
||||
env: &HashMap<String, String>,
|
||||
) -> Result<ExitStatus, io::Error> {
|
||||
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<String, String>) -> Result<Outcome, Error> {
|
||||
pub fn exec(interactive: bool, cmd: &[String], env: &mut HashMap<String, String>) -> Result<Outcome, Error> {
|
||||
let Some((cmd, args)) = cmd.split_first() else {
|
||||
return Ok(Outcome::ok());
|
||||
};
|
||||
@ -102,8 +123,7 @@ pub fn exec(cmd: &[String], env: &mut HashMap<String, String>) -> Result<Outcome
|
||||
if let Some(builtin) = builtins::get_builtin(cmd) {
|
||||
builtin(args, env)
|
||||
} else {
|
||||
let status = Command::new(&cmd).args(args).envs(env.iter()).status()?;
|
||||
|
||||
let status = exec_binary(interactive, cmd, args, env)?;
|
||||
Ok(Outcome::from(status))
|
||||
}
|
||||
}
|
||||
@ -123,7 +143,7 @@ fn run(mut input: Input, vars: &mut HashMap<String, String>) -> io::Result<ExitC
|
||||
let line = line.trim();
|
||||
let cmd = parser::parse_line(vars, line).unwrap();
|
||||
|
||||
match exec(&cmd, vars) {
|
||||
match exec(input.is_interactive(), &cmd, vars) {
|
||||
Ok(status) => {
|
||||
if input.is_interactive() {
|
||||
match status {
|
||||
|
@ -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"
|
||||
|
73
sysutils/src/hexd.rs
Normal file
73
sysutils/src/hexd.rs
Normal file
@ -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::<Vec<_>>();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -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<T> ToExitCode for io::Result<T> {
|
||||
fn to_exit_code(&self) -> i32 {
|
||||
match self {
|
||||
Ok(_) => 0,
|
||||
_ => 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Input {
|
||||
Stdin(io::Stdin),
|
||||
File(io::BufReader<File>)
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn open_str(arg: &str) -> io::Result<Self> {
|
||||
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<io::Stdin> for Input {
|
||||
fn from(value: io::Stdin) -> Self {
|
||||
Self::Stdin(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> 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<usize> {
|
||||
match self {
|
||||
Self::Stdin(value) => value.read(buf),
|
||||
Self::File(value) => value.read(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user