Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions frontends/rioterm/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ impl<T: EventListener + Clone + std::marker::Send + 'static> ContextManager<T> {
tracing::info!("rio -> teletypewriter: create_pty_with_fork");
pty = match create_pty_with_fork(
&Cow::Borrowed(&config.shell.program),
config.shell.args.as_ref(),
cols,
rows,
) {
Expand Down Expand Up @@ -414,6 +415,16 @@ impl<T: EventListener + Clone + std::marker::Send + 'static> ContextManager<T> {
cwd: false,
..ContextManagerConfig::default()
};
Self::start_with_capacity_and_config(capacity, config, event_proxy, window_id)
}

#[cfg(test)]
pub fn start_with_capacity_and_config(
capacity: usize,
config: ContextManagerConfig,
event_proxy: T,
window_id: WindowId,
) -> Result<Self, Box<dyn Error>> {
let initial_context = ContextManager::create_context(
(&Cursor::default(), false),
event_proxy.clone(),
Expand Down Expand Up @@ -1767,4 +1778,65 @@ pub mod test {
assert_eq!(context_manager.current_index, 4);
assert_eq!(context_manager.current().rich_text_id, 1);
}

/// Common functionality between [`test_forking_context_creation_propagate_correct_arguments`]
/// and [`test_spawning_context_creation_propagate_correct_arguments`]
#[cfg(not(target_os = "windows"))]
fn test_context_creation_propagate_correct_arguments(use_fork: bool) {
let window_id = WindowId::from(0);
let test_file_path: &str = if use_fork {
"/tmp/rio_test_forking_context_creation_propagate_correct_arguments"
} else {
"/tmp/rio_test_spawning_context_creation_propagate_correct_arguments"
};

let config = ContextManagerConfig {
use_fork,
working_dir: None,
shell: Shell {
program: "touch".to_string(),
args: vec![test_file_path.to_string()],
},
spawn_performer: true,
is_native: false,
should_update_title_extra: false,
cwd: false,
..ContextManagerConfig::default()
};

// Make sure the file doesn't exist already
let _ = std::fs::remove_file(test_file_path);

let mut context_manager = ContextManager::start_with_capacity_and_config(
5,
config,
VoidListener {},
window_id,
)
.unwrap();
context_manager.add_context(true, 0);
// Wait for the command to finish running
context_manager
.current_mut()
._io_thread
.take()
.map(|thread| thread.join());

assert!(matches!(std::fs::exists(test_file_path), Ok(true)));

// Clean up
let _ = std::fs::remove_file(test_file_path);
}

#[test]
#[cfg(not(target_os = "windows"))]
fn test_forking_context_creation_propagate_correct_arguments() {
test_context_creation_propagate_correct_arguments(true);
}

#[test]
#[cfg(not(target_os = "windows"))]
fn test_spawning_context_creation_propagate_correct_arguments() {
test_context_creation_propagate_correct_arguments(false);
}
}
2 changes: 1 addition & 1 deletion teletypewriter/examples/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() -> std::io::Result<()> {
use teletypewriter::{create_pty_with_fork, ProcessReadWrite, Pty};

let shell = Cow::Borrowed("bash");
let mut process: Pty = create_pty_with_fork(&shell, 80, 25)?;
let mut process: Pty = create_pty_with_fork(&shell, &[], 80, 25)?;

process.writer().write_all(b"1").unwrap();
process.writer().write_all(b"2").unwrap();
Expand Down
39 changes: 18 additions & 21 deletions teletypewriter/src/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,21 @@ extern "C" {
fn ptsname(fd: *mut libc::c_int) -> *mut libc::c_char;
}

#[cfg(target_os = "macos")]
fn default_shell_command(shell: &str) {
fn default_shell_command(shell: &str, args: &[String]) {
let command_shell_string = CString::new(shell).unwrap();
let command_pointer = command_shell_string.as_ptr();
let args = CString::new("--login").unwrap();
let args_pointer = args.as_ptr();
unsafe {
libc::execvp(command_pointer, vec![args_pointer].as_ptr());
}
}

#[cfg(not(target_os = "macos"))]
fn default_shell_command(shell: &str) {
let command_shell_string = CString::new(shell).unwrap();
let command_pointer = command_shell_string.as_ptr();
// let home = std::env::var("HOME").unwrap();
// let args = CString::new(home).unwrap();
// let args_pointer = args.as_ptr() as *const i8;
let args = args
.iter()
.map(|arg| CString::new(arg.as_str()).unwrap())
.collect::<Vec<_>>();

let args_pointers = std::iter::once(command_pointer)
.chain(args.iter().map(|arg| arg.as_ptr()))
.chain(std::iter::once(ptr::null()))
.collect::<Vec<_>>();
unsafe {
libc::execvp(
command_pointer,
vec![command_pointer, std::ptr::null()].as_ptr(),
);
libc::execvp(command_pointer, args_pointers.as_ptr());
}
}

Expand Down Expand Up @@ -621,7 +613,12 @@ pub fn create_pty_with_spawn(
///
/// It returns two [`Pty`] along with respective process name [`String`] and process id (`libc::pid_`)
///
pub fn create_pty_with_fork(shell: &str, columns: u16, rows: u16) -> Result<Pty, Error> {
pub fn create_pty_with_fork(
shell: &str,
args: &[String],
columns: u16,
rows: u16,
) -> Result<Pty, Error> {
let mut main = 0;
let winsize = Winsize {
ws_row: rows as libc::c_ushort,
Expand Down Expand Up @@ -657,7 +654,7 @@ pub fn create_pty_with_fork(shell: &str, columns: u16, rows: u16) -> Result<Pty,
)
} {
0 => {
default_shell_command(shell_program);
default_shell_command(shell_program, args);
Err(Error::other(format!(
"forkpty has reach unreachable with {shell_program}"
)))
Expand Down
Loading