Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Last active April 27, 2023 02:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andrewrk/182ace5dee6c4025d8c4b0ca22ca98ca to your computer and use it in GitHub Desktop.
Save andrewrk/182ace5dee6c4025d8c4b0ca22ca98ca to your computer and use it in GitHub Desktop.
rust vs zig implementation of istty for windows
pub fn isatty(handle: winapi::HANDLE) -> bool {
unsafe {
let handle = kernel32::GetStdHandle(handle);
// check for msys/cygwin
if is_cygwin_pty(handle) {
return true;
}
let mut out = 0;
kernel32::GetConsoleMode(handle, &mut out) != 0
}
}
/// Returns true if there is an MSYS/cygwin tty on the given handle.
fn is_cygwin_pty(handle: winapi::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 self::kernel32::GetFileInformationByHandleEx;
use self::winapi::fileapi::FILE_NAME_INFO;
use self::winapi::minwinbase::FileNameInfo;
use self::winapi::minwindef::MAX_PATH;
unsafe {
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")
}
}
pub const windows = @import("windows/index.zig");
pub fn windowsIsTty(handle: windows.HANDLE) -> bool {
if (windowsIsCygwinPty(handle))
return true;
var out: windows.DWORD = undefined;
return windows.GetConsoleMode(handle, &out);
}
pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool {
const size = @sizeOf(windows.FILE_NAME_INFO);
var name_info_bytes = []u8{0} ** (size + windows.MAX_PATH);
if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo,
@ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len)))
{
return true;
}
const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]);
const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)];
const name_wide = ([]u16)(name_bytes);
return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or
mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment