1
0
mirror of https://github.com/BurntSushi/ripgrep.git synced 2025-11-29 05:57:07 +02:00

Replace internal atty module with atty crate.

This removes all use of explicit unsafe in ripgrep proper except for
one: accessing the contents of a memory map. (Which may never go away.)
This commit is contained in:
Andrew Gallant
2017-01-15 16:32:30 -05:00
parent b1d1cd2366
commit f5a2d022ec
5 changed files with 41 additions and 152 deletions

View File

@@ -394,8 +394,8 @@ impl<'a> ArgMatches<'a> {
self.values_of_os("file").map_or(false, |mut files| {
files.any(|f| f == "-")
});
let search_cwd = atty::on_stdin()
|| !atty::stdin_is_readable()
let search_cwd = atty::is(atty::Stream::Stdin)
|| !stdin_is_readable()
|| (self.is_present("file") && file_is_stdin)
|| self.is_present("files")
|| self.is_present("type-list");
@@ -584,7 +584,7 @@ impl<'a> ArgMatches<'a> {
} else {
self.is_present("line-number")
|| self.is_present("column")
|| atty::on_stdout()
|| atty::is(atty::Stream::Stdout)
|| self.is_present("pretty")
|| self.is_present("vimgrep")
}
@@ -602,7 +602,7 @@ impl<'a> ArgMatches<'a> {
false
} else {
self.is_present("heading")
|| atty::on_stdout()
|| atty::is(atty::Stream::Stdout)
|| self.is_present("pretty")
}
}
@@ -667,7 +667,7 @@ impl<'a> ArgMatches<'a> {
} else if self.is_present("vimgrep") {
false
} else if preference == "auto" {
atty::on_stdout() || self.is_present("pretty")
atty::is(atty::Stream::Stdout) || self.is_present("pretty")
} else {
false
}
@@ -687,7 +687,7 @@ impl<'a> ArgMatches<'a> {
} else if self.is_present("vimgrep") {
termcolor::ColorChoice::Never
} else if preference == "auto" {
if atty::on_stdout() || self.is_present("pretty") {
if atty::is(atty::Stream::Stdout) || self.is_present("pretty") {
termcolor::ColorChoice::Auto
} else {
termcolor::ColorChoice::Never
@@ -869,3 +869,24 @@ impl QuietMatched {
}
}
}
/// Returns true if and only if stdin is deemed searchable.
#[cfg(unix)]
fn stdin_is_readable() -> bool {
use std::os::unix::fs::FileTypeExt;
use same_file::Handle;
let ft = match Handle::stdin().and_then(|h| h.as_file().metadata()) {
Err(_) => return false,
Ok(md) => md.file_type(),
};
ft.is_file() || ft.is_fifo()
}
/// Returns true if and only if stdin is deemed searchable.
#[cfg(windows)]
fn stdin_is_readable() -> bool {
// On Windows, it's not clear what the possibilities are to me, so just
// always return true.
true
}

View File

@@ -1,145 +0,0 @@
/*!
This atty module contains functions for detecting whether ripgrep is being fed
from (or to) a terminal. Windows and Unix do this differently, so implement
both here.
*/
#[cfg(windows)]
use winapi::minwindef::DWORD;
#[cfg(windows)]
use winapi::winnt::HANDLE;
#[cfg(unix)]
pub fn stdin_is_readable() -> bool {
use std::os::unix::fs::FileTypeExt;
use same_file::Handle;
let ft = match Handle::stdin().and_then(|h| h.as_file().metadata()) {
Err(_) => return false,
Ok(md) => md.file_type(),
};
ft.is_file() || ft.is_fifo()
}
#[cfg(windows)]
pub fn stdin_is_readable() -> bool {
// ???
true
}
/// Returns true if there is a tty on stdin.
#[cfg(unix)]
pub fn on_stdin() -> bool {
use libc;
0 < unsafe { libc::isatty(libc::STDIN_FILENO) }
}
/// Returns true if there is a tty on stdout.
#[cfg(unix)]
pub fn on_stdout() -> bool {
use libc;
0 < unsafe { libc::isatty(libc::STDOUT_FILENO) }
}
/// Returns true if there is a tty on stdin.
#[cfg(windows)]
pub fn on_stdin() -> bool {
use kernel32::GetStdHandle;
use winapi::winbase::{
STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE,
};
unsafe {
let stdin = GetStdHandle(STD_INPUT_HANDLE);
if console_on_handle(stdin) {
// False positives aren't possible. If we got a console then
// we definitely have a tty on stdin.
return true;
}
// Otherwise, it's possible to get a false negative. If we know that
// there's a console on stdout or stderr however, then this is a true
// negative.
if console_on_fd(STD_OUTPUT_HANDLE)
|| console_on_fd(STD_ERROR_HANDLE) {
return false;
}
// Otherwise, we can't really tell, so we do a weird hack.
msys_tty_on_handle(stdin)
}
}
/// Returns true if there is a tty on stdout.
#[cfg(windows)]
pub fn on_stdout() -> bool {
use kernel32::GetStdHandle;
use winapi::winbase::{
STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE,
};
unsafe {
let stdout = GetStdHandle(STD_OUTPUT_HANDLE);
if console_on_handle(stdout) {
// False positives aren't possible. If we got a console then
// we definitely have a tty on stdout.
return true;
}
// Otherwise, it's possible to get a false negative. If we know that
// there's a console on stdin or stderr however, then this is a true
// negative.
if console_on_fd(STD_INPUT_HANDLE) || console_on_fd(STD_ERROR_HANDLE) {
return false;
}
// Otherwise, we can't really tell, so we do a weird hack.
msys_tty_on_handle(stdout)
}
}
/// Returns true if there is an MSYS tty on the given handle.
#[cfg(windows)]
unsafe fn msys_tty_on_handle(handle: HANDLE) -> bool {
use std::ffi::OsString;
use std::mem;
use std::os::raw::c_void;
use std::os::windows::ffi::OsStringExt;
use std::slice;
use kernel32::{GetFileInformationByHandleEx};
use winapi::fileapi::FILE_NAME_INFO;
use winapi::minwinbase::FileNameInfo;
use winapi::minwindef::MAX_PATH;
let size = mem::size_of::<FILE_NAME_INFO>();
let mut name_info_bytes = vec![0u8; size + MAX_PATH];
let res = GetFileInformationByHandleEx(
handle,
FileNameInfo,
&mut *name_info_bytes as *mut _ as *mut c_void,
name_info_bytes.len() as u32);
if res == 0 {
return true;
}
let name_info: FILE_NAME_INFO =
*(name_info_bytes[0..size].as_ptr() as *const FILE_NAME_INFO);
let name_bytes =
&name_info_bytes[size..size + name_info.FileNameLength as usize];
let name_u16 = slice::from_raw_parts(
name_bytes.as_ptr() as *const u16, name_bytes.len() / 2);
let name = OsString::from_wide(name_u16)
.as_os_str().to_string_lossy().into_owned();
name.contains("msys-") || name.contains("-pty")
}
/// Returns true if there is a console on the given file descriptor.
#[cfg(windows)]
unsafe fn console_on_fd(fd: DWORD) -> bool {
use kernel32::GetStdHandle;
console_on_handle(GetStdHandle(fd))
}
/// Returns true if there is a console on the given handle.
#[cfg(windows)]
unsafe fn console_on_handle(handle: HANDLE) -> bool {
use kernel32::GetConsoleMode;
let mut out = 0;
GetConsoleMode(handle, &mut out) != 0
}

View File

@@ -1,3 +1,4 @@
extern crate atty;
extern crate bytecount;
#[macro_use]
extern crate clap;
@@ -46,7 +47,6 @@ macro_rules! eprintln {
mod app;
mod args;
mod atty;
mod pathutil;
mod printer;
mod search_buffer;