From 3f8dad6b9a390ac24a9b5ff8df4a1be8aeb7e9d4 Mon Sep 17 00:00:00 2001 From: itycodes Date: Thu, 23 Oct 2025 19:09:51 +0200 Subject: [PATCH] Add open-file option Todo: This is absolutely atrocious code. Fix it. --- src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index bd94652..bbc347e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![allow(static_mut_refs)] + use chrono::Local; use libc::kill; use nix::poll::{PollFd, PollFlags, PollTimeout, poll}; @@ -13,6 +15,7 @@ use std::ptr; static mut USE_KERNEL_ORDERING: bool = false; static mut PLAIN_MODE: bool = false; +static mut OUT_FILE: Mutex>> = Mutex::new(Option::None); #[derive(Debug, Default)] struct Ptys { @@ -43,7 +46,15 @@ fn handle_data(mut stream: StdioStream) -> Result<(), bool> { Ok(n) => { let bufc = &buf[..n]; if unsafe {PLAIN_MODE} { - std::io::stdout().write_all(bufc).unwrap(); + if unsafe{OUT_FILE.get_mut().unwrap().is_none()} { + std::io::stdout().write_all(bufc).unwrap(); + } else { + unsafe { + OUT_FILE.lock().unwrap().as_mut().map(|f| { + f.write_all(bufc).unwrap(); + }); + }; + } } else { for c in bufc { stream.buffer.push(*c); @@ -63,8 +74,22 @@ fn handle_data(mut stream: StdioStream) -> Result<(), bool> { } }; let now = Local::now().format(&format).to_string(); - std::io::stdout().write_all(now.as_bytes()).unwrap(); - std::io::stdout().write_all(&stream.buffer).unwrap(); + if unsafe{OUT_FILE.lock().unwrap().is_none()} { + let mut data: Vec = Vec::new(); + data.extend(now.as_bytes()); + data.extend_from_slice(&stream.buffer); + std::io::stdout().write_all(&data).unwrap(); + } else { + unsafe { + OUT_FILE.lock().unwrap().as_mut().map(|f| { + let mut data: Vec = Vec::new(); + data.extend(now.as_bytes()); + data.extend_from_slice(&stream.buffer); + //std::io::stdout().write_all(data.as_slice()).unwrap(); + f.write_all(&data).unwrap(); + }); + }; + } stream.buffer.clear(); } } @@ -130,6 +155,7 @@ fn handle_poll( } } +#[allow(unreachable_code)] fn spawn_child(ptys: &Ptys, user_cmd: String) { let cmd = CString::new("/bin/bash").unwrap(); let bcmd = user_cmd; @@ -285,12 +311,14 @@ fn main_loop(child: Pid, ptys: &Ptys) { } use std::ffi::OsString; +use std::sync::Mutex; #[derive(Debug)] struct Args { kernel_order: bool, plain: bool, command: String, + file: Option, } fn parse_args() -> Args { @@ -300,15 +328,22 @@ fn parse_args() -> Args { let mut kernel_order = false; let mut plain = false; let mut command_parts: Vec = Vec::new(); + let mut parsing_open_file = false; + let mut file: Option = Option::None; while let Some(arg) = args.next() { - if arg == "--kernel-order" { + if parsing_open_file { + file = Option::from(File::options().write(true).open(&arg).expect(format!("Failed to open {}", &arg.to_str().unwrap()).as_str())); + parsing_open_file = false; + } else if arg == "--kernel-order" { kernel_order = true; } else if arg == "--plain" { plain = true; } else if arg == "-c" || arg == "--command" { command_parts.extend(args); break; + } else if arg == "--open-file" { + parsing_open_file = true; } else { command_parts.push(arg); command_parts.extend(args); @@ -316,6 +351,11 @@ fn parse_args() -> Args { } } + if !kernel_order && file.is_some() { + eprintln!("--open-file has to be used with --kernel-order"); + std::process::exit(-1); + } + let command = command_parts .into_iter() .map(|s| s.to_string_lossy().into_owned()) @@ -326,6 +366,7 @@ fn parse_args() -> Args { kernel_order, command, plain, + file, }; parsed @@ -337,9 +378,16 @@ fn main() { let cmd = args.command; unsafe { - IS_TTY = libc::isatty(libc::STDOUT_FILENO) != 0; USE_KERNEL_ORDERING = args.kernel_order; PLAIN_MODE = args.plain; + let is_open_file = args.file.is_some(); + args.file.map(|f| { + IS_TTY = libc::isatty((&f).as_raw_fd()) != 0; + OUT_FILE = Mutex::new(Option::from(Box::new(f) as Box)); + }); + if !is_open_file { + IS_TTY = libc::isatty(libc::STDOUT_FILENO) != 0; + } }; let mut ptys = Ptys::default(); open_ptys(&mut ptys);