mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-29 14:00:29 +00:00
Fix bugs in termios library and cleanup code
This change fixes an issue with the tcflow() magic numbers that was causing bash to freeze up on Linux. While auditing termios polyfills, several other issues were identified with XNU/BSD compatibility. Out of an abundance of caution this change undefines as much surface area from libc/calls/struct/termios.h as possible, so that autoconf scripts are less likely to detect non-POSIX teletypewriter APIs that haven't been polyfilled by Cosmopolitan. This is a *breaking change* for your static archives in /opt/cosmos if you use the cosmocc toolchain. That's because this change disables the ioctl() undiamonding trick for code outside the monorepo, specifically because it'll lead to brittle ABI breakages like this. If you're using the cosmocc toolchain, you'll need to rebuild libraries like ncurses, readline, etc. Yes diamonds cause bloat. To work around that, consider using tcgetwinsize() instead of ioctl(TIOCGWINSZ) since it'll help you avoid pulling every single ioctl-related polyfill into the linkage. The cosmocc script was specifying -DNDEBUG for some reason. It's fixed.
This commit is contained in:
parent
06b749ae03
commit
4778cd4d27
187 changed files with 1025 additions and 1848 deletions
|
@ -25,9 +25,11 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
extern const unsigned FIODGNAME;
|
||||
extern const unsigned TIOCPTSNAME;
|
||||
extern const unsigned TIOCPTYGNAME;
|
||||
|
||||
#define TIOCPTYGNAME 0x40807453 // xnu
|
||||
#define TIOCPTSNAME 0x48087448 // netbsd
|
||||
#define FIODGNAME 0x80106678 // freebsd
|
||||
|
||||
struct fiodgname_arg {
|
||||
int len;
|
||||
|
|
|
@ -105,6 +105,8 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: private \
|
|||
|
||||
# we always want -O3 because:
|
||||
# it makes the code size smaller too
|
||||
# we need -mstringop-strategy=loop because:
|
||||
# privileged code might generate memcpy call
|
||||
o/$(MODE)/libc/calls/termios2host.o \
|
||||
o/$(MODE)/libc/calls/sigenter-freebsd.o \
|
||||
o/$(MODE)/libc/calls/sigenter-netbsd.o \
|
||||
|
@ -112,7 +114,8 @@ o/$(MODE)/libc/calls/sigenter-openbsd.o \
|
|||
o/$(MODE)/libc/calls/sigenter-xnu.o \
|
||||
o/$(MODE)/libc/calls/ntcontext2linux.o: private \
|
||||
COPTS += \
|
||||
-O3
|
||||
-O3 \
|
||||
-mstringop-strategy=loop
|
||||
|
||||
# we must disable static stack safety because:
|
||||
# these functions use alloca(n)
|
||||
|
@ -147,14 +150,6 @@ o//libc/calls/ioctl_fioclex-nt.o \
|
|||
o//libc/calls/ioctl_fioclex.o \
|
||||
o//libc/calls/ioctl_siocgifconf-nt.o \
|
||||
o//libc/calls/ioctl_siocgifconf.o \
|
||||
o//libc/calls/ioctl_tcgets-nt.o \
|
||||
o//libc/calls/ioctl_tcgets.o \
|
||||
o//libc/calls/ioctl_tcsets-nt.o \
|
||||
o//libc/calls/ioctl_tcsets.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz.o \
|
||||
o//libc/calls/ioctl_tiocswinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocswinsz.o \
|
||||
o//libc/calls/fcntl.o: private \
|
||||
CFLAGS += \
|
||||
-Os
|
||||
|
|
|
@ -17,18 +17,22 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define CBAUD 0x100f
|
||||
#define CBAUDEX 0x1000
|
||||
|
||||
/**
|
||||
* Returns input baud rate.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
uint32_t cfgetispeed(const struct termios *t) {
|
||||
if (CBAUD) {
|
||||
if (IsLinux()) {
|
||||
return t->c_cflag & CBAUD;
|
||||
} else {
|
||||
return t->c_ispeed;
|
||||
return t->_c_ispeed;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,43 +41,23 @@ uint32_t cfgetispeed(const struct termios *t) {
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
uint32_t cfgetospeed(const struct termios *t) {
|
||||
if (CBAUD) {
|
||||
if (IsLinux()) {
|
||||
return t->c_cflag & CBAUD;
|
||||
} else {
|
||||
return t->c_ospeed;
|
||||
return t->_c_ospeed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets input baud rate.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int cfsetispeed(struct termios *t, unsigned speed) {
|
||||
if (speed) {
|
||||
if (CBAUD) {
|
||||
if (!(speed & ~CBAUD)) {
|
||||
t->c_cflag &= ~CBAUD;
|
||||
t->c_cflag |= speed;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
t->c_ispeed = speed;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets output baud rate.
|
||||
*
|
||||
* @param speed can be `B0`, `B50`, `B38400`, `B4000000`, etc.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `speed` isn't valid
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int cfsetospeed(struct termios *t, unsigned speed) {
|
||||
if (CBAUD) {
|
||||
int cfsetospeed(struct termios *t, uint32_t speed) {
|
||||
if (IsLinux()) {
|
||||
if (!(speed & ~CBAUD)) {
|
||||
t->c_cflag &= ~CBAUD;
|
||||
t->c_cflag |= speed;
|
||||
|
@ -82,7 +66,28 @@ int cfsetospeed(struct termios *t, unsigned speed) {
|
|||
return einval();
|
||||
}
|
||||
} else {
|
||||
t->c_ospeed = speed;
|
||||
t->_c_ospeed = speed;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets input baud rate.
|
||||
*
|
||||
* @param speed can be `B0`, `B50`, `B38400`, `B4000000`, etc.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `speed` isn't valid
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int cfsetispeed(struct termios *t, uint32_t speed) {
|
||||
if (IsLinux()) {
|
||||
if (speed) {
|
||||
return cfsetospeed(t, speed);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
t->_c_ispeed = speed;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ int fcntl(int fd, int cmd, ...) {
|
|||
STRACE("fcntl(%d, %s, %s) → %d% m", fd, DescribeFcntlCmd(cmd),
|
||||
DescribeDnotifyFlags(arg), rc);
|
||||
} else {
|
||||
STRACE("fcntl(%d, %s, %ld) → %#x% m", fd, DescribeFcntlCmd(cmd), arg, rc);
|
||||
STRACE("fcntl(%d, %s, %ld) → %d% m", fd, DescribeFcntlCmd(cmd), arg, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
/**
|
||||
* Returns dimensions of controlling terminal.
|
||||
*
|
||||
* It is recommended that programs err on the side of showing more
|
||||
* information, if this value can't be obtained with certainty.
|
||||
*
|
||||
* @param out stores determined dimensions, only on success
|
||||
* @returns -1 on error or something else on success
|
||||
*/
|
||||
int _getttysize(int fd, struct winsize *out) {
|
||||
if (__nocolor) {
|
||||
out->ws_col = atoi(firstnonnull(getenv("COLUMNS"), "80"));
|
||||
out->ws_row = atoi(firstnonnull(getenv("ROWS"), "40"));
|
||||
out->ws_xpixel = 0;
|
||||
out->ws_ypixel = 0;
|
||||
return 0;
|
||||
} else {
|
||||
return ioctl(fd, TIOCGWINSZ, out);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
||||
extern const unsigned TIOCPTYGRANT;
|
||||
#define TIOCPTYGRANT 0x20007454
|
||||
|
||||
/**
|
||||
* Grants access to subordinate pseudoteletypewriter.
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#undef __STRICT_ANSI__
|
||||
#endif
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
#define EQUAL(X, Y) ((X) == (Y))
|
||||
|
||||
|
@ -34,5 +36,7 @@ int(ioctl)(int fd, uint64_t request, ...) {
|
|||
va_start(va, request);
|
||||
arg = va_arg(va, void *);
|
||||
va_end(va);
|
||||
if (request == TIOCGWINSZ) return tcgetwinsize(fd, arg);
|
||||
if (request == TIOCSWINSZ) return tcsetwinsize(fd, arg);
|
||||
return __IOCTL_DISPATCH(EQUAL, -1, fd, request, arg);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_IOCTL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_IOCTL_H_
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
@ -12,7 +13,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
int ioctl(int, uint64_t, ...);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(COSMO)
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » ioctl » undiamonding ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
@ -26,19 +27,7 @@ int ioctl(int, uint64_t, ...);
|
|||
#define __IOCTL_DISPATCH(CMP, DEFAULT, FD, REQUEST, ...) \
|
||||
({ \
|
||||
int ReZ; \
|
||||
if (CMP(REQUEST, TIOCGWINSZ)) { \
|
||||
ReZ = ioctl_tiocgwinsz(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, TIOCSWINSZ)) { \
|
||||
ReZ = ioctl_tiocswinsz(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, TCGETS)) { \
|
||||
ReZ = ioctl_tcgets(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, TCSETS)) { \
|
||||
ReZ = ioctl_tcsets(FD, REQUEST, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, TCSETSW)) { \
|
||||
ReZ = ioctl_tcsets(FD, REQUEST, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, TCSETSF)) { \
|
||||
ReZ = ioctl_tcsets(FD, REQUEST, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFCONF)) { \
|
||||
if (CMP(REQUEST, SIOCGIFCONF)) { \
|
||||
ReZ = ioctl_siocgifconf(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFADDR)) { \
|
||||
ReZ = ioctl_siocgifaddr(FD, ##__VA_ARGS__); \
|
||||
|
@ -70,10 +59,6 @@ int ioctl_siocgifconf(int, ...);
|
|||
int ioctl_siocgifdstaddr(int, ...);
|
||||
int ioctl_siocgifflags(int, ...);
|
||||
int ioctl_siocgifnetmask(int, ...);
|
||||
int ioctl_tcgets(int, ...);
|
||||
int ioctl_tcsets(int, uint64_t, ...);
|
||||
int ioctl_tiocgwinsz(int, ...);
|
||||
int ioctl_tiocswinsz(int, ...);
|
||||
|
||||
#endif /* GNUC && !ANSI */
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/calls/ttydefaults.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_tcgets_nt(int, struct termios *) _Hide;
|
||||
|
||||
static int ioctl_tcgets_metal(int fd, struct termios *tio) {
|
||||
bzero(tio, sizeof(*tio));
|
||||
tio->c_iflag = TTYDEF_IFLAG;
|
||||
tio->c_oflag = TTYDEF_OFLAG;
|
||||
tio->c_lflag = TTYDEF_LFLAG;
|
||||
tio->c_cflag = TTYDEF_CFLAG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
|
||||
int rc;
|
||||
union metatermios mt;
|
||||
if (IsLinux()) {
|
||||
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
|
||||
return sys_ioctl(fd, TCGETS, tio);
|
||||
} else {
|
||||
if ((rc = sys_ioctl(fd, TCGETS, &mt)) != -1) {
|
||||
if (IsXnu()) {
|
||||
COPY_TERMIOS(tio, &mt.xnu);
|
||||
} else if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
COPY_TERMIOS(tio, &mt.bsd);
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about terminal.
|
||||
*
|
||||
* @see tcgetattr(fd, tio) dispatches here
|
||||
* @see ioctl(fd, TCGETS, tio) dispatches here
|
||||
* @see ioctl(fd, TIOCGETA, tio) dispatches here
|
||||
*/
|
||||
int ioctl_tcgets(int fd, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
struct termios *tio;
|
||||
va_start(va, fd);
|
||||
tio = va_arg(va, struct termios *);
|
||||
va_end(va);
|
||||
if (fd >= 0) {
|
||||
if (!tio || (IsAsan() && !__asan_is_valid(tio, sizeof(*tio)))) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsMetal()) {
|
||||
rc = ioctl_tcgets_metal(fd, tio);
|
||||
} else if (!IsWindows()) {
|
||||
rc = ioctl_tcgets_sysv(fd, tio);
|
||||
} else {
|
||||
rc = ioctl_tcgets_nt(fd, tio);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("ioctl_tcgets(%d, %p) → %d% m", fd, tio, rc);
|
||||
return rc;
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
void __on_ioctl_tcsets(int);
|
||||
int ioctl_tcsets_nt(int, uint64_t, const struct termios *);
|
||||
|
||||
static int ioctl_tcsets_metal(int fd, uint64_t request,
|
||||
const struct termios *tio) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_tcsets_sysv(int fd, uint64_t request,
|
||||
const struct termios *tio) {
|
||||
union metatermios mt;
|
||||
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
|
||||
return sys_ioctl(fd, request, __termios2host(&mt, tio));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes terminal behavior.
|
||||
*
|
||||
* @see tcsetattr(fd, TCSA{NOW,DRAIN,FLUSH}, tio) dispatches here
|
||||
* @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here
|
||||
* @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here
|
||||
*/
|
||||
int ioctl_tcsets(int fd, uint64_t request, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
static bool once;
|
||||
const struct termios *tio;
|
||||
va_start(va, request);
|
||||
tio = va_arg(va, const struct termios *);
|
||||
va_end(va);
|
||||
if (0 <= fd && fd <= 2 && _weaken(__on_ioctl_tcsets)) {
|
||||
if (!once) {
|
||||
_weaken(__on_ioctl_tcsets)(fd);
|
||||
once = true;
|
||||
}
|
||||
}
|
||||
if (!tio || (IsAsan() && !__asan_is_valid(tio, sizeof(*tio)))) {
|
||||
rc = efault();
|
||||
} else if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsMetal()) {
|
||||
rc = ioctl_tcsets_metal(fd, request, tio);
|
||||
} else if (!IsWindows()) {
|
||||
rc = ioctl_tcsets_sysv(fd, request, tio);
|
||||
} else {
|
||||
rc = ioctl_tcsets_nt(fd, request, tio);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
|
||||
return rc;
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns width and height of terminal.
|
||||
*
|
||||
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
|
||||
*/
|
||||
int ioctl_tiocgwinsz(int fd, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
struct winsize *ws;
|
||||
va_start(va, fd);
|
||||
ws = va_arg(va, struct winsize *);
|
||||
va_end(va);
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) {
|
||||
rc = efault();
|
||||
} else if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
} else {
|
||||
rc = ioctl_tiocgwinsz_nt(g_fds.p + fd, ws);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "ioctl_tiocgwinsz", fd, rc);
|
||||
return rc;
|
||||
}
|
|
@ -22,6 +22,8 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
#define TIOCPTMASTER 0x2000741c
|
||||
|
||||
int _isptmaster(int fd) {
|
||||
if (IsFreebsd()) {
|
||||
if (!sys_ioctl(fd, TIOCPTMASTER)) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/pushpop.h"
|
||||
#include "libc/intrin/pushpop.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define PTMGET 0x40287401 // openbsd
|
||||
|
||||
struct IoctlPtmGet {
|
||||
int m;
|
||||
int s;
|
||||
|
@ -49,7 +51,6 @@ static int openpty_impl(int *mfd, int *sfd, char *name,
|
|||
const struct termios *tio, //
|
||||
const struct winsize *wsz) {
|
||||
int m, s, p;
|
||||
union metatermios mt;
|
||||
struct IoctlPtmGet t;
|
||||
RETURN_ON_ERROR((m = posix_openpt(O_RDWR | O_NOCTTY)));
|
||||
if (!IsOpenbsd()) {
|
||||
|
@ -66,8 +67,8 @@ static int openpty_impl(int *mfd, int *sfd, char *name,
|
|||
*mfd = m;
|
||||
*sfd = s;
|
||||
if (name) strcpy(name, t.sname);
|
||||
if (tio) _npassert(!sys_ioctl(s, TCSETSF, __termios2host(&mt, tio)));
|
||||
if (wsz) _npassert(!sys_ioctl(s, TIOCGWINSZ, wsz));
|
||||
if (tio) _npassert(!tcsetattr(s, TCSAFLUSH, tio));
|
||||
if (wsz) _npassert(!tcgetwinsize(s, wsz));
|
||||
return 0;
|
||||
OnError:
|
||||
if (m != -1) sys_close(m);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,38 +16,52 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_tiocswinsz_nt(int, const struct winsize *);
|
||||
|
||||
/**
|
||||
* Sets width and height of terminal.
|
||||
* @fileoverview Terminal Restoration Helper for System Five.
|
||||
*
|
||||
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
|
||||
* This is used by the crash reporting functions, e.g. __die(), to help
|
||||
* ensure the terminal is in an unborked state after a crash happens.
|
||||
*/
|
||||
int ioctl_tiocswinsz(int fd, ...) {
|
||||
va_list va;
|
||||
const struct winsize *ws;
|
||||
va_start(va, fd);
|
||||
ws = va_arg(va, const struct winsize *);
|
||||
va_end(va);
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) return efault();
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
} else if (!IsWindows()) {
|
||||
return sys_ioctl(fd, TIOCSWINSZ, ws);
|
||||
} else {
|
||||
return ioctl_tiocswinsz_nt(fd, ws);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
|
||||
#define RESET_COLOR "\e[0m"
|
||||
#define SHOW_CURSOR "\e[?25h"
|
||||
#define DISABLE_MOUSE "\e[?1000;1002;1015;1006l"
|
||||
#define ANSI_RESTORE RESET_COLOR SHOW_CURSOR DISABLE_MOUSE
|
||||
|
||||
static bool __isrestorable;
|
||||
static struct termios __oldtermios;
|
||||
|
||||
static size_t __strlen(const char *s) {
|
||||
size_t i = 0;
|
||||
while (s[i]) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
// called weakly by libc/calls/tcsetattr.c to avoid pledge("tty")
|
||||
void __on_tcsetattr(int fd) {
|
||||
int e;
|
||||
e = errno;
|
||||
if (tcgetattr(fd, &__oldtermios) != -1) {
|
||||
__isrestorable = true;
|
||||
}
|
||||
errno = e;
|
||||
}
|
||||
|
||||
void __restore_tty(void) {
|
||||
int e;
|
||||
if (__isrestorable && !__isworker && !__nocolor) {
|
||||
e = errno;
|
||||
sys_write(0, ANSI_RESTORE, __strlen(ANSI_RESTORE));
|
||||
tcsetattr(0, TCSAFLUSH, &__oldtermios);
|
||||
errno = e;
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ textwindows void _check_sigwinch(struct Fd *fd) {
|
|||
old = __ws;
|
||||
e = errno;
|
||||
if (old.ws_row != 0xffff) {
|
||||
if (ioctl_tiocgwinsz_nt(fd, &ws) != -1) {
|
||||
if (tcgetwinsize_nt(fd, &ws) != -1) {
|
||||
if (old.ws_col != ws.ws_col || old.ws_row != ws.ws_row) {
|
||||
__ws = ws;
|
||||
if (old.ws_col | old.ws_row) {
|
||||
|
|
|
@ -10,8 +10,8 @@ struct termios_xnu {
|
|||
uint64_t c_cflag;
|
||||
uint64_t c_lflag;
|
||||
uint8_t c_cc[20];
|
||||
uint64_t c_ispeed;
|
||||
uint64_t c_ospeed;
|
||||
uint64_t _c_ispeed;
|
||||
uint64_t _c_ospeed;
|
||||
};
|
||||
|
||||
struct termios_bsd {
|
||||
|
@ -20,8 +20,8 @@ struct termios_bsd {
|
|||
uint32_t c_cflag;
|
||||
uint32_t c_lflag;
|
||||
uint8_t c_cc[20];
|
||||
uint32_t c_ispeed;
|
||||
uint32_t c_ospeed;
|
||||
uint32_t _c_ispeed;
|
||||
uint32_t _c_ospeed;
|
||||
};
|
||||
|
||||
union metatermios {
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_TERMIOS_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_TERMIOS_H_
|
||||
|
||||
#define NCCS 20
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct termios { /* GNU/Systemd ABI */
|
||||
uint32_t c_iflag; /* input modes */
|
||||
uint32_t c_oflag; /* output modes */
|
||||
uint32_t c_cflag; /* control modes */
|
||||
uint32_t c_lflag; /* local modes */
|
||||
uint8_t c_cc[20]; /* code mappings */
|
||||
uint32_t c_ispeed; /* input speed */
|
||||
uint32_t c_ospeed; /* output speed */
|
||||
struct termios { /* cosmo abi */
|
||||
uint32_t c_iflag; /* input modes */
|
||||
uint32_t c_oflag; /* output modes */
|
||||
uint32_t c_cflag; /* control modes */
|
||||
uint32_t c_lflag; /* local modes */
|
||||
uint8_t c_cc[NCCS]; /* code mappings */
|
||||
uint32_t _c_ispeed; /* use cfgetispeed() and cfsetispeed() */
|
||||
uint32_t _c_ospeed; /* use cfgetospeed() and cfsetospeed() */
|
||||
};
|
||||
|
||||
#define c_line c_cc[0] /* line discipline */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TERMIOS_H_ */
|
||||
|
|
|
@ -10,8 +10,6 @@ struct winsize {
|
|||
uint16_t ws_ypixel;
|
||||
};
|
||||
|
||||
int _getttysize(int, struct winsize *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_WINSIZE_H_ */
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_WINSIZE_INTERNAL_H_
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) _Hide;
|
||||
int tcgetwinsize_nt(struct Fd *, struct winsize *) _Hide;
|
||||
const char *DescribeWinsize(char[64], int, struct winsize *);
|
||||
#define DescribeWinsize(rc, ws) DescribeWinsize(alloca(12), rc, ws)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -27,7 +27,10 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows int sys_tcdrain_nt(int fd) {
|
||||
#define TCSBRK 0x5409 // linux
|
||||
#define TIOCDRAIN 0x2000745e // xnu, freebsd, openbsd, netbsd
|
||||
|
||||
static dontinline textwindows int sys_tcdrain_nt(int fd) {
|
||||
if (!__isfdopen(fd)) return ebadf();
|
||||
if (_check_interrupts(false, g_fds.p)) return -1;
|
||||
if (!FlushFileBuffers(g_fds.p[fd].handle)) return __winerr();
|
||||
|
@ -40,7 +43,7 @@ static textwindows int sys_tcdrain_nt(int fd) {
|
|||
* @param fd is file descriptor of tty
|
||||
* @raise EBADF if `fd` isn't an open file descriptor
|
||||
* @raise ENOTTY if `fd` is open but not a teletypewriter
|
||||
* @raise EIO if process group of writer is orphoned, calling thread is
|
||||
* @raise EIO if process group of writer is orphaned, calling thread is
|
||||
* not blocking `SIGTTOU`, and process isn't ignoring `SIGTTOU`
|
||||
* @raise ECANCELED if thread was cancelled in masked mode
|
||||
* @raise EINTR if signal was delivered
|
||||
|
@ -51,12 +54,14 @@ static textwindows int sys_tcdrain_nt(int fd) {
|
|||
int tcdrain(int fd) {
|
||||
int rc;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
if (IsMetal()) {
|
||||
rc = enosys();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ioctl_cp(fd, TCSBRK, (void *)(intptr_t)1);
|
||||
} else {
|
||||
if (IsLinux()) {
|
||||
rc = sys_ioctl_cp(fd, TCSBRK, (uintptr_t)1);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl_cp(fd, TIOCDRAIN, 0);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_tcdrain_nt(fd);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
END_CANCELLATION_POINT;
|
||||
STRACE("tcdrain(%d) → %d% m", fd, rc);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
|
@ -32,6 +33,13 @@
|
|||
#define kNtPurgeTxabort 1
|
||||
#define kNtPurgeRxabort 2
|
||||
|
||||
#define TCXONC 0x0000540A // linux
|
||||
#define TIOCGETA 0x40487413 // bsd
|
||||
#define TIOCSTOP 0x2000746f // bsd
|
||||
#define TIOCSTART 0x2000746e // bsd
|
||||
#define TIOCIXON 0x20007481 // xnu
|
||||
#define TIOCIXOFF 0x20007480 // xnu
|
||||
|
||||
static const char *DescribeFlow(char buf[12], int action) {
|
||||
if (action == TCOOFF) return "TCOOFF";
|
||||
if (action == TCOON) return "TCOON";
|
||||
|
@ -41,33 +49,61 @@ static const char *DescribeFlow(char buf[12], int action) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
static int sys_tcflow_bsd(int fd, int action) {
|
||||
int rc;
|
||||
uint8_t c;
|
||||
struct termios t;
|
||||
if (action == TCOOFF) return sys_ioctl(fd, TIOCSTOP, 0);
|
||||
if (action == TCOON) return sys_ioctl(fd, TIOCSTART, 0);
|
||||
if (action != TCIOFF && action != TCION) return einval();
|
||||
if (sys_ioctl(fd, TCGETS, &t) == -1) return -1;
|
||||
c = t.c_cc[action == TCIOFF ? VSTOP : VSTART];
|
||||
if (c == 255) return 0; // code is disabled
|
||||
if (sys_write(fd, &c, 1) == -1) return -1;
|
||||
static int sys_tcflow_bsd_write(int fd, int cc) {
|
||||
unsigned char c;
|
||||
struct termios_bsd term;
|
||||
if (sys_ioctl(fd, TIOCGETA, &term) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if ((c = term.c_cc[cc]) != _POSIX_VDISABLE &&
|
||||
sys_write(fd, &c, sizeof(c)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_tcflow_bsd(int fd, int action) {
|
||||
switch (action) {
|
||||
case TCOOFF:
|
||||
return sys_ioctl(fd, TIOCSTOP, 0);
|
||||
case TCOON:
|
||||
return sys_ioctl(fd, TIOCSTART, 0);
|
||||
case TCION:
|
||||
if (IsXnu()) {
|
||||
return sys_ioctl(fd, TIOCIXON, 0);
|
||||
} else {
|
||||
return sys_tcflow_bsd_write(fd, VSTART);
|
||||
}
|
||||
case TCIOFF:
|
||||
if (IsXnu()) {
|
||||
return sys_ioctl(fd, TIOCIXOFF, 0);
|
||||
} else {
|
||||
return sys_tcflow_bsd_write(fd, VSTOP);
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static dontinline textwindows int sys_tcflow_nt(int fd, int action) {
|
||||
bool32 ok;
|
||||
int64_t h;
|
||||
if (!__isfdopen(fd)) return ebadf();
|
||||
h = g_fds.p[fd].handle;
|
||||
if (action == TCOOFF) {
|
||||
ok = PurgeComm(h, kNtPurgeTxabort);
|
||||
} else if (action == TCIOFF) {
|
||||
ok = PurgeComm(h, kNtPurgeRxabort);
|
||||
} else if (action == TCOON || action == TCION) {
|
||||
ok = ClearCommBreak(h);
|
||||
} else {
|
||||
return einval();
|
||||
switch (action) {
|
||||
case TCOON:
|
||||
case TCION:
|
||||
ok = ClearCommBreak(h);
|
||||
break;
|
||||
case TCOOFF:
|
||||
ok = PurgeComm(h, kNtPurgeTxabort);
|
||||
break;
|
||||
case TCIOFF:
|
||||
ok = PurgeComm(h, kNtPurgeRxabort);
|
||||
break;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
return ok ? 0 : __winerr();
|
||||
}
|
||||
|
@ -92,14 +128,14 @@ static dontinline textwindows int sys_tcflow_nt(int fd, int action) {
|
|||
*/
|
||||
int tcflow(int fd, int action) {
|
||||
int rc;
|
||||
if (IsMetal()) {
|
||||
rc = enosys();
|
||||
if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCXONC, action);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl(fd, TCXONC, action);
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ioctl(fd, TCXONC, action);
|
||||
} else {
|
||||
rc = sys_tcflow_bsd(fd, action);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_tcflow_nt(fd, action);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("tcflow(%d, %s) → %d% m", fd, DescribeFlow(alloca(12), action), rc);
|
||||
return rc;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TCFLSH 0x0000540b
|
||||
#define TIOCFLUSH 0x80047410
|
||||
|
||||
#define kNtPurgeTxclear 4
|
||||
#define kNtPurgeRxclear 8
|
||||
|
||||
|
@ -73,12 +76,14 @@ static dontinline textwindows int sys_tcflush_nt(int fd, int queue) {
|
|||
*/
|
||||
int tcflush(int fd, int queue) {
|
||||
int rc;
|
||||
if (IsMetal()) {
|
||||
rc = enosys();
|
||||
} else if (!IsWindows()) {
|
||||
if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCFLSH, queue);
|
||||
} else {
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl(fd, TIOCFLUSH, &queue);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_tcflush_nt(fd, queue);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("tcflush(%d, %s) → %d% m", fd, DescribeFlush(alloca(12), queue), rc);
|
||||
return rc;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
||||
textwindows int tcgetattr_nt(int ignored, struct termios *tio) {
|
||||
int64_t in, out;
|
||||
bool32 inok, outok;
|
||||
uint32_t inmode, outmode;
|
|
@ -16,21 +16,56 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/calls/ttydefaults.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TCGETS 0x00005401 // linux
|
||||
#define TIOCGETA 0x40487413 // bsd
|
||||
|
||||
int tcgetattr_nt(int, struct termios *);
|
||||
|
||||
static int tcgetattr_metal(int fd, struct termios *tio) {
|
||||
bzero(tio, sizeof(*tio));
|
||||
tio->c_iflag = TTYDEF_IFLAG;
|
||||
tio->c_oflag = TTYDEF_OFLAG;
|
||||
tio->c_lflag = TTYDEF_LFLAG;
|
||||
tio->c_cflag = TTYDEF_CFLAG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcgetattr_bsd(int fd, struct termios *tio) {
|
||||
int rc;
|
||||
union metatermios mt;
|
||||
if ((rc = sys_ioctl(fd, TIOCGETA, &mt)) != -1) {
|
||||
if (IsXnu()) {
|
||||
COPY_TERMIOS(tio, &mt.xnu);
|
||||
} else {
|
||||
COPY_TERMIOS(tio, &mt.bsd);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the termios struct.
|
||||
*
|
||||
* Here are the general defaults you can expect across platforms:
|
||||
* Here are the approximate defaults you can expect across platforms:
|
||||
*
|
||||
* c_iflag = ICRNL IXON
|
||||
* c_oflag = OPOST ONLCR NL0 CR0 TAB0 BS0 VT0 FF0
|
||||
* c_cflag = ISIG CREAD CS8
|
||||
* c_lflag = ISIG ICANON ECHO ECHOE ECHOK IEXTEN ECHOCTL ECHOKE
|
||||
* c_ispeed = 38400
|
||||
* c_ospeed = 38400
|
||||
* cfgetispeed() = B38400
|
||||
* cfgetospeed() = B38400
|
||||
* c_cc[VINTR] = CTRL-C
|
||||
* c_cc[VQUIT] = CTRL-\ # ignore this comment
|
||||
* c_cc[VERASE] = CTRL-?
|
||||
|
@ -54,6 +89,25 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int(tcgetattr)(int fd, struct termios *tio) {
|
||||
return ioctl(fd, TCGETS, tio);
|
||||
int tcgetattr(int fd, struct termios *tio) {
|
||||
int rc;
|
||||
if (fd < 0) {
|
||||
rc = einval();
|
||||
} else if (!tio || (IsAsan() && !__asan_is_valid(tio, sizeof(*tio)))) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCGETS, tio);
|
||||
} else if (IsBsd()) {
|
||||
rc = tcgetattr_bsd(fd, tio);
|
||||
} else if (IsMetal()) {
|
||||
rc = tcgetattr_metal(fd, tio);
|
||||
} else if (IsWindows()) {
|
||||
rc = tcgetattr_nt(fd, tio);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("tcgetattr(%d, %p) → %d% m", fd, tio, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TIOCGPGRP_linux 0x0000540f
|
||||
#define TIOCGPGRP_bsd 0x40047477
|
||||
|
||||
/**
|
||||
* Returns which process group controls terminal.
|
||||
*
|
||||
|
@ -34,10 +37,12 @@
|
|||
*/
|
||||
int tcgetpgrp(int fd) {
|
||||
int rc, pgrp;
|
||||
if (IsWindows() || IsMetal()) {
|
||||
rc = enosys();
|
||||
if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TIOCGPGRP_linux, &pgrp);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_ioctl(fd, TIOCGPGRP_bsd, &pgrp);
|
||||
} else {
|
||||
rc = sys_ioctl(fd, TIOCGPGRP, &pgrp);
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("tcgetpgrp(%d) → %d% m", fd, rc == -1 ? rc : pgrp);
|
||||
return rc == -1 ? rc : pgrp;
|
||||
|
|
|
@ -18,10 +18,17 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
||||
#define TIOCGSID (IsLinux() ? 0x5429 : 0x40047463)
|
||||
|
||||
/**
|
||||
* Returns session id controlling terminal.
|
||||
*/
|
||||
int tcgetsid(int fd) {
|
||||
int sid;
|
||||
if (sys_ioctl(fd, TIOCGSID, &sid) < 0) return -1;
|
||||
return sid;
|
||||
int rc, sid;
|
||||
rc = sys_ioctl(fd, TIOCGSID, &sid);
|
||||
STRACE("tcgetsid(%d) → %d% m", fd, rc);
|
||||
return rc != -1 ? sid : -1;
|
||||
}
|
||||
|
|
|
@ -16,24 +16,23 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/startupinfo.h"
|
||||
#include "libc/nt/struct/consolescreenbufferinfoex.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
|
||||
textwindows int tcgetwinsize_nt(struct Fd *fd, struct winsize *ws) {
|
||||
int i, e, rc;
|
||||
uint32_t mode;
|
||||
struct Fd *fds[3];
|
|
@ -16,13 +16,37 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Gets terminal window size.
|
||||
*/
|
||||
int tcgetwinsize(int fd, struct winsize *ws) {
|
||||
return ioctl_tiocgwinsz(fd, ws);
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) {
|
||||
ws = 0;
|
||||
rc = efault();
|
||||
} else if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (IsWindows()) {
|
||||
rc = tcgetwinsize_nt(g_fds.p + fd, ws);
|
||||
} else {
|
||||
rc = sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("tcgetwinsize(%d, [%s]) → %d% m", fd, DescribeWinsize(rc, ws), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,15 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/comms.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TCSBRK 0x5409 // linux
|
||||
#define TIOCSBRK 0x2000747b // bsd
|
||||
#define TIOCCBRK 0x2000747a // bsd
|
||||
|
||||
static int sys_tcsendbreak_bsd(int fd) {
|
||||
if (sys_ioctl(fd, TIOCSBRK, 0) == -1) return -1;
|
||||
usleep(400000);
|
||||
|
@ -55,14 +57,14 @@ static textwindows int sys_tcsendbreak_nt(int fd) {
|
|||
*/
|
||||
int tcsendbreak(int fd, int duration) {
|
||||
int rc;
|
||||
if (IsMetal()) {
|
||||
rc = enosys();
|
||||
if (IsLinux()) {
|
||||
rc = sys_ioctl(fd, TCSBRK, 0);
|
||||
} else if (IsBsd()) {
|
||||
rc = sys_tcsendbreak_bsd(fd);
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ioctl(fd, TCSBRK, 0);
|
||||
} else {
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_tcsendbreak_nt(fd);
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("tcsendbreak(%d, %u) → %d% m", fd, duration, rc);
|
||||
return rc;
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
||||
const struct termios *tio) {
|
||||
textwindows int tcsetattr_nt(int ignored, int opt, const struct termios *tio) {
|
||||
int64_t in, out;
|
||||
bool32 ok, inok, outok;
|
||||
uint32_t inmode, outmode;
|
||||
|
@ -39,7 +38,7 @@ textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
|||
if (inok | outok) {
|
||||
|
||||
if (inok) {
|
||||
if (request == TCSETSF) {
|
||||
if (opt == TCSAFLUSH) {
|
||||
FlushConsoleInputBuffer(in);
|
||||
}
|
||||
inmode &=
|
|
@ -16,11 +16,77 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define TCSETS 0x5402
|
||||
#define TCSETSW 0x5403
|
||||
#define TCSETSF 0x5404
|
||||
#define TIOCSETA 0x80487414
|
||||
#define TIOCSETAW 0x80487415
|
||||
#define TIOCSETAF 0x80487416
|
||||
|
||||
void __on_tcsetattr(int);
|
||||
int tcsetattr_nt(int, int, const struct termios *);
|
||||
|
||||
static const char *DescribeTcsa(char buf[12], int opt) {
|
||||
if (opt == TCSANOW) return "TCSANOW";
|
||||
if (opt == TCSADRAIN) return "TCSADRAIN";
|
||||
if (opt == TCSAFLUSH) return "TCSAFLUSH";
|
||||
FormatInt32(buf, opt);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int tcsetattr_impl(int fd, int opt, const struct termios *tio) {
|
||||
if (fd < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return enotty();
|
||||
}
|
||||
|
||||
if (0 <= fd && fd <= 2 && _weaken(__on_tcsetattr)) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
_weaken(__on_tcsetattr)(fd);
|
||||
once = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (IsMetal()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
return tcsetattr_nt(fd, opt, tio);
|
||||
}
|
||||
|
||||
if (IsLinux() || IsBsd()) {
|
||||
union metatermios mt;
|
||||
return sys_ioctl(fd, (IsLinux() ? TCSETS : TIOCSETA) + opt,
|
||||
__termios2host(&mt, tio));
|
||||
}
|
||||
|
||||
return enosys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets struct on teletypewriter w/ drains and flushes.
|
||||
*
|
||||
|
@ -32,15 +98,10 @@
|
|||
* @return 0 on success, -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int(tcsetattr)(int fd, int opt, const struct termios *tio) {
|
||||
switch (opt) {
|
||||
case TCSANOW:
|
||||
return ioctl(fd, TCSETS, (void *)tio);
|
||||
case TCSADRAIN:
|
||||
return ioctl(fd, TCSETSW, (void *)tio);
|
||||
case TCSAFLUSH:
|
||||
return ioctl(fd, TCSETSF, (void *)tio);
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
int tcsetattr(int fd, int opt, const struct termios *tio) {
|
||||
int rc;
|
||||
rc = tcsetattr_impl(fd, opt, tio);
|
||||
STRACE("tcsetattr(%d, %s, %p) → %d% m", fd, DescribeTcsa(alloca(12), opt),
|
||||
tio, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int ioctl_tiocswinsz_nt(int fd, const struct winsize *ws) {
|
||||
textwindows int tcsetwinsize_nt(int fd, const struct winsize *ws) {
|
||||
uint32_t mode;
|
||||
struct NtCoord coord;
|
||||
if (!ws) return efault();
|
|
@ -16,13 +16,37 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int tcsetwinsize_nt(int, const struct winsize *);
|
||||
|
||||
/**
|
||||
* Sets terminal window size attributes.
|
||||
*/
|
||||
int tcsetwinsize(int fd, const struct winsize *ws) {
|
||||
return ioctl_tiocswinsz(fd, ws);
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(ws, sizeof(*ws))) {
|
||||
rc = efault();
|
||||
} else if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = enotty();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_ioctl(fd, TIOCSWINSZ, ws);
|
||||
} else {
|
||||
rc = tcsetwinsize_nt(fd, ws);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("tcsetwinsize(%d, %s) → %d% m", fd, DescribeWinsize(rc, ws), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -3,28 +3,29 @@
|
|||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
|
||||
#define COPY_TERMIOS(TO, FROM) \
|
||||
do { \
|
||||
uint32_t Cc3; \
|
||||
uint64_t Cc1, Cc2; \
|
||||
autotype((TO)->c_iflag) c_iflag = (FROM)->c_iflag; \
|
||||
autotype((TO)->c_oflag) c_oflag = (FROM)->c_oflag; \
|
||||
autotype((TO)->c_cflag) c_cflag = (FROM)->c_cflag; \
|
||||
autotype((TO)->c_lflag) c_lflag = (FROM)->c_lflag; \
|
||||
__builtin_memcpy(&Cc1, (FROM)->c_cc + 000, 8); \
|
||||
__builtin_memcpy(&Cc2, (FROM)->c_cc + 010, 8); \
|
||||
__builtin_memcpy(&Cc3, (FROM)->c_cc + 020, 4); \
|
||||
autotype((TO)->c_ispeed) c_ispeed = (FROM)->c_ispeed; \
|
||||
autotype((TO)->c_ospeed) c_ospeed = (FROM)->c_ospeed; \
|
||||
(TO)->c_iflag = c_iflag; \
|
||||
(TO)->c_oflag = c_oflag; \
|
||||
(TO)->c_cflag = c_cflag; \
|
||||
(TO)->c_lflag = c_lflag; \
|
||||
__builtin_memcpy((TO)->c_cc + 000, &Cc1, 8); \
|
||||
__builtin_memcpy((TO)->c_cc + 010, &Cc2, 8); \
|
||||
__builtin_memcpy((TO)->c_cc + 020, &Cc3, 4); \
|
||||
(TO)->c_ispeed = c_ispeed; \
|
||||
(TO)->c_ospeed = c_ospeed; \
|
||||
#define COPY_TERMIOS(TO, FROM) \
|
||||
do { \
|
||||
uint32_t Cc3; \
|
||||
uint64_t Cc1, Cc2; \
|
||||
autotype((TO)->c_iflag) c_iflag = (FROM)->c_iflag; \
|
||||
autotype((TO)->c_oflag) c_oflag = (FROM)->c_oflag; \
|
||||
autotype((TO)->c_cflag) c_cflag = (FROM)->c_cflag; \
|
||||
autotype((TO)->c_lflag) c_lflag = (FROM)->c_lflag; \
|
||||
__builtin_memcpy(&Cc1, (FROM)->c_cc + 000, 8); \
|
||||
__builtin_memcpy(&Cc2, (FROM)->c_cc + 010, 8); \
|
||||
__builtin_memcpy(&Cc3, (FROM)->c_cc + 020, 4); \
|
||||
autotype((TO)->_c_ispeed) _c_ispeed = (FROM)->_c_ispeed; \
|
||||
autotype((TO)->_c_ospeed) _c_ospeed = (FROM)->_c_ospeed; \
|
||||
(TO)->c_iflag = c_iflag; \
|
||||
(TO)->c_oflag = c_oflag; \
|
||||
(TO)->c_cflag = c_cflag; \
|
||||
(TO)->c_lflag = c_lflag; \
|
||||
__builtin_memcpy((TO)->c_cc + 000, &Cc1, 8); \
|
||||
__builtin_memcpy((TO)->c_cc + 010, &Cc2, 8); \
|
||||
__builtin_memcpy((TO)->c_cc + 020, &Cc3, 4); \
|
||||
(TO)->_c_ispeed = _c_ispeed; \
|
||||
/* null c_ospeed causes bsd to hangup terminal */ \
|
||||
(TO)->_c_ospeed = _c_ospeed ? _c_ospeed : 9600; \
|
||||
} while (0)
|
||||
|
||||
void *__termios2host(union metatermios *, const struct termios *);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/dce.h"
|
||||
|
||||
void *__termios2host(union metatermios *mt, const struct termios *lt) {
|
||||
if (!IsXnu() && !IsFreebsd() && !IsOpenbsd() && !IsNetbsd()) {
|
||||
if (!IsBsd()) {
|
||||
return (/*unconst*/ void *)lt;
|
||||
} else if (IsXnu()) {
|
||||
COPY_TERMIOS(&mt->xnu, lt);
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define FIODGNAME 0x80106678 // freebsd
|
||||
|
||||
static textwindows dontinline int sys_ttyname_nt(int fd, char *buf,
|
||||
size_t size) {
|
||||
uint32_t mode;
|
||||
|
@ -49,7 +51,6 @@ static textwindows dontinline int sys_ttyname_nt(int fd, char *buf,
|
|||
}
|
||||
|
||||
static int ttyname_freebsd(int fd, char *buf, size_t size) {
|
||||
const unsigned FIODGNAME = 2148558456;
|
||||
struct fiodgname_arg {
|
||||
int len;
|
||||
void *buf;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/sysv/consts/pty.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
extern const uint32_t TIOCPTYUNLK;
|
||||
#define TIOCPTYUNLK 0x20007452
|
||||
|
||||
/**
|
||||
* Unlocks pseudoteletypewriter pair.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/elf/scalar.h"
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/elf/struct/phdr.h"
|
||||
|
@ -30,6 +31,13 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
// needed to avoid asan restrictions on strcmp
|
||||
static int StrCmp(const char *l, const char *r) {
|
||||
size_t i = 0;
|
||||
while (l[i] == r[i] && r[i]) ++i;
|
||||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
|
||||
const char *name, char *strtab) {
|
||||
Elf64_Verdaux *aux;
|
||||
|
@ -37,7 +45,7 @@ static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
|
|||
if (!(vd->vd_flags & VER_FLG_BASE) &&
|
||||
(vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) {
|
||||
aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux);
|
||||
return !strcmp(name, strtab + aux->vda_name);
|
||||
return !StrCmp(name, strtab + aux->vda_name);
|
||||
}
|
||||
if (!vd->vd_next) {
|
||||
return 0;
|
||||
|
@ -133,7 +141,7 @@ void *__vdsosym(const char *version, const char *name) {
|
|||
if (!symtab[i].st_shndx) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(name, strtab + symtab[i].st_name)) {
|
||||
if (StrCmp(name, strtab + symtab[i].st_name)) {
|
||||
continue;
|
||||
}
|
||||
if (versym && !CheckDsoSymbolVersion(verdef, versym[i], version, strtab)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue