@@ -58,11 +58,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5858 writeln ! ( stdout, "{}" , translate!( "tty-not-a-tty" ) )
5959 } ;
6060 #[ cfg( target_os = "windows" ) ]
61- let write_result = if std:: io:: stdin ( ) . is_terminal ( ) {
62- writeln ! ( stdout, r"\\.\CON" )
63- } else {
64- set_exit_code ( 1 ) ;
65- writeln ! ( stdout, "{}" , translate!( "tty-not-a-tty" ) )
61+ let write_result = {
62+ use std:: os:: windows:: io:: AsHandle ;
63+ let stdin = std:: io:: stdin ( ) ;
64+ let stdin_handle = stdin. as_handle ( ) ;
65+ if stdin_handle. is_terminal ( ) {
66+ writeln ! (
67+ stdout,
68+ "{}" ,
69+ file_name( stdin_handle) . as_deref( ) . unwrap_or( r"\\.\CON" )
70+ )
71+ } else {
72+ set_exit_code ( 1 ) ;
73+ writeln ! ( stdout, "{}" , translate!( "tty-not-a-tty" ) )
74+ }
6675 } ;
6776
6877 if write_result. is_err ( ) || stdout. flush ( ) . is_err ( ) {
@@ -74,6 +83,44 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7483 Ok ( ( ) )
7584}
7685
86+ #[ cfg( target_os = "windows" ) ]
87+ fn file_name ( handle : std:: os:: windows:: io:: BorrowedHandle ) -> Option < String > {
88+ // This code is adapted from rust's standard library
89+ // https://github.com/rust-lang/rust/blob/0424cc16731e6141a18077f8ccde77ba148d9649/library/std/src/sys/io/is_terminal/windows.rs#L25
90+ use std:: mem:: MaybeUninit ;
91+ use std:: os:: windows:: io:: AsRawHandle ;
92+ use windows_sys:: Win32 :: Foundation :: MAX_PATH ;
93+ use windows_sys:: Win32 :: Storage :: FileSystem :: { FileNameInfo , GetFileInformationByHandleEx } ;
94+ // Manually define FILE_NAME_INFO so we can more easily construct a stack buffer.
95+ #[ repr( C ) ]
96+ #[ allow( non_snake_case) ]
97+ struct FILE_NAME_INFO {
98+ FileNameLength : u32 ,
99+ FileName : [ MaybeUninit < u16 > ; MAX_PATH as usize ] ,
100+ }
101+ let mut name = FILE_NAME_INFO {
102+ FileNameLength : 0 ,
103+ FileName : [ MaybeUninit :: uninit ( ) ; MAX_PATH as usize ] ,
104+ } ;
105+ unsafe {
106+ let result = GetFileInformationByHandleEx (
107+ handle. as_raw_handle ( ) ,
108+ FileNameInfo ,
109+ ( & raw mut name) . cast ( ) ,
110+ size_of :: < FILE_NAME_INFO > ( ) as u32 ,
111+ ) ;
112+ if result == 0 {
113+ None
114+ } else {
115+ let name = name. FileName . get ( ..name. FileNameLength as usize / 2 ) ?;
116+ // SAFETY: all elements up to FileNameLength have been initialized
117+ let name: & [ u16 ] = & * ( std:: ptr:: from_ref :: < [ MaybeUninit < u16 > ] > ( name) as * const [ u16 ] ) ;
118+ // This should never fail for a valid msys terminal because they use ASCII names.
119+ String :: from_utf16 ( name) . ok ( )
120+ }
121+ }
122+ }
123+
77124pub fn uu_app ( ) -> Command {
78125 let cmd = Command :: new ( "tty" )
79126 . version ( uucore:: crate_version!( ) )
0 commit comments