Make improvements

- Polyfill readlink("foo/") dir check on Windows
- Support asynchronous signal delivery on Windows
- Restore Windows Console from execve() daisy chain
- Work around bug in AARCH64 Optimized Routines memcmp()
- Disable unbourne.com shell completion on Windows for now
- Don't always set virtual terminal input state on console
- Remove Musl Libc's unusual preservation of realpath("//")
- Make realpath() strongly link malloc() to pass configure test
- Delete cosh.com shell, now that unbourne.com works on Windows!
This commit is contained in:
Justine Tunney 2023-09-06 22:39:36 -07:00
parent f9c9a323fe
commit 425c055116
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
40 changed files with 581 additions and 706 deletions

View file

@ -1,47 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2022 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/macros.internal.h"
.text.windows
// Used by clone() on Windows to launch thread.
//
// Windows owns the stack memory when we initially enter threads.
// This function switches us over, so that we can start using the
// runtime facilities.
//
// @param %rdi is arg
// @param %rsi is tid
// @param %rdx is func
// @param %rcx is stack
// @return %rax is exit code
// @see clone()
WinThreadLaunch:
push %rbx
push %r15
mov %rbp,%r15
mov %rsp,%rbx
mov %rcx,%rsp
xor %rbp,%rbp
call *%rdx
mov %r15,%rbp
mov %rbx,%rsp
pop %r15
pop %rbx
ret
.endfn WinThreadLaunch,globl,hidden

View file

@ -40,8 +40,6 @@
extern unsigned char __tls_mov_nt_rax[];
extern unsigned char __tls_add_nt_rax[];
struct Dll *_pthread_list;
pthread_spinlock_t _pthread_lock;
static struct PosixThread _pthread_main;
_Alignas(TLS_ALIGNMENT) static char __static_tls[6016];

View file

