1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use crate::marker::PhantomData;
use crate::mem::size_of;
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
use crate::slice;
use crate::sys::{c, Align8};
use core;
use libc;
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSlice<'a> {
vec: c::WSABUF,
_p: PhantomData<&'a [u8]>,
}
impl<'a> IoSlice<'a> {
#[inline]
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
assert!(buf.len() <= c::ULONG::MAX as usize);
IoSlice {
vec: c::WSABUF {
len: buf.len() as c::ULONG,
buf: buf.as_ptr() as *mut u8 as *mut c::CHAR,
},
_p: PhantomData,
}
}
#[inline]
pub fn advance(&mut self, n: usize) {
if (self.vec.len as usize) < n {
panic!("advancing IoSlice beyond its length");
}
unsafe {
self.vec.len -= n as c::ULONG;
self.vec.buf = self.vec.buf.add(n);
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize) }
}
}
#[repr(transparent)]
pub struct IoSliceMut<'a> {
vec: c::WSABUF,
_p: PhantomData<&'a mut [u8]>,
}
impl<'a> IoSliceMut<'a> {
#[inline]
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
assert!(buf.len() <= c::ULONG::MAX as usize);
IoSliceMut {
vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() as *mut c::CHAR },
_p: PhantomData,
}
}
#[inline]
pub fn advance(&mut self, n: usize) {
if (self.vec.len as usize) < n {
panic!("advancing IoSliceMut beyond its length");
}
unsafe {
self.vec.len -= n as c::ULONG;
self.vec.buf = self.vec.buf.add(n);
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.len as usize) }
}
}
pub fn is_terminal(h: &impl AsHandle) -> bool {
unsafe { handle_is_console(h.as_handle()) }
}
unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
let handle = handle.as_raw_handle();
if handle.is_null() {
return false;
}
let mut out = 0;
if c::GetConsoleMode(handle, &mut out) != 0 {
return true;
}
for std_handle in [c::STD_INPUT_HANDLE, c::STD_OUTPUT_HANDLE, c::STD_ERROR_HANDLE] {
let std_handle = c::GetStdHandle(std_handle);
if !std_handle.is_null()
&& std_handle != handle
&& c::GetConsoleMode(std_handle, &mut out) != 0
{
return false;
}
}
msys_tty_on(handle)
}
unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
return false;
}
const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>();
let mut name_info_bytes = Align8([0u8; SIZE]);
let res = c::GetFileInformationByHandleEx(
handle,
c::FileNameInfo,
name_info_bytes.0.as_mut_ptr() as *mut libc::c_void,
SIZE as u32,
);
if res == 0 {
return false;
}
let name_info: &c::FILE_NAME_INFO = &*(name_info_bytes.0.as_ptr() as *const c::FILE_NAME_INFO);
let name_len = name_info.FileNameLength as usize / 2;
let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>();
let s = core::slice::from_raw_parts(name_ptr, name_len);
let name = String::from_utf16_lossy(s);
let name = name.rsplit('\\').next().unwrap_or(&name);
let is_msys = name.starts_with("msys-") || name.starts_with("cygwin-");
let is_pty = name.contains("-pty");
is_msys && is_pty
}