Skip to content

Commit

Permalink
WIP: temporarily commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pollenjp committed Oct 27, 2024
1 parent a61c471 commit 5269ba3
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 64 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.uv
/pycmd
/target

##################
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ repository = "https://github.com/pollenjp/tee-rs"
license = "MIT"

[dependencies]
anyhow = "1.0.91"
libc = "0.2.161"

# The profile that 'cargo dist' will build with
Expand Down
46 changes: 46 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
pub mod unix;

use ::anyhow::Result;
use ::std::env;
use ::std::fs::File;
use ::std::io::{self, Write};
use ::std::process;

fn open_output(path: &str) -> Result<Box<dyn Write>> {
if path == "-" {
Ok(Box::new(io::stdout()))
} else {
Ok(Box::new(File::create(path)?))
}
}

fn tee(outputs: &mut [Box<dyn Write>]) -> Result<()> {
#[cfg(any(target_os = "linux", target_os = "macos"))]
{
return unix::tee(outputs);
}

#[cfg(any(target_os = "windows"))]
{
bail!("unsupported platform");
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
bail!("unsupported platform");
}

pub fn run() -> Result<()> {
let args: Vec<String> = env::args().collect();
let mut outputs: Vec<Box<dyn Write>> = vec![Box::new(io::stdout())];
for path in &args[1..] {
match open_output(path) {
Ok(output) => outputs.push(output),
Err(e) => {
eprintln!("Error opening {}: {}", path, e);
process::exit(1);
}
}
}

tee(&mut outputs)
}
65 changes: 1 addition & 64 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,7 @@
use ::std::env;
use ::std::fs::File;
use ::std::io::{self, Read, Write};
use ::std::os::unix::io::AsRawFd;
use ::std::process;

fn open_output(path: &str) -> io::Result<Box<dyn Write>> {
if path == "-" {
Ok(Box::new(io::stdout()))
} else {
Ok(Box::new(File::create(path)?))
}
}

fn tee(outputs: &mut [Box<dyn Write>]) -> io::Result<()> {
let stdin_fd = io::stdin().as_raw_fd();
let mut pollfd = libc::pollfd {
fd: stdin_fd,
events: libc::POLLIN,
revents: 0,
};

let mut buffer = Vec::new();
loop {
// iopoll で入力を待つ
unsafe {
libc::poll(&mut pollfd, 1, -1);
}

if pollfd.revents & libc::POLLIN != 0 {
// 入力がある場合
let mut buf = [0; 4096];
let bytes_read = io::stdin().read(&mut buf)?;
if bytes_read == 0 {
break; // EOF
}
buffer.extend_from_slice(&buf[..bytes_read]);

// 出力
let s = String::from_utf8_lossy(&buffer);
for output in outputs.iter_mut() {
output.write_all(s.as_bytes())?;
output.flush()?;
}
buffer.clear();
} else if pollfd.revents & libc::POLLHUP != 0 {
break; // 入力ストリームが閉じられた
}
}

Ok(())
}

fn main() {
let args: Vec<String> = env::args().collect();
let mut outputs: Vec<Box<dyn Write>> = vec![Box::new(io::stdout())];
for path in &args[1..] {
match open_output(path) {
Ok(output) => outputs.push(output),
Err(e) => {
eprintln!("Error opening {}: {}", path, e);
process::exit(1);
}
}
}

if let Err(e) = tee(&mut outputs) {
if let Err(e) = tee_rs::run() {
eprintln!("Error: {}", e);
process::exit(1);
}
Expand Down
44 changes: 44 additions & 0 deletions src/unix/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use ::anyhow::Result;
use ::std::io::{self, Read, Write};
#[cfg(any(target_os = "linux", target_os = "macos"))]
use ::std::os::unix::io::AsRawFd;

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn tee(outputs: &mut [Box<dyn Write>]) -> Result<()> {
let stdin_fd = io::stdin().as_raw_fd();
let mut pollfd = ::libc::pollfd {
fd: stdin_fd,
events: ::libc::POLLIN,
revents: 0,
};

let mut buffer = Vec::new();
loop {
// iopoll で入力を待つ
unsafe {
::libc::poll(&mut pollfd, 1, -1);
}

if pollfd.revents & ::libc::POLLIN != 0 {
// 入力がある場合
let mut buf = [0; 4096];
let bytes_read = io::stdin().read(&mut buf)?;
if bytes_read == 0 {
break; // EOF
}
buffer.extend_from_slice(&buf[..bytes_read]);

// 出力
let s = String::from_utf8_lossy(&buffer);
for output in outputs.iter_mut() {
output.write_all(s.as_bytes())?;
output.flush()?;
}
buffer.clear();
} else if pollfd.revents & ::libc::POLLHUP != 0 {
break; // 入力ストリームが閉じられた
}
}

Ok(())
}

0 comments on commit 5269ba3

Please sign in to comment.