summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2025-02-22 11:27:33 -0500
committerRich Felker <dalias@aerifal.cx>2025-02-22 16:44:39 -0500
commita34ca6ead1f04283ebd04ffcc42f8dbc6995f2d1 (patch)
treeb79aea82495e91038bb36720f8ea021336ef6327
parentb6b81f697b38ef915a5dbf1311baba164822e917 (diff)
downloadmusl-a34ca6ead1f04283ebd04ffcc42f8dbc6995f2d1.tar.gz
termios: fix input speed handling
traditionally, our cfsetispeed just set the output speed. this was not conforming or reasonable behavior. use of the input baud bits in termios c_cflag depends on kernel support, which was added to linux along with TCSETS2 ioctl and arbitrary-baud functionality sometime in the 2.6 series. with older kernels, the separate input baud will not take, but this is the best behavior we can hope for anyway, certainly better than wrongly clobbering output baud setting. the nonstandard cfsetspeed is now moved to a separate file, since it no longer admits the weak alias implementation that made it namespace-safe. it now sets the output speed, and on success, sets the input speed to 0 (matched to output).
-rw-r--r--src/termios/cfgetospeed.c2
-rw-r--r--src/termios/cfsetospeed.c10
-rw-r--r--src/termios/cfsetspeed.c11
3 files changed, 19 insertions, 4 deletions
diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c
index 55fa6f55..de46a1d8 100644
--- a/src/termios/cfgetospeed.c
+++ b/src/termios/cfgetospeed.c
@@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio)
speed_t cfgetispeed(const struct termios *tio)
{
- return cfgetospeed(tio);
+ return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD);
}
diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c
index c9cbdd9d..3eab092a 100644
--- a/src/termios/cfsetospeed.c
+++ b/src/termios/cfsetospeed.c
@@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed)
int cfsetispeed(struct termios *tio, speed_t speed)
{
- return speed ? cfsetospeed(tio, speed) : 0;
+ if (speed & ~CBAUD) {
+ errno = EINVAL;
+ return -1;
+ }
+ tio->c_cflag &= ~CIBAUD;
+ tio->c_cflag |= speed * (CIBAUD/CBAUD);
+ return 0;
}
-
-weak_alias(cfsetospeed, cfsetspeed);
diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c
new file mode 100644
index 00000000..2c369db9
--- /dev/null
+++ b/src/termios/cfsetspeed.c
@@ -0,0 +1,11 @@
+#define _BSD_SOURCE
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+int cfsetspeed(struct termios *tio, speed_t speed)
+{
+ int r = cfsetospeed(tio, speed);
+ if (!r) cfsetispeed(tio, 0);
+ return r;
+}