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:
Justine Tunney 2023-06-14 17:02:57 -07:00
parent 06b749ae03
commit 4778cd4d27
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
187 changed files with 1025 additions and 1848 deletions

View file

@ -201,8 +201,6 @@ include tool/build/lib/buildlib.mk
include third_party/chibicc/chibicc.mk
include third_party/chibicc/test/test.mk
include third_party/python/python.mk
include tool/build/emucrt/emucrt.mk
include tool/build/emubin/emubin.mk
include tool/build/build.mk
include tool/curl/curl.mk
include third_party/qemu/qemu.mk

View file

@ -356,6 +356,7 @@ SECTIONS {
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array))
KEEP(*(.dtors))
PROVIDE_HIDDEN(__fini_array_end = .);
@ -376,7 +377,7 @@ SECTIONS {
/* initialization image for thread-local storage, this is copied */
/* out to actual TLS areas at runtime, so just make it read-only */
.tdata . : {
.tdata : {
_tdata_start = .;
*(SORT_BY_ALIGNMENT(.tdata))
*(SORT_BY_ALIGNMENT(.tdata.*))
@ -387,7 +388,7 @@ SECTIONS {
/* this only tells the linker about the layout of uninitialized */
/* TLS data, and does not advance the linker's location counter */
.tbss . : {
.tbss : {
_tbss_start = .;
*(SORT_BY_ALIGNMENT(.tbss))
*(SORT_BY_ALIGNMENT(.tbss.*))

View file

@ -13,12 +13,14 @@
#
ifeq ($(MODE),)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
ifeq ($(MODE), aarch64)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
@ -31,11 +33,13 @@ endif
# - Better GDB debugging
#
ifeq ($(MODE), zero)
CONFIG_OFLAGS ?= -g
OVERRIDE_CFLAGS += -O0
OVERRIDE_CXXFLAGS += -O0
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
ifeq ($(MODE), aarch64-zero)
CONFIG_OFLAGS ?= -g
OVERRIDE_CFLAGS += -O0
OVERRIDE_CXXFLAGS += -O0
CONFIG_CPPFLAGS += -DSYSDEBUG
@ -55,7 +59,6 @@ ifeq ($(MODE), fastbuild)
ENABLE_FTRACE = 1
CONFIG_CCFLAGS += $(BACKTRACES) -O
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
CONFIG_OFLAGS += -g0
CONFIG_LDFLAGS += -S
TARGET_ARCH ?= -msse3
endif
@ -74,9 +77,10 @@ endif
#
ifeq ($(MODE), opt)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -msse2avx -Wa,-msse2avx
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
TARGET_ARCH ?= -march=native
TARGET_ARCH ?= -march=skylake
endif
# Optimized Linux Mode
@ -89,6 +93,7 @@ endif
# - Turns off support for other operating systems
#
ifeq ($(MODE), optlinux)
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DNDEBUG -msse2avx -Wa,-msse2avx -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
CONFIG_COPTS += -mred-zone
@ -103,6 +108,7 @@ endif
# - More optimized
# - Reasonably small
# - Numeric backtraces
# - No DWARF data bloat
# - Toilsome debuggability
# - assert() statements removed
# - DCHECK_xx() statements removed
@ -129,6 +135,7 @@ endif
#
ifeq ($(MODE), asan)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
CONFIG_COPTS += -fsanitize=address
TARGET_ARCH ?= -msse3
@ -147,6 +154,7 @@ endif
#
ifeq ($(MODE), dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DMODE_DBG
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
@ -156,6 +164,7 @@ QUOTA ?= -C64 -L300
endif
ifeq ($(MODE), aarch64-dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DMODE_DBG
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
CONFIG_COPTS += -fsanitize=undefined
@ -174,6 +183,7 @@ endif
#
ifeq ($(MODE), sysv)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
TARGET_ARCH ?= -msse3
@ -206,10 +216,6 @@ CONFIG_CCFLAGS += \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls \
-DDWARFLESS
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
@ -232,10 +238,6 @@ CONFIG_CCFLAGS += \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls \
-DDWARFLESS
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
PYFLAGS += \
-O2 \
-B
@ -261,10 +263,6 @@ CONFIG_CPPFLAGS += \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=1 \
-DDWARFLESS
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
CONFIG_CCFLAGS += \
-Os \
-fno-align-functions \
@ -296,10 +294,6 @@ CONFIG_CPPFLAGS += \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=113 \
-DDWARFLESS
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
CONFIG_CCFLAGS += \
-Os \
-fno-align-functions \
@ -336,10 +330,6 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
TARGET_ARCH ?= \
-msse3
endif
@ -370,37 +360,10 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
TARGET_ARCH ?= \
-msse3
endif
# GCC11 Mode
# https://justine.lol/compilers/x86_64-linux-musl__x86_64-linux-musl__g++-11.2.0.tar.xz
ifeq ($(MODE), gcc11)
ENABLE_FTRACE = 1
.UNVEIL += rx:/opt/gcc11
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
AS = /opt/gcc11/bin/x86_64-linux-musl-as
CC = /opt/gcc11/bin/x86_64-linux-musl-gcc
CXX = /opt/gcc11/bin/x86_64-linux-musl-g++
CXXFILT = /opt/gcc11/bin/x86_64-linux-musl-c++filt
LD = /opt/gcc11/bin/x86_64-linux-musl-ld.bfd
NM = /opt/gcc11/bin/x86_64-linux-musl-nm
GCC = /opt/gcc11/bin/x86_64-linux-musl-gcc
STRIP = /opt/gcc11/bin/x86_64-linux-musl-strip
OBJCOPY = /opt/gcc11/bin/x86_64-linux-musl-objcopy
OBJDUMP = /opt/gcc11/bin/x86_64-linux-musl-objdump
ADDR2LINE = /opt/gcc11/bin/x86_64-linux-musl-addr2line
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -Wno-stringop-overread
CONFIG_CFLAGS += -Wno-old-style-definition
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
# LLVM Mode
ifeq ($(MODE), llvm)
TARGET_ARCH ?= -msse3
@ -442,14 +405,11 @@ endif
# such as MSVC or XCode. You can run your binary objects through a tool
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
# rollup one header file that'll enable linkage with minimal issues.
ifeq ($(MODE), ansi)
CONFIG_CFLAGS += -std=c11
#CONFIG_CPPFLAGS += -ansi
CONFIG_CXXFLAGS += -std=c++11
TARGET_ARCH ?= -msse3
endif
ifneq ($(ENABLE_FTRACE),)

View file

@ -175,11 +175,6 @@ DEFAULT_CCFLAGS += \
-fdebug-prefix-map='$(PWD)'= \
-frecord-gcc-switches
DEFAULT_OFLAGS ?= \
-g \
-gdwarf-4 \
-gdescribe-dies
DEFAULT_COPTS ?= \
-fno-math-errno \
-fno-ident \
@ -246,7 +241,7 @@ DEFAULT_LDFLAGS = \
-nostdlib \
--gc-sections \
--build-id=none \
--no-dynamic-linker #--cref -Map=$@.map
--no-dynamic-linker --cref -Map=$@.map
ifeq ($(ARCH), aarch64)
DEFAULT_LDFLAGS += \

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsp/tty/tty.h"
#include "libc/intrin/pushpop.h"
#include "libc/dce.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"

View file

@ -355,7 +355,7 @@ int getCursorPosition(int64_t ifd, int64_t ofd, int *rows, int *cols) {
* Returns 0 on success, -1 on error. */
int getWindowSize(int64_t ifd, int64_t ofd, int *rows, int *cols) {
struct winsize ws;
if (_getttysize(1, &ws) == -1 || ws.ws_col == 0) {
if (tcgetwinsize(1, &ws) == -1 || ws.ws_col == 0) {
/* ioctl() failed. Try to query the terminal itself. */
int orig_row, orig_col, retval;

View file

@ -14,6 +14,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
@ -287,7 +288,7 @@ void GetTermSize(void) {
struct winsize wsize_;
wsize_.ws_row = 25;
wsize_.ws_col = 80;
_getttysize(0, &wsize_);
tcgetwinsize(0, &wsize_);
FreeSamplingSolution(ssy_);
FreeSamplingSolution(ssx_);
tyn_ = wsize_.ws_row * 2;

View file

@ -12,6 +12,7 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/log/check.h"
#include "libc/log/gdb.h"
@ -77,7 +78,7 @@ void GetTtySize(void) {
struct winsize wsize;
wsize.ws_row = tyn;
wsize.ws_col = txn;
_getttysize(1, &wsize);
tcgetwinsize(1, &wsize);
tyn = wsize.ws_row;
txn = wsize.ws_col;
}
@ -87,7 +88,7 @@ int Write(const char *s) {
}
void Setup(void) {
CHECK_NE(-1, ioctl(1, TCGETS, &oldterm));
CHECK_NE(-1, tcgetattr(1, &oldterm));
}
void Enter(void) {
@ -100,13 +101,13 @@ void Enter(void) {
term.c_cflag &= ~(CSIZE | PARENB);
term.c_cflag |= CS8;
term.c_iflag |= IUTF8;
CHECK_NE(-1, ioctl(1, TCSETS, &term));
CHECK_NE(-1, tcsetattr(1, TCSANOW, &term));
Write("\e[?25l");
}
void Leave(void) {
Write(gc(xasprintf("\e[?25h\e[%d;%dH\e[S\r\n", tyn, txn)));
ioctl(1, TCSETS, &oldterm);
tcsetattr(1, TCSANOW, &oldterm);
}
void Clear(void) {

View file

@ -177,7 +177,7 @@ main(int argc, char *argv[])
playback(fscript);
if (tcgetattr(STDIN_FILENO, &tt) == -1 ||
ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) {
tcgetwinsize(STDIN_FILENO, &win) == -1) {
if (errno != ENOTTY) /* For debugger. */
err(1, "tcgetattr/ioctl");
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)

View file

@ -48,14 +48,14 @@ void onkilled(int sig) {
void restoretty(void) {
WRITE(1, DISABLE_MOUSE_TRACKING);
ioctl(1, TCSETS, &oldterm);
tcsetattr(1, TCSANOW, &oldterm);
}
int rawmode(void) {
static bool once;
struct termios t;
if (!once) {
if (ioctl(1, TCGETS, &oldterm) != -1) {
if (tcgetattr(1, &oldterm) != -1) {
atexit(restoretty);
} else {
return -1;
@ -72,7 +72,7 @@ int rawmode(void) {
t.c_oflag &= ~OPOST;
t.c_cflag |= CS8;
t.c_iflag |= IUTF8;
ioctl(1, TCSETS, &t);
tcsetattr(1, TCSANOW, &t);
WRITE(1, ENABLE_SAFE_PASTE);
WRITE(1, ENABLE_MOUSE_TRACKING);
WRITE(1, PROBE_DISPLAY_SIZE);
@ -80,7 +80,7 @@ int rawmode(void) {
}
void getsize(void) {
if (_getttysize(1, &wsize) != -1) {
if (tcgetwinsize(1, &wsize) != -1) {
printf("termios says terminal size is %hu×%hu\r\n", wsize.ws_col,
wsize.ws_row);
} else {

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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);
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)) {

View file

@ -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"

View file

@ -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);

View file

@ -17,7 +17,9 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/log/internal.h"
#include "libc/runtime/runtime.h"
@ -36,7 +38,7 @@
#define ANSI_RESTORE RESET_COLOR SHOW_CURSOR DISABLE_MOUSE
static bool __isrestorable;
static union metatermios __oldtermios;
static struct termios __oldtermios;
static size_t __strlen(const char *s) {
size_t i = 0;
@ -44,11 +46,11 @@ static size_t __strlen(const char *s) {
return i;
}
// called weakly by libc/calls/ioctl_tcsets.c to avoid pledge("tty")
void __on_ioctl_tcsets(int fd) {
// called weakly by libc/calls/tcsetattr.c to avoid pledge("tty")
void __on_tcsetattr(int fd) {
int e;
e = errno;
if (sys_ioctl(fd, TCGETS, &__oldtermios) != -1) {
if (tcgetattr(fd, &__oldtermios) != -1) {
__isrestorable = true;
}
errno = e;
@ -59,7 +61,7 @@ void __restore_tty(void) {
if (__isrestorable && !__isworker && !__nocolor) {
e = errno;
sys_write(0, ANSI_RESTORE, __strlen(ANSI_RESTORE));
sys_ioctl(0, TCSETSF, &__oldtermios);
tcsetattr(0, TCSAFLUSH, &__oldtermios);
errno = e;
}
}

View file

@ -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) {

View file

@ -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 {

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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) */

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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];

View file

@ -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;
}

View file

@ -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;

View file

@ -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 &=

View file

@ -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;
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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 *);

View file

@ -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);

View file

@ -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;

View file

@ -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.

View file

@ -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)) {

View file

@ -21,7 +21,7 @@
#include "libc/dns/hoststxt.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"

View file

@ -19,7 +19,7 @@
#include "libc/dce.h"
#include "libc/dns/resolvconf.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"

View file

@ -6,10 +6,6 @@ COSMOPOLITAN_C_START_
#define CheckUnsigned(x) ((x) / !((typeof(x))(-1) < 0))
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits
*/
extern const uint8_t kReverseBits[256];
int _bitreverse8(int) libcesque pureconst;
@ -23,138 +19,96 @@ unsigned long _roundup2log(unsigned long) libcesque pureconst;
unsigned long _rounddown2pow(unsigned long) libcesque pureconst;
unsigned _bextra(const unsigned *, size_t, char);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits » no assembly required
*/
#define READ16LE(P) \
(__extension__({ \
uint16_t __x; \
__builtin_memcpy(&__x, P, 16 / 8); \
__x; \
}))
#ifdef __STRICT_ANSI__
#define READ16LE(S) ((255 & (S)[1]) << 8 | (255 & (S)[0]))
#define READ16BE(S) ((255 & (S)[0]) << 8 | (255 & (S)[1]))
#define READ32LE(S) \
((uint32_t)(255 & (S)[3]) << 030 | (uint32_t)(255 & (S)[2]) << 020 | \
(uint32_t)(255 & (S)[1]) << 010 | (uint32_t)(255 & (S)[0]) << 000)
#define READ32BE(S) \
((uint32_t)(255 & (S)[0]) << 030 | (uint32_t)(255 & (S)[1]) << 020 | \
(uint32_t)(255 & (S)[2]) << 010 | (uint32_t)(255 & (S)[3]) << 000)
#define READ64LE(S) \
((uint64_t)(255 & (S)[7]) << 070 | (uint64_t)(255 & (S)[6]) << 060 | \
(uint64_t)(255 & (S)[5]) << 050 | (uint64_t)(255 & (S)[4]) << 040 | \
(uint64_t)(255 & (S)[3]) << 030 | (uint64_t)(255 & (S)[2]) << 020 | \
(uint64_t)(255 & (S)[1]) << 010 | (uint64_t)(255 & (S)[0]) << 000)
#define READ64BE(S) \
((uint64_t)(255 & (S)[0]) << 070 | (uint64_t)(255 & (S)[1]) << 060 | \
(uint64_t)(255 & (S)[2]) << 050 | (uint64_t)(255 & (S)[3]) << 040 | \
(uint64_t)(255 & (S)[4]) << 030 | (uint64_t)(255 & (S)[5]) << 020 | \
(uint64_t)(255 & (S)[6]) << 010 | (uint64_t)(255 & (S)[7]) << 000)
#else /* gcc needs help knowing above are mov if s isn't a variable */
#define READ16LE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
Ptr[1] << 8 | Ptr[0]; \
})
#define READ16BE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
Ptr[0] << 8 | Ptr[1]; \
})
#define READ32LE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
((uint32_t)Ptr[3] << 030 | (uint32_t)Ptr[2] << 020 | \
(uint32_t)Ptr[1] << 010 | (uint32_t)Ptr[0] << 000); \
})
#define READ32BE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
((uint32_t)Ptr[0] << 030 | (uint32_t)Ptr[1] << 020 | \
(uint32_t)Ptr[2] << 010 | (uint32_t)Ptr[3] << 000); \
})
#define READ64LE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
((uint64_t)Ptr[7] << 070 | (uint64_t)Ptr[6] << 060 | \
(uint64_t)Ptr[5] << 050 | (uint64_t)Ptr[4] << 040 | \
(uint64_t)Ptr[3] << 030 | (uint64_t)Ptr[2] << 020 | \
(uint64_t)Ptr[1] << 010 | (uint64_t)Ptr[0] << 000); \
})
#define READ64BE(S) \
({ \
const uint8_t *Ptr = (const uint8_t *)(S); \
((uint64_t)Ptr[0] << 070 | (uint64_t)Ptr[1] << 060 | \
(uint64_t)Ptr[2] << 050 | (uint64_t)Ptr[3] << 040 | \
(uint64_t)Ptr[4] << 030 | (uint64_t)Ptr[5] << 020 | \
(uint64_t)Ptr[6] << 010 | (uint64_t)Ptr[7] << 000); \
})
#endif
#define READ16BE(P) \
(__extension__({ \
uint16_t __x; \
__builtin_memcpy(&__x, P, 16 / 8); \
__builtin_bswap16(__x); \
}))
#define WRITE16LE(P, V) \
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
(P)[1] = (0x000000000000FF00 & (V)) >> 010, (P) + 2)
#define WRITE16BE(P, V) \
((P)[0] = (0x000000000000FF00 & (V)) >> 010, \
(P)[1] = (0x00000000000000FF & (V)) >> 000, (P) + 2)
#define WRITE32LE(P, V) \
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
(P)[1] = (0x000000000000FF00 & (V)) >> 010, \
(P)[2] = (0x0000000000FF0000 & (V)) >> 020, \
(P)[3] = (0x00000000FF000000 & (V)) >> 030, (P) + 4)
#define WRITE32BE(P, V) \
((P)[0] = (0x00000000FF000000 & (V)) >> 030, \
(P)[1] = (0x0000000000FF0000 & (V)) >> 020, \
(P)[2] = (0x000000000000FF00 & (V)) >> 010, \
(P)[3] = (0x00000000000000FF & (V)) >> 000, (P) + 4)
#define WRITE64LE(P, V) \
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
(P)[1] = (0x000000000000FF00 & (V)) >> 010, \
(P)[2] = (0x0000000000FF0000 & (V)) >> 020, \
(P)[3] = (0x00000000FF000000 & (V)) >> 030, \
(P)[4] = (0x000000FF00000000 & (V)) >> 040, \
(P)[5] = (0x0000FF0000000000 & (V)) >> 050, \
(P)[6] = (0x00FF000000000000 & (V)) >> 060, \
(P)[7] = (0xFF00000000000000 & (V)) >> 070, (P) + 8)
#define WRITE64BE(P, V) \
((P)[0] = (0xFF00000000000000 & (V)) >> 070, \
(P)[1] = (0x00FF000000000000 & (V)) >> 060, \
(P)[2] = (0x0000FF0000000000 & (V)) >> 050, \
(P)[3] = (0x000000FF00000000 & (V)) >> 040, \
(P)[4] = (0x00000000FF000000 & (V)) >> 030, \
(P)[5] = (0x0000000000FF0000 & (V)) >> 020, \
(P)[6] = (0x000000000000FF00 & (V)) >> 010, \
(P)[7] = (0x00000000000000FF & (V)) >> 000, (P) + 8)
#define READ32LE(P) \
(__extension__({ \
uint32_t __x; \
__builtin_memcpy(&__x, P, 32 / 8); \
__x; \
}))
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits » some assembly required
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define READ32BE(P) \
(__extension__({ \
uint32_t __x; \
__builtin_memcpy(&__x, P, 32 / 8); \
__builtin_bswap32(__x); \
}))
#define lockinc(MEM) __ArithmeticOp1("lock inc", MEM)
#define lockdec(MEM) __ArithmeticOp1("lock dec", MEM)
#define locknot(MEM) __ArithmeticOp1("lock not", MEM)
#define lockneg(MEM) __ArithmeticOp1("lock neg", MEM)
#define READ64LE(P) \
(__extension__({ \
uint64_t __x; \
__builtin_memcpy(&__x, P, 64 / 8); \
__x; \
}))
#define lockaddeq(MEM, VAL) __ArithmeticOp2("lock add", VAL, MEM)
#define locksubeq(MEM, VAL) __ArithmeticOp2("lock sub", VAL, MEM)
#define lockxoreq(MEM, VAL) __ArithmeticOp2("lock xor", VAL, MEM)
#define lockandeq(MEM, VAL) __ArithmeticOp2("lock and", VAL, MEM)
#define lockoreq(MEM, VAL) __ArithmeticOp2("lock or", VAL, MEM)
#define READ64BE(P) \
(__extension__({ \
uint64_t __x; \
__builtin_memcpy(&__x, P, 64 / 8); \
__builtin_bswap64(__x); \
}))
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits » implementation details
*/
#define WRITE16LE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint16_t __x = (X); \
__builtin_memcpy(__p, &__x, 16 / 8); \
__p + 16 / 8; \
}))
#define __ArithmeticOp1(OP, MEM) \
({ \
asm(OP "%z0\t%0" : "+m"(*(MEM)) : /* no inputs */ : "cc"); \
MEM; \
})
#define WRITE16BE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint16_t __x = __builtin_bswap16(X); \
__builtin_memcpy(__p, &__x, 16 / 8); \
__p + 16 / 8; \
}))
#define __ArithmeticOp2(OP, VAL, MEM) \
({ \
asm(OP "%z0\t%1,%0" : "+m,m"(*(MEM)) : "i,r"(VAL) : "cc"); \
MEM; \
})
#define WRITE32LE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint32_t __x = (X); \
__builtin_memcpy(__p, &__x, 32 / 8); \
__p + 32 / 8; \
}))
#define WRITE32BE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint32_t __x = __builtin_bswap32(X); \
__builtin_memcpy(__p, &__x, 32 / 8); \
__p + 32 / 8; \
}))
#define WRITE64LE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint64_t __x = (X); \
__builtin_memcpy(__p, &__x, 64 / 8); \
__p + 64 / 8; \
}))
#define WRITE64BE(P, X) \
(__extension__({ \
__typeof__(&(P)[0]) __p = (P); \
uint64_t __x = __builtin_bswap64(X); \
__builtin_memcpy(__p, &__x, 64 / 8); \
__p + 64 / 8; \
}))
#endif /* __GNUC__ && !__STRICT_ANSI__ */
#endif /* COSMO */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -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,37 @@
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/syscall-sysv.internal.h"
#include "libc/calls/struct/winsize.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
int ioctl_tiocswinsz_nt(int, const struct winsize *);
#define N 64
/**
* Sets width and height of terminal.
*
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
*/
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 append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeWinsize)(char buf[N], int rc, struct winsize *ws) {
char b64[64];
const char *d;
int i, j, o = 0;
if (!ws) return "NULL";
if (rc == -1) return "n/a";
if ((!IsAsan() && kisdangerous(ws)) ||
(IsAsan() && !__asan_is_valid(ws, sizeof(*ws)))) {
ksnprintf(buf, N, "%p", ws);
return buf;
}
append("{.ws_row=%d, .ws_col=%d", ws->ws_row, ws->ws_col);
if (ws->ws_xpixel | ws->ws_ypixel) {
append(", .ws_xpixel=%d, .ws_ypixel=%d", ws->ws_xpixel, ws->ws_ypixel);
}
append("}");
return buf;
}

