From 9355093234d7d6c3048ff98fdbac30885aefaa51 Mon Sep 17 00:00:00 2001 From: wtcpython <1762993226@qq.com> Date: Sun, 26 Jul 2026 11:06:19 +0800 Subject: [PATCH] tail: warn when --pid=0 is ignored --- src/uu/tail/src/args.rs | 20 +++++++++++++++----- src/uu/tail/src/tail.rs | 2 +- tests/by-util/test_tail.rs | 11 ++++++++++- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/uu/tail/src/args.rs b/src/uu/tail/src/args.rs index 3f0f7abffd8..2a8efe618cc 100644 --- a/src/uu/tail/src/args.rs +++ b/src/uu/tail/src/args.rs @@ -10,7 +10,7 @@ use crate::{Quotable, parse, platform}; use clap::{Arg, ArgAction, ArgMatches, Command, value_parser}; use same_file::Handle; use std::ffi::OsString; -use std::io::IsTerminal; +use std::io::{IsTerminal, Write}; use std::time::Duration; use uucore::error::{UResult, USimpleError, UUsageError}; use uucore::parser::parse_signed_num::{SignPrefix, parse_signed_num_max}; @@ -135,6 +135,7 @@ pub struct Settings { pub max_unchanged_stats: u32, pub mode: FilterMode, pub pid: platform::Pid, + pid_specified: bool, pub retry: bool, pub sleep_sec: Duration, pub use_polling: bool, @@ -153,6 +154,7 @@ impl Default for Settings { follow: Option::default(), mode: FilterMode::default(), pid: Default::default(), + pid_specified: false, retry: Default::default(), use_polling: Default::default(), verbose: Default::default(), @@ -265,6 +267,7 @@ impl Settings { } settings.pid = pid; + settings.pid_specified = true; } Err(e) => { return Err(USimpleError::new( @@ -300,7 +303,7 @@ impl Settings { /// Check [`Settings`] for problematic configurations of tail originating from user provided /// command line arguments and print appropriate warnings. - pub fn check_warnings(&self) { + pub fn check_warnings(&self) -> std::io::Result<()> { if self.retry { if self.follow.is_none() { show_warning!("{}", translate!("tail-warning-retry-ignored")); @@ -309,10 +312,15 @@ impl Settings { } } - if self.pid != 0 { + if self.pid_specified { if self.follow.is_none() { - show_warning!("{}", translate!("tail-warning-pid-ignored")); - } else if !platform::supports_pid_checks(self.pid) { + writeln!( + std::io::stderr().lock(), + "{}: warning: {}", + uucore::util_name(), + translate!("tail-warning-pid-ignored") + )?; + } else if self.pid != 0 && !platform::supports_pid_checks(self.pid) { show_warning!("{}", translate!("tail-warning-pid-not-supported")); } } @@ -336,6 +344,8 @@ impl Settings { show_warning!("{}", translate!("tail-warning-following-stdin-ineffective")); } } + + Ok(()) } /// Verify [`Settings`] and try to find unsolvable misconfigurations of tail originating from diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 4ab5e34c60e..2ff69d5b9a2 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -41,7 +41,7 @@ use uucore::{show, show_error}; pub fn uumain(args: impl uucore::Args) -> UResult<()> { let settings = parse_args(args)?; - settings.check_warnings(); + settings.check_warnings()?; match settings.verify() { args::VerificationResult::CannotFollowStdinByName => { diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 5330d0df55a..1d8d1c550d0 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -4070,7 +4070,7 @@ fn test_args_when_settings_check_warnings_then_shows_warnings() { ); scene .ucmd() - .args(&["--pid=1000", "data"]) + .args(&["--pid=0", "data"]) .stderr_to_stdout() .succeeds() .stdout_only(expected_stdout); @@ -5071,6 +5071,15 @@ fn test_failed_write_is_reported() { .stderr_is("tail: No space left on device\n"); } +#[cfg(target_os = "linux")] +#[test] +fn test_failed_warning_write_is_reported() { + new_ucmd!() + .args(&["--pid=0", "/dev/null"]) + .set_stderr(File::create("/dev/full").unwrap()) + .fails_with_code(1); +} + #[cfg(target_os = "linux")] #[test] fn test_failed_write_is_reported_on_seekable_input() {