@@ -4,7 +4,7 @@ use std::convert::TryInto;
44use std:: fs:: {
55 read_dir, remove_dir, remove_file, rename, DirBuilder , File , FileType , OpenOptions , ReadDir ,
66} ;
7- use std:: io:: { self , ErrorKind , Read , Seek , SeekFrom , Write } ;
7+ use std:: io:: { self , ErrorKind , IsTerminal , Read , Seek , SeekFrom , Write } ;
88use std:: path:: { Path , PathBuf } ;
99use std:: time:: SystemTime ;
1010
@@ -65,6 +65,8 @@ trait FileDescriptor: std::fmt::Debug {
6565
6666 fn dup ( & mut self ) -> io:: Result < Box < dyn FileDescriptor > > ;
6767
68+ fn is_tty ( & self ) -> bool ;
69+
6870 #[ cfg( unix) ]
6971 fn as_unix_host_fd ( & self ) -> Option < i32 > {
7072 None
@@ -143,6 +145,10 @@ impl FileDescriptor for FileHandle {
143145 use std:: os:: unix:: io:: AsRawFd ;
144146 Some ( self . file . as_raw_fd ( ) )
145147 }
148+
149+ fn is_tty ( & self ) -> bool {
150+ self . file . is_terminal ( )
151+ }
146152}
147153
148154impl FileDescriptor for io:: Stdin {
@@ -170,6 +176,10 @@ impl FileDescriptor for io::Stdin {
170176 fn as_unix_host_fd ( & self ) -> Option < i32 > {
171177 Some ( libc:: STDIN_FILENO )
172178 }
179+
180+ fn is_tty ( & self ) -> bool {
181+ self . is_terminal ( )
182+ }
173183}
174184
175185impl FileDescriptor for io:: Stdout {
@@ -202,6 +212,10 @@ impl FileDescriptor for io::Stdout {
202212 fn as_unix_host_fd ( & self ) -> Option < i32 > {
203213 Some ( libc:: STDOUT_FILENO )
204214 }
215+
216+ fn is_tty ( & self ) -> bool {
217+ self . is_terminal ( )
218+ }
205219}
206220
207221impl FileDescriptor for io:: Stderr {
@@ -227,12 +241,16 @@ impl FileDescriptor for io::Stderr {
227241 fn as_unix_host_fd ( & self ) -> Option < i32 > {
228242 Some ( libc:: STDERR_FILENO )
229243 }
244+
245+ fn is_tty ( & self ) -> bool {
246+ self . is_terminal ( )
247+ }
230248}
231249
232250#[ derive( Debug ) ]
233- struct DummyOutput ;
251+ struct NullOutput ;
234252
235- impl FileDescriptor for DummyOutput {
253+ impl FileDescriptor for NullOutput {
236254 fn name ( & self ) -> & ' static str {
237255 "stderr and stdout"
238256 }
@@ -247,7 +265,11 @@ impl FileDescriptor for DummyOutput {
247265 }
248266
249267 fn dup ( & mut self ) -> io:: Result < Box < dyn FileDescriptor > > {
250- Ok ( Box :: new ( DummyOutput ) )
268+ Ok ( Box :: new ( NullOutput ) )
269+ }
270+
271+ fn is_tty ( & self ) -> bool {
272+ false
251273 }
252274}
253275
@@ -267,8 +289,8 @@ impl FileHandler {
267289 let mut handles: BTreeMap < _ , Box < dyn FileDescriptor > > = BTreeMap :: new ( ) ;
268290 handles. insert ( 0i32 , Box :: new ( io:: stdin ( ) ) ) ;
269291 if mute_stdout_stderr {
270- handles. insert ( 1i32 , Box :: new ( DummyOutput ) ) ;
271- handles. insert ( 2i32 , Box :: new ( DummyOutput ) ) ;
292+ handles. insert ( 1i32 , Box :: new ( NullOutput ) ) ;
293+ handles. insert ( 2i32 , Box :: new ( NullOutput ) ) ;
272294 } else {
273295 handles. insert ( 1i32 , Box :: new ( io:: stdout ( ) ) ) ;
274296 handles. insert ( 2i32 , Box :: new ( io:: stderr ( ) ) ) ;
@@ -1662,35 +1684,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
16621684 }
16631685
16641686 #[ cfg_attr( not( unix) , allow( unused) ) ]
1665- fn isatty ( & mut self , miri_fd : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx , i32 > {
1687+ fn isatty (
1688+ & mut self ,
1689+ miri_fd : & OpTy < ' tcx , Provenance > ,
1690+ ) -> InterpResult < ' tcx , Scalar < Provenance > > {
16661691 let this = self . eval_context_mut ( ) ;
1667- #[ cfg( unix) ]
1692+ // "returns 1 if fd is an open file descriptor referring to a terminal;
1693+ // otherwise 0 is returned, and errno is set to indicate the error"
16681694 if matches ! ( this. machine. isolated_op, IsolatedOp :: Allow ) {
1669- let miri_fd = this. read_scalar ( miri_fd) ?. to_i32 ( ) ?;
1670- if let Some ( host_fd) =
1671- this. machine . file_handler . handles . get ( & miri_fd) . and_then ( |fd| fd. as_unix_host_fd ( ) )
1672- {
1673- // "returns 1 if fd is an open file descriptor referring to a terminal;
1674- // otherwise 0 is returned, and errno is set to indicate the error"
1675- // SAFETY: isatty has no preconditions
1676- let is_tty = unsafe { libc:: isatty ( host_fd) } ;
1677- if is_tty == 0 {
1678- let errno = std:: io:: Error :: last_os_error ( )
1679- . raw_os_error ( )
1680- . map ( Scalar :: from_i32)
1681- . unwrap ( ) ;
1682- this. set_last_error ( errno) ?;
1683- }
1684- return Ok ( is_tty) ;
1695+ let fd = this. read_scalar ( miri_fd) ?. to_i32 ( ) ?;
1696+ if this. machine . file_handler . handles . get ( & fd) . map ( |fd| fd. is_tty ( ) ) == Some ( true ) {
1697+ return Ok ( Scalar :: from_i32 ( 1 ) ) ;
16851698 }
16861699 }
1687- // We are attemping to use a Unix interface on a non-Unix platform, or we are on a Unix
1688- // platform and the passed file descriptor is not open, or isolation is enabled
1689- // FIXME: It should be possible to emulate this at least on Windows by using
1690- // GetConsoleMode.
1700+ // Fallback when the FD was not found or isolation is enabled.
16911701 let enotty = this. eval_libc ( "ENOTTY" ) ?;
16921702 this. set_last_error ( enotty) ?;
1693- Ok ( 0 )
1703+ Ok ( Scalar :: from_i32 ( 0 ) )
16941704 }
16951705
16961706 fn realpath (
0 commit comments