Make improvements for Actually Portable Emacs

- Get SIGWINCH working again on the New Technology
- Correctly handle O_NOFOLLOW in open() on Windows
- Implement synthetic umask() functionality on Windows
- Do a better job managing file execute access on Windows
- Fill in `st_uid` and `st_gid` with username hash on Windows
- Munge UNICODE control pictures into control codes on Windows
- Do a better job ensuring Windows console settings are restored
- Introduce KPRINTF_LOG environment variable to log kprintf to a file
This commit is contained in:
Justine Tunney 2023-08-19 06:41:06 -07:00
parent 9c7b81ee0f
commit 965516e313
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
108 changed files with 1126 additions and 807 deletions

View file

@ -22,7 +22,7 @@
#define ToUpper(c) \
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
dontasan struct Env __getenv(char **p, const char *k) {
dontasan privileged struct Env __getenv(char **p, const char *k) {
char *t;
int i, j;
for (i = 0; (t = p[i]); ++i) {

View file

@ -1,33 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 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/macros.internal.h"
#include "libc/notice.inc"
// __pid_exec is __pid that isn't updated on fork()
.initbss 301,_init__pid_exec
__pid_exec:
.quad 0
.endobj __pid_exec,globl
.previous
.init.start 301,_init__pid_exec
mov __pid(%rip),%rax
stosq
.init.end 301,_init__pid_exec

View file

@ -344,7 +344,7 @@ static void __asan_exit(void) {
kprintf("your asan runtime needs\n"
"\t__static_yoink(\"__die\");\n"
"in order to show you backtraces\n");
_Exitr(99);
_Exit(99);
}
dontdiscard static __asan_die_f *__asan_die(void) {
@ -1483,7 +1483,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
if (!_cmpxchg(&once, false, true)) return;
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
__write_str("error: asan binaries require windows10\r\n");
_Exitr(0); /* So `make MODE=dbg test` passes w/ Windows7 */
_Exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */
}
REQUIRE(_mmi);
REQUIRE(sys_mmap);

View file

@ -21,6 +21,8 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/errors.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
@ -33,30 +35,50 @@ __msabi extern typeof(Sleep) *const __imp_Sleep;
/**
* Opens file on the New Technology.
*
* @return handle, or -1 on failure
* @return handle, or -1 on failure w/ `errno` set appropriately
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
*/
textwindows int64_t CreateFile(
const char16_t *lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode,
struct NtSecurityAttributes *opt_lpSecurityAttributes,
int dwCreationDisposition, uint32_t dwFlagsAndAttributes,
int64_t opt_hTemplateFile) {
textwindows int64_t CreateFile(const char16_t *lpFileName, //
uint32_t dwDesiredAccess, //
uint32_t dwShareMode, //
struct NtSecurityAttributes *opt_lpSecurity, //
int dwCreationDisposition, //
uint32_t dwFlagsAndAttributes, //
int64_t opt_hTemplateFile) {
int64_t hHandle;
uint32_t micros = 1;
TryAgain:
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
opt_lpSecurityAttributes, dwCreationDisposition,
opt_lpSecurity, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile);
if (hHandle == -1 && __imp_GetLastError() == kNtErrorPipeBusy) {
if (micros >= 1024) __imp_Sleep(micros / 1024);
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
goto TryAgain;
if (hHandle == -1) {
switch (__imp_GetLastError()) {
case kNtErrorPipeBusy:
if (micros >= 1024) __imp_Sleep(micros / 1024);
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
goto TryAgain;
case kNtErrorAccessDenied:
// GetNtOpenFlags() always greedily requests execute permissions
// because the POSIX flag O_EXEC doesn't mean the same thing. It
// seems however this causes the opening of certain files to not
// work, possibly due to Windows Defender or some security thing
// In that case, we'll cross our fingers the file isn't a binary
if ((dwDesiredAccess & kNtGenericExecute) &&
(dwCreationDisposition == kNtOpenExisting ||
dwCreationDisposition == kNtTruncateExisting)) {
dwDesiredAccess &= ~kNtGenericExecute;
goto TryAgain;
}
break;
default:
break;
}
__winerr();
}
if (hHandle == -1) __winerr();
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode),
DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
DescribeNtSecurityAttributes(opt_lpSecurity),
DescribeNtCreationDisposition(dwCreationDisposition),
DescribeNtFileFlagAttr(dwFlagsAndAttributes), opt_hTemplateFile,
hHandle);

View file

@ -43,10 +43,12 @@ textwindows int64_t CreateFileMapping(
flProtect, dwMaximumSizeHigh,
dwMaximumSizeLow, opt_lpName);
if (!hHandle) __winerr();
#if 1
NTTRACE("CreateFileMapping(%ld, %s, %s, %'zu, %#hs) → %ld% m", opt_hFile,
DescribeNtSecurityAttributes(opt_lpFileMappingAttributes),
DescribeNtPageFlags(flProtect),
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
hHandle);
#endif
return hHandle;
}

View file

@ -120,10 +120,6 @@ const char *(DescribeTermios)(char buf[N], ssize_t rc, struct termios *tio) {
append(", .c_lflag=%s",
DescribeFlags(b128, 128, kLocal, ARRAYLEN(kLocal), "", tio->c_lflag));
append(", c_cc[VINTR]=%#o", tio->c_cc[VINTR]);
append(", c_cc[VERASE]=%#o", tio->c_cc[VERASE]);
append(", c_cc[VWERASE]=%#o", tio->c_cc[VWERASE]);
append("}");
return buf;

View file

@ -19,31 +19,30 @@
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/errno.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/errors.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
int flags, int fd, int64_t off) {
int iscow;
int64_t handle;
uint32_t oldprot;
struct DirectMap dm;
struct ProtectNt fl;
const struct NtSecurityAttributes *sec;
int64_t handle;
if (flags & MAP_ANONYMOUS) {
handle = kNtInvalidHandleValue;
} else {
handle = g_fds.p[fd].handle;
}
const struct NtSecurityAttributes *sec;
if ((flags & MAP_TYPE) != MAP_SHARED) {
sec = 0; // MAP_PRIVATE isn't inherited across fork()
} else {
@ -54,7 +53,8 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
// later using mprotect(). the workaround is to always request execute
// and then virtualprotect() it away until we actually need it. please
// note that open-nt.c always requests an kNtGenericExecute accessmask
iscow = false;
int iscow = false;
struct ProtectNt fl;
if (handle != -1) {
if ((flags & MAP_TYPE) != MAP_SHARED) {
// windows has cow pages but they can't propagate across fork()
@ -77,16 +77,43 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
kNtFileMapWrite | kNtFileMapExecute};
}
int e = errno;
struct DirectMap dm;
TryAgain:
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
(size + off) >> 32, (size + off), 0))) {
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
size, addr))) {
uint32_t oldprot;
if (VirtualProtect(addr, size, __prot2nt(prot, iscow), &oldprot)) {
return dm;
}
UnmapViewOfFile(dm.addr);
}
CloseHandle(dm.maphandle);
} else if (!(prot & PROT_EXEC) && //
(fl.flags2 & kNtFileMapExecute) && //
GetLastError() == kNtErrorAccessDenied) {
// your file needs to have been O_CREAT'd with exec `mode` bits in
// order to be mapped with executable permission. we always try to
// get execute permission if the kernel will give it to us because
// win32 would otherwise forbid mprotect() from elevating later on
fl.flags2 &= ~kNtFileMapExecute;
switch (fl.flags1) {
case kNtPageExecuteWritecopy:
fl.flags1 = kNtPageWritecopy;
break;
case kNtPageExecuteReadwrite:
fl.flags1 = kNtPageReadwrite;
break;
case kNtPageExecuteRead:
fl.flags1 = kNtPageReadonly;
break;
default:
__builtin_unreachable();
}
errno = e;
goto TryAgain;
}
dm.maphandle = kNtInvalidHandleValue;

