diff --git a/Cargo.lock b/Cargo.lock index 3904277da..700a5bb05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2984,6 +2984,7 @@ dependencies = [ name = "uu_tail" version = "0.0.16" dependencies = [ + "atty", "clap", "libc", "memchr", diff --git a/src/uu/tail/Cargo.toml b/src/uu/tail/Cargo.toml index 4c2552d0c..3f7b00436 100644 --- a/src/uu/tail/Cargo.toml +++ b/src/uu/tail/Cargo.toml @@ -22,6 +22,7 @@ memchr = "2.5.0" notify = { version = "=5.0.0", features=["macos_kqueue"]} uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] } same-file = "1.0.6" +atty = "0.2" [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.42.0", default-features = false, features = ["Win32_System_Threading", "Win32_Foundation"] } diff --git a/src/uu/tail/src/args.rs b/src/uu/tail/src/args.rs index 27e69b994..7bae64095 100644 --- a/src/uu/tail/src/args.rs +++ b/src/uu/tail/src/args.rs @@ -7,8 +7,10 @@ use crate::paths::Input; use crate::{parse, platform, Quotable}; +use atty::Stream; use clap::crate_version; use clap::{parser::ValueSource, Arg, ArgAction, ArgMatches, Command}; +use same_file::Handle; use std::collections::VecDeque; use std::ffi::OsString; use std::time::Duration; @@ -120,11 +122,6 @@ pub enum VerificationResult { NoOutput, } -pub enum CheckResult { - Ok, - NoPidSupport, -} - #[derive(Debug, Default)] pub struct Settings { pub follow: Option, @@ -202,6 +199,7 @@ impl Settings { format!("invalid PID: {}", pid_str.quote()), )); } + settings.pid = pid; } Err(e) => { @@ -243,7 +241,11 @@ impl Settings { self.inputs.iter().any(|input| input.is_stdin()) } - pub fn check_warnings(&self) -> CheckResult { + pub fn num_inputs(&self) -> usize { + self.inputs.len() + } + + pub fn check_warnings(&self) { if self.retry { if self.follow.is_none() { show_warning!("--retry ignored; --retry is useful only when following"); @@ -257,11 +259,24 @@ impl Settings { show_warning!("PID ignored; --pid=PID is useful only when following"); } else if !platform::supports_pid_checks(self.pid) { show_warning!("--pid=PID is not supported on this system"); - return CheckResult::NoPidSupport; } } - CheckResult::Ok + if self.follow.is_some() && self.has_stdin() { + let blocking_stdin = self.pid == 0 + && self.follow == Some(FollowMode::Descriptor) + && self.num_inputs() == 1 + && Handle::stdin().map_or(false, |handle| { + handle + .as_file() + .metadata() + .map_or(false, |meta| !meta.is_file()) + }); + + if !blocking_stdin && atty::is(Stream::Stdin) { + show_warning!("following standard input indefinitely is ineffective"); + } + } } pub fn verify(&self) -> VerificationResult { diff --git a/src/uu/tail/src/follow/watch.rs b/src/uu/tail/src/follow/watch.rs index c21da2fae..31a6d70cb 100644 --- a/src/uu/tail/src/follow/watch.rs +++ b/src/uu/tail/src/follow/watch.rs @@ -107,6 +107,12 @@ impl Observer { files: FileHandling, pid: platform::Pid, ) -> Self { + let pid = if platform::supports_pid_checks(pid) { + pid + } else { + 0 + }; + Self { retry, follow, diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 771284c5c..2a5a94352 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -42,12 +42,7 @@ use uucore::{show, show_error}; pub fn uumain(args: impl uucore::Args) -> UResult<()> { let settings = parse_args(args)?; - let mut observer = Observer::from(&settings); - - match settings.check_warnings() { - args::CheckResult::NoPidSupport => observer.pid = 0, - args::CheckResult::Ok => {} - } + settings.check_warnings(); match settings.verify() { args::VerificationResult::CannotFollowStdinByName => { @@ -62,11 +57,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { args::VerificationResult::Ok => {} } - uu_tail(&settings, observer) + uu_tail(&settings) } -fn uu_tail(settings: &Settings, mut observer: Observer) -> UResult<()> { +fn uu_tail(settings: &Settings) -> UResult<()> { let mut printer = HeaderPrinter::new(settings.verbose, true); + let mut observer = Observer::from(settings); observer.start(settings)?; // Do an initial tail print of each path's content. diff --git a/src/uu/tail/src/text.rs b/src/uu/tail/src/text.rs index 62ad9cf70..19d13fadb 100644 --- a/src/uu/tail/src/text.rs +++ b/src/uu/tail/src/text.rs @@ -19,3 +19,5 @@ pub static BACKEND: &str = "kqueue"; #[cfg(target_os = "windows")] pub static BACKEND: &str = "ReadDirectoryChanges"; pub static FD0: &str = "/dev/fd/0"; +pub static IS_A_DIRECTORY: &str = "Is a directory"; +pub static DEV_TTY: &str = "/dev/tty";