|
|
|
|
@ -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<Option<Box<dyn Write>>> = 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} {
|
|
|
|
|
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<u8> = 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<u8> = 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<File>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<OsString> = Vec::new();
|
|
|
|
|
let mut parsing_open_file = false;
|
|
|
|
|
let mut file: Option<File> = 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<dyn Write>));
|
|
|
|
|
});
|
|
|
|
|
if !is_open_file {
|
|
|
|
|
IS_TTY = libc::isatty(libc::STDOUT_FILENO) != 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let mut ptys = Ptys::default();
|
|
|
|
|
open_ptys(&mut ptys);
|
|
|
|
|
|