View file

@ -20,7 +20,7 @@
#include "libc/calls/state.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/extend.internal.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/nt/runtime.h"

View file

@ -31,10 +31,6 @@
.balign 4
.underrun
kOpenFlags:
.e O_RDWR,"RDWR" // order matters
.e O_RDONLY,"RDONLY" //
.e O_WRONLY,"WRONLY" //
.e O_ACCMODE,"ACCMODE" // mask of prev three
.e O_CREAT,"CREAT" //
.e O_EXCL,"EXCL" //
.e O_TRUNC,"TRUNC" //

View file

@ -4,7 +4,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#ifdef COSMO
#if !defined(__GNUC__) || defined(__STRICT_ANSI__) || !defined(__x86_64__)
#if !defined(__GNUC__) || defined(__STRICT_ANSI__) || !defined(__x86_64__) || \
!defined(__MNO_RED_ZONE__)
#define pushpop(x) (x)
#else
/**
@ -32,7 +33,8 @@
})
#endif
#if !defined(__GNUC__) || defined(__STRICT_ANSI__) || !defined(__x86_64__)
#if !defined(__GNUC__) || defined(__STRICT_ANSI__) || !defined(__x86_64__) || \
!defined(__MNO_RED_ZONE__)
#define pushmov(d, x) (*(d) = (x))
#else
#define pushmov(d, x) \

View file

@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/log/color.internal.h"

View file

@ -528,7 +528,7 @@ static int CloneLinux(int (*func)(void *arg, int rc), char *stk, size_t stksz,
/**
* Creates thread without malloc being linked.
*
* If you use clone() you're on you're own, e.g.
* If you use clone() you're on your own. Example:
*
* int worker(void *arg) { return 0; }
* struct CosmoTib tib = {.tib_self = &tib, .tib_tid = -1};

View file

@ -41,7 +41,7 @@ static bool IsMyDebugBinaryImpl(const char *path) {
// which is currently running in memory.
if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
(map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) {
if (READ32LE(map) == READ32LE("\177ELF") &&
if (READ32LE((char *)map) == READ32LE("\177ELF") &&
GetElfSymbolValue(map, "_etext", &value)) {
res = !_etext || value == (uintptr_t)_etext;
}

View file

@ -24,6 +24,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/internal.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
/**
* Modifies restrictions on virtual memory address range.
@ -37,13 +38,11 @@ int mprotect(void *addr, size_t size, int prot) {
int64_t rc;
if (prot &
~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_GROWSDOWN | PROT_GROWSUP)) {
errno = EINVAL; // unix checks prot before checking size
rc = -1;
rc = einval(); // unix checks prot before checking size
} else if (!size) {
return 0; // make new technology consistent with unix
} else if (UNLIKELY((intptr_t)addr & 4095)) {
errno = EINVAL; // unix checks prot before checking size
rc = -1;
rc = einval(); // unix checks prot before checking size
} else if (!IsWindows()) {
rc = sys_mprotect(addr, size, prot);
} else {

View file

@ -19,6 +19,7 @@
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
.privileged
@ -36,12 +37,12 @@ _OpenExecutable:
pushq __NR_open(%rip) // -0x08(%rbp)
pushq __NR_mmap(%rip) // -0x10(%rbp)
pushq __NR_munmap(%rip) // -0x18(%rbp)
pushq O_RDWR(%rip) // -0x20(%rbp)
pushq $O_RDWR // -0x20(%rbp)
pushq MAP_ANONYMOUS(%rip) // -0x28(%rbp)
pushq MAP_PRIVATE(%rip) // -0x30(%rbp)
pushq MAP_FIXED(%rip) // -0x38(%rbp)
pushq __NR_mprotect(%rip) // -0x40(%rbp)
pushq O_RDONLY(%rip) // -0x48(%rbp)
pushq $O_RDONLY // -0x48(%rbp)
push %rbx // code buffer
push %r12 // data buffer
push %r14 // filename

View file

@ -56,7 +56,7 @@ static struct SymbolTable *OpenSymbolTableImpl(const char *filename) {
if (filesize < 64) goto RaiseEnoexec;
elf = map = mmap(0, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) goto SystemError;
if (READ32LE(map) != READ32LE("\177ELF")) goto RaiseEnoexec;
if (READ32LE((char *)map) != READ32LE("\177ELF")) goto RaiseEnoexec;
if (!(name_base = GetStrtab(map, &m))) goto RaiseEnobufs;
if (!(symtab = GetSymtab(map, &n))) goto RaiseEnobufs;
tsz = 0;

View file

@ -162,9 +162,9 @@ textstartup void __printargs(const char *prologue) {
char **env;
sigset_t ss;
bool gotsome;
unsigned i, n;
int e, x, flags;
uintptr_t *auxp;
unsigned i, n, b;
struct rlimit rlim;
struct utsname uts;
struct sigaction sa;
@ -391,7 +391,7 @@ textstartup void __printargs(const char *prologue) {
PRINT("ARGUMENTS (%p)", __argv);
if (*__argv) {
for (i = 0; i < __argc; ++i) {
PRINT(" %p %s", __argv[i], __argv[i]);
PRINT(" %s", __argv[i]);
}
} else {
PRINT(" none");
@ -401,7 +401,7 @@ textstartup void __printargs(const char *prologue) {
PRINT("ENVIRONMENT (%p)", __envp);
if (*__envp) {
for (env = __envp; *env; ++env) {
PRINT(" %p %s", *env, *env);
PRINT(" %s", *env);
}
} else {
PRINT(" none");
@ -414,9 +414,9 @@ textstartup void __printargs(const char *prologue) {
for (auxp = __auxv; *auxp; auxp += 2) {
if ((auxinfo = DescribeAuxv(auxp[0]))) {
ksnprintf(u.path, sizeof(u.path), auxinfo->fmt, auxp[1]);
PRINT(" %p %16s[%4ld] = %s", auxp, auxinfo->name, auxp[0], u.path);
PRINT(" %16s[%4ld] = %s", auxinfo->name, auxp[0], u.path);
} else {
PRINT(" %p %16s[%4ld] = %014p", auxp, "unknown", auxp[0], auxp[1]);
PRINT(" %16s[%4ld] = %014p", "unknown", auxp[0], auxp[1]);
}
}
}
@ -558,63 +558,65 @@ textstartup void __printargs(const char *prologue) {
} else if ((termios.c_cflag & CSIZE) == CS8) {
kprintf(" CS8");
}
if ((termios.c_cflag & CBAUD) == B0) {
b = cfgetospeed(&termios);
if (b == B0) {
kprintf(" B0");
} else if ((termios.c_cflag & CBAUD) == B50) {
} else if (b == B50) {
kprintf(" B50");
} else if ((termios.c_cflag & CBAUD) == B75) {
} else if (b == B75) {
kprintf(" B75");
} else if ((termios.c_cflag & CBAUD) == B110) {
} else if (b == B110) {
kprintf(" B110");
} else if ((termios.c_cflag & CBAUD) == B134) {
} else if (b == B134) {
kprintf(" B134");
} else if ((termios.c_cflag & CBAUD) == B150) {
} else if (b == B150) {
kprintf(" B150");
} else if ((termios.c_cflag & CBAUD) == B200) {
} else if (b == B200) {
kprintf(" B200");
} else if ((termios.c_cflag & CBAUD) == B300) {
} else if (b == B300) {
kprintf(" B300");
} else if ((termios.c_cflag & CBAUD) == B600) {
} else if (b == B600) {
kprintf(" B600");
} else if ((termios.c_cflag & CBAUD) == B1200) {
} else if (b == B1200) {
kprintf(" B1200");
} else if ((termios.c_cflag & CBAUD) == B1800) {
} else if (b == B1800) {
kprintf(" B1800");
} else if ((termios.c_cflag & CBAUD) == B2400) {
} else if (b == B2400) {
kprintf(" B2400");
} else if ((termios.c_cflag & CBAUD) == B4800) {
} else if (b == B4800) {
kprintf(" B4800");
} else if ((termios.c_cflag & CBAUD) == B9600) {
} else if (b == B9600) {
kprintf(" B9600");
} else if ((termios.c_cflag & CBAUD) == B19200) {
} else if (b == B19200) {
kprintf(" B19200");
} else if ((termios.c_cflag & CBAUD) == B38400) {
} else if (b == B38400) {
kprintf(" B38400");
} else if ((termios.c_cflag & CBAUD) == B57600) {
} else if (b == B57600) {
kprintf(" B57600");
} else if ((termios.c_cflag & CBAUD) == B115200) {
} else if (b == B115200) {
kprintf(" B115200");
} else if ((termios.c_cflag & CBAUD) == B230400) {
} else if (b == B230400) {
kprintf(" B230400");
} else if ((termios.c_cflag & CBAUD) == B500000) {
} else if (b == B500000) {
kprintf(" B500000");
} else if ((termios.c_cflag & CBAUD) == B576000) {
} else if (b == B576000) {
kprintf(" B576000");
} else if ((termios.c_cflag & CBAUD) == B1000000) {
} else if (b == B1000000) {
kprintf(" B1000000");
} else if ((termios.c_cflag & CBAUD) == B1152000) {
} else if (b == B1152000) {
kprintf(" B1152000");
} else if ((termios.c_cflag & CBAUD) == B1500000) {
} else if (b == B1500000) {
kprintf(" B1500000");
} else if ((termios.c_cflag & CBAUD) == B2000000) {
} else if (b == B2000000) {
kprintf(" B2000000");
} else if ((termios.c_cflag & CBAUD) == B2500000) {
} else if (b == B2500000) {
kprintf(" B2500000");
} else if ((termios.c_cflag & CBAUD) == B3000000) {
} else if (b == B3000000) {
kprintf(" B3000000");
} else if ((termios.c_cflag & CBAUD) == B3500000) {
} else if (b == B3500000) {
kprintf(" B3500000");
} else if ((termios.c_cflag & CBAUD) == B4000000) {
} else if (b == B4000000) {
kprintf(" B4000000");
}
kprintf("\n");
@ -636,8 +638,8 @@ textstartup void __printargs(const char *prologue) {
if (termios.c_lflag & PENDIN) kprintf(" PENDIN");
if (termios.c_lflag & XCASE) kprintf(" XCASE");
kprintf("\n");
PRINT(" c_ispeed = %u", cfgetispeed(&termios));
PRINT(" c_ospeed = %u", cfgetospeed(&termios));
PRINT(" cfgetispeed() = %u", cfgetispeed(&termios));
PRINT(" cfgetospeed() = %u", cfgetospeed(&termios));
PRINT(" c_cc[VMIN] = %d", termios.c_cc[VMIN]);
PRINT(" c_cc[VTIME] = %d", termios.c_cc[VTIME]);
PRINT(" c_cc[VINTR] = CTRL-%c", CTRL(termios.c_cc[VINTR]));

View file

@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/mem.h"

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/bits.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/intrin/repmovsb.h"
#include "libc/nexgen32e/kompressor.h"
#include "libc/str/str.h"

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/str/locale.h"
#include "libc/str/str.h"
@ -28,12 +29,17 @@
* "You can have any locale you want as long as it's C." -- Henry Ford
*/
char *setlocale(int category, const char *locale) {
if (!locale || (*locale == '\0')) return "C";
if (!strcmp(locale, "C") || //
!strcmp(locale, "POSIX") || //
!strcmp(locale, "C.UTF-8")) {
return locale;
char *res;
if (!locale || (*locale == '\0')) {
res = "C";
} else if (!strcmp(locale, "C") || //
!strcmp(locale, "POSIX") || //
!strcmp(locale, "C.UTF-8") || //
!strcmp(locale, "en_US.UTF-8")) {
res = locale;
} else {
return NULL;
res = NULL;
}
STRACE("setlocale(%d, %#s) → %s", category, locale, res);
return res;
}

View file

@ -180,10 +180,7 @@ syscon compat SIGIOT 6 6 6 6 6 6 6 6 # PDP-11 feature; same
# open() flags
#
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD Windoze Commentary
syscon open O_RDONLY 0 0 0 0 0 0 0 0 # consensus
syscon open O_WRONLY 1 1 1 1 1 1 1 1 # consensus
syscon open O_RDWR 2 2 2 2 2 2 2 2 # consensus
syscon open O_ACCMODE 3 3 3 3 3 3 3 3 # O_RDONLY|O_WRONLY|O_RDWR
syscon open O_APPEND 0x00000400 0x00000400 8 8 8 8 8 0x00000400 # bsd consensus & kNtFileAppendData; won't pose issues w/ mknod(S_IFIFO) [SYNC libc/calls/open-nt.c]
syscon open O_CREAT 0x00000040 0x00000040 0x00000200 0x00000200 0x00000200 0x00000200 0x00000200 0x00000040 # bsd consensus & NT faked as Linux [SYNC libc/calls/open-nt.c]
syscon open O_EXCL 0x00000080 0x00000080 0x00000800 0x00000800 0x00000800 0x00000800 0x00000800 0x00000080 # bsd consensus & NT faked as Linux [SYNC libc/calls/open-nt.c]
@ -1324,29 +1321,11 @@ syscon sched SCHED_RESET_ON_FORK 0x40000000 0x40000000 0 0 0 0 0 0
# = TIOCSETA → About 3,110 results (0.41 seconds)
#
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon termios TCGETS 0x5401 0x5401 0x40487413 0x40487413 0x402c7413 0x402c7413 0x402c7413 0 # Gets console settings; tcgetattr(tty, argp) → ioctl(tty, TCGETS, struct termios *argp); polyfilled NT
syscon compat TIOCGETA 0x5401 0x5401 0x40487413 0x40487413 0x402c7413 0x402c7413 0x402c7413 0 # Gets console settings; = tcgetattr(tty, struct termios *argp)
#syscon compat TCGETA 0x5405 0x5405 0 0 0 0 0 0 # Gets console settings; ≈ ioctl(fd, TCGETA, struct termio *argp)
syscon termios TCSANOW 0 0 0 0 0 0 0 0 # Sets console settings; tcsetattr(fd, TCSANOW, argp); polyfilled NT
syscon termios TCSETS 0x5402 0x5402 0x80487414 0x80487414 0x802c7414 0x802c7414 0x802c7414 0x5402 # Sets console settings; = ioctl(tty, TCSETS, const struct termios *argp); polyfilled NT
syscon compat TIOCSETA 0x5402 0x5402 0x80487414 0x80487414 0x802c7414 0x802c7414 0x802c7414 0x5402 # Sets console settings; = ioctl(tty, TIOCSETA, const struct termios *argp); polyfilled NT
#syscon compat TCSETA 0x5402 0x5402 0x80487414 0x80487414 0x802c7414 0x802c7414 0x802c7414 0x5402 # Sets console settings; ≈ ioctl(tty, TCSETA, const struct termio *argp); polyfilled NT
syscon termios TCSADRAIN 1 1 1 1 1 1 1 1 # Drains output & sets console settings; tcsetawttr(fd, TCSADRAIN, argp); polyfilled NT
syscon termios TCSETSW 0x5403 0x5403 0x80487415 0x80487415 0x802c7415 0x802c7415 0x802c7415 0x5403 # Drains output & sets console settings; = ioctl(tty, TCSETSW, const struct termios *argp); polyfilled NT
syscon compat TIOCSETAW 0x5403 0x5403 0x80487415 0x80487415 0x802c7415 0x802c7415 0x802c7415 0x5403 # Drains output & sets console settings; = ioctl(tty, TIOCSETAW, const struct termios *argp); polyfilled NT
#syscon compat TCSETAW 0x5403 0x5403 0x80487415 0x80487415 0x802c7415 0x802c7415 0x802c7415 0x5403 # Drains output & sets console settings; ≈ ioctl(tty, TCSETAW, const struct termio *argp); polyfilled NT
syscon termios TCSAFLUSH 2 2 2 2 2 2 2 2 # Drops input & drains output & sets console settings; tcsetafttr(fd, TCSAFLUSH, argp); polyfilled NT
syscon termios TCSETSF 0x5404 0x5404 0x80487416 0x80487416 0x802c7416 0x802c7416 0x802c7416 0x5404 # Drops input & drains output & sets console settings; = ioctl(tty, TCSETSF, const struct termios *argp); polyfilled NT
syscon compat TIOCSETAF 0x5404 0x5404 0x80487416 0x80487416 0x802c7416 0x802c7416 0x802c7416 0x5402 # Drops input & drains output & sets console settings; = ioctl(tty, TIOCSETAF, const struct termios *argp); polyfilled NT
#syscon compat TCSETAF 0x5404 0x5404 0x80487416 0x80487416 0x802c7416 0x802c7416 0x802c7416 0x5402 # Drops input & drains output & sets console settings; ≈ ioctl(tty, TCSETAF, const struct termio *argp); polyfilled NT
syscon termios TIOCGWINSZ 0x5413 0x5413 1074295912 1074295912 1074295912 1074295912 1074295912 0x5413 # ioctl(tty, TIOCGWINSZ, struct winsize *argp); polyfilled NT
syscon termios TIOCSWINSZ 0x5414 0x5414 0x80087467 0x80087467 0x80087467 0x80087467 0x80087467 0x5414 # ioctl(tty, TIOCSWINSZ, const struct winsize *argp) (faked NT)
syscon termios TIOCINQ 0x541b 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f # [Linuxism] same as FIONREAD
syscon termios TIOCOUTQ 0x5411 0x5411 0x40047473 0x40047473 0x40047473 0x40047473 0x40047473 0 # get # bytes queued in TTY's output buffer ioctl(tty, TIOCSWINSZ, const struct winsize *argp)
syscon termios TIOCGPGRP 0x540f 0x540f 0x40047477 0x40047477 0x40047477 0x40047477 0x40047477 0 # tcgetpgrp(): get pgrp of tty
syscon termios TIOCSPGRP 0x5410 0x5410 0x80047476 0x80047476 0x80047476 0x80047476 0x80047476 0 # tcsetpgrp(): set pgrp of tty
syscon termios TIOCSBRK 0x5427 0x5427 0x2000747b 0x2000747b 0x2000747b 0x2000747b 0x2000747b 0 # set break bit
syscon termios TIOCCBRK 0x5428 0x5428 0x2000747a 0x2000747a 0x2000747a 0x2000747a 0x2000747a 0 # boop
syscon termios TIOCCONS 0x541d 0x541d 0x80047462 0x80047462 0x80047462 0x80047462 0x80047462 0 # boop
syscon termios TIOCGETD 0x5424 0x5424 0x4004741a 0x4004741a 0x4004741a 0x4004741a 0x4004741a 0 # boop
syscon termios TIOCNOTTY 0x5422 0x5422 0x20007471 0x20007471 0x20007471 0x20007471 0x20007471 0 # boop
@ -1354,44 +1333,7 @@ syscon termios TIOCNXCL 0x540d 0x540d 0x2000740e 0x2000740e 0x2000740e
syscon termios TIOCSCTTY 0x540e 0x540e 0x20007461 0x20007461 0x20007461 0x20007461 0x20007461 0 # makes terminal controlling terminal of calling process (see login_tty)
syscon termios TIOCSETD 0x5423 0x5423 0x8004741b 0x8004741b 0x8004741b 0x8004741b 0x8004741b 0 # boop
syscon termios TIOCSIG 0x40045436 0x40045436 0x2000745f 0x2000745f 0x2004745f 0x8004745f 0x8004745f 0 # boop
syscon termios TIOCSTI 0x5412 0x5412 0x80017472 0x80017472 0x80017472 0 0 0 # boop
syscon termios TIOCGSID 0x5429 0x5429 0x40047463 0x40047463 0x40047463 0x40047463 0x40047463 0 # boop
syscon termios TABLDISC 0 0 0x3 0x3 0 0x3 0x3 0 # boop
syscon termios SLIPDISC 0 0 0x4 0x4 0x4 0x4 0x4 0 # boop
syscon termios PPPDISC 0 0 0x5 0x5 0x5 0x5 0x5 0 # boop
syscon termios TCSBRK 0x5409 0x5409 0x2000745e 0x2000745e 0x2000745e 0x2000745e 0x2000745e 0 # TIOCDRAIN on BSD; TIOCDRAIN on BSD
syscon termios TIOCSTAT 0 0 0x20007465 0x20007465 0x20007465 0x20007465 0x20007465 0 # boop
syscon termios TIOCSTART 0 0 0x2000746e 0x2000746e 0x2000746e 0x2000746e 0x2000746e 0 # boop
syscon termios TIOCCDTR 0 0 0x20007478 0x20007478 0x20007478 0x20007478 0x20007478 0 # clear data terminal ready
syscon termios TIOCSDTR 0 0 0x20007479 0x20007479 0x20007479 0x20007479 0x20007479 0 # boop
syscon termios TIOCEXT 0 0 0x80047460 0x80047460 0x80047460 0x80047460 0x80047460 0 # boop
syscon termios TIOCGDRAINWAIT 0 0 0x40047456 0x40047456 0x40047456 0 0 0 # boop
syscon termios TIOCTIMESTAMP 0 0 0x40107459 0x40107459 0x40107459 0 0 0 # boop
syscon termios TIOCSDRAINWAIT 0 0 0x80047457 0x80047457 0x80047457 0 0 0 # boop
syscon termios TIOCREMOTE 0 0 0x80047469 0x80047469 0 0x80047469 0x80047469 0 # boop
syscon termios TTYDISC 0 0 0 0 0 0 0 0 # boop
syscon termios TIOCFLAG_SOFTCAR 0 0 0 0 0 0x1 0x1 0 # boop
syscon termios TIOCFLAG_PPS 0 0 0 0 0 0x10 0x10 0 # boop
syscon termios TIOCFLAG_CLOCAL 0 0 0 0 0 0x2 0x2 0 # boop
syscon termios TIOCCHKVERAUTH 0 0 0 0 0 0x2000741e 0x2000741e 0 # boop
syscon termios TIOCGFLAGS 0 0 0 0 0 0x4004745d 0x4004745d 0 # boop
syscon termios TIOCGTSTAMP 0 0 0 0 0 0x4010745b 0x4010745b 0 # boop
syscon termios STRIPDISC 0 0 0 0 0 0x6 0x6 0 # boop
syscon termios NMEADISC 0 0 0 0 0 0x7 0x7 0 # boop
syscon termios TIOCUCNTL_CBRK 0 0 0 0 0 0x7a 0x7a 0 # boop
syscon termios TIOCFLAG_MDMBUF 0 0 0 0 0 0x8 0x8 0 # boop
syscon termios TIOCSETVERAUTH 0 0 0 0 0 0x8004741c 0x8004741c 0 # boop
syscon termios TIOCSFLAGS 0 0 0 0 0 0x8004745c 0x8004745c 0 # boop
syscon termios TIOCSTSTAMP 0 0 0 0 0 0x8008745a 0x8008745a 0 # boop
syscon termios ENDRUNDISC 0 0 0 0 0 0x9 0x9 0 # boop
syscon termios TIOCPTMASTER 0 0 0 0 0x2000741c 0 0 0 # boop
syscon termios TIOCPTYGRANT 0 0 0x20007454 0x20007454 0 0 0 0 # xnu grantpt()
syscon termios TIOCPTYUNLK 0 0 0x20007452 0x20007452 0 0 0 0 # xnu unlockpt()
syscon termios TIOCPTYGNAME 0 0 0x40807453 0x40807453 0 0 0 0 # xnu ptyname()
syscon termios TIOCPTSNAME 0 0 0 0 0 0 0x48087448 0 # netbsd ptyname()
syscon termios FIODGNAME 0 0 0 0 0x80106678 0 0 0 # freebsd ptsname_r()
syscon termios NETGRAPHDISC 0 0 0 0 0x6 0 0 0 # boop
syscon termios H4DISC 0 0 0 0 0x7 0 0 0 # boop
syscon termios TIOCSTI 0x5412 0x5412 0x80017472 0x80017472 0x80017472 0 0x80017472 0 # boop
# Teletypewriter Control Modes
#
@ -1406,7 +1348,9 @@ syscon termios CREAD 0b0000000010000000 0b0000000010000000 0b000000100000000
syscon termios PARENB 0b0000000100000000 0b0000000100000000 0b000001000000000000 0b000001000000000000 0b000001000000000000 0b0001000000000000 0b0001000000000000 0b0000000100000000 # termios.c_cflag
syscon termios PARODD 0b0000001000000000 0b0000001000000000 0b000010000000000000 0b000010000000000000 0b000010000000000000 0b0010000000000000 0b0010000000000000 0b0000001000000000 # termios.c_cflag
syscon termios HUPCL 0b0000010000000000 0b0000010000000000 0b000100000000000000 0b000100000000000000 0b000100000000000000 0b0100000000000000 0b0100000000000000 0b0000010000000000 # termios.c_cflag; bsd consensus
syscon termios CLOCAL 0b0000100000000000 0b0000100000000000 0b1000000000000000 0b1000000000000000 0b1000000000000000 0b1000000000000000 0b1000000000000000 0b0000100000000000 # termios.c_cflag; consensus
syscon termios CLOCAL 0b0000100000000000 0b0000100000000000 0b001000000000000000 0b001000000000000000 0b001000000000000000 0b1000000000000000 0b1000000000000000 0b0000100000000000 # termios.c_cflag; consensus
syscon termios CMSPAR 0x40000000 0x40000000 0 0 0 0 0 0 # termios.c_cflag; not in POSIX
syscon termios CRTSCTS 0x80000000 0x80000000 0x00030000 0x00030000 0x00030000 0x00010000 0x00010000 0x80000000 # termios.c_cflag
# Teletypewriter Local Modes
#
@ -1459,29 +1403,23 @@ syscon termios ONLRET 0b0000000000100000 0b0000000000100000 0b00000000000100
syscon termios OFILL 0b0000000001000000 0b0000000001000000 0b000000000010000000 0b000000000010000000 0 0 0 0b0000000001000000 # termios.c_oflag
syscon termios OFDEL 0b0000000010000000 0b0000000010000000 0b100000000000000000 0b100000000000000000 0 0 0 0b0000000010000000 # termios.c_oflag
syscon termios NLDLY 0b0000000100000000 0b0000000100000000 0b000000001100000000 0b000000001100000000 0b000000001100000000 0 0 0b0000000100000000 # (termios.c_oflag & NLDLY) ∈ {NL0,NL1,NL2,NL3}
syscon termios NL0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0b000000000000000000 0b0000000000000000 # (termios.c_oflag & NLDLY) == NL0
syscon termios NL1 0b0000000100000000 0b0000000100000000 0b000000000100000000 0b000000000100000000 0b000000000100000000 0 0b000000000100000000 0b0000000100000000 # (termios.c_oflag & NLDLY) == NL1
syscon termios NL2 0 0 0b000000001000000000 0b000000001000000000 0b000000001000000000 0 0b000000001000000000 0 # (termios.c_oflag & NLDLY) == NL2
syscon termios NL3 0 0 0b000000001100000000 0b000000001100000000 0b000000001100000000 0 0b000000001100000000 0 # (termios.c_oflag & NLDLY) == NL3
syscon termios CRDLY 0b0000011000000000 0b0000011000000000 0b000011000000000000 0b000011000000000000 0b000011000000000000 0 0 0b0000011000000000 # (termios.c_oflag & CRDLY) ∈ {CR0,CR1,CR2,CR3}
syscon termios CR0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0b000000000000000000 0b0000000000000000 # (termios.c_oflag & CRDLY) == CR0
syscon termios CR1 0b0000001000000000 0b0000001000000000 0b000001000000000000 0b000001000000000000 0b000001000000000000 0 0b000001000000000000 0b0000001000000000 # (termios.c_oflag & CRDLY) == CR1
syscon termios CR2 0b0000010000000000 0b0000010000000000 0b000010000000000000 0b000010000000000000 0b000010000000000000 0 0b000000010000000000 0b0000010000000000 # (termios.c_oflag & CRDLY) == CR2
syscon termios CR3 0b0000011000000000 0b0000011000000000 0b000011000000000000 0b000011000000000000 0b000011000000000000 0 0b000000011000000000 0b0000011000000000 # (termios.c_oflag & CRDLY) == CR3
syscon termios TABDLY 0b0001100000000000 0b0001100000000000 0b000000110000000100 0b000000110000000100 0b000000000000000100 0 0 0b0001100000000000 # (termios.c_oflag & TABDLY) ∈ {TAB0,TAB1,TAB2,TAB3,XTABS}
syscon termios TAB0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0b000000000000000000 0b0000000000000000 # (termios.c_oflag & TABDLY) == TAB0
syscon termios TAB1 0b0000100000000000 0b0000100000000000 0b000000010000000000 0b000000010000000000 0b000000010000000000 0 0b000000010000000000 0b0000100000000000 # (termios.c_oflag & TABDLY) == TAB1
syscon termios TAB2 0b0001000000000000 0b0001000000000000 0b000000100000000000 0b000000100000000000 0b000000100000000000 0 0b000000100000000000 0b0001000000000000 # (termios.c_oflag & TABDLY) == TAB2
syscon termios TAB3 0b0001100000000000 0b0001100000000000 0b000000000000000100 0b000000000000000100 0b000000000000000100 0 0b000000000000000100 0b0001100000000000 # (termios.c_oflag & TABDLY) == TAB3
syscon termios XTABS 0b0001100000000000 0b0001100000000000 0b000000110000000000 0b000000110000000000 0b000000110000000000 0 0b000000110000000000 0b0001100000000000 # (termios.c_oflag & TABDLY) == XTABS
syscon termios BSDLY 0b0010000000000000 0b0010000000000000 0b001000000000000000 0b001000000000000000 0b001000000000000000 0 0 0b0010000000000000 # termios.c_oflag
syscon termios BS0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0 0b0000000000000000 # termios.c_oflag
syscon termios BS1 0b0010000000000000 0b0010000000000000 0b001000000000000000 0b001000000000000000 0b001000000000000000 0 0 0b0010000000000000 # termios.c_oflag
syscon termios VTDLY 0b0100000000000000 0b0100000000000000 0b010000000000000000 0b010000000000000000 0b010000000000000000 0 0 0b0100000000000000 # termios.c_oflag
syscon termios VT0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0 0b0000000000000000 # termios.c_oflag
syscon termios VT1 0b0100000000000000 0b0100000000000000 0b010000000000000000 0b010000000000000000 0b010000000000000000 0 0 0b0100000000000000 # termios.c_oflag
syscon termios FFDLY 0b1000000000000000 0b1000000000000000 0b000100000000000000 0b000100000000000000 0b000100000000000000 0 0 0b1000000000000000 # termios.c_oflag
syscon termios FF0 0b0000000000000000 0b0000000000000000 0b000000000000000000 0b000000000000000000 0b000000000000000000 0 0 0b0000000000000000 # termios.c_oflag
syscon termios FF1 0b1000000000000000 0b1000000000000000 0b000100000000000000 0b000100000000000000 0b000100000000000000 0 0 0b1000000000000000 # termios.c_oflag
# Teletypewriter Special Control Character Assignments
@ -1489,7 +1427,6 @@ syscon termios FF1 0b1000000000000000 0b1000000000000000 0b000100000000000
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon termios VMIN 6+1 6+1 16 16 16 16 16 6 # termios.c_cc[VMIN]=𝑥 in non-canonical mode can be set to 0 for non-blocking reads, 1 for single character raw mode reads, or higher to buffer
syscon termios VTIME 5+1 5+1 17 17 17 17 17 5 # termios.c_cc[VTIME]=𝑥 sets non-canonical read timeout to 𝑥×𝟷𝟶𝟶ms which is needed when entering escape sequences manually with the escape key
syscon termios NCCS 20 20 20 20 20 20 20 20 # ARRAYLEN(termios.c_cc); we schlep c_line into c_cc on linux
syscon termios VINTR 0+1 0+1 8 8 8 8 8 0 # termios.c_cc[VINTR]=𝑥
syscon termios VQUIT 1+1 1+1 9 9 9 9 9 1 # termios.c_cc[VQUIT]=𝑥
syscon termios VERASE 2+1 2+1 3 3 3 3 3 2 # termios.c_cc[VERASE]=𝑥
@ -1505,35 +1442,11 @@ syscon termios VDISCARD 13+1 13+1 15 15 15 15 15 13 # termios
syscon termios VWERASE 14+1 14+1 4 4 4 4 4 14 # termios.c_cc[VWERASE]=𝑥
syscon termios VLNEXT 15+1 15+1 14 14 14 14 14 15 # termios.c_cc[VLNEXT]=𝑥
syscon termios VEOL2 16+1 16+1 2 2 2 2 2 16 # termios.c_cc[VEOL2]=𝑥
syscon termios _POSIX_VDISABLE 0 0 255 255 255 255 255 0 # termios.c_cc tombstone value
syscon termios TIOCSERGETLSR 0x5459 0x5459 0 0 0 0 0 0 #
syscon termios TIOCSERGETMULTI 0x545a 0x545a 0 0 0 0 0 0 #
syscon termios TIOCSERSETMULTI 0x545b 0x545b 0 0 0 0 0 0 #
syscon termios TIOCSER_TEMT 1 1 0 0 0 0 0 0 #
syscon termios VERIFY 47 47 0 0 0 0 0 0
syscon termios CIBAUD 0x100f0000 0x100f0000 0 0 0 0 0 0
syscon termios CMSPAR 0x40000000 0x40000000 0 0 0 0 0 0
syscon termios BUSY 4 4 0 0 0 0 0 0
syscon termios CBAUD 0x100f 0x100f 0 0 0 0 0 0
syscon termios CBAUDEX 0x1000 0x1000 0 0 0 0 0 0
syscon termios EXTA 14 14 0x4b00 0x4b00 0x4b00 0x4b00 0x4b00 0 # bsd consensus
syscon termios EXTB 15 15 0x9600 0x9600 0x9600 0x9600 0x9600 0 # bsd consensus
syscon termios ERA 0x02002c 0x02002c 45 45 45 0 0 0
syscon termios EMPTY 0 0 0 0 0 0 0 0 # consensus
syscon termios TCFLSH 0x540b 0x540b 0x80047410 0x80047410 0x80047410 0x80047410 0x80047410 0 # see tcflush; TIOCFLUSH on BSD
syscon termios TIOCFLUSH 0x540b 0x540b 0x80047410 0x80047410 0x80047410 0x80047410 0x80047410 0 # see tcflush; TCFLSH on Linux
syscon termios TCIFLUSH 0 0 1 1 1 1 1 0 # see tcflush; bsd consensus; faked nt
syscon termios TCOFLUSH 1 1 2 2 2 2 2 1 # see tcflush; bsd consensus; faked nt
syscon termios TCIOFLUSH 2 2 3 3 3 3 3 2 # see tcflush; bsd consensus; faked nt
syscon termios TCXONC 0x540A 0x540A 0 0 0 0 0 0 # see tcflow
syscon termios TIOCSTOP 0x540A 0x540A 0x2000746f 0x2000746f 0x2000746f 0x2000746f 0x2000746f 0 # see tcflow
syscon termios TIOCSTART 0x540A 0x540A 0x2000746e 0x2000746e 0x2000746e 0x2000746e 0x2000746e 0 # see tcflow
syscon termios TCOOFF 0 0 1 1 1 1 1 0 # see tcflow; bsd consensus
syscon termios TCOON 1 1 2 2 2 2 2 1 # see tcflow; bsd consensus
syscon termios TCIOFF 2 2 3 3 3 3 3 2 # see tcflow; bsd consensus
syscon termios TCION 3 3 4 4 4 4 4 3 # see tcflow; bsd consensus
syscon termios TCIFLUSH 0 0 1 1 1 1 1 0 # see tcflush; FREAD on BSD; faked nt
syscon termios TCOFLUSH 1 1 2 2 2 2 2 1 # see tcflush; FWRITE on BSD; faked nt
syscon termios TCIOFLUSH 2 2 3 3 3 3 3 2 # see tcflush; FREAD|FWRITE on BSD; faked nt
syscon termios CSTART 17 17 17 17 17 17 17 0 # unix consensus
syscon termios CSTOP 19 19 19 19 19 19 19 0 # unix consensus
@ -1552,7 +1465,6 @@ syscon pty TIOCPKT_START 8 8 8 8 8 8 8 8 # unix consensus
syscon pty TIOCPKT_NOSTOP 16 16 16 16 16 16 16 16 # unix consensus
syscon pty TIOCPKT_DOSTOP 32 32 32 32 32 32 32 32 # unix consensus
syscon pty TIOCPKT_IOCTL 64 64 64 64 64 64 64 64 # unix consensus
syscon pty PTMGET 0 0 0 0 0 0x40287401 0x40287401 -1 # for /dev/ptm
# Modem Control
#

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,BS0,0b0000000000000000,0b0000000000000000,0b000000000000000000,0b000000000000000000,0b000000000000000000,0,0,0b0000000000000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,BUSY,4,4,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CBAUD,0x100f,0x100f,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CBAUDEX,0x1000,0x1000,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CIBAUD,0x100f0000,0x100f0000,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CLOCAL,0b0000100000000000,0b0000100000000000,0b1000000000000000,0b1000000000000000,0b1000000000000000,0b1000000000000000,0b1000000000000000,0b0000100000000000
.syscon termios,CLOCAL,0b0000100000000000,0b0000100000000000,0b001000000000000000,0b001000000000000000,0b001000000000000000,0b1000000000000000,0b1000000000000000,0b0000100000000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CR0,0b0000000000000000,0b0000000000000000,0b000000000000000000,0b000000000000000000,0b000000000000000000,0,0b000000000000000000,0b0000000000000000

View file

@ -0,0 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,CRTSCTS,0x80000000,0x80000000,0x00030000,0x00030000,0x00030000,0x00010000,0x00010000,0x80000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,EMPTY,0,0,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,ENDRUNDISC,0,0,0,0,0,0x9,0x9,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,ERA,0x02002c,0x02002c,45,45,45,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,EXTA,14,14,0x4b00,0x4b00,0x4b00,0x4b00,0x4b00,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,EXTB,15,15,0x9600,0x9600,0x9600,0x9600,0x9600,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,FF0,0b0000000000000000,0b0000000000000000,0b000000000000000000,0b000000000000000000,0b000000000000000000,0,0,0b0000000000000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,FIODGNAME,0,0,0,0,0x80106678,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,H4DISC,0,0,0,0,0x7,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,NCCS,20,20,20,20,20,20,20,20

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,NETGRAPHDISC,0,0,0,0,0x6,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,NL0,0b0000000000000000,0b0000000000000000,0b000000000000000000,0b000000000000000000,0b000000000000000000,0,0b000000000000000000,0b0000000000000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,NMEADISC,0,0,0,0,0,0x7,0x7,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon open,O_ACCMODE,3,3,3,3,3,3,3,3

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon open,O_RDONLY,0,0,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon open,O_WRONLY,1,1,1,1,1,1,1,1

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,PPPDISC,0,0,0x5,0x5,0x5,0x5,0x5,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon pty,PTMGET,0,0,0,0,0,0x40287401,0x40287401,-1

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,SLIPDISC,0,0,0x4,0x4,0x4,0x4,0x4,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,STRIPDISC,0,0,0,0,0,0x6,0x6,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TAB0,0b0000000000000000,0b0000000000000000,0b000000000000000000,0b000000000000000000,0b000000000000000000,0,0b000000000000000000,0b0000000000000000

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TABLDISC,0,0,0x3,0x3,0,0x3,0x3,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TCFLSH,0x540b,0x540b,0x80047410,0x80047410,0x80047410,0x80047410,0x80047410,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TCGETS,0x5401,0x5401,0x40487413,0x40487413,0x402c7413,0x402c7413,0x402c7413,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TCIOFF,2,2,3,3,3,3,3,2

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,TCION,3,3,4,4,4,4,4,3

Some files were not shown because too many files have changed in this diff Show more