@ -68,7 +68,7 @@
__static_yoink("_check_sigchld");
extern int64_t __wincrashearly;
bool32 __onntconsoleevent_nt(uint32_t);
bool32 __onntconsoleevent(uint32_t);
void sys_setitimer_nt_reset(void);
void kmalloc_unlock(void);
@ -308,8 +308,8 @@ textwindows void WinMainForked(void) {
}
AddVectoredExceptionHandler(1, (void *)_weaken(__wincrash_nt));
}
if (_weaken(__onntconsoleevent_nt)) {
SetConsoleCtrlHandler(_weaken(__onntconsoleevent_nt), 1);
if (_weaken(__onntconsoleevent)) {
SetConsoleCtrlHandler(_weaken(__onntconsoleevent), 1);
}
// jump back into function below

View file

@ -53,6 +53,7 @@
#include "libc/runtime/stack.h"
#include "libc/runtime/winargs.internal.h"
#include "libc/sock/internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/prot.h"
#ifdef __x86_64__
@ -66,6 +67,7 @@ __msabi extern typeof(GetConsoleMode) *const __imp_GetConsoleMode;
__msabi extern typeof(GetCurrentProcess) *const __imp_GetCurrentProcess;
__msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId;
__msabi extern typeof(GetEnvironmentStrings) *const __imp_GetEnvironmentStringsW;
__msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
__msabi extern typeof(SetConsoleCP) *const __imp_SetConsoleCP;
@ -73,7 +75,6 @@ __msabi extern typeof(SetConsoleMode) *const __imp_SetConsoleMode;
__msabi extern typeof(SetConsoleOutputCP) *const __imp_SetConsoleOutputCP;
__msabi extern typeof(SetStdHandle) *const __imp_SetStdHandle;
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
// clang-format on
extern void cosmo(int, char **, char **, long (*)[2]) wontreturn;
@ -84,20 +85,6 @@ static const signed char kNtStdio[3] = {
(signed char)kNtStdErrorHandle,
};
static const short kConsoleModes[3] = {
kNtEnableProcessedInput | kNtEnableLineInput | kNtEnableEchoInput |
kNtEnableMouseInput | kNtEnableQuickEditMode | kNtEnableExtendedFlags |
kNtEnableAutoPosition | kNtEnableInsertMode |
kNtEnableVirtualTerminalInput,
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
kNtEnableVirtualTerminalProcessing,
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
kNtEnableVirtualTerminalProcessing,
};
static uint32_t __init_pid;
static uint32_t __console_mode[3];
forceinline int IsAlpha(int c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
@ -108,16 +95,6 @@ __msabi long __oops_win32(void) {
return 0;
}
// called by _exit to undo our config changes to cmd.exe
// it must never ever be called from forked subprocesses
void __restore_console_win32(void) {
if (__imp_GetCurrentProcessId() == __init_pid) {
for (int i = 0; i < 3; ++i) {
__imp_SetConsoleMode(__imp_GetStdHandle(kNtStdio[i]), __console_mode[i]);
}
}
}
// https://nullprogram.com/blog/2022/02/18/
__msabi static inline char16_t *MyCommandLine(void) {
void *cmd;
@ -128,6 +105,15 @@ __msabi static inline char16_t *MyCommandLine(void) {
return cmd;
}
// returns true if utf-8 path is a win32-style path that exists
__msabi static textwindows bool32 WinFileExists(const char *path) {
uint16_t path16[PATH_MAX];
size_t z = ARRAYLEN(path16);
size_t n = tprecode8to16(path16, z, path).ax;
if (n >= z - 1) return false;
return __imp_GetFileAttributesW(path16) != -1u;
}
// this ensures close(1) won't accidentally close(2) for example
__msabi static textwindows void DeduplicateStdioHandles(void) {
for (long i = 0; i < 3; ++i) {
@ -144,27 +130,30 @@ __msabi static textwindows void DeduplicateStdioHandles(void) {
}
}
__msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
size_t stacksize;
struct WinArgs *wa;
uintptr_t stackaddr;
__init_pid = __pid;
// main function of windows init process
// i.e. first process spawned that isn't forked
__msabi static textwindows wontreturn void WinInit(const char16_t *cmdline) {
__oldstack = (intptr_t)__builtin_frame_address(0);
// make console into utf-8 ansi/xterm style tty
if (NtGetPeb()->OSMajorVersion >= 10 &&
(intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui) {
__imp_SetConsoleCP(kNtCpUtf8);
__imp_SetConsoleOutputCP(kNtCpUtf8);
for (int i = 0; i < 3; ++i) {
int64_t hand = __imp_GetStdHandle(kNtStdio[i]);
__imp_GetConsoleMode(hand, __console_mode + i);
__imp_SetConsoleMode(hand, kConsoleModes[i]);
for (int i = 1; i <= 2; ++i) {
uint32_t m;
intptr_t h = __imp_GetStdHandle(kNtStdio[i]);
__imp_GetConsoleMode(h, &m);
__imp_SetConsoleMode(h, m | kNtEnableVirtualTerminalProcessing);
}
}
// allocate memory for stack and argument block
_Static_assert(sizeof(struct WinArgs) % FRAMESIZE == 0, "");
_mmi.p = _mmi.s;
_mmi.n = ARRAYLEN(_mmi.s);
stackaddr = GetStaticStackAddr(0);
stacksize = GetStaticStackSize();
uintptr_t stackaddr = GetStaticStackAddr(0);
size_t stacksize = GetStaticStackSize();
__imp_MapViewOfFileEx((_mmi.p[0].h = __imp_CreateFileMappingW(
-1, &kNtIsInheritable, kNtPageExecuteReadwrite,
stacksize >> 32, stacksize, NULL)),
@ -181,25 +170,47 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
_mmi.p[0].flags = 0x00000026; // stack+anonymous
_mmi.p[0].size = stacksize;
_mmi.i = 1;
wa = (struct WinArgs *)(stackaddr + (stacksize - sizeof(struct WinArgs)));
struct WinArgs *wa =
(struct WinArgs *)(stackaddr + (stacksize - sizeof(struct WinArgs)));
// parse utf-16 command into utf-8 argv array in argument block
int count = GetDosArgv(cmdline, wa->argblock, ARRAYLEN(wa->argblock),
wa->argv, ARRAYLEN(wa->argv));
for (int i = 0; wa->argv[0][i]; ++i) {
if (wa->argv[0][i] == '\\') {
wa->argv[0][i] = '/';
// munge argv so dos paths become cosmo paths
for (int i = 0; wa->argv[i]; ++i) {
if (wa->argv[i][0] == '\\' && //
wa->argv[i][1] == '\\') {
// don't munge new technology style paths
continue;
}
if (!WinFileExists(wa->argv[i])) {
// don't munge if we're not certain it's a file
continue;
}
// use forward slashes
for (int j = 0; wa->argv[i][j]; ++j) {
if (wa->argv[i][j] == '\\') {
wa->argv[i][j] = '/';
}
}
// turn c:/... into /c/...
if (IsAlpha(wa->argv[i][0]) && //
wa->argv[i][1] == ':' && //
wa->argv[i][2] == '/') {
wa->argv[i][1] = wa->argv[i][0];
wa->argv[i][0] = '/';
}
}
if (IsAlpha(wa->argv[0][0]) && //
wa->argv[0][1] == ':' && //
wa->argv[0][2] == '/') {
wa->argv[0][1] = wa->argv[0][0];
wa->argv[0][0] = '/';
}
// translate utf-16 win32 environment into utf-8 environment variables
char16_t *env16 = __imp_GetEnvironmentStringsW();
GetDosEnviron(env16, wa->envblock, ARRAYLEN(wa->envblock) - 8, wa->envp,
ARRAYLEN(wa->envp) - 1);
__imp_FreeEnvironmentStringsW(env16);
__envp = &wa->envp[0];
// handover control to cosmopolitan runtime
_jmpstack((char *)(stackaddr + (stacksize - sizeof(struct WinArgs))), cosmo,
count, wa->argv, wa->envp, wa->auxv);
}
@ -227,7 +238,7 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
if (_weaken(WinMainForked)) {
_weaken(WinMainForked)();
}
WinMainNew(cmdline);
WinInit(cmdline);
}
#endif /* __x86_64__ */