diff --git a/Cargo.lock b/Cargo.lock index ba035a72c4d..f68054b80df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3030,7 +3030,7 @@ version = "0.0.14" dependencies = [ "atty", "clap 3.2.17", - "libc", + "nix", "uucore", ] diff --git a/src/uu/tty/Cargo.toml b/src/uu/tty/Cargo.toml index 7f5a7b05992..65bfbf405a1 100644 --- a/src/uu/tty/Cargo.toml +++ b/src/uu/tty/Cargo.toml @@ -16,7 +16,7 @@ path = "src/tty.rs" [dependencies] clap = { version = "3.2", features = ["wrap_help", "cargo"] } -libc = "0.2.126" +nix = "0.25" atty = "0.2" uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["fs"] } diff --git a/src/uu/tty/src/tty.rs b/src/uu/tty/src/tty.rs index a8806703b4e..3048b30499e 100644 --- a/src/uu/tty/src/tty.rs +++ b/src/uu/tty/src/tty.rs @@ -10,9 +10,9 @@ // spell-checker:ignore (ToDO) ttyname filedesc use clap::{crate_version, Arg, Command}; -use std::ffi::CStr; use std::io::Write; -use uucore::error::UResult; +use std::os::unix::io::AsRawFd; +use uucore::error::{UResult, set_exit_code}; use uucore::format_usage; static ABOUT: &str = "Print the file name of the terminal connected to standard input."; @@ -24,42 +24,39 @@ mod options { #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let args = args.collect_lossy(); - let matches = uu_app().get_matches_from(args); let silent = matches.contains_id(options::SILENT); - // Call libc function ttyname - let tty = unsafe { - let ptr = libc::ttyname(libc::STDIN_FILENO); - if !ptr.is_null() { - String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string() + // If silent, we don't need the name, only whether or not stdin is a tty. + if silent { + return if atty::is(atty::Stream::Stdin) { + Ok(()) } else { - "".to_owned() + Err(1.into()) } }; let mut stdout = std::io::stdout(); - if !silent { - let write_result = if !tty.chars().all(|c| c.is_whitespace()) { - writeln!(stdout, "{}", tty) - } else { - writeln!(stdout, "not a tty") - }; - if write_result.is_err() || stdout.flush().is_err() { - // Don't return to prevent a panic later when another flush is attempted - // because the `uucore_procs::main` macro inserts a flush after execution for every utility. - std::process::exit(3); + // Get the ttyname via nix + let name = nix::unistd::ttyname(std::io::stdin().as_raw_fd()); + + let write_result = match name { + Ok(name) => writeln!(stdout, "{}", name.display()), + Err(_) => { + set_exit_code(1); + writeln!(stdout, "{}", "not a tty") } - } + }; + + if write_result.is_err() || stdout.flush().is_err() { + // Don't return to prevent a panic later when another flush is attempted + // because the `uucore_procs::main` macro inserts a flush after execution for every utility. + std::process::exit(3); + }; - if atty::is(atty::Stream::Stdin) { - Ok(()) - } else { - Err(libc::EXIT_FAILURE.into()) - } + Ok(()) } pub fn uu_app<'a>() -> Command<'a> {