Re: [PATCH RFC v3 5/8] linux: implement arbitrary and split speeds in termios
H. Peter Anvin
hpa@zytor.com
Thu May 8 21:15:12 GMT 2025
On May 8, 2025 11:20:44 AM PDT, Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> wrote:
>
>
>On 03/05/25 22:42, H. Peter Anvin wrote:
>> Linux has supported arbitrary speeds and split speeds in the kernel
>> since 2008 on all platforms except Alpha (fixed in 2020), but glibc
>> was never updated to match. This is further complicated by POSIX uses
>> of macros for the cf[gs]et[io]speed interfaces, rather than plain
>> numbers, as it really ought to have.
>>
>> On most platforms, the glibc ABI includes the c_[io]speed fields in
>> struct termios, but they are incorrectly used. On MIPS and SPARC, they
>> are entirely missing.
>>
>> For backwards compatibility, the kernel will still use the legacy
>> speed fields unless they are set to BOTHER, and will use the legacy
>> output speed as the input speed if the latter is 0 (== B0). However,
>> the specific encoding used is visible to user space applications,
>> including ones other than the one running.
>>
>> - SPARC and MIPS get a new struct termios, and tc[gs]etattr() is
>> versioned accordingly. However, the new struct termios is set to be
>> a strict extension of the old one, which means that cf* interfaces
>> other than the speed-related ones do not need versioning.
>> - The Bxxx constants are redefined as equivalent to their integer
>> values and the legacy Bxxx constants are renamed __Bxxx.
>> - cf[gs]et[io]speed() and cfsetspeed() are versioned accordingly.
>> - tcgetattr() and cfset[io]speed() are adjusted to always keep the
>> c_[io]speed fields correct (unlike earlier versions), but to
>> canonicalize the representation to ALSO configure the legacy fields
>> if a valid legacy representation exists.
>> - tcsetattr(), too, canonicalizes the representation in this way
>> before passing it to the kernel, to maximize compatibility with
>> older applications/tools.
>> - The old IBAUD0 hack is removed; it is no longer necessary since
>> even the legacy c_cflag baud rate fields have had separate input
>> values for a long time.
>>
>> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
>
>The patch looks ok, thanks for working on this. There are just minor
>nits below.
>
>Although it is a simple interface, where most of the complexity are
>on architecture differences and compat symbols handling, even in such
>cases we usually add some regression tests. It does not really
>require to be as compreensible as Linux selftests or LTP, but at
>least some test to check if the glibc interface is working as expected.
>
>We have some test infrastructure that we name 'test-container' which
>uses namespaces to simulate a pristine system to check some interfaces
>that either require to run in priviledge mode (like ld.so.cache handling),
>modify system files, or require some configuration not easily reproducible
>with default tests.
>
>The test-container already mount bind devpts, maybe we can add some
>tests just to check if the newer interfaces work as expecteded. We
>also have some interfaces to check for compat symbol, where it mimics
>a binary built against an old glibc (so it might be also an option to
>check for new compat symbols as well).
>
>> ---
>> NEWS | 4 +
>> sysdeps/unix/sysv/linux/Versions | 7 +
>> sysdeps/unix/sysv/linux/aarch64/libc.abilist | 5 +
>> .../sysv/linux/alpha/bits/termios-c_cflag.h | 2 +
>> .../bits/{termios-baud.h => termios-cbaud.h} | 42 +--
>> .../unix/sysv/linux/alpha/kernel-features.h | 11 +
>> .../unix/sysv/linux/alpha/kernel_termios.h | 43 ---
>> sysdeps/unix/sysv/linux/alpha/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/arc/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/arm/be/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/arm/le/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/bits/termios-baud.h | 65 ++--
>> .../unix/sysv/linux/bits/termios-c_cflag.h | 4 +-
>> sysdeps/unix/sysv/linux/bits/termios-cbaud.h | 47 +++
>> sysdeps/unix/sysv/linux/bits/termios-struct.h | 2 +-
>> sysdeps/unix/sysv/linux/bits/termios.h | 52 +--
>> sysdeps/unix/sysv/linux/cfsetspeed.c | 58 +++
>> sysdeps/unix/sysv/linux/csky/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/hppa/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/i386/libc.abilist | 5 +
>> .../{sparc/kernel_termios.h => isatty.c} | 36 +-
>> sysdeps/unix/sysv/linux/kernel-features.h | 4 +
>> sysdeps/unix/sysv/linux/kernel_termios.h | 20 +-
>> sysdeps/unix/sysv/linux/local_isatty.c | 9 +-
>> .../sysv/linux/loongarch/lp64/libc.abilist | 5 +
>> .../sysv/linux/m68k/coldfire/libc.abilist | 5 +
>> .../unix/sysv/linux/m68k/m680x0/libc.abilist | 5 +
>> .../sysv/linux/microblaze/be/libc.abilist | 5 +
>> .../sysv/linux/microblaze/le/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/mips/Versions | 4 +
>> .../sysv/linux/mips/bits/termios-struct.h | 34 --
>> sysdeps/unix/sysv/linux/mips/kernel_termios.h | 37 --
>> .../sysv/linux/mips/mips32/fpu/libc.abilist | 7 +
>> .../sysv/linux/mips/mips32/nofpu/libc.abilist | 7 +
>> .../sysv/linux/mips/mips64/n32/libc.abilist | 7 +
>> .../sysv/linux/mips/mips64/n64/libc.abilist | 7 +
>> sysdeps/unix/sysv/linux/mips/old_termios.h | 12 +
>> sysdeps/unix/sysv/linux/old_termios.h | 4 +
>> sysdeps/unix/sysv/linux/or1k/libc.abilist | 5 +
>> .../sysv/linux/powerpc/bits/termios-c_cflag.h | 4 +-
>> .../bits/{termios-baud.h => termios-cbaud.h} | 42 +--
>> .../unix/sysv/linux/powerpc/kernel_termios.h | 53 ---
>> .../linux/powerpc/powerpc32/fpu/libc.abilist | 5 +
>> .../powerpc/powerpc32/nofpu/libc.abilist | 5 +
>> .../linux/powerpc/powerpc64/be/libc.abilist | 5 +
>> .../linux/powerpc/powerpc64/le/libc.abilist | 5 +
>> .../unix/sysv/linux/riscv/rv32/libc.abilist | 5 +
>> .../unix/sysv/linux/riscv/rv64/libc.abilist | 5 +
>> .../unix/sysv/linux/s390/s390-32/libc.abilist | 5 +
>> .../unix/sysv/linux/s390/s390-64/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/sh/be/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/sh/le/libc.abilist | 5 +
>> sysdeps/unix/sysv/linux/sparc/Versions | 4 +
>> .../bits/{termios-baud.h => termios-cbaud.h} | 39 +-
>> .../sysv/linux/sparc/bits/termios-struct.h | 34 --
>> sysdeps/unix/sysv/linux/sparc/old_termios.h | 12 +
>> .../sysv/linux/sparc/sparc32/libc.abilist | 7 +
>> .../sysv/linux/sparc/sparc64/libc.abilist | 7 +
>> sysdeps/unix/sysv/linux/speed.c | 347 +++++++++++++++---
>> sysdeps/unix/sysv/linux/tcgetattr.c | 85 ++---
>> sysdeps/unix/sysv/linux/tcsetattr.c | 121 +++---
>> sysdeps/unix/sysv/linux/termios_internals.h | 97 +++++
>> .../unix/sysv/linux/x86_64/64/libc.abilist | 5 +
>> .../unix/sysv/linux/x86_64/x32/libc.abilist | 5 +
>> 64 files changed, 1017 insertions(+), 490 deletions(-)
>> rename sysdeps/unix/sysv/linux/alpha/bits/{termios-baud.h => termios-cbaud.h} (58%)
>> delete mode 100644 sysdeps/unix/sysv/linux/alpha/kernel_termios.h
>> create mode 100644 sysdeps/unix/sysv/linux/bits/termios-cbaud.h
>> create mode 100644 sysdeps/unix/sysv/linux/cfsetspeed.c
>> rename sysdeps/unix/sysv/linux/{sparc/kernel_termios.h => isatty.c} (51%)
>> delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/termios-struct.h
>> delete mode 100644 sysdeps/unix/sysv/linux/mips/kernel_termios.h
>> create mode 100644 sysdeps/unix/sysv/linux/mips/old_termios.h
>> create mode 100644 sysdeps/unix/sysv/linux/old_termios.h
>> rename sysdeps/unix/sysv/linux/powerpc/bits/{termios-baud.h => termios-cbaud.h} (58%)
>> delete mode 100644 sysdeps/unix/sysv/linux/powerpc/kernel_termios.h
>> rename sysdeps/unix/sysv/linux/sparc/bits/{termios-baud.h => termios-cbaud.h} (57%)
>> delete mode 100644 sysdeps/unix/sysv/linux/sparc/bits/termios-struct.h
>> create mode 100644 sysdeps/unix/sysv/linux/sparc/old_termios.h
>> create mode 100644 sysdeps/unix/sysv/linux/termios_internals.h
>>
>> diff --git a/NEWS b/NEWS
>> index df7268e5d0af..0d70a2601078 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -21,6 +21,10 @@ Major new features:
>> * The ISO C2Y family of unsigned abs functions, i.e.
>> uabs, ulabs, ullabs and uimaxabs, are now supported.
>>
>> +* On Linux, the <termios.h> interface now supports arbitrary baud rates;
>> + speed_t is redefined to simply be the baud rate specified as an
>> + unsigned int, which matches the kernel interface.
>> +
>> Deprecated and removed features, and other changes affecting compatibility:
>>
>> * The glibc.rtld.execstack now supports a compatibility mode to allow
>> diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
>> index 55d565545ab3..b721331bf71d 100644
>> --- a/sysdeps/unix/sysv/linux/Versions
>> +++ b/sysdeps/unix/sysv/linux/Versions
>> @@ -332,6 +332,13 @@ libc {
>> sched_getattr;
>> sched_setattr;
>> }
>> + GLIBC_2.42 {
>> + cfgetospeed;
>> + cfgetispeed;
>> + cfsetospeed;
>> + cfsetispeed;
>> + cfsetspeed;
>> + }
>> GLIBC_PRIVATE {
>> # functions used in other libraries
>> __syscall_rt_sigqueueinfo;
>> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> index aa6bf483dd70..fdccf84d8f88 100644
>> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> @@ -2752,6 +2752,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/alpha/bits/termios-c_cflag.h b/sysdeps/unix/sysv/linux/alpha/bits/termios-c_cflag.h
>> index 1f9f7f2680d1..d8308848c624 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/bits/termios-c_cflag.h
>> +++ b/sysdeps/unix/sysv/linux/alpha/bits/termios-c_cflag.h
>> @@ -36,4 +36,6 @@
>>
>> #ifdef __USE_MISC
>> # define ADDRB 04000000000
>> +# define CMSPAR 010000000000 /* Mark or space (stick) parity. */
>> +# define CRTSCTS 020000000000 /* Flow control. */
>> #endif
>> diff --git a/sysdeps/unix/sysv/linux/alpha/bits/termios-baud.h b/sysdeps/unix/sysv/linux/alpha/bits/termios-cbaud.h
>> similarity index 58%
>> rename from sysdeps/unix/sysv/linux/alpha/bits/termios-baud.h
>> rename to sysdeps/unix/sysv/linux/alpha/bits/termios-cbaud.h
>> index 324d5d8776d3..9918921bec5e 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/bits/termios-baud.h
>> +++ b/sysdeps/unix/sysv/linux/alpha/bits/termios-cbaud.h
>> @@ -17,30 +17,30 @@
>> <https://www.gnu.org/licenses/>. */
>>
>> #ifndef _TERMIOS_H
>> -# error "Never include <bits/termios-baud.h> directly; use <termios.h> instead."
>> +# error "Never include <bits/termios-cbaud.h> directly; use <termios.h> instead."
>> #endif
>>
>> #ifdef __USE_MISC
>> -# define CBAUD 0000037
>> -# define CBAUDEX 0000000
>> -# define CMSPAR 010000000000 /* mark or space (stick) parity */
>> -# define CRTSCTS 020000000000 /* flow control */
>> +# define CBAUD 000000037
>> +# define CBAUDEX 000000000
>> +# define CIBAUD 011200000
>> +# define IBSHIFT 16
>> #endif
>>
>> -#define B57600 00020
>> -#define B115200 00021
>> -#define B230400 00022
>> -#define B460800 00023
>> -#define B500000 00024
>> -#define B576000 00025
>> -#define B921600 00026
>> -#define B1000000 00027
>> -#define B1152000 00030
>> -#define B1500000 00031
>> -#define B2000000 00032
>> -#define B2500000 00033
>> -#define B3000000 00034
>> -#define B3500000 00035
>> -#define B4000000 00036
>> +#define __B57600 00020
>> +#define __B115200 00021
>> +#define __B230400 00022
>> +#define __B460800 00023
>> +#define __B500000 00024
>> +#define __B576000 00025
>> +#define __B921600 00026
>> +#define __B1000000 00027
>> +#define __B1152000 00030
>> +#define __B1500000 00031
>> +#define __B2000000 00032
>> +#define __B2500000 00033
>> +#define __B3000000 00034
>> +#define __B3500000 00035
>> +#define __B4000000 00036
>> +#define __BOTHER 00037
>>
>> -#define __MAX_BAUD B4000000
>> diff --git a/sysdeps/unix/sysv/linux/alpha/kernel-features.h b/sysdeps/unix/sysv/linux/alpha/kernel-features.h
>> index 6eae48f13e74..83fdf91222a7 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/kernel-features.h
>> +++ b/sysdeps/unix/sysv/linux/alpha/kernel-features.h
>> @@ -54,4 +54,15 @@
>> #undef __ASSUME_CLONE3
>> #define __ASSUME_CLONE3 0
>>
>> +/* Alpha did not provide BOTHER, CIBAUD or the termios2 ioctls until
>> + kernel 4.20. Even though struct __kernel_termios and struct
>> + termios2 are the same on Alpha, Calling the legacy TCSETS* ioctls
>> + with BOTHER set triggers a bug in these old kernels, so only use
>> + the legacy TCSETS* ioctl numbers if neither BOTHER nor split speed is
>> + needed; that way the code will fail gracefully. */
>> +#if __LINUX_KERNEL_VERSION < 0x041400
>> +# undef __ASSUME_TERMIOS2
>> +# define __ASSUME_TERMIOS2 0
>> +#endif
>> +
>> #endif /* _KERNEL_FEATURES_H */
>> diff --git a/sysdeps/unix/sysv/linux/alpha/kernel_termios.h b/sysdeps/unix/sysv/linux/alpha/kernel_termios.h
>> deleted file mode 100644
>> index 6a777ddb6e77..000000000000
>> --- a/sysdeps/unix/sysv/linux/alpha/kernel_termios.h
>> +++ /dev/null
>> @@ -1,43 +0,0 @@
>> -/* Copyright (C) 1997-2025 Free Software Foundation, Inc.
>> - This file is part of the GNU C Library.
>> -
>> - The GNU C Library is free software; you can redistribute it and/or
>> - modify it under the terms of the GNU Lesser General Public
>> - License as published by the Free Software Foundation; either
>> - version 2.1 of the License, or (at your option) any later version.
>> -
>> - The GNU C Library is distributed in the hope that it will be useful,
>> - but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> - Lesser General Public License for more details.
>> -
>> - You should have received a copy of the GNU Lesser General Public
>> - License along with the GNU C Library. If not, see
>> - <https://www.gnu.org/licenses/>. */
>> -
>> -#ifndef _KERNEL_TERMIOS_H
>> -#define _KERNEL_TERMIOS_H 1
>> -
>> -/* The following corresponds to the values from the Linux 2.1.20 kernel. */
>> -
>> -/* We need the definition of tcflag_t, cc_t, and speed_t. */
>> -#include <termios.h>
>> -
>> -#define __KERNEL_NCCS 19
>> -
>> -struct __kernel_termios
>> - {
>> - tcflag_t c_iflag; /* input mode flags */
>> - tcflag_t c_oflag; /* output mode flags */
>> - tcflag_t c_cflag; /* control mode flags */
>> - tcflag_t c_lflag; /* local mode flags */
>> - cc_t c_cc[__KERNEL_NCCS]; /* control characters */
>> - cc_t c_line; /* line discipline */
>> - speed_t c_ispeed; /* input speed */
>> - speed_t c_ospeed; /* output speed */
>> - };
>> -
>> -#define _HAVE_C_ISPEED 1
>> -#define _HAVE_C_OSPEED 1
>> -
>> -#endif /* kernel_termios.h */
>> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> index d5df9656a892..1e3f2781553e 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> @@ -3099,6 +3099,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
>> index c46c08da85c9..7b7717d1d146 100644
>> --- a/sysdeps/unix/sysv/linux/arc/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
>> @@ -2513,6 +2513,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
>> index 4df150c0f042..f64bf3f3278e 100644
>> --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
>> @@ -2805,6 +2805,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
>> index be294783f685..c065fe80fcd0 100644
>> --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
>> @@ -2802,6 +2802,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/bits/termios-baud.h b/sysdeps/unix/sysv/linux/bits/termios-baud.h
>> index e63a3eb4182e..1e41338b5739 100644
>> --- a/sysdeps/unix/sysv/linux/bits/termios-baud.h
>> +++ b/sysdeps/unix/sysv/linux/bits/termios-baud.h
>> @@ -20,29 +20,44 @@
>> # error "Never include <bits/termios-baud.h> directly; use <termios.h> instead."
>> #endif
>>
>> -#ifdef __USE_MISC
>> -# define CBAUD 000000010017 /* Baud speed mask (not in POSIX). */
>> -# define CBAUDEX 000000010000 /* Extra baud speed mask, included in CBAUD.
>> - (not in POSIX). */
>> -# define CIBAUD 002003600000 /* Input baud rate (not used). */
>> -# define CMSPAR 010000000000 /* Mark or space (stick) parity. */
>> -# define CRTSCTS 020000000000 /* Flow control. */
>> -#endif
>> +#define B0 0U
>> +#define B50 50U
>> +#define B75 75U
>> +#define B110 110U
>> +#define B134 134U
>> +#define B150 150U
>> +#define B200 200U
>> +#define B300 300U
>> +#define B600 600U
>> +#define B1200 1200U
>> +#define B1800 1800U
>> +#define B2400 2400U
>> +#define B4800 4800U
>> +#define B7200 7200U
>> +#define B9600 9600U
>> +#define B14400 14400U
>> +#define B19200 19200U
>> +#define B28800 28800U
>> +#define B33600 33600U
>> +#define B38400 38400U
>> +#define B57600 57600U
>> +#define B76800 76800U
>> +#define B115200 115200U
>> +#define B153600 153600U
>> +#define B230400 230400U
>> +#define B307200 307200U
>> +#define B460800 460800U
>> +#define B500000 500000U
>> +#define B576000 576000U
>> +#define B614400 614400U
>> +#define B921600 921600U
>> +#define B1000000 1000000U
>> +#define B1152000 1152000U
>> +#define B1500000 1500000U
>> +#define B2000000 2000000U
>> +#define B2500000 2500000U
>> +#define B3000000 3000000U
>> +#define B3500000 3500000U
>> +#define B4000000 4000000U
>>
>> -/* Extra output baud rates (not in POSIX). */
>> -#define B57600 0010001
>> -#define B115200 0010002
>> -#define B230400 0010003
>> -#define B460800 0010004
>> -#define B500000 0010005
>> -#define B576000 0010006
>> -#define B921600 0010007
>> -#define B1000000 0010010
>> -#define B1152000 0010011
>> -#define B1500000 0010012
>> -#define B2000000 0010013
>> -#define B2500000 0010014
>> -#define B3000000 0010015
>> -#define B3500000 0010016
>> -#define B4000000 0010017
>> -#define __MAX_BAUD B4000000
>> +#define __MAX_BAUD 4294967295U
>> diff --git a/sysdeps/unix/sysv/linux/bits/termios-c_cflag.h b/sysdeps/unix/sysv/linux/bits/termios-c_cflag.h
>> index bbbb621d4ef0..befd25a758dd 100644
>> --- a/sysdeps/unix/sysv/linux/bits/termios-c_cflag.h
>> +++ b/sysdeps/unix/sysv/linux/bits/termios-c_cflag.h
>> @@ -34,5 +34,7 @@
>> #define CLOCAL 0004000
>>
>> #ifdef __USE_MISC
>> -# define ADDRB 04000000000
>> +# define ADDRB 04000000000
>> +# define CMSPAR 010000000000 /* Mark or space (stick) parity. */
>> +# define CRTSCTS 020000000000 /* Flow control. */
>> #endif
>> diff --git a/sysdeps/unix/sysv/linux/bits/termios-cbaud.h b/sysdeps/unix/sysv/linux/bits/termios-cbaud.h
>> new file mode 100644
>> index 000000000000..bdc702074371
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/bits/termios-cbaud.h
>> @@ -0,0 +1,47 @@
>> +/* termios baud rate selection definitions. Linux/generic version.
>> + Copyright (C) 2019-2023 Free Software Foundation, Inc.
>
>I think it should be 2025 here.
>
>> + This file is part of the GNU C Library.
>> +
>> + The GNU C Library is free software; you can redistribute it and/or
>> + modify it under the terms of the GNU Lesser General Public
>> + License as published by the Free Software Foundation; either
>> + version 2.1 of the License, or (at your option) any later version.
>> +
>> + The GNU C Library is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + Lesser General Public License for more details.
>> +
>> + You should have received a copy of the GNU Lesser General Public
>> + License along with the GNU C Library. If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef _TERMIOS_H
>> +# error "Never include <bits/termios-cbaud.h> directly; use <termios.h> instead."
>> +#endif
>> +
>> +#ifdef __USE_MISC
>> +# define CBAUD 000000010017 /* Baud speed mask (not in POSIX). */
>> +# define CBAUDEX 000000010000 /* Extra baud speed mask, included in CBAUD.
>> + (not in POSIX). */
>> +# define CIBAUD 002003600000 /* Input baud rate. */
>> +# define IBSHIFT 16
>> +#endif
>> +
>> +/* Extra output baud rates (not in POSIX). */
>> +#define __BOTHER 0010000
>> +#define __B57600 0010001
>> +#define __B115200 0010002
>> +#define __B230400 0010003
>> +#define __B460800 0010004
>> +#define __B500000 0010005
>> +#define __B576000 0010006
>> +#define __B921600 0010007
>> +#define __B1000000 0010010
>> +#define __B1152000 0010011
>> +#define __B1500000 0010012
>> +#define __B2000000 0010013
>> +#define __B2500000 0010014
>> +#define __B3000000 0010015
>> +#define __B3500000 0010016
>> +#define __B4000000 0010017
>> diff --git a/sysdeps/unix/sysv/linux/bits/termios-struct.h b/sysdeps/unix/sysv/linux/bits/termios-struct.h
>> index 4c501a54b058..d7167dfa20c8 100644
>> --- a/sysdeps/unix/sysv/linux/bits/termios-struct.h
>> +++ b/sysdeps/unix/sysv/linux/bits/termios-struct.h
>> @@ -27,7 +27,7 @@ struct termios
>> tcflag_t c_oflag; /* output mode flags */
>> tcflag_t c_cflag; /* control mode flags */
>> tcflag_t c_lflag; /* local mode flags */
>> - cc_t c_line; /* line discipline */
>> + cc_t c_line; /* line discipline */
>> cc_t c_cc[NCCS]; /* control characters */
>> speed_t c_ispeed; /* input speed */
>> speed_t c_ospeed; /* output speed */
>> diff --git a/sysdeps/unix/sysv/linux/bits/termios.h b/sysdeps/unix/sysv/linux/bits/termios.h
>> index 3bd1e228297c..3b7df8137734 100644
>> --- a/sysdeps/unix/sysv/linux/bits/termios.h
>> +++ b/sysdeps/unix/sysv/linux/bits/termios.h
>> @@ -18,41 +18,49 @@
>>
>> #ifndef _TERMIOS_H
>> # error "Never include <bits/termios.h> directly; use <termios.h> instead."
>> +#elif defined(_TERMIOS_H) && defined(_TERMIO_H)
>> +# error "<termio.h> and <termios.h> cannot both be included"
>> #endif
>>
>> typedef unsigned char cc_t;
>> typedef unsigned int speed_t;
>> typedef unsigned int tcflag_t;
>>
>> -#include <bits/termios-struct.h>
>> +#ifdef _TERMIOS_H
>> +# include <bits/termios-struct.h>
>> +#endif
>> +
>> #include <bits/termios-c_cc.h>
>> #include <bits/termios-c_iflag.h>
>> #include <bits/termios-c_oflag.h>
>>
>> /* c_cflag bit meaning */
>> -#define B0 0000000 /* hang up */
>> -#define B50 0000001
>> -#define B75 0000002
>> -#define B110 0000003
>> -#define B134 0000004
>> -#define B150 0000005
>> -#define B200 0000006
>> -#define B300 0000007
>> -#define B600 0000010
>> -#define B1200 0000011
>> -#define B1800 0000012
>> -#define B2400 0000013
>> -#define B4800 0000014
>> -#define B9600 0000015
>> -#define B19200 0000016
>> -#define B38400 0000017
>> +#include <bits/termios-c_cflag.h>
>> +
>> +#define __B0 0000000 /* hang up */
>> +#define __B50 0000001
>> +#define __B75 0000002
>> +#define __B110 0000003
>> +#define __B134 0000004
>> +#define __B150 0000005
>> +#define __B200 0000006
>> +#define __B300 0000007
>> +#define __B600 0000010
>> +#define __B1200 0000011
>> +#define __B1800 0000012
>> +#define __B2400 0000013
>> +#define __B4800 0000014
>> +#define __B9600 0000015
>> +#define __B19200 0000016
>> +#define __B38400 0000017
>> +#include <bits/termios-cbaud.h>
>> +
>> #ifdef __USE_MISC
>> -# define EXTA B19200
>> -# define EXTB B38400
>> +# define EXTA __B19200
>> +# define EXTB __B38400
>> +# define BOTHER __BOTHER
>> #endif
>> -#include <bits/termios-baud.h>
>>
>> -#include <bits/termios-c_cflag.h>
>> #include <bits/termios-c_lflag.h>
>>
>> #ifdef __USE_MISC
>> @@ -74,3 +82,5 @@ typedef unsigned int tcflag_t;
>> #include <bits/termios-tcflow.h>
>>
>> #include <bits/termios-misc.h>
>> +
>> +#include <bits/termios-baud.h>
>> diff --git a/sysdeps/unix/sysv/linux/cfsetspeed.c b/sysdeps/unix/sysv/linux/cfsetspeed.c
>> new file mode 100644
>> index 000000000000..f350add35444
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/cfsetspeed.c
>> @@ -0,0 +1,58 @@
>> +/* cfsetspeed(), Linux version.
>> + Copyright (C) 1991-2025 Free Software Foundation, Inc.
>> + This file is part of the GNU C Library.
>> +
>> + The GNU C Library is free software; you can redistribute it and/or
>> + modify it under the terms of the GNU Lesser General Public
>> + License as published by the Free Software Foundation; either
>> + version 2.1 of the License, or (at your option) any later version.
>> +
>> + The GNU C Library is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + Lesser General Public License for more details.
>> +
>> + You should have received a copy of the GNU Lesser General Public
>> + License along with the GNU C Library; if not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <termios_internals.h>
>> +
>> +/* Set both the input and ouptut baud rates stored in *TERMIOS_P to SPEED. */
>> +int
>> +__cfsetspeed (struct termios *termios_p, speed_t speed)
>> +{
>> + tcflag_t cbaud = ___speed_to_cbaud (speed);
>> +
>> + termios_p->c_ospeed = speed;
>> + termios_p->c_ispeed = speed;
>> + termios_p->c_cflag &= ~(CBAUD | CIBAUD);
>> + termios_p->c_cflag |= cbaud | (cbaud << IBSHIFT);
>> +
>> + return 0;
>> +}
>> +versioned_symbol (libc, __cfsetspeed, cfsetspeed, GLIBC_2_42);
>> +
>> +#if _TERMIOS_OLD_COMPAT
>> +
>> +int
>> +attribute_compat_text_section
>> +__old_cfsetspeed (old_termios_t *termios_p, speed_t speed)
>> +{
>> + speed_t real_speed = ___cbaud_to_speed (speed, -1);
>> + if (real_speed == (speed_t)-1)
>> + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
>> +
>> +#if !_HAVE_STRUCT_OLD_TERMIOS
>> + /* Otherwise these fields don't exist in old_termios_t */
>> + termios_p->c_ospeed = real_speed;
>> + termios_p->c_ispeed = real_speed;
>> +#endif
>> + termios_p->c_cflag &= ~(CBAUD | CIBAUD);
>> + termios_p->c_cflag |= speed | (speed << IBSHIFT);
>> +
>> + return 0;
>> +}
>> +compat_symbol (libc, __old_cfsetspeed, cfsetspeed, GLIBC_2_0);
>> +
>> +#endif /* _TERMIOS_OLD_COMPAT */
>> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
>> index f123757134c6..69ba60ea093e 100644
>> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
>> @@ -2789,6 +2789,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> index 2dc85b953303..dea7c09692bd 100644
>> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> @@ -2826,6 +2826,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
>> index 1e38217ec6ad..4c05ab1c6e07 100644
>> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
>> @@ -3009,6 +3009,11 @@ GLIBC_2.41 sched_getattr F
>> GLIBC_2.41 sched_setattr F
>> GLIBC_2.42 __inet_ntop_chk F
>> GLIBC_2.42 __inet_pton_chk F
>> +GLIBC_2.42 cfgetispeed F
>> +GLIBC_2.42 cfgetospeed F
>> +GLIBC_2.42 cfsetispeed F
>> +GLIBC_2.42 cfsetospeed F
>> +GLIBC_2.42 cfsetspeed F
>> GLIBC_2.42 pthread_gettid_np F
>> GLIBC_2.42 uabs F
>> GLIBC_2.42 uimaxabs F
>> diff --git a/sysdeps/unix/sysv/linux/sparc/kernel_termios.h b/sysdeps/unix/sysv/linux/isatty.c
>> similarity index 51%
>> rename from sysdeps/unix/sysv/linux/sparc/kernel_termios.h
>> rename to sysdeps/unix/sysv/linux/isatty.c
>> index 401079c4e55d..96be7655193b 100644
>> --- a/sysdeps/unix/sysv/linux/sparc/kernel_termios.h
>> +++ b/sysdeps/unix/sysv/linux/isatty.c
>> @@ -1,4 +1,4 @@
>> -/* Copyright (C) 1997-2025 Free Software Foundation, Inc.
>> +/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
>> This file is part of the GNU C Library.
>>
>> The GNU C Library is free software; you can redistribute it and/or
>> @@ -15,26 +15,14 @@
>> License along with the GNU C Library; if not, see
>> <https://www.gnu.org/licenses/>. */
>>
>> -#ifndef _KERNEL_TERMIOS_H
>> -#define _KERNEL_TERMIOS_H 1
>> -/* The following corresponds to the values from the Linux 2.1.20 kernel. */
>> -
>> -/* We need the definition of tcflag_t, cc_t, and speed_t. */
>> -#include <termios.h>
>> -
>> -#define __KERNEL_NCCS 17
>> -
>> -struct __kernel_termios
>> - {
>> - tcflag_t c_iflag; /* input mode flags */
>> - tcflag_t c_oflag; /* output mode flags */
>> - tcflag_t c_cflag; /* control mode flags */
>> - tcflag_t c_lflag; /* local mode flags */
>> - cc_t c_line; /* line discipline */
>> - cc_t c_cc[__KERNEL_NCCS]; /* control characters */
>> - };
>> -
>> -#define _HAVE_C_ISPEED 0
>> -#define _HAVE_C_OSPEED 0
>> -
>> -#endif /* kernel_termios.h */
>> +#include <termios_internals.h>
>> +
>> +/* Return 1 if FD is a terminal, 0 if not. This simply does a
>> + TCGETS2 ioctl into a dummy buffer without parsing the result. */
>> +int
>> +__isatty (int fd)
>> +{
>> + struct termios2 k_termios;
>> + return INLINE_SYSCALL (ioctl, 3, fd, TCGETS2, &k_termios) == 0;
>
>Use INLINE_SYSCALL_CALL macro here.
>
>> +}
>> +weak_alias (__isatty, isatty)
>> diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
>> index 86b2d3ce5125..a49a9159cfa7 100644
>> --- a/sysdeps/unix/sysv/linux/kernel-features.h
>> +++ b/sysdeps/unix/sysv/linux/kernel-features.h
>> @@ -54,6 +54,10 @@
>> configurations). */
>> #define __ASSUME_SET_ROBUST_LIST
This is a good idea. It hadn't occurred to me, but using a pty as a test target is a really good idea. It is simple enough to feed the kernel ioctls equivalent to legacy applications, libraries, and the unfortunate number of applications which have popped up using the termios2 ioctls directly because glibc has failed for so very long.
Then check to make sure all the normalization works as intended, etc.
More information about the Libc-alpha
mailing list