Merge "<termios.h>: add two new POSIX functions." into main am: b130e6dae0 am: f9189bb67d am: 0e87776adc

Original change: https://android-review.googlesource.com/c/platform/bionic/+/2729340

Change-Id: I2404cdadad8598375e5d9ee8eb3b1dc0967872f6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Elliott Hughes 2023-08-30 00:03:57 +00:00 committed by Automerger Merge Worker
commit 42fd8dbd98
8 changed files with 145 additions and 0 deletions

View file

@ -56,6 +56,7 @@ list of POSIX functions implemented by glibc but not by bionic.
Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
New libc functions in V (API level 35):
* `tcgetwinsize`, `tcsetwinsize` (POSIX Issue 8 additions).
* `timespec_getres` (C23 addition).
* `localtime_rz`, `mktime_z`, `tzalloc`, and `tzfree` (NetBSD
extensions implemented in tzcode, and the "least non-standard"

View file

@ -34,6 +34,10 @@
#define __BIONIC_TERMIOS_INLINE /* Out of line. */
#include <bits/termios_inlines.h>
// POSIX added a couple more functions much later, so do the same for them.
#define __BIONIC_TERMIOS_WINSIZE_INLINE /* Out of line. */
#include <bits/termios_winsize_inlines.h>
// Actually declared in <unistd.h>, present on all API levels.
pid_t tcgetpgrp(int fd) {
pid_t pid;

View file

@ -43,3 +43,10 @@
#include <bits/termios_inlines.h>
#endif
#if __ANDROID_API__ < 35
#define __BIONIC_TERMIOS_WINSIZE_INLINE static __inline
#include <bits/termios_winsize_inlines.h>
#endif

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <errno.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/termios.h>
#if !defined(__BIONIC_TERMIOS_WINSIZE_INLINE)
#define __BIONIC_TERMIOS_WINSIZE_INLINE static __inline
#endif
__BEGIN_DECLS
__BIONIC_TERMIOS_WINSIZE_INLINE int tcgetwinsize(int __fd, struct winsize* _Nonnull __size) {
return ioctl(__fd, TIOCGWINSZ, __size);
}
__BIONIC_TERMIOS_WINSIZE_INLINE int tcsetwinsize(int __fd, const struct winsize* _Nonnull __size) {
return ioctl(__fd, TIOCSWINSZ, __size);
}
__END_DECLS

View file

@ -149,6 +149,25 @@ int tcsetattr(int __fd, int __optional_actions, const struct termios* _Nonnull _
#endif
#if __ANDROID_API__ >= 35
// These two functions were POSIX Issue 8 additions that we can also trivially
// implement as inlines for older OS version.
/**
* tcgetwinsize(3) gets the window size of the given terminal.
*
* Returns 0 on success and returns -1 and sets `errno` on failure.
*/
int tcgetwinsize(int __fd, struct winsize* _Nonnull __size);
/**
* tcsetwinsize(3) sets the window size of the given terminal.
*
* Returns 0 on success and returns -1 and sets `errno` on failure.
*/
int tcsetwinsize(int __fd, const struct winsize* _Nonnull __size);
#endif
__END_DECLS
#include <android/legacy_termios_inlines.h>

View file

@ -1591,6 +1591,8 @@ LIBC_V { # introduced=VanillaIceCream
mktime_z;
__riscv_flush_icache; # riscv64
__riscv_hwprobe; # riscv64
tcgetwinsize;
tcsetwinsize;
timespec_getres;
tzalloc;
tzfree;

View file

@ -42,6 +42,12 @@ static void termios_h() {
STRUCT_MEMBER(struct termios, tcflag_t, c_lflag);
STRUCT_MEMBER_ARRAY(struct termios, cc_t/*[]*/, c_cc);
#if !defined(__GLIBC__) // Our glibc is too old.
TYPE(struct winsize);
STRUCT_MEMBER(struct winsize, unsigned short, ws_row);
STRUCT_MEMBER(struct winsize, unsigned short, ws_col);
#endif
MACRO(NCCS);
MACRO(VEOF);
@ -162,6 +168,12 @@ static void termios_h() {
FUNCTION(tcflush, int (*f)(int, int));
FUNCTION(tcgetattr, int (*f)(int, struct termios*));
FUNCTION(tcgetsid, pid_t (*f)(int));
#if !defined(__GLIBC__) // Our glibc is too old.
FUNCTION(tcgetwinsize, int (*f)(int, struct winsize*));
#endif
FUNCTION(tcsendbreak, int (*f)(int, int));
FUNCTION(tcsetattr, int (*f)(int, int, const struct termios*));
#if !defined(__GLIBC__) // Our glibc is too old.
FUNCTION(tcsetwinsize, int (*f)(int, const struct winsize*));
#endif
}

View file

@ -29,6 +29,8 @@
#include <termios.h>
#include <errno.h>
#include <fcntl.h>
#include <pty.h>
#include <gtest/gtest.h>
@ -96,3 +98,49 @@ TEST(termios, cfmakeraw) {
EXPECT_EQ(1, t.c_cc[VMIN]);
EXPECT_EQ(0, t.c_cc[VTIME]);
}
TEST(termios, tcgetwinsize_tcsetwinsize_invalid) {
#if !defined(__GLIBC__)
winsize ws = {};
errno = 0;
ASSERT_EQ(-1, tcgetwinsize(-1, &ws));
ASSERT_EQ(EBADF, errno);
errno = 0;
ASSERT_EQ(-1, tcsetwinsize(-1, &ws));
ASSERT_EQ(EBADF, errno);
#else
GTEST_SKIP() << "glibc too old";
#endif
}
TEST(termios, tcgetwinsize_tcsetwinsize) {
#if !defined(__GLIBC__)
int pty, tty;
winsize ws = {123, 456, 9999, 9999};
ASSERT_EQ(0, openpty(&pty, &tty, nullptr, nullptr, &ws));
winsize actual = {};
ASSERT_EQ(0, tcgetwinsize(tty, &actual));
EXPECT_EQ(ws.ws_xpixel, actual.ws_xpixel);
EXPECT_EQ(ws.ws_ypixel, actual.ws_ypixel);
EXPECT_EQ(ws.ws_row, actual.ws_row);
EXPECT_EQ(ws.ws_col, actual.ws_col);
ws = {1, 2, 3, 4};
ASSERT_EQ(0, tcsetwinsize(tty, &ws));
actual = {};
ASSERT_EQ(0, tcgetwinsize(tty, &actual));
EXPECT_EQ(ws.ws_xpixel, actual.ws_xpixel);
EXPECT_EQ(ws.ws_ypixel, actual.ws_ypixel);
EXPECT_EQ(ws.ws_row, actual.ws_row);
EXPECT_EQ(ws.ws_col, actual.ws_col);
close(pty);
close(tty);
#else
GTEST_SKIP() << "glibc too old";
#endif
}