/* Copyright (C) 1993-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 . */ #include #define static_assert_equal(x,y) _Static_assert ((x) == (y), #x " != " #y) /* Set the state of FD to *TERMIOS_P. */ int __tcsetattr (int fd, int optional_actions, const struct termios *termios_p) { struct termios2 k_termios; unsigned long cmd; memset (&k_termios, 0, sizeof k_termios); k_termios.c_iflag = termios_p->c_iflag; k_termios.c_oflag = termios_p->c_oflag; k_termios.c_cflag = termios_p->c_cflag; k_termios.c_lflag = termios_p->c_lflag; k_termios.c_line = termios_p->c_line; k_termios.c_ospeed = termios_p->c_ospeed; k_termios.c_ispeed = termios_p->c_ispeed; ___termios2_canonicalize_speeds (&k_termios); copy_c_cc (k_termios.c_cc, _TERMIOS2_NCCS, termios_p->c_cc, NCCS); /* * Choose the proper ioctl number to invoke. * * Alpha got TCSETS2 late (Linux 4.20), but has the same structure * format, and it only needs TCSETS2 if either it needs to use * __BOTHER or split speed. All other architectures have TCSETS2 as * far back as the current glibc supports. Calling TCSETS with * __BOTHER causes unpredictable results on old Alpha kernels and * could even crash them. */ static_assert_equal(TCSADRAIN, TCSANOW + 1); static_assert_equal(TCSAFLUSH, TCSANOW + 2); static_assert_equal(TCSETSW2, TCSETS2 + 1); static_assert_equal(TCSETSF2, TCSETS2 + 2); static_assert_equal(TCSETSW, TCSETS + 1); static_assert_equal(TCSETSF, TCSETS + 2); cmd = (long)optional_actions - TCSANOW; if (cmd > 2) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); if (__ASSUME_TERMIOS2 || k_termios.c_ospeed != k_termios.c_ispeed || cbaud (k_termios.c_cflag) == __BOTHER) { cmd += TCSETS2; } else { cmd += TCSETS; k_termios.c_cflag &= ~CIBAUD; } return INLINE_SYSCALL_CALL (ioctl, fd, cmd, &k_termios); } libc_hidden_def (__tcsetattr) #if _HAVE_STRUCT_OLD_TERMIOS && _TERMIOS_OLD_COMPAT versioned_symbol (libc, __tcsetattr, tcsetattr, GLIBC_2_42); /* Legacy version for shorter struct termios without speed fields */ int attribute_compat_text_section __old_tcsetattr (int fd, int optional_actions, const old_termios_t *termios_p) { struct termios new_termios; memset (&new_termios, 0, sizeof (new_termios)); new_termios.c_iflag = termios_p->c_iflag; new_termios.c_oflag = termios_p->c_oflag; new_termios.c_cflag = termios_p->c_cflag; new_termios.c_lflag = termios_p->c_lflag; new_termios.c_line = termios_p->c_line; copy_c_cc(new_termios.c_cc, NCCS, termios_p->c_cc, OLD_NCCS); return __tcsetattr (fd, optional_actions, &new_termios); } compat_symbol (libc, __old_tcsetattr, tcsetattr, GLIBC_2_0); #else weak_alias (__tcsetattr, tcsetattr) #endif