@@ -4,7 +4,7 @@ use std::convert::TryInto;
4
4
use std:: fs:: {
5
5
read_dir, remove_dir, remove_file, rename, DirBuilder , File , FileType , OpenOptions , ReadDir ,
6
6
} ;
7
- use std:: io:: { self , ErrorKind , Read , Seek , SeekFrom , Write } ;
7
+ use std:: io:: { self , ErrorKind , IsTerminal , Read , Seek , SeekFrom , Write } ;
8
8
use std:: path:: { Path , PathBuf } ;
9
9
use std:: time:: SystemTime ;
10
10
@@ -65,6 +65,8 @@ trait FileDescriptor: std::fmt::Debug {
65
65
66
66
fn dup ( & mut self ) -> io:: Result < Box < dyn FileDescriptor > > ;
67
67
68
+ fn is_tty ( & self ) -> bool ;
69
+
68
70
#[ cfg( unix) ]
69
71
fn as_unix_host_fd ( & self ) -> Option < i32 > {
70
72
None
@@ -143,6 +145,10 @@ impl FileDescriptor for FileHandle {
143
145
use std:: os:: unix:: io:: AsRawFd ;
144
146
Some ( self . file . as_raw_fd ( ) )
145
147
}
148
+
149
+ fn is_tty ( & self ) -> bool {
150
+ self . file . is_terminal ( )
151
+ }
146
152
}
147
153
148
154
impl FileDescriptor for io:: Stdin {
@@ -170,6 +176,10 @@ impl FileDescriptor for io::Stdin {
170
176
fn as_unix_host_fd ( & self ) -> Option < i32 > {
171
177
Some ( libc:: STDIN_FILENO )
172
178
}
179
+
180
+ fn is_tty ( & self ) -> bool {
181
+ self . is_terminal ( )
182
+ }
173
183
}
174
184
175
185
impl FileDescriptor for io:: Stdout {
@@ -202,6 +212,10 @@ impl FileDescriptor for io::Stdout {
202
212
fn as_unix_host_fd ( & self ) -> Option < i32 > {
203
213
Some ( libc:: STDOUT_FILENO )
204
214
}
215
+
216
+ fn is_tty ( & self ) -> bool {
217
+ self . is_terminal ( )
218
+ }
205
219
}
206
220
207
221
impl FileDescriptor for io:: Stderr {
@@ -227,12 +241,16 @@ impl FileDescriptor for io::Stderr {
227
241
fn as_unix_host_fd ( & self ) -> Option < i32 > {
228
242
Some ( libc:: STDERR_FILENO )
229
243
}
244
+
245
+ fn is_tty ( & self ) -> bool {
246
+ self . is_terminal ( )
247
+ }
230
248
}
231
249
232
250
#[ derive( Debug ) ]
233
- struct DummyOutput ;
251
+ struct NullOutput ;
234
252
235
- impl FileDescriptor for DummyOutput {
253
+ impl FileDescriptor for NullOutput {
236
254
fn name ( & self ) -> & ' static str {
237
255
"stderr and stdout"
238
256
}
@@ -247,7 +265,11 @@ impl FileDescriptor for DummyOutput {
247
265
}
248
266
249
267
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
251
273
}
252
274
}
253
275
@@ -267,8 +289,8 @@ impl FileHandler {
267
289
let mut handles: BTreeMap < _ , Box < dyn FileDescriptor > > = BTreeMap :: new ( ) ;
268
290
handles. insert ( 0i32 , Box :: new ( io:: stdin ( ) ) ) ;
269
291
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 ) ) ;
272
294
} else {
273
295
handles. insert ( 1i32 , Box :: new ( io:: stdout ( ) ) ) ;
274
296
handles. insert ( 2i32 , Box :: new ( io:: stderr ( ) ) ) ;
@@ -1662,35 +1684,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1662
1684
}
1663
1685
1664
1686
#[ 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 > > {
1666
1691
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"
1668
1694
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) ?;
1695
+ let fd = this. read_scalar ( miri_fd) ?. to_i32 ( ) ?;
1696
+ if let Some ( is_tty) = this. machine . file_handler . handles . get ( & fd) . map ( |fd| fd. is_tty ( ) ) {
1697
+ if is_tty {
1698
+ return Ok ( Scalar :: from_i32 ( 1 ) ) ;
1683
1699
}
1684
- return Ok ( is_tty) ;
1685
1700
}
1686
1701
}
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.
1702
+ // Fallback when the FD was not found or isolation is enabled.
1691
1703
let enotty = this. eval_libc ( "ENOTTY" ) ?;
1692
1704
this. set_last_error ( enotty) ?;
1693
- Ok ( 0 )
1705
+ Ok ( Scalar :: from_i32 ( 0 ) )
1694
1706
}
1695
1707
1696
1708
fn realpath (
0 commit comments