use std::fs::{File, OpenOptions};
use std::hash::Hash;
use std::io;
-use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
+use std::io::{Cursor, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write};
use std::mem::ManuallyDrop;
use std::net::{Shutdown, TcpStream};
use std::ops::{Deref, DerefMut};
#[inline]
pub fn stdin(arena: &mut Arena, add_history: bool) -> Stream {
- Stream::Readline(arena_alloc!(
- StreamLayout::new(ReadlineStream::new("", add_history)),
- arena
- ))
+ if std::io::stdin().is_terminal() {
+ Stream::Readline(arena_alloc!(
+ StreamLayout::new(ReadlineStream::new("", add_history)),
+ arena
+ ))
+ } else {
+ #[cfg(unix)]
+ {
+ use std::os::unix::io::{FromRawFd, RawFd};
+ // dup fd 0 so the File can be owned (and closed later) without
+ // closing the real stdin.
+ let fd = unsafe { libc::dup(0 as RawFd) };
+ let file = unsafe { File::from_raw_fd(fd) };
+ return Stream::from_file_as_input(atom!("user_input"), file, arena);
+ }
+ #[allow(unreachable_code)]
+ Stream::Readline(arena_alloc!(
+ StreamLayout::new(ReadlineStream::new("", add_history)),
+ arena
+ ))
+ }
}
pub fn from_tag(tag: ArenaHeaderTag, ptr: UntypedArenaPtr) -> Self {
use crate::helper::load_module_test;
+use crate::helper::load_module_test_with_input;
#[cfg(not(target_arch = "wasm32"))]
use crate::helper::load_module_test_with_tokio_runtime;
use serial_test::serial;
load_module_test("tests-pl/issue_rename_file.pl", "file_renamed");
}
+// issue #3262: read/1 on non-TTY stdin should resolve without requiring a newline
+#[test]
+#[cfg_attr(miri, ignore = "unsupported operation when isolation is enabled")]
+fn issue3262_read_from_stdin_no_newline() {
+ load_module_test_with_input("tests-pl/issue3262.pl", "hello.", "hello");
+}
+
#[test]
#[cfg(feature = "http")]
#[cfg(not(target_arch = "wasm32"))]