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']
|
[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']
|
[patch.'https://git.alnyan.me/yggdrasil/yggdrasil-rt.git']
|
||||||
yggdrasil-rt = { path = "rt" }
|
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}/mount ${root_dir}/sbin/
|
||||||
cp ${build_dir}/login ${root_dir}/sbin/
|
cp ${build_dir}/login ${root_dir}/sbin/
|
||||||
cp ${build_dir}/ls ${root_dir}/bin/
|
cp ${build_dir}/ls ${root_dir}/bin/
|
||||||
|
cp ${build_dir}/hexd ${root_dir}/bin/
|
||||||
|
|
||||||
cp -r ${workspace_dir}/etc ${root_dir}/
|
cp -r ${workspace_dir}/etc ${root_dir}/
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![feature(yggdrasil_os)]
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env,
|
env,
|
||||||
@ -22,7 +23,7 @@ pub struct Args {
|
|||||||
#[arg(short)]
|
#[arg(short)]
|
||||||
login: bool,
|
login: bool,
|
||||||
script: Option<String>,
|
script: Option<String>,
|
||||||
args: Vec<String>
|
args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Outcome {
|
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
|
// 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 {
|
let Some((cmd, args)) = cmd.split_first() else {
|
||||||
return Ok(Outcome::ok());
|
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) {
|
if let Some(builtin) = builtins::get_builtin(cmd) {
|
||||||
builtin(args, env)
|
builtin(args, env)
|
||||||
} else {
|
} else {
|
||||||
let status = Command::new(&cmd).args(args).envs(env.iter()).status()?;
|
let status = exec_binary(interactive, cmd, args, env)?;
|
||||||
|
|
||||||
Ok(Outcome::from(status))
|
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 line = line.trim();
|
||||||
let cmd = parser::parse_line(vars, line).unwrap();
|
let cmd = parser::parse_line(vars, line).unwrap();
|
||||||
|
|
||||||
match exec(&cmd, vars) {
|
match exec(input.is_interactive(), &cmd, vars) {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
if input.is_interactive() {
|
if input.is_interactive() {
|
||||||
match status {
|
match status {
|
||||||
|
@ -14,6 +14,7 @@ yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git" }
|
|||||||
[lib]
|
[lib]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
# /sbin
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mount"
|
name = "mount"
|
||||||
path = "src/mount.rs"
|
path = "src/mount.rs"
|
||||||
@ -22,6 +23,11 @@ path = "src/mount.rs"
|
|||||||
name = "login"
|
name = "login"
|
||||||
path = "src/login.rs"
|
path = "src/login.rs"
|
||||||
|
|
||||||
|
# /bin
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "ls"
|
name = "ls"
|
||||||
path = "src/ls.rs"
|
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