diff --git a/lib/runtime/src/io/terminal.rs b/lib/runtime/src/io/terminal.rs index 88f856a2..94babfd0 100644 --- a/lib/runtime/src/io/terminal.rs +++ b/lib/runtime/src/io/terminal.rs @@ -2,7 +2,7 @@ pub use abi::io::{ TerminalInputOptions, TerminalLineOptions, TerminalOptions, TerminalOutputOptions, TerminalSize, }; -use abi::{error::Error, io::RawFd}; +use abi::{error::Error, io::RawFd, process::ProcessGroupId}; use super::device::{self, device_request}; @@ -33,6 +33,11 @@ pub fn set_terminal_size(fd: RawFd, size: &TerminalSize) -> Result<(), Error> { device_request::(fd, &mut buffer, size) } +pub fn set_terminal_group(fd: RawFd, group: ProcessGroupId) -> Result<(), Error> { + let mut buffer = [0; 8]; + device_request::(fd, &mut buffer, &group) +} + pub fn is_terminal(fd: RawFd) -> bool { let mut buffer = [0; 0]; device_request::(fd, &mut buffer, &()).is_ok() diff --git a/userspace/Cargo.lock b/userspace/Cargo.lock index c9c0c554..4191557a 100644 --- a/userspace/Cargo.lock +++ b/userspace/Cargo.lock @@ -1396,6 +1396,7 @@ dependencies = [ "clap", "cross", "nom", + "runtime", "thiserror", ] diff --git a/userspace/shell/Cargo.toml b/userspace/shell/Cargo.toml index 3eb7c16f..e6741383 100644 --- a/userspace/shell/Cargo.toml +++ b/userspace/shell/Cargo.toml @@ -11,5 +11,11 @@ thiserror.workspace = true nom = "7.1.3" +[target.'cfg(target_os = "yggdrasil")'.dependencies] +runtime.workspace = true + +[dev-dependencies] +runtime.workspace = true + [lints] workspace = true diff --git a/userspace/shell/src/exec.rs b/userspace/shell/src/exec.rs index 658421fb..0430e11f 100644 --- a/userspace/shell/src/exec.rs +++ b/userspace/shell/src/exec.rs @@ -1,14 +1,22 @@ use std::{ fmt, fs::File, - io::{self, BufRead, BufReader, Stderr, Stdout, Write}, + io::{self, stdin, BufRead, BufReader, Stderr, Stdout, Write}, marker::PhantomData, - os::fd::{FromRawFd, IntoRawFd}, + os::{ + fd::{FromRawFd, IntoRawFd}, + yggdrasil::{ + io::terminal::set_terminal_group, + process::{create_process_group, CommandExt}, + }, + }, pipe::{PipeReader, PipeWriter}, process::{self, Child, ExitCode, ExitStatus, Stdio}, thread::{self, JoinHandle}, }; +use runtime::rt::process::ProcessGroupId; + use crate::{builtin, env::Command, Error}; pub enum Outcome { @@ -150,7 +158,7 @@ impl Outcome { } // TODO move pipelines into process groups -fn spawn_command(execution: Execution) -> Result { +fn spawn_command(execution: Execution, pgid: ProcessGroupId) -> Result { let mut command = process::Command::new(execution.program); command @@ -159,6 +167,9 @@ fn spawn_command(execution: Execution) -> Result { .stdout(execution.stdout) .stderr(execution.stderr); + #[cfg(any(target_os = "yggdrasil", rust_analyzer))] + command.process_group(pgid); + for (key, value) in execution.envs { command.env(key, value); } @@ -168,10 +179,10 @@ fn spawn_command(execution: Execution) -> Result { Ok(child) } -pub fn exec_pipeline>( - pipeline: I, -) -> Result, Error> { +pub fn exec_pipeline>(pipeline: I) -> Result, Error> { let mut handles = vec![]; + #[cfg(any(target_os = "yggdrasil", rust_analyzer))] + let pgid = create_process_group(); for element in pipeline.into_iter() { let handle = if let Some(builtin) = builtin::get(&element.program) { let io = builtin::Io { @@ -184,13 +195,17 @@ pub fn exec_pipeline>( builtin(io, element.arguments, element.envs.into()) })) } else { - let child = spawn_command(element)?; + let child = spawn_command(element, pgid)?; Handle::Process(child) }; handles.push(handle); } + #[cfg(any(target_os = "yggdrasil", rust_analyzer))] + unsafe { + set_terminal_group(&stdin(), pgid)?; + } Ok(handles) } diff --git a/userspace/shell/src/main.rs b/userspace/shell/src/main.rs index 8a36def4..db12a133 100644 --- a/userspace/shell/src/main.rs +++ b/userspace/shell/src/main.rs @@ -5,7 +5,7 @@ trait_alias, exitcode_exit_method )] -#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os))] +#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os, rustc_private))] #![allow(clippy::new_without_default, clippy::should_implement_trait)] use std::{