mirror of
https://sourceware.org/git/glibc.git
synced 2025-06-27 00:01:05 +03:00
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> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
71 lines
2.1 KiB
C
71 lines
2.1 KiB
C
/* Copyright (C) 1992-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>
|
|
|
|
/* Put the state of FD into *TERMIOS_P. */
|
|
int
|
|
__tcgetattr (int fd, struct termios *termios_p)
|
|
{
|
|
struct termios2 k_termios;
|
|
long int retval = INLINE_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios);
|
|
|
|
if (__glibc_likely (retval != -1))
|
|
{
|
|
___termios2_canonicalize_speeds (&k_termios);
|
|
|
|
memset (termios_p, 0, sizeof (*termios_p));
|
|
termios_p->c_iflag = k_termios.c_iflag;
|
|
termios_p->c_oflag = k_termios.c_oflag;
|
|
termios_p->c_cflag = k_termios.c_cflag;
|
|
termios_p->c_lflag = k_termios.c_lflag;
|
|
termios_p->c_line = k_termios.c_line;
|
|
termios_p->c_ospeed = k_termios.c_ospeed;
|
|
termios_p->c_ispeed = k_termios.c_ispeed;
|
|
|
|
copy_c_cc (termios_p->c_cc, NCCS, k_termios.c_cc, _TERMIOS2_NCCS);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
libc_hidden_def (__tcgetattr)
|
|
|
|
#if _TERMIOS_OLD_COMPAT && _HAVE_STRUCT_OLD_TERMIOS
|
|
|
|
versioned_symbol (libc, __tcgetattr, tcgetattr, GLIBC_2_42);
|
|
|
|
/* Legacy version for shorter struct termios */
|
|
int
|
|
attribute_compat_text_section
|
|
__old_tcgetattr (int fd, old_termios_t *termios_p)
|
|
{
|
|
struct termios new_termios;
|
|
int retval = __tcgetattr (fd, &new_termios);
|
|
if (__glibc_likely (retval != -1))
|
|
{
|
|
memcpy (termios_p, &new_termios, sizeof (*termios_p));
|
|
}
|
|
return retval;
|
|
}
|
|
compat_symbol (libc, __old_tcgetattr, tcgetattr, GLIBC_2_0);
|
|
|
|
#else
|
|
|
|
weak_alias (__tcgetattr, tcgetattr)
|
|
|
|
#endif
|