summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@oxide.computer>2020-04-04 09:53:26 -0700
committerJoshua M. Clulow <jmc@oxide.computer>2020-04-04 16:53:26 +0000
commit5b6a3335cac79730d20860b3b9aa5738d0c40377 (patch)
tree43d3b3f186643d325060669e07f72cf0a6736fdd /src
parent08e8a3ae8f3e8dd63cd7cf28975b53d94e68f52f (diff)
downloadrust-libc-5b6a3335cac79730d20860b3b9aa5738d0c40377.tar.gz
fix cfmakeraw() for illumos and Solaris
This change fixes two issues. First, the current cfmakeraw() implementation in this crate appears to be making a stack copy of the input "struct termios" before modifying it, rather than correctly modifying the original through the pointer. Before this modification the routine did not, thus, set the flags for raw mode. Second, we address the default settings of the MIN and TIME terminal options. On at least FreeBSD and Linux systems, the modern default value for MIN appears to be 1; i.e., block and wait for at least one input byte. On most Solaris and illumos systems, the MIN control character slot overlaps with EOF, and thus has a default value of 4. This breaks at least the examples in the "termion" crate, and probably quite a lot of other software written first and foremost for Linux systems. We need to force the MIN value to 1 while switching to raw mode.
Diffstat (limited to 'src')
-rw-r--r--src/unix/solarish/compat.rs27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/unix/solarish/compat.rs b/src/unix/solarish/compat.rs
index a33645211c..610dd10973 100644
--- a/src/unix/solarish/compat.rs
+++ b/src/unix/solarish/compat.rs
@@ -4,8 +4,7 @@
use unix::solarish::*;
pub unsafe fn cfmakeraw(termios: *mut ::termios) {
- let mut t = *termios as ::termios;
- t.c_iflag &= !(IMAXBEL
+ (*termios).c_iflag &= !(IMAXBEL
| IGNBRK
| BRKINT
| PARMRK
@@ -14,10 +13,26 @@ pub unsafe fn cfmakeraw(termios: *mut ::termios) {
| IGNCR
| ICRNL
| IXON);
- t.c_oflag &= !OPOST;
- t.c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- t.c_cflag &= !(CSIZE | PARENB);
- t.c_cflag |= CS8;
+ (*termios).c_oflag &= !OPOST;
+ (*termios).c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ (*termios).c_cflag &= !(CSIZE | PARENB);
+ (*termios).c_cflag |= CS8;
+
+ // By default, most software expects a pending read to block until at
+ // least one byte becomes available. As per termio(7I), this requires
+ // setting the MIN and TIME parameters appropriately.
+ //
+ // As a somewhat unfortunate artefact of history, the MIN and TIME slots
+ // in the control character array overlap with the EOF and EOL slots used
+ // for canonical mode processing. Because the EOF character needs to be
+ // the ASCII EOT value (aka Control-D), it has the byte value 4. When
+ // switching to raw mode, this is interpreted as a MIN value of 4; i.e.,
+ // reads will block until at least four bytes have been input.
+ //
+ // Other platforms with a distinct MIN slot like Linux and FreeBSD appear
+ // to default to a MIN value of 1, so we'll force that value here:
+ (*termios).c_cc[VMIN] = 1;
+ (*termios).c_cc[VTIME] = 0;
}
pub unsafe fn cfsetspeed(