aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kotur <qtr@google.com>2021-03-16 20:22:32 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-03-16 20:22:32 +0000
commit10c4ddc5cb3c52fbd780498ec6fda4259cbdb482 (patch)
tree454836b622e98ef51c0faec40dad2836c0cee672
parentc46616738591f7bcaee466cd2db36af5cab4775f (diff)
parentfaf7e5a27c73a45668a80f49775d3ec7f6b3744c (diff)
downloadatty-10c4ddc5cb3c52fbd780498ec6fda4259cbdb482.tar.gz
Initial import of atty-0.2.14 am: 94f54147b0 am: 1cabb091a5 am: faf7e5a27c
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/atty/+/1620967 Change-Id: I3191bcd2342b9cb1263fb997e740430ede1119e6
-rw-r--r--.cargo_vcs_info.json5
-rw-r--r--.gitignore3
-rw-r--r--CHANGELOG.md73
-rw-r--r--Cargo.toml34
-rw-r--r--Cargo.toml.orig26
-rw-r--r--README.md74
-rw-r--r--examples/atty.rs9
-rw-r--r--rustfmt.toml4
-rw-r--r--src/lib.rs210
9 files changed, 438 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..b409616
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+ "git": {
+ "sha1": "7b5df17888997d57c2c1c8f91da1db5691f49953"
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..afc9901
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+target
+Cargo.lock
+*.bk
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..4e9673f
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,73 @@
+# 0.2.14
+
+* add support for [RustyHermit](https://github.com/hermitcore/libhermit-rs), a Rust-based unikernel [#41](https://github.com/softprops/atty/pull/41)
+
+# 0.2.13
+
+* support older versions of rust that do now support 2018 edition
+
+# 0.2.12
+
+* Redox is now in the unix family so redox cfg is no longer needed [#35](https://github.com/softprops/atty/pull/35)
+
+# 0.2.11
+
+* fix msys detection with `winapi@0.3.5` [#28](https://github.com/softprops/atty/pull/28)
+
+# 0.2.10
+
+* fix wasm regression [#27](https://github.com/softprops/atty/pull/27)
+
+# 0.2.9
+
+* Fix fix pty detection [#25](https://github.com/softprops/atty/pull/25)
+
+# 0.2.8
+
+* Fix an inverted condition on MinGW [#22](https://github.com/softprops/atty/pull/22)
+
+# 0.2.7
+
+* Change `||` to `&&` for whether MSYS is a tty [#24](https://github.com/softprops/atty/pull/24/)
+
+# 0.2.6
+
+* updated winapi dependency to [0.3](https://retep998.github.io/blog/winapi-0.3/) [#18](https://github.com/softprops/atty/pull/18)
+
+# 0.2.5
+
+* added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17)
+
+# 0.2.4
+
+* added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17)
+
+# 0.2.3
+
+* added support for Redox OS [#14](https://github.com/softprops/atty/pull/14)
+
+# 0.2.2
+
+* use target specific dependencies [#11](https://github.com/softprops/atty/pull/11)
+* Add tty detection for MSYS terminals [#12](https://github.com/softprops/atty/pull/12)
+
+# 0.2.1
+
+* fix windows bug
+
+# 0.2.0
+
+* support for various stream types
+
+# 0.1.2
+
+* windows support (with automated testing)
+* automated code coverage
+
+# 0.1.1
+
+* bumped libc dep from `0.1` to `0.2`
+
+# 0.1.0
+
+* initial release
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d6bf2d0
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,34 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "atty"
+version = "0.2.14"
+authors = ["softprops <d.tangren@gmail.com>"]
+exclude = ["/.travis.yml", "/appveyor.yml"]
+description = "A simple interface for querying atty"
+homepage = "https://github.com/softprops/atty"
+documentation = "http://softprops.github.io/atty"
+readme = "README.md"
+keywords = ["terminal", "tty", "isatty"]
+license = "MIT"
+repository = "https://github.com/softprops/atty"
+[target."cfg(target_os = \"hermit\")".dependencies.hermit-abi]
+version = "0.1.6"
+[target."cfg(unix)".dependencies.libc]
+version = "0.2"
+default-features = false
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3"
+features = ["consoleapi", "processenv", "minwinbase", "minwindef", "winbase"]
+[badges.travis-ci]
+repository = "softprops/atty"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..aa2cbb7
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,26 @@
+[package]
+name = "atty"
+version = "0.2.14"
+authors = ["softprops <d.tangren@gmail.com>"]
+description = "A simple interface for querying atty"
+documentation = "http://softprops.github.io/atty"
+homepage = "https://github.com/softprops/atty"
+repository = "https://github.com/softprops/atty"
+keywords = ["terminal", "tty", "isatty"]
+license = "MIT"
+readme = "README.md"
+exclude = ["/.travis.yml", "/appveyor.yml"]
+
+[badges]
+travis-ci = { repository = "softprops/atty" }
+
+[target.'cfg(unix)'.dependencies]
+libc = { version = "0.2", default-features = false }
+
+[target.'cfg(target_os = "hermit")'.dependencies]
+hermit-abi = "0.1.6"
+
+[target.'cfg(windows)'.dependencies.winapi]
+version = "0.3"
+features = ["consoleapi", "processenv", "minwinbase", "minwindef", "winbase"]
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cd85593
--- /dev/null
+++ b/README.md
@@ -0,0 +1,74 @@
+# atty
+
+[![Build Status](https://travis-ci.org/softprops/atty.svg?branch=master)](https://travis-ci.org/softprops/atty) [![Build status](https://ci.appveyor.com/api/projects/status/geggrsnsjsuse8cv?svg=true)](https://ci.appveyor.com/project/softprops/atty) [![Coverage Status](https://coveralls.io/repos/softprops/atty/badge.svg?branch=master&service=github)](https://coveralls.io/github/softprops/atty?branch=master) [![crates.io](https://img.shields.io/crates/v/atty.svg)](https://crates.io/crates/atty) [![Released API docs](https://docs.rs/atty/badge.svg)](http://docs.rs/atty) [![Master API docs](https://img.shields.io/badge/docs-master-green.svg)](https://softprops.github.io/atty)
+
+> are you or are you not a tty?
+
+
+## install
+
+Add the following to your `Cargo.toml`
+
+```toml
+[dependencies]
+atty = "0.2"
+```
+
+## usage
+
+```rust
+use atty::Stream;
+
+fn main() {
+ if atty::is(Stream::Stdout) {
+ println!("I'm a terminal");
+ } else {
+ println!("I'm not");
+ }
+}
+```
+
+## testing
+
+This library has been unit tested on both unix and windows platforms (via appveyor).
+
+
+A simple example program is provided in this repo to test various tty's. By default.
+
+It prints
+
+```bash
+$ cargo run --example atty
+stdout? true
+stderr? true
+stdin? true
+```
+
+To test std in, pipe some text to the program
+
+```bash
+$ echo "test" | cargo run --example atty
+stdout? true
+stderr? true
+stdin? false
+```
+
+To test std out, pipe the program to something
+
+```bash
+$ cargo run --example atty | grep std
+stdout? false
+stderr? true
+stdin? true
+```
+
+To test std err, pipe the program to something redirecting std err
+
+```bash
+$ cargo run --example atty 2>&1 | grep std
+stdout? false
+stderr? false
+stdin? true
+```
+
+Doug Tangren (softprops) 2015-2019
diff --git a/examples/atty.rs b/examples/atty.rs
new file mode 100644
index 0000000..3b3635e
--- /dev/null
+++ b/examples/atty.rs
@@ -0,0 +1,9 @@
+extern crate atty;
+
+use atty::{is, Stream};
+
+fn main() {
+ println!("stdout? {}", is(Stream::Stdout));
+ println!("stderr? {}", is(Stream::Stderr));
+ println!("stdin? {}", is(Stream::Stdin));
+}
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..899a094
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,4 @@
+# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#fn_args_layout
+fn_args_layout = "Vertical"
+# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#merge_imports
+merge_imports = true \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..501cad6
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,210 @@
+//! atty is a simple utility that answers one question
+//! > is this a tty?
+//!
+//! usage is just as simple
+//!
+//! ```
+//! if atty::is(atty::Stream::Stdout) {
+//! println!("i'm a tty")
+//! }
+//! ```
+//!
+//! ```
+//! if atty::isnt(atty::Stream::Stdout) {
+//! println!("i'm not a tty")
+//! }
+//! ```
+
+#![cfg_attr(unix, no_std)]
+
+#[cfg(unix)]
+extern crate libc;
+#[cfg(windows)]
+extern crate winapi;
+
+#[cfg(windows)]
+use winapi::shared::minwindef::DWORD;
+#[cfg(windows)]
+use winapi::shared::ntdef::WCHAR;
+
+/// possible stream sources
+#[derive(Clone, Copy, Debug)]
+pub enum Stream {
+ Stdout,
+ Stderr,
+ Stdin,
+}
+
+/// returns true if this is a tty
+#[cfg(all(unix, not(target_arch = "wasm32")))]
+pub fn is(stream: Stream) -> bool {
+ extern crate libc;
+
+ let fd = match stream {
+ Stream::Stdout => libc::STDOUT_FILENO,
+ Stream::Stderr => libc::STDERR_FILENO,
+ Stream::Stdin => libc::STDIN_FILENO,
+ };
+ unsafe { libc::isatty(fd) != 0 }
+}
+
+/// returns true if this is a tty
+#[cfg(target_os = "hermit")]
+pub fn is(stream: Stream) -> bool {
+ extern crate hermit_abi;
+
+ let fd = match stream {
+ Stream::Stdout => hermit_abi::STDOUT_FILENO,
+ Stream::Stderr => hermit_abi::STDERR_FILENO,
+ Stream::Stdin => hermit_abi::STDIN_FILENO,
+ };
+ hermit_abi::isatty(fd)
+}
+
+/// returns true if this is a tty
+#[cfg(windows)]
+pub fn is(stream: Stream) -> bool {
+ use winapi::um::winbase::{
+ STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT,
+ STD_OUTPUT_HANDLE as STD_OUTPUT,
+ };
+
+ let (fd, others) = match stream {
+ Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]),
+ Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]),
+ Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]),
+ };
+ if unsafe { console_on_any(&[fd]) } {
+ // False positives aren't possible. If we got a console then
+ // we definitely have a tty on stdin.
+ return true;
+ }
+
+ // At this point, we *could* have a false negative. We can determine that
+ // this is true negative if we can detect the presence of a console on
+ // any of the other streams. If another stream has a console, then we know
+ // we're in a Windows console and can therefore trust the negative.
+ if unsafe { console_on_any(&others) } {
+ return false;
+ }
+
+ // Otherwise, we fall back to a very strange msys hack to see if we can
+ // sneakily detect the presence of a tty.
+ unsafe { msys_tty_on(fd) }
+}
+
+/// returns true if this is _not_ a tty
+pub fn isnt(stream: Stream) -> bool {
+ !is(stream)
+}
+
+/// Returns true if any of the given fds are on a console.
+#[cfg(windows)]
+unsafe fn console_on_any(fds: &[DWORD]) -> bool {
+ use winapi::um::{consoleapi::GetConsoleMode, processenv::GetStdHandle};
+
+ for &fd in fds {
+ let mut out = 0;
+ let handle = GetStdHandle(fd);
+ if GetConsoleMode(handle, &mut out) != 0 {
+ return true;
+ }
+ }
+ false
+}
+
+/// Returns true if there is an MSYS tty on the given handle.
+#[cfg(windows)]
+unsafe fn msys_tty_on(fd: DWORD) -> bool {
+ use std::{mem, slice};
+
+ use winapi::{
+ ctypes::c_void,
+ shared::minwindef::MAX_PATH,
+ um::{
+ fileapi::FILE_NAME_INFO, minwinbase::FileNameInfo, processenv::GetStdHandle,
+ winbase::GetFileInformationByHandleEx,
+ },
+ };
+
+ let size = mem::size_of::<FILE_NAME_INFO>();
+ let mut name_info_bytes = vec![0u8; size + MAX_PATH * mem::size_of::<WCHAR>()];
+ let res = GetFileInformationByHandleEx(
+ GetStdHandle(fd),
+ FileNameInfo,
+ &mut *name_info_bytes as *mut _ as *mut c_void,
+ name_info_bytes.len() as u32,
+ );
+ if res == 0 {
+ return false;
+ }
+ let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO);
+ let s = slice::from_raw_parts(
+ name_info.FileName.as_ptr(),
+ name_info.FileNameLength as usize / 2,
+ );
+ let name = String::from_utf16_lossy(s);
+ // This checks whether 'pty' exists in the file name, which indicates that
+ // a pseudo-terminal is attached. To mitigate against false positives
+ // (e.g., an actual file name that contains 'pty'), we also require that
+ // either the strings 'msys-' or 'cygwin-' are in the file name as well.)
+ let is_msys = name.contains("msys-") || name.contains("cygwin-");
+ let is_pty = name.contains("-pty");
+ is_msys && is_pty
+}
+
+/// returns true if this is a tty
+#[cfg(target_arch = "wasm32")]
+pub fn is(_stream: Stream) -> bool {
+ false
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{is, Stream};
+
+ #[test]
+ #[cfg(windows)]
+ fn is_err() {
+ // appveyor pipes its output
+ assert!(!is(Stream::Stderr))
+ }
+
+ #[test]
+ #[cfg(windows)]
+ fn is_out() {
+ // appveyor pipes its output
+ assert!(!is(Stream::Stdout))
+ }
+
+ #[test]
+ #[cfg(windows)]
+ fn is_in() {
+ assert!(is(Stream::Stdin))
+ }
+
+ #[test]
+ #[cfg(unix)]
+ fn is_err() {
+ assert!(is(Stream::Stderr))
+ }
+
+ #[test]
+ #[cfg(unix)]
+ fn is_out() {
+ assert!(is(Stream::Stdout))
+ }
+
+ #[test]
+ #[cfg(target_os = "macos")]
+ fn is_in() {
+ // macos on travis seems to pipe its input
+ assert!(is(Stream::Stdin))
+ }
+
+ #[test]
+ #[cfg(all(not(target_os = "macos"), unix))]
+ fn is_in() {
+ assert!(is(Stream::Stdin))
+ }
+}