mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
parent
956e68be59
commit
ac125d3e1f
4 changed files with 49 additions and 60 deletions
|
@ -16,8 +16,6 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
|
||||||
#include "libc/atomic.h"
|
|
||||||
#include "libc/calls/createfileflags.internal.h"
|
#include "libc/calls/createfileflags.internal.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
|
@ -29,14 +27,11 @@
|
||||||
#include "libc/cosmo.h"
|
#include "libc/cosmo.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/atomic.h"
|
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/dll.h"
|
#include "libc/intrin/dll.h"
|
||||||
#include "libc/intrin/nomultics.internal.h"
|
#include "libc/intrin/nomultics.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/intrin/weaken.h"
|
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/nt/console.h"
|
#include "libc/nt/console.h"
|
||||||
#include "libc/nt/createfile.h"
|
#include "libc/nt/createfile.h"
|
||||||
#include "libc/nt/enum/accessmask.h"
|
#include "libc/nt/enum/accessmask.h"
|
||||||
|
@ -51,6 +46,7 @@
|
||||||
#include "libc/nt/synchronization.h"
|
#include "libc/nt/synchronization.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/str/utf16.h"
|
#include "libc/str/utf16.h"
|
||||||
|
#include "libc/sysv/consts/limits.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/sicode.h"
|
#include "libc/sysv/consts/sicode.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
@ -134,7 +130,7 @@ struct Keystrokes {
|
||||||
bool end_of_file;
|
bool end_of_file;
|
||||||
bool ohno_decckm;
|
bool ohno_decckm;
|
||||||
uint16_t utf16hs;
|
uint16_t utf16hs;
|
||||||
atomic_int_fast16_t used;
|
int16_t freekeys;
|
||||||
int64_t cin, cot;
|
int64_t cin, cot;
|
||||||
struct Dll *list;
|
struct Dll *list;
|
||||||
struct Dll *line;
|
struct Dll *line;
|
||||||
|
@ -150,12 +146,42 @@ textwindows void __keystroke_wipe(void) {
|
||||||
bzero(&__keystroke, sizeof(__keystroke));
|
bzero(&__keystroke, sizeof(__keystroke));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static textwindows void FreeKeystrokeImpl(struct Dll *key) {
|
||||||
|
dll_make_first(&__keystroke.free, key);
|
||||||
|
++__keystroke.freekeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static textwindows struct Keystroke *NewKeystroke(void) {
|
||||||
|
struct Dll *e = dll_first(__keystroke.free);
|
||||||
|
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
|
||||||
|
dll_remove(&__keystroke.free, &k->elem);
|
||||||
|
--__keystroke.freekeys;
|
||||||
|
k->buflen = 0;
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
static textwindows void FreeKeystroke(struct Dll **list, struct Dll *key) {
|
||||||
|
dll_remove(list, key);
|
||||||
|
FreeKeystrokeImpl(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static textwindows void FreeKeystrokes(struct Dll **list) {
|
||||||
|
struct Dll *key;
|
||||||
|
while ((key = dll_first(*list))) {
|
||||||
|
FreeKeystroke(list, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static textwindows void OpenConsole(void) {
|
static textwindows void OpenConsole(void) {
|
||||||
__keystroke.vkt = kVirtualKey;
|
__keystroke.vkt = kVirtualKey;
|
||||||
__keystroke.cin = CreateFile(u"CONIN$", kNtGenericRead | kNtGenericWrite,
|
__keystroke.cin = CreateFile(u"CONIN$", kNtGenericRead | kNtGenericWrite,
|
||||||
kNtFileShareRead, 0, kNtOpenExisting, 0, 0);
|
kNtFileShareRead, 0, kNtOpenExisting, 0, 0);
|
||||||
__keystroke.cot = CreateFile(u"CONOUT$", kNtGenericRead | kNtGenericWrite,
|
__keystroke.cot = CreateFile(u"CONOUT$", kNtGenericRead | kNtGenericWrite,
|
||||||
kNtFileShareWrite, 0, kNtOpenExisting, 0, 0);
|
kNtFileShareWrite, 0, kNtOpenExisting, 0, 0);
|
||||||
|
for (int i = 0; i < ARRAYLEN(__keystroke.pool); ++i) {
|
||||||
|
dll_init(&__keystroke.pool[i].elem);
|
||||||
|
FreeKeystrokeImpl(&__keystroke.pool[i].elem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows int AddSignal(int sig) {
|
static textwindows int AddSignal(int sig) {
|
||||||
|
@ -413,34 +439,6 @@ static textwindows int ConvertConsoleInputToAnsi(const struct NtInputRecord *r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows struct Keystroke *NewKeystroke(void) {
|
|
||||||
struct Dll *e;
|
|
||||||
struct Keystroke *k = 0;
|
|
||||||
int i, n = ARRAYLEN(__keystroke.pool);
|
|
||||||
if (atomic_load_explicit(&__keystroke.used, memory_order_acquire) < n &&
|
|
||||||
(i = atomic_fetch_add(&__keystroke.used, 1)) < n) {
|
|
||||||
k = __keystroke.pool + i;
|
|
||||||
} else {
|
|
||||||
if ((e = dll_first(__keystroke.free))) {
|
|
||||||
k = KEYSTROKE_CONTAINER(e);
|
|
||||||
dll_remove(&__keystroke.free, &k->elem);
|
|
||||||
}
|
|
||||||
if (!k) {
|
|
||||||
if (_weaken(malloc)) {
|
|
||||||
k = _weaken(malloc)(sizeof(struct Keystroke));
|
|
||||||
} else {
|
|
||||||
enomem();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k) {
|
|
||||||
bzero(k, sizeof(*k));
|
|
||||||
dll_init(&k->elem);
|
|
||||||
}
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
static textwindows void WriteTty(const char *p, size_t n) {
|
static textwindows void WriteTty(const char *p, size_t n) {
|
||||||
WriteFile(__keystroke.cot, p, n, 0, 0);
|
WriteFile(__keystroke.cot, p, n, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -479,8 +477,7 @@ static textwindows bool EraseKeystroke(void) {
|
||||||
struct Dll *e;
|
struct Dll *e;
|
||||||
if ((e = dll_last(__keystroke.line))) {
|
if ((e = dll_last(__keystroke.line))) {
|
||||||
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
|
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
|
||||||
dll_remove(&__keystroke.line, e);
|
FreeKeystroke(&__keystroke.line, e);
|
||||||
dll_make_first(&__keystroke.free, e);
|
|
||||||
for (int i = k->buflen; i--;) {
|
for (int i = k->buflen; i--;) {
|
||||||
if ((k->buf[i] & 0300) == 0200) continue; // utf-8 cont
|
if ((k->buf[i] & 0300) == 0200) continue; // utf-8 cont
|
||||||
EraseCharacter();
|
EraseCharacter();
|
||||||
|
@ -521,11 +518,7 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate object to hold keystroke
|
// allocate object to hold keystroke
|
||||||
struct Keystroke *k;
|
struct Keystroke *k = NewKeystroke();
|
||||||
if (!(k = NewKeystroke())) {
|
|
||||||
STRACE("out of keystroke memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(k->buf, buf, sizeof(k->buf));
|
memcpy(k->buf, buf, sizeof(k->buf));
|
||||||
k->buflen = len;
|
k->buflen = len;
|
||||||
|
|
||||||
|
@ -541,11 +534,11 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
|
||||||
} else {
|
} else {
|
||||||
dll_make_last(&__keystroke.line, &k->elem);
|
dll_make_last(&__keystroke.line, &k->elem);
|
||||||
|
|
||||||
// handle enter in canonical mode
|
// flush canonical mode line if oom or enter
|
||||||
if (len == 1 && buf[0] &&
|
if (!__keystroke.freekeys || (len == 1 && buf[0] &&
|
||||||
((buf[0] & 255) == '\n' || //
|
((buf[0] & 255) == '\n' || //
|
||||||
(buf[0] & 255) == __ttyconf.veol || //
|
(buf[0] & 255) == __ttyconf.veol || //
|
||||||
(buf[0] & 255) == __ttyconf.veol2)) {
|
(buf[0] & 255) == __ttyconf.veol2))) {
|
||||||
dll_make_last(&__keystroke.list, __keystroke.line);
|
dll_make_last(&__keystroke.list, __keystroke.line);
|
||||||
__keystroke.line = 0;
|
__keystroke.line = 0;
|
||||||
}
|
}
|
||||||
|
@ -556,12 +549,13 @@ static textwindows void IngestConsoleInput(void) {
|
||||||
uint32_t i, n;
|
uint32_t i, n;
|
||||||
struct NtInputRecord records[16];
|
struct NtInputRecord records[16];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
if (!__keystroke.freekeys) return;
|
||||||
if (__keystroke.end_of_file) return;
|
if (__keystroke.end_of_file) return;
|
||||||
if (!GetNumberOfConsoleInputEvents(__keystroke.cin, &n)) {
|
if (!GetNumberOfConsoleInputEvents(__keystroke.cin, &n)) {
|
||||||
goto UnexpectedEof;
|
goto UnexpectedEof;
|
||||||
}
|
}
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
n = MIN(ARRAYLEN(records), n);
|
n = MIN(__keystroke.freekeys, MIN(ARRAYLEN(records), n));
|
||||||
if (!ReadConsoleInput(__keystroke.cin, records, n, &n)) {
|
if (!ReadConsoleInput(__keystroke.cin, records, n, &n)) {
|
||||||
goto UnexpectedEof;
|
goto UnexpectedEof;
|
||||||
}
|
}
|
||||||
|
@ -576,19 +570,15 @@ UnexpectedEof:
|
||||||
|
|
||||||
// Discards all unread stdin bytes.
|
// Discards all unread stdin bytes.
|
||||||
textwindows int FlushConsoleInputBytes(void) {
|
textwindows int FlushConsoleInputBytes(void) {
|
||||||
int rc;
|
|
||||||
BLOCK_SIGNALS;
|
BLOCK_SIGNALS;
|
||||||
InitConsole();
|
InitConsole();
|
||||||
LockKeystrokes();
|
LockKeystrokes();
|
||||||
FlushConsoleInputBuffer(__keystroke.cin);
|
FlushConsoleInputBuffer(__keystroke.cin);
|
||||||
dll_make_first(&__keystroke.free, __keystroke.list);
|
FreeKeystrokes(&__keystroke.list);
|
||||||
__keystroke.list = 0;
|
FreeKeystrokes(&__keystroke.line);
|
||||||
dll_make_first(&__keystroke.free, __keystroke.line);
|
|
||||||
__keystroke.line = 0;
|
|
||||||
rc = 0;
|
|
||||||
UnlockKeystrokes();
|
UnlockKeystrokes();
|
||||||
ALLOW_SIGNALS;
|
ALLOW_SIGNALS;
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns number of stdin bytes that may be read without blocking.
|
// Returns number of stdin bytes that may be read without blocking.
|
||||||
|
@ -700,11 +690,10 @@ static textwindows bool DigestConsoleInput(char *data, size_t size, int *rc) {
|
||||||
}
|
}
|
||||||
if (remain) {
|
if (remain) {
|
||||||
memmove(k->buf, k->buf + got, remain);
|
memmove(k->buf, k->buf + got, remain);
|
||||||
|
k->buflen = remain;
|
||||||
} else {
|
} else {
|
||||||
dll_remove(&__keystroke.list, e);
|
FreeKeystroke(&__keystroke.list, e);
|
||||||
dll_make_first(&__keystroke.free, e);
|
|
||||||
}
|
}
|
||||||
k->buflen = remain;
|
|
||||||
if ((__ttyconf.magic & kTtyUncanon) && toto >= __ttyconf.vmin) {
|
if ((__ttyconf.magic & kTtyUncanon) && toto >= __ttyconf.vmin) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
||||||
}
|
}
|
||||||
|
|
||||||
// intercept ansi tty configuration sequences
|
// intercept ansi tty configuration sequences
|
||||||
if (isconsole && _weaken(InterceptTerminalCommands)) {
|
if (isconsole && _weaken(GetConsoleOutputHandle)) {
|
||||||
_weaken(InterceptTerminalCommands)(data, size);
|
_weaken(InterceptTerminalCommands)(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ syscon mount MNT_SNAPSHOT 0 0 0x40000000 0x40000000 0x01000000 0 0
|
||||||
# limits
|
# limits
|
||||||
#
|
#
|
||||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||||
syscon limits PIPE_BUF 4096 4096 512 512 512 512 512 512 # bsd consensus
|
syscon limits PIPE_BUF 4096 4096 512 512 512 512 512 4096 # bsd consensus
|
||||||
syscon limits NGROUPS_MAX 65536 65536 16 16 1023 16 16 0 #
|
syscon limits NGROUPS_MAX 65536 65536 16 16 1023 16 16 0 #
|
||||||
syscon limits LINK_MAX 127 127 32767 32767 32767 32767 32767 64 # freebsd/windows are educated guesses
|
syscon limits LINK_MAX 127 127 32767 32767 32767 32767 32767 64 # freebsd/windows are educated guesses
|
||||||
syscon limits MAX_CANON 255 255 1024 1024 255 255 255 255 # windows is guessed
|
syscon limits MAX_CANON 255 255 1024 1024 255 255 255 255 # windows is guessed
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon limits,PIPE_BUF,4096,4096,512,512,512,512,512,512
|
.syscon limits,PIPE_BUF,4096,4096,512,512,512,512,512,4096
|
||||||
|
|
Loading…
Reference in a new issue