use std::os::unix::io::{AsFd, AsRawFd}; use tempfile::tempfile;
use nix::errno::Errno; use nix::fcntl; use nix::pty::openpty; use nix::sys::termios::{self, tcgetattr, BaudRate, LocalFlags, OutputFlags}; use nix::unistd::{read, write};
/// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s fn write_all<Fd: AsFd>(f: Fd, buf: &[u8]) { letmut len = 0; while len < buf.len() {
len += write(f.as_fd(), &buf[len..]).unwrap();
}
}
// Test tcgetattr on a terminal #[test] fn test_tcgetattr_pty() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock();
let pty = openpty(None, None).expect("openpty failed");
termios::tcgetattr(&pty.slave).unwrap();
}
// Test tcgetattr on something that isn't a terminal #[test] fn test_tcgetattr_enotty() { let file = tempfile().unwrap();
assert_eq!(termios::tcgetattr(&file).err(), Some(Errno::ENOTTY));
}
// Test modifying output flags #[test] fn test_output_flags() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock();
// Open one pty to get attributes for the second one letmut termios = { let pty = openpty(None, None).expect("openpty failed");
tcgetattr(&pty.slave).expect("tcgetattr failed")
};
// Make sure postprocessing '\r' isn't specified by default or this test is useless.
assert!(!termios
.output_flags
.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
// Specify that '\r' characters should be transformed to '\n' // OPOST is specified to enable post-processing
termios
.output_flags
.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
// Open a pty let pty = openpty(None, &termios).unwrap();
// Write into the master let string = "foofoofoo\r";
write_all(&pty.master, string.as_bytes());
// Read from the slave verifying that the output has been properly transformed letmut buf = [0u8; 10]; crate::read_exact(&pty.slave, &mut buf); let transformed_string = "foofoofoo\n";
assert_eq!(&buf, transformed_string.as_bytes());
}
// Test modifying local flags #[test] fn test_local_flags() { // openpty uses ptname(3) internally let _m = crate::PTSNAME_MTX.lock();
// Open one pty to get attributes for the second one letmut termios = { let pty = openpty(None, None).unwrap();
tcgetattr(&pty.slave).unwrap()
};
// Make sure echo is specified by default or this test is useless.
assert!(termios.local_flags.contains(LocalFlags::ECHO));
// Disable local echo
termios.local_flags.remove(LocalFlags::ECHO);
// Open a new pty with our modified termios settings let pty = openpty(None, &termios).unwrap();
// Set the master is in nonblocking mode or reading will never return. let flags = fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_GETFL).unwrap(); let new_flags =
fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_SETFL(new_flags)).unwrap();
// Write into the master let string = "foofoofoo\r";
write_all(&pty.master, string.as_bytes());
// Try to read from the master, which should not have anything as echoing was disabled. letmut buf = [0u8; 10]; let read = read(pty.master.as_raw_fd(), &mut buf).unwrap_err();
assert_eq!(read, Errno::EAGAIN);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.