View file

@ -19,29 +19,30 @@
#include "libc/dce.h"
#include "libc/intrin/promises.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/nr.h"
/**
* Terminates process, ignoring destructors and atexit() handlers.
*
* When running on bare metal, this function will reboot your computer
* by hosing the interrupt descriptors and triple faulting the system.
*
* Exit codes are narrowed to an unsigned char on most platforms. The
* exceptions would be Windows, NetBSD, and OpenBSD, which should let
* you have larger exit codes.
*
* When running on bare metal, this function will reboot your computer
* by hosing the interrupt descriptors and triple faulting the system.
*
* @asyncsignalsafe
* @threadsafe
* @vforksafe
* @noreturn
*/
wontreturn void _Exit(int exitcode) {
int i;
STRACE("_Exit(%d)", exitcode);
if (!IsWindows() && !IsMetal()) {
// On Linux _Exit1 (exit) must be called in pledge("") mode. If we
@ -84,19 +85,24 @@ wontreturn void _Exit(int exitcode) {
#endif
} else if (IsWindows()) {
uint32_t waitstatus;
// Restoring the CMD.EXE program to its original state is critical.
if (_weaken(__restore_console_win32)) {
_weaken(__restore_console_win32)();
}
// What Microsoft calls an exit code, POSIX calls a status code. See
// also the WEXITSTATUS() and WIFEXITED() macros that POSIX defines.
waitstatus = exitcode;
waitstatus <<= 8;
// "The GetExitCodeProcess function returns a valid error code
// defined by the application only after the thread terminates.
// Therefore, an application should not use kNtStillActive (259) as
// an error code (kNtStillActive is a macro for kNtStatusPending).
// If a thread returns kNtStillActive (259) as an error code, then
// applications that test for that value could interpret it to mean
// that the thread is still running, and continue to test for the
// completion of the thread after the thread has terminated, which
// could put the application into an infinite loop." -Quoth MSDN
if (waitstatus == kNtStillActive) {
// The GetExitCodeProcess function returns a valid error code
// defined by the application only after the thread terminates.
// Therefore, an application should not use STILL_ACTIVE (259) as
// an error code (STILL_ACTIVE is a macro for STATUS_PENDING
// (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as an
// error code, then applications that test for that value could
// interpret it to mean that the thread is still running, and
// continue to test for the completion of the thread after the
// thread has terminated, which could put the application into an
// infinite loop. -Quoth MSDN (see also libc/calls/wait4-nt.c)
waitstatus = 0xc9af3d51u;
}
ExitProcess(waitstatus);

View file

@ -1,27 +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 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/dce.h"
#include "libc/runtime/runtime.h"
wontreturn void _Exitr(int exitcode) {
#if SupportsWindows()
_restorewintty();
#endif
_Exit(exitcode);
}

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/intrin/kprintf.h"
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
@ -30,20 +29,29 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
#include "libc/intrin/asmflag.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/getenv.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
@ -57,8 +65,13 @@
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "libc/str/utf16.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.h"
@ -107,6 +120,17 @@
break; \
}
// clang-format off
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
__msabi extern typeof(GetCurrentProcess) *const __imp_GetCurrentProcess;
__msabi extern typeof(GetEnvironmentVariable) *const __imp_GetEnvironmentVariableW;
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(SetLastError) *const __imp_SetLastError;
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
// clang-format on
long __klog_handle;
extern struct SymbolTable *__symtab;
@ -188,24 +212,180 @@ privileged bool kisdangerous(const void *p) {
if (IsStackFrame(frame)) return false;
if (kismapped(frame)) return false;
}
if (GetStackAddr() + 16384 <= (uintptr_t)p &&
if (GetStackAddr() + GetGuardSize() <= (uintptr_t)p &&
(uintptr_t)p < GetStackAddr() + GetStackSize()) {
return false;
}
return true;
}
privileged static long kloghandle(void) {
if (__klog_handle) {
return __klog_handle;
} else if (!IsWindows()) {
return 2;
} else {
return __imp_GetStdHandle(kNtStdErrorHandle);
}
privileged static void klogclose(long fd) {
#ifdef __x86_64__
long ax = __NR_close;
asm volatile("syscall"
: "+a"(ax), "+D"(fd)
: /* inputs already specified */
: "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
#elif defined(__aarch64__)
register long x0 asm("x0") = fd;
register int x8 asm("x8") = __NR_close;
register int x16 asm("x16") = __NR_close;
asm volatile("svc\t0" : "+r"(x0) : "r"(x8), "r"(x16) : "x9", "memory");
#else
#error "unsupported architecture"
#endif
}
privileged void _klog(const char *b, size_t n) {
privileged static long klogfcntl(long fd, long cmd, long arg) {
#ifdef __x86_64__
char cf;
long ax = __NR_fcntl;
asm volatile("clc\n\tsyscall"
: CFLAG_CONSTRAINT(cf), "+a"(ax), "+D"(fd), "+S"(cmd), "+d"(arg)
: /* inputs already specified */
: "rcx", "r8", "r9", "r10", "r11", "memory");
if (cf) ax = -ax;
return ax;
#elif defined(__aarch64__)
register long x0 asm("x0") = fd;
register long x1 asm("x1") = cmd;
register long x2 asm("x2") = arg;
register int x8 asm("x8") = __NR_fcntl;
register int x16 asm("x16") = __NR_fcntl;
asm volatile("mov\tx9,0\n\t" // clear carry flag
"adds\tx9,x9,0\n\t" // clear carry flag
"svc\t0\n\t"
"bcs\t1f\n\t"
"b\t2f\n1:\t"
"neg\tx0,x0\n2:"
: "+r"(x0)
: "r"(x1), "r"(x2), "r"(x8), "r"(x16)
: "x9", "memory");
return x0;
#else
#error "unsupported architecture"
#endif
}
privileged static long klogopen(const char *path) {
long dirfd = AT_FDCWD;
long flags = O_WRONLY | O_CREAT | O_APPEND;
long mode = 0600;
#ifdef __x86_64__
char cf;
long ax = __NR_openat;
register long r10 asm("r10") = mode;
asm volatile(CFLAG_ASM("clc\n\tsyscall")
: CFLAG_CONSTRAINT(cf), "+a"(ax), "+D"(dirfd), "+S"(path),
"+d"(flags), "+r"(r10)
: /* inputs already specified */
: "rcx", "r8", "r9", "r11", "memory");
if (cf) ax = -ax;
return ax;
#elif defined(__aarch64__)
register long x0 asm("x0") = dirfd;
register long x1 asm("x1") = (long)path;
register long x2 asm("x2") = flags;
register long x3 asm("x3") = mode;
register int x8 asm("x8") = __NR_openat;
register int x16 asm("x16") = __NR_openat;
asm volatile("mov\tx9,0\n\t" // clear carry flag
"adds\tx9,x9,0\n\t" // clear carry flag
"svc\t0\n\t"
"bcs\t1f\n\t"
"b\t2f\n1:\t"
"neg\tx0,x0\n2:"
: "+r"(x0)
: "r"(x1), "r"(x2), "r"(x3), "r"(x8), "r"(x16)
: "x9", "memory");
return x0;
#else
#error "unsupported architecture"
#endif
}
// returns log handle or -1 if logging shouldn't happen
privileged long kloghandle(void) {
// kprintf() needs to own a file descriptor in case apps closes stderr
// our close() and dup() implementations will trigger this initializer
// to minimize a chance that the user accidentally closes their logger
// while at the same time, avoiding a mandatory initialization syscall
if (!__klog_handle) {
long hand;
// setting KPRINTF_LOG="/tmp/foo.log" will override stderr
// setting KPRINTF_LOG="INTEGER" logs to a file descriptor
// setting KPRINTF_LOG="" shall disable kprintf altogether
if (IsMetal()) {
hand = STDERR_FILENO;
} else if (IsWindows()) {
uint32_t e, n;
const char16_t path[512];
e = __imp_GetLastError();
n = __imp_GetEnvironmentVariableW(u"KPRINTF_LOG", path, 512);
if (!n && __imp_GetLastError() == kNtErrorEnvvarNotFound) {
long proc;
proc = __imp_GetCurrentProcess();
hand = __imp_GetStdHandle(kNtStdErrorHandle);
__imp_DuplicateHandle(proc, hand, proc, &hand, 0, true,
kNtDuplicateSameAccess);
} else if (n && n < 512) {
hand = __imp_CreateFileW(
path, kNtGenericWrite | kNtFileAppendData,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
&kNtIsInheritable, kNtOpenAlways, kNtFileAttributeNormal, 0);
} else {
hand = -1; // KPRINTF_LOG was empty string or too long
}
__imp_SetLastError(e);
} else {
long fd, fd2;
bool closefd;
const char *path;
if (!__NR_write || !__envp) {
// it's too early in the initialization process for kprintf
return -1;
}
path = __getenv(__envp, "KPRINTF_LOG").s;
closefd = false;
if (!path) {
fd = STDERR_FILENO;
} else if (*path) {
const char *p;
for (fd = 0, p = path; *p; ++p) {
if ('0' <= *p && *p <= '9') {
fd *= 10;
fd += *p - '0';
} else {
fd = klogopen(path);
closefd = true;
break;
}
}
} else {
fd = -1;
}
if (fd >= 0) {
// avoid interfering with hard-coded assumptions about fds
if ((fd2 = klogfcntl(fd, F_DUPFD, 100)) >= 0) {
klogfcntl(fd2, F_SETFD, FD_CLOEXEC);
if (closefd) {
klogclose(fd);
}
} else {
// RLIMIT_NOFILE was probably too low for safe duplicate
fd2 = fd;
}
} else {
fd2 = -1;
}
hand = fd2;
}
__klog_handle = hand;
}
return __klog_handle;
}
privileged void klog(const char *b, size_t n) {
#ifdef __x86_64__
int e;
long h;
@ -215,7 +395,9 @@ privileged void _klog(const char *b, size_t n) {
uint32_t wrote;
unsigned char al;
long rax, rdi, rsi, rdx;
h = kloghandle();
if ((h = kloghandle()) == -1) {
return;
}
if (IsWindows()) {
e = __imp_GetLastError();
__imp_WriteFile(h, b, n, &wrote, 0);
@ -243,7 +425,7 @@ privileged void _klog(const char *b, size_t n) {
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}
#elif defined(__aarch64__)
register long r0 asm("x0") = (long)kloghandle();
register long r0 asm("x0") = kloghandle();
register long r1 asm("x1") = (long)b;
register long r2 asm("x2") = (long)n;
register long r8 asm("x8") = (long)__NR_write;
@ -262,7 +444,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
va_list va) {
int si, y;
wint_t t, u;
char errnum[12];
const char *abet;
signed char type;
const char *s, *f;
@ -545,11 +726,16 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
break;
} else {
type = 0;
#if defined(SYSDEBUG) && _NTTRACE
strerror_r(e, z, sizeof(z));
s = z;
#else
s = _strerrno(e);
if (!s) {
FormatInt32(errnum, e);
s = errnum;
FormatInt32(z, e);
s = z;
}
#endif
goto FormatString;
}
}
@ -851,7 +1037,7 @@ privileged void kvprintf(const char *fmt, va_list v) {
size_t n;
char b[4000];
n = kformat(b, sizeof(b), fmt, v);
_klog(b, MIN(n, sizeof(b) - 1));
klog(b, MIN(n, sizeof(b) - 1));
}
/**
@ -926,9 +1112,9 @@ privileged void kvprintf(const char *fmt, va_list v) {
* @vforksafe
*/
privileged void kprintf(const char *fmt, ...) {
/* system call support runtime depends on this function */
/* function tracing runtime depends on this function */
/* asan runtime depends on this function */
// system call support runtime depends on this function
// function tracing runtime depends on this function
// asan runtime depends on this function
va_list v;
va_start(v, fmt);
kvprintf(fmt, v);

View file

@ -2,10 +2,12 @@
#define COSMOPOLITAN_LIBC_INTRIN_KPRINTF_H_
#ifdef _COSMO_SOURCE
#define klog __klog
#define kprintf __kprintf
#define ksnprintf __ksnprintf
#define kvprintf __kvprintf
#define kvsnprintf __kvsnprintf
#define kloghandle __kloghandle
#define kisdangerous __kisdangerous
#if !(__ASSEMBLER__ + __LINKER__ + 0)
@ -21,8 +23,10 @@ void kprintf(const char *, ...);
size_t ksnprintf(char *, size_t, const char *, ...);
void kvprintf(const char *, va_list);
size_t kvsnprintf(char *, size_t, const char *, va_list);
bool kisdangerous(const void *);
void _klog(const char *, size_t);
void klog(const char *, size_t);
long kloghandle(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -31,7 +31,6 @@
wontreturn void quick_exit(int exitcode) {
const uintptr_t *p;
STRACE("quick_exit(%d)", exitcode);
_restorewintty();
if (_weaken(fflush)) {
_weaken(fflush)(0);
}

View file

@ -1,47 +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 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/dce.h"
#include "libc/nt/console.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/internal.h"
__msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId;
__msabi extern typeof(SetConsoleMode) *const __imp_SetConsoleMode;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
extern uint32_t __pid_exec;
const signed char kNtConsoleHandles[3] = {
(signed char)kNtStdInputHandle,
(signed char)kNtStdOutputHandle,
(signed char)kNtStdErrorHandle,
};
// Puts cmd.exe gui back the way it was.
void _restorewintty(void) {
int i;
if (!IsWindows()) return;
if (__imp_GetCurrentProcessId() != __pid_exec) return;
for (i = 0; i < 3; ++i) {
__imp_SetConsoleMode(__imp_GetStdHandle(kNtConsoleHandles[i]),
__ntconsolemode[i]);
}
}

View file

@ -16,9 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/str/str.h"
// clang-format off
#if defined(SYSDEBUG) && _NTTRACE
dontasan dontubsan privileged
#endif
/**
* Converts errno value to string.
@ -27,6 +35,6 @@
* @return 0 on success, or error code
*/
int strerror_r(int err, char *buf, size_t size) {
int winerr = IsWindows() ? GetLastError() : 0;
int winerr = IsWindows() ? __imp_GetLastError() : 0;
return strerror_wr(err, winerr, buf, size);
}

View file

@ -21,11 +21,17 @@
#include "libc/fmt/fmt.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/formatmessageflags.h"
#include "libc/nt/enum/lang.h"
#include "libc/nt/process.h"
#include "libc/str/str.h"
// clang-format off
#if defined(SYSDEBUG) && _NTTRACE
dontasan dontubsan privileged
#endif
/**
* Converts errno value to string with explicit windows errno too.
@ -53,7 +59,7 @@ int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
for (; (c = *sym++); --size)
if (size > 1) *buf++ = c;
if (size) *buf = 0;
} else if (!IsWindows() || ((err == winerr || !winerr) && !wanting)) {
} else if (!IsWindows() /* || ((err == winerr || !winerr) && !wanting) */) {
ksnprintf(buf, size, "%s/%d/%s", sym, err, msg);
} else {
if ((n = __imp_FormatMessageW(

View file

@ -206,7 +206,7 @@ static void __ubsan_exit(void) {
kprintf("your ubsan runtime needs\n"
"\t__static_yoink(\"__die\");\n"
"in order to show you backtraces\n");
_Exitr(99);
_Exit(99);
}
static char *__ubsan_stpcpy(char *d, const char *s) {

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 2021 Justine Alexandra Roberts Tunney
Copyright 2023 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,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/internal.h"
#include "libc/atomic.h"
#include "libc/calls/internal.h"
uint32_t __ntconsolemode[3];
atomic_int __umask;