Description
Attempting to run:
use nix::sys::termios::{tcgetattr, tcsetattr};
fn main() {
let tty_in = std::io::stdin();
let original_mode = tcgetattr(&tty_in).unwrap();
println!("tcgetattr(): {original_mode:?}");
println!("c_iflag: {}", libc::BRKINT | libc::IGNPAR | libc::ICRNL | libc::IXON |
libc::IMAXBEL);
println!("c_oflag: {}", libc::OPOST | libc::ONLCR);
println!("c_cflag: {}", libc::CS6 | libc::CS7 | libc::CREAD);
println!("c_lflag: {}", libc::ECHOKE | libc::ECHOE | libc::ECHOK | libc::ECHO | libc::ECHOCTL |
libc::ISIG | libc::ICANON | libc::IEXTEN);
std::thread::sleep(std::time::Duration::from_secs(10));
tcsetattr(&tty_in, nix::sys::termios::SetArg::TCSADRAIN, &original_mode).unwrap();
println!("Back from tcsetattr()?");
std::thread::sleep(std::time::Duration::from_secs(10));
}
will output something like:
tcgetattr(): Termios { inner: RefCell { value: termios { c_iflag: 9478, c_oflag: 6149, c_cflag: 983231, c_lflag: 35387, c_cc: [3, 28, 127, 21, 4, 0, 0, 0, 17, 19, 26, 25, 18, 15, 23, 22, 20, 8, 0] } }, input_flags: InputFlags(BRKINT | IGNPAR | ICRNL | IXON | IMAXBEL), output_flags: OutputFlags(OPOST | ONLCR), control_flags: ControlFlags(CS6 | CS7 | CREAD), local_flags: LocalFlags(ECHOKE | ECHOE | ECHOK | ECHO | ECHOCTL | ISIG | ICANON | IEXTEN), control_chars: [3, 28, 127, 21, 4, 0, 0, 0, 17, 19, 26, 25, 18, 15, 23, 22, 20, 8, 0] }
c_iflag: 9478
c_oflag: 5
c_cflag: 176
c_lflag: 35387
Please notice two things:
- The values of c_oflag and c_cflag have been truncated.
- The terminal was hung up/terminated prior to the string Back from tcsetattr()? had any chance to get printed.
Quoting tcsetattr (3C):
The effect of tcsetattr() is undefined if the value of the termios structure pointed to by termios_p was not derived from the result of a call to tcgetattr(3C) on fildes; an application should modify only fields and flags defined by this document between the call to tcgetattr(3C) and tcsetattr(), leaving all other fields and flags unmodified.
There are also other relevant sections in the manual, but the bottom line is that tcsetattr()
practically always close the terminal when called on illumos as currently implemented.
I can think of three ways to improve the current situation:
- Make nix and libc aware of all flags on illumos.
- Pass through the original values unmodified from their raw representation for all unknown bits.
- Simply disable
tcsetattr()
on illumos.
Given the state of #935 and rust-lang/libc#1405, the first alternative does not seems likely to happen any time soon. The second alternative seems pragmatic, but would be a bit messy both to implement and maintain. The third alternative seems less desired than actually fixing the functionality.
I could do a PR to remove tcsetattr()
(or rather the entire termios module?) on illumos, unless someone has a better feasible idea.