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