mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
tail: Add gnu's warning when following stdin is ineffective. If no pid support set to 0 in Observer.
This commit is contained in:
parent
d57545d09c
commit
2dc8a1b55e
6 changed files with 37 additions and 16 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2984,6 +2984,7 @@ dependencies = [
|
||||||
name = "uu_tail"
|
name = "uu_tail"
|
||||||
version = "0.0.16"
|
version = "0.0.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atty",
|
||||||
"clap",
|
"clap",
|
||||||
"libc",
|
"libc",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
|
@ -22,6 +22,7 @@ memchr = "2.5.0"
|
||||||
notify = { version = "=5.0.0", features=["macos_kqueue"]}
|
notify = { version = "=5.0.0", features=["macos_kqueue"]}
|
||||||
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] }
|
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] }
|
||||||
same-file = "1.0.6"
|
same-file = "1.0.6"
|
||||||
|
atty = "0.2"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows-sys = { version = "0.42.0", default-features = false, features = ["Win32_System_Threading", "Win32_Foundation"] }
|
windows-sys = { version = "0.42.0", default-features = false, features = ["Win32_System_Threading", "Win32_Foundation"] }
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
|
|
||||||
use crate::paths::Input;
|
use crate::paths::Input;
|
||||||
use crate::{parse, platform, Quotable};
|
use crate::{parse, platform, Quotable};
|
||||||
|
use atty::Stream;
|
||||||
use clap::crate_version;
|
use clap::crate_version;
|
||||||
use clap::{parser::ValueSource, Arg, ArgAction, ArgMatches, Command};
|
use clap::{parser::ValueSource, Arg, ArgAction, ArgMatches, Command};
|
||||||
|
use same_file::Handle;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -120,11 +122,6 @@ pub enum VerificationResult {
|
||||||
NoOutput,
|
NoOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum CheckResult {
|
|
||||||
Ok,
|
|
||||||
NoPidSupport,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub follow: Option<FollowMode>,
|
pub follow: Option<FollowMode>,
|
||||||
|
@ -202,6 +199,7 @@ impl Settings {
|
||||||
format!("invalid PID: {}", pid_str.quote()),
|
format!("invalid PID: {}", pid_str.quote()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.pid = pid;
|
settings.pid = pid;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -243,7 +241,11 @@ impl Settings {
|
||||||
self.inputs.iter().any(|input| input.is_stdin())
|
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.retry {
|
||||||
if self.follow.is_none() {
|
if self.follow.is_none() {
|
||||||
show_warning!("--retry ignored; --retry is useful only when following");
|
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");
|
show_warning!("PID ignored; --pid=PID is useful only when following");
|
||||||
} else if !platform::supports_pid_checks(self.pid) {
|
} else if !platform::supports_pid_checks(self.pid) {
|
||||||
show_warning!("--pid=PID is not supported on this system");
|
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 {
|
pub fn verify(&self) -> VerificationResult {
|
||||||
|
|
|
@ -107,6 +107,12 @@ impl Observer {
|
||||||
files: FileHandling,
|
files: FileHandling,
|
||||||
pid: platform::Pid,
|
pid: platform::Pid,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let pid = if platform::supports_pid_checks(pid) {
|
||||||
|
pid
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
retry,
|
retry,
|
||||||
follow,
|
follow,
|
||||||
|
|
|
@ -42,12 +42,7 @@ use uucore::{show, show_error};
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let settings = parse_args(args)?;
|
let settings = parse_args(args)?;
|
||||||
|
|
||||||
let mut observer = Observer::from(&settings);
|
settings.check_warnings();
|
||||||
|
|
||||||
match settings.check_warnings() {
|
|
||||||
args::CheckResult::NoPidSupport => observer.pid = 0,
|
|
||||||
args::CheckResult::Ok => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
match settings.verify() {
|
match settings.verify() {
|
||||||
args::VerificationResult::CannotFollowStdinByName => {
|
args::VerificationResult::CannotFollowStdinByName => {
|
||||||
|
@ -62,11 +57,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
args::VerificationResult::Ok => {}
|
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 printer = HeaderPrinter::new(settings.verbose, true);
|
||||||
|
let mut observer = Observer::from(settings);
|
||||||
|
|
||||||
observer.start(settings)?;
|
observer.start(settings)?;
|
||||||
// Do an initial tail print of each path's content.
|
// Do an initial tail print of each path's content.
|
||||||
|
|
|
@ -19,3 +19,5 @@ pub static BACKEND: &str = "kqueue";
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub static BACKEND: &str = "ReadDirectoryChanges";
|
pub static BACKEND: &str = "ReadDirectoryChanges";
|
||||||
pub static FD0: &str = "/dev/fd/0";
|
pub static FD0: &str = "/dev/fd/0";
|
||||||
|
pub static IS_A_DIRECTORY: &str = "Is a directory";
|
||||||
|
pub static DEV_TTY: &str = "/dev/tty";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue