Improve system call support

This commit is contained in:
Justine Tunney 2021-08-25 21:35:58 -07:00
parent 63b867bd2f
commit 3085ac7837
65 changed files with 900 additions and 544 deletions

View file

@ -87,6 +87,7 @@ int chdir(const char *);
int chmod(const char *, uint32_t);
int chown(const char *, uint32_t, uint32_t);
int chroot(const char *);
int clone(int (*)(void *), void *, int, void *, ...);
int close(int);
int closedir(DIR *);
int creat(const char *, uint32_t);

View file

@ -28,7 +28,7 @@
* @asyncsignalsafe
* @vforksafe
*/
nodiscard int dup(int fd) {
int dup(int fd) {
if (!IsWindows()) {
return sys_dup(fd);
} else {

View file

@ -16,6 +16,7 @@
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/ntspawn.h"
#include "libc/mem/alloca.h"
@ -44,6 +45,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
startinfo.hStdError = g_fds.p[2].handle;
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
if (rc == -1) return -1;
CloseHandle(g_fds.p[0].handle);
CloseHandle(g_fds.p[1].handle);
CloseHandle(procinfo.hThread);
do {
WaitForSingleObject(procinfo.hProcess, -1);

View file

@ -30,7 +30,8 @@
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len, int advice) {
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len,
int advice) {
int64_t h2;
NtStatus status;
uint32_t sharemode;

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
@ -26,26 +27,44 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns true if file exists at path.
*
* This function is equivalent to:
*
* struct stat st;
* return stat(path, &st) != -1;
*
* Please note that things which aren't strictly files, e.g. directories
* or sockets, could be considered files for the purposes of this
* function. The stat() function may be used to differentiate them.
*/
bool fileexists(const char *path) {
int rc, olderr;
int e;
struct stat st;
struct ZiposUri zipname;
uint16_t path16[PATH_MAX];
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
olderr = errno;
rc = __sys_fstatat(AT_FDCWD, path, &st, 0);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st) != -1) {
return true;
} else {
errno = e;
return false;
}
} else if (IsMetal()) {
return false;
} else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) {
return true;
} else {
errno = e;
return false;
}
return rc != -1;
} else {
if (__mkntpath(path, path16) == -1) return -1;
return GetFileAttributes(path16) != -1u;

View file

@ -16,11 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/fileinfobyhandleclass.h"
@ -37,12 +38,6 @@
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#if 0
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#else
#define DEBUG(FMT, ...) (void)0
#endif
static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
wint_t x, y;
const char16_t *p;
@ -69,7 +64,7 @@ static textwindows uint32_t GetSizeOfReparsePoint(int64_t fh) {
z += x < 0200 ? 1 : bsrl(tpenc(x)) >> 3;
}
} else {
DEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
SYSDEBUG("GetSizeOfReparsePoint failed %d", GetLastError());
}
return z;
}
@ -122,8 +117,10 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
&fci, sizeof(fci))) {
actualsize = fci.CompressedFileSize;
}
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
st->st_blocks = ROUNDUP(actualsize, PAGESIZE) / 512;
}
} else {
SYSDEBUG("GetFileInformationByHandle failed %d", GetLastError());
}
break;
default:
@ -131,6 +128,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
}
return 0;
} else {
SYSDEBUG("GetFileType failed %d", GetLastError());
return __winerr();
}
}

View file

@ -109,9 +109,9 @@ char *sys_getcwd(char *, u64) hidden;
char *sys_getcwd_xnu(char *, u64) hidden;
i32 __sys_dup3(i32, i32, i32) hidden;
i32 __sys_execve(const char *, char *const[], char *const[]) hidden;
i32 __sys_fcntl(i32, i32, u64) hidden;
i32 __sys_fstat(i32, struct stat *) hidden;
i32 __sys_fstatat(i32, const char *, struct stat *, i32) hidden;
i32 __sys_fcntl(i32, i32, ...) hidden;
i32 __sys_fstat(i32, void *) hidden;
i32 __sys_fstatat(i32, const char *, void *, i32) hidden;
i32 __sys_getrusage(i32, struct rusage *) hidden;
i32 __sys_openat(i32, const char *, i32, u32) hidden;
i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;

View file

@ -16,21 +16,56 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns true if file descriptor is backed by character i/o.
*
* This function is equivalent to:
*
* struct stat st;
* return stat(path, &st) != -1 && S_ISCHR(st.st_mode);
*
* Except faster and with fewer dependencies.
*
* @see isregularfile(), isdirectory(), issymlink(), fileexists()
*/
textstartup bool32 ischardev(int fd) {
int olderr;
struct stat st;
olderr = errno;
if (fstat(fd, &st) != -1) {
return S_ISCHR(st.st_mode);
bool32 ischardev(int fd) {
int e;
union metastat st;
if (__isfdkind(fd, kFdZip)) {
e = errno;
if (weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, &st.linux) !=
-1) {
return S_ISCHR(st.linux.st_mode);
} else {
errno = e;
return false;
}
} else if (IsMetal()) {
return true;
} else if (!IsWindows()) {
e = errno;
if (__sys_fstat(fd, &st) != -1) {
return S_ISCHR(METASTAT(st, st_mode));
} else {
errno = e;
return false;
}
} else {
errno = olderr;
return false;
return __isfdkind(fd, kFdConsole) ||
(__isfdkind(fd, kFdFile) &&
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar);
}
}

View file

@ -16,8 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -25,19 +27,44 @@
#include "libc/nt/files.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns true if file exists and is a directory.
*
* This function is equivalent to:
*
* struct stat st;
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
* S_ISDIR(st.st_mode);
*
* Except faster and with fewer dependencies.
*
* @see isregularfile(), issymlink(), ischardev()
*/
bool isdirectory(const char *path) {
struct stat st;
int rc, olderr;
int rc, e;
union metastat st;
struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) errno = olderr;
return rc != -1 && S_ISDIR(st.st_mode);
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
return S_ISDIR(st.linux.st_mode);
} else {
errno = e;
return false;
}
} else if (IsMetal()) {
return false;
} else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
return S_ISDIR(METASTAT(st, st_mode));
} else {
errno = e;
return false;
}
} else {
return isdirectory_nt(path);
}

View file

@ -16,29 +16,52 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns true if file exists and is a regular file.
*
* This function is equivalent to:
*
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
* S_ISREG(st.st_mode);
*
* Except faster and with fewer dependencies.
*
* @see isdirectory(), ischardev(), issymlink()
*/
bool isregularfile(const char *path) {
struct stat st;
int rc, olderr;
int rc, e;
union metastat st;
struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
errno = olderr;
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
return S_ISREG(st.linux.st_mode);
} else {
errno = e;
return false;
}
} else if (IsMetal()) {
return false;
} else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
return S_ISREG(METASTAT(st, st_mode));
} else {
errno = e;
return false;
}
return rc != -1 && S_ISREG(st.st_mode);
} else {
return isregularfile_nt(path);
}

View file

@ -16,8 +16,10 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -25,19 +27,38 @@
#include "libc/nt/files.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/**
* Returns true if file exists and is a symbolic link.
*
* This function is equivalent to:
*
* struct stat st;
* return fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1 &&
* S_ISLNK(st.st_mode);
*
* Except faster and with fewer dependencies.
*
* @see isregularfile(), isdirectory(), fileexists(), ischardev()
*/
bool issymlink(const char *path) {
struct stat st;
int rc, olderr;
int e;
union metastat st;
struct ZiposUri zipname;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (!IsWindows()) {
olderr = errno;
rc = sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW);
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) errno = olderr;
return rc != -1 && S_ISLNK(st.st_mode);
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
return false;
} else if (IsMetal()) {
return false;
} else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
return S_ISLNK(METASTAT(st, st_mode));
} else {
errno = e;
return false;
}
} else {
return issymlink_nt(path);
}

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityimpersonationlevel.h"
@ -34,12 +35,6 @@
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h"
#if 0
#define DEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#else
#define DEBUG(FMT, ...) (void)0
#endif
/**
* Asks Microsoft if we're authorized to use a folder or file.
*
@ -92,24 +87,24 @@ TryAgain:
if (result || flags == F_OK) {
rc = 0;
} else {
DEBUG("ntaccesscheck finale failed %d %d", result, flags);
SYSDEBUG("ntaccesscheck finale failed %d %d", result, flags);
rc = eacces();
}
} else {
rc = __winerr();
DEBUG("AccessCheck failed: %m");
SYSDEBUG("AccessCheck failed: %m");
}
} else {
rc = __winerr();
DEBUG("DuplicateToken failed: %m");
SYSDEBUG("DuplicateToken failed: %m");
}
} else {
rc = __winerr();
DEBUG("OpenProcessToken failed: %m");
SYSDEBUG("OpenProcessToken failed: %m");
}
} else {
e = GetLastError();
DEBUG("GetFileSecurity failed: %d %d", e, secsize);
SYSDEBUG("GetFileSecurity failed: %d %d", e, secsize);
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
if (!freeme && weaken(malloc) && (freeme = weaken(malloc)(secsize))) {
s = freeme;

View file

@ -17,28 +17,45 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
int fd, err;
err = errno;
fd = __sys_openat(dirfd, file, flags, mode);
static bool once, modernize;
int d, e, f;
/*
* RHEL5 doesn't support O_CLOEXEC
* What on earth is it doing here?
* It returns -530!
* RHEL5 doesn't support O_CLOEXEC. It's hard to test for this.
* Sometimes the system call succeeds and it just doesn't set the
* flag. Other times, it return -530 which makes no sense.
*/
if (IsLinux() && fd == -1 && errno > 255) {
errno = err;
fd = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode);
if (fd != -1 && (flags & O_CLOEXEC)) {
__sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
if (!IsLinux() || !(flags & O_CLOEXEC) || modernize) {
return __sys_openat(dirfd, file, flags, mode);
} else if (once) {
if ((d = __sys_openat(dirfd, file, flags & ~O_CLOEXEC, mode)) != -1) {
e = errno;
if (__sys_fcntl(d, F_SETFD, FD_CLOEXEC) == -1) {
errno = e;
}
}
} else {
e = errno;
if ((d = __sys_openat(dirfd, file, flags, mode)) != -1) {
if ((f = __sys_fcntl(d, F_GETFD)) != -1) {
if (f & FD_CLOEXEC) {
modernize = true;
} else {
__sys_fcntl(d, F_SETFD, FD_CLOEXEC);
}
}
errno = e;
once = true;
} else if (errno > 255) {
once = true;
return sys_openat(dirfd, file, flags, mode);
}
}
return fd;
return d;
}

View file

@ -45,10 +45,6 @@ int openat(int dirfd, const char *file, int flags, ...) {
va_list va;
unsigned mode;
struct ZiposUri zipname;
if (strstr(file, "0/o/dbg/test")) {
(dprintf)(2, "-- wut %`'s\n", file);
if (weaken(__die)) weaken(__die)();
}
va_start(va, flags);
mode = va_arg(va, unsigned);
va_end(va);

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/framebuffervirtualscreeninfo.h"
#include "libc/dce.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/system.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
@ -70,9 +71,9 @@ int reboot(int howto) {
if (howto == 0xD000FCE2u) {
ok = !!SetSuspendState(0, 0, 0);
} else {
howto |= kNtShutdownForceOthers;
howto |= kNtShutdownForceSelf;
if (NtGetVersion() >= 8) {
howto |= kNtShutdownForceOthers;
if (NtGetVersion() >= kNtVersionWindows8) {
howto |= kNtShutdownHybrid;
}
if (immediately) {

View file

@ -5,6 +5,14 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define METASTAT(x, field) \
(IsLinux() || IsMetal() ? x.linux.field \
: IsXnu() ? x.xnu.field \
: IsFreebsd() ? x.freebsd.field \
: IsOpenbsd() ? x.openbsd.field \
: IsNetbsd() ? x.netbsd.field \
: 0)
struct stat_xnu {
int32_t st_dev;
uint16_t st_mode, st_nlink;

View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_
#include "libc/calls/calls.h"
#if 0
#define SYSDEBUG(FMT, ...) (dprintf)(2, FMT "\n", ##__VA_ARGS__)
#else
#define SYSDEBUG(FMT, ...) (void)0
#endif
#endif /* COSMOPOLITAN_LIBC_CALLS_SYSDEBUG_INTERNAL_H_ */

View file

@ -16,9 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
@ -62,12 +64,21 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
dwExitCode = kNtStillActive;
if (options & WNOHANG) {
i = WaitForMultipleObjects(count, handles, false, 0);
if (i == kNtWaitTimeout) return 0;
if (i == kNtWaitTimeout) {
return 0;
}
} else {
i = WaitForMultipleObjects(count, handles, false, -1);
}
if (i == kNtWaitFailed) return __winerr();
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return __winerr();
if (i == kNtWaitFailed) {
SYSDEBUG("WaitForMultipleObjects failed %d", GetLastError());
return __winerr();
}
assert(__isfdkind(pids[i], kFdProcess));
if (!GetExitCodeProcess(handles[i], &dwExitCode)) {
SYSDEBUG("GetExitCodeProcess failed %d", GetLastError());
return __winerr();
}
if (dwExitCode == kNtStillActive) continue;
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
@ -76,14 +87,12 @@ textwindows int sys_wait4_nt(int pid, int *opt_out_wstatus, int options,
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
if (GetProcessTimes(g_fds.p[pids[i]].handle, &createfiletime,
&exitfiletime, &kernelfiletime, &userfiletime)) {
opt_out_rusage->ru_utime.tv_sec =
ReadFileTime(userfiletime) / HECTONANOSECONDS;
opt_out_rusage->ru_utime.tv_usec =
ReadFileTime(userfiletime) % HECTONANOSECONDS;
opt_out_rusage->ru_stime.tv_sec =
ReadFileTime(kernelfiletime) / HECTONANOSECONDS;
opt_out_rusage->ru_stime.tv_usec =
ReadFileTime(kernelfiletime) % HECTONANOSECONDS;
opt_out_rusage->ru_utime =
WindowsDurationToTimeVal(ReadFileTime(userfiletime));
opt_out_rusage->ru_stime =
WindowsDurationToTimeVal(ReadFileTime(kernelfiletime));
} else {
SYSDEBUG("GetProcessTimes failed %d", GetLastError());
}
}
CloseHandle(g_fds.p[pids[i]].handle);

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/calls/ucontext.h"
#include "libc/nt/enum/exceptionhandleractions.h"
#include "libc/nt/enum/signal.h"
@ -29,6 +30,7 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
ucontext_t ctx;
struct siginfo si;
} g;
SYSDEBUG("__wincrash");
switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint:
sig = SIGTRAP;

View file

@ -19,6 +19,13 @@
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"
/**
* Returns New Technology version, e.g.
*
* if (IsWindows() && NtGetVersion() >= kNtVersionWindows10) {...}
*
* This can only be called on Windows.
*/
textwindows noasan int NtGetVersion(void) {
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
}

View file

@ -19,7 +19,9 @@
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/log/color.internal.h"
#include "libc/log/gdb.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nexgen32e/vendor.internal.h"
@ -32,8 +34,6 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/w.h"
#define RESTORE_TTY "\e[?1000;1002;1015;1006l\e[?25h"
/**
* Launches GDB debugger GUI for current process.
*
@ -59,7 +59,7 @@ relegated int(attachdebugger)(intptr_t continuetoaddr) {
(ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) == -1) {
return -1;
}
write(ttyfd, RESTORE_TTY, strlen(RESTORE_TTY));
__restore_tty(ttyfd);
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
layout = "layout asm";
if ((elf = FindDebugBinary())) {

View file

@ -17,9 +17,11 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/log/color.internal.h"
#include "libc/log/log.h"
#include "libc/nt/enum/version.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
@ -47,7 +49,9 @@ bool cancolor(void) {
static bool once;
static bool result;
if (!once) {
result = !!strcmp(nulltoempty(getenv("DONTANSIMEBRO")), "1") &&
result = (!IsWindows() || NtGetVersion() >= kNtVersionWindows10 ||
!ischardev(1)) &&
!!strcmp(nulltoempty(getenv("DONTANSIMEBRO")), "1") &&
!!strcmp(nulltoempty(getenv("TERM")), "dumb");
once = true;
}

View file

@ -30,7 +30,7 @@
relegated wontreturn void __die(void) {
static bool once;
if (cmpxchg(&once, false, true)) {
__restore_tty();
__restore_tty(1);
if (IsDebuggerPresent(false)) DebugBreak();
ShowBacktrace(2, NULL);
}

View file

@ -14,7 +14,7 @@ extern struct sigaction g_oldcrashacts[8] hidden;
void __start_fatal(const char *, int) hidden;
void __start_fatal_ndebug(void) hidden;
void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
void __restore_tty(void);
void __restore_tty(int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -265,7 +265,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
: 0);
}
if (gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT)) return;
__restore_tty();
__restore_tty(1);
ShowCrashReport(err, STDERR_FILENO, sig, si, ctx);
exit(128 + sig);
unreachable;

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/termios.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/str/str.h"
@ -36,9 +37,9 @@ const void *const g_oldtermios_ctor[] initarray = {
g_oldtermios_init,
};
void __restore_tty(void) {
if (g_oldtermios.c_lflag && isatty(1)) {
write(1, ANSI_RESTORE, strlen(ANSI_RESTORE));
tcsetattr(1, TCSAFLUSH, &g_oldtermios);
void __restore_tty(int fd) {
if (g_oldtermios.c_lflag && isatty(fd) && cancolor()) {
write(fd, ANSI_RESTORE, strlen(ANSI_RESTORE));
tcsetattr(fd, TCSAFLUSH, &g_oldtermios);
}
}

View file

@ -32,7 +32,7 @@
relegated void __start_fatal(const char *file, int line) {
bool colorful;
char s[16 + 16 + 16 + 16 + PATH_MAX + 16 + NAME_MAX + 16], *p = s;
__restore_tty();
__restore_tty(1);
colorful = cancolor();
*p++ = '\r';
if (colorful) p = stpcpy(p, "\e[J\e[30;101m");

View file

@ -29,7 +29,7 @@
*/
relegated void __start_fatal_ndebug(void) {
char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s;
__restore_tty();
__restore_tty(1);
*p++ = '\r';
if (cancolor()) p = stpcpy(p, "\e[J");
p = stpcpy(p, "error:");

107
libc/runtime/clone.c Normal file
View file

@ -0,0 +1,107 @@
/*-*- 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
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/dce.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thread.h"
#include "libc/sysv/consts/clone.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/errfuns.h"
struct WinThread {
int (*func)(void *);
void *param;
void *stack;
};
static noasan textwindows uint32_t winthread(void *param) {
struct WinThread *wt = param;
asm volatile("mov\t%%rbp,%%r14\n\t"
"mov\t%%rsp,%%r15\n\t"
"xor\t%%ebp,%%ebp\n\t"
"mov\t%2,%%rsp\n\t"
"call\t*%0\n\t"
"mov\t%%r14,%%rbp\n\t"
"mov\t%%r15,%%rsp"
: /* no outputs */
: "m"(wt->func), "D"(wt->param), "m"(wt->stack)
: "r14", "r15", "memory");
return 0;
}
/**
* Creates thread.
*
* @note CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND creates thread
* @note CLONE_VFORK|CLONE_VM|SIGCHLD does vfork()
* @note SIGCHLD does fork()
*/
privileged int clone(int (*f)(void *), void *stack, int flags, void *arg, ...) {
int64_t h;
va_list va;
intptr_t ax;
uint32_t tid;
int32_t *ptid;
register void *tls asm("r8");
register int32_t *ctid asm("r10");
register int (*func)(void *) asm("r9");
if (IsLinux() || IsNetbsd()) {
va_start(va, arg);
ptid = va_arg(va, int32_t *);
tls = va_arg(va, void *);
ctid = va_arg(va, int32_t *);
va_end(va);
func = f;
stack = (void *)(((uintptr_t)stack & -16) - 8);
*(intptr_t *)stack = (intptr_t)arg;
asm volatile("syscall"
: "=a"(ax)
: "0"(__NR_clone), "D"(flags), "S"(stack), "d"(ptid),
"r"(ctid), "r"(tls), "r"(func)
: "rcx", "r11", "memory");
if (ax) return ax;
asm volatile("xor\t%%ebp,%%ebp\n\t"
"pop\t%%rdi\n\t"
"call\t%1"
: "=a"(ax)
: "r"(func)
: "memory");
asm volatile("syscall"
: /* no outputs */
: "a"(__NR_exit), "D"(ax)
: "memory");
unreachable;
} else if (IsWindows()) {
if (flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) {
if ((h = CreateThread(0, PAGESIZE, NT2SYSV(winthread),
&(struct WinThread){f, arg, stack}, 0, &tid))) {
CloseHandle(h);
return tid;
} else {
return __winerr();
}
} else {
return einval();
}
} else {
return enosys();
}
}

View file

@ -20,6 +20,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/macros.internal.h"
@ -90,7 +91,10 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
f = flags | MAP_FIXED;
if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */
dm = sys_mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off);
if (dm.addr == MAP_FAILED) return MAP_FAILED;
if (dm.addr == MAP_FAILED) {
SYSDEBUG("sys_mmap failed");
return MAP_FAILED;
}
}
dm = sys_mmap(addr, size, prot, f, fd, off);
if (dm.addr == MAP_FAILED || dm.addr != addr) {

View file

@ -24,9 +24,12 @@
#include "libc/sock/internal.h"
#include "libc/sock/yoink.inc"
#include "libc/sysv/consts/fio.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
@ -38,33 +41,28 @@ textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
for (;;) {
if (!WSAPoll(&(struct sys_pollfd_nt){fd->handle, POLLIN}, 1, 1000))
continue;
if ((client = __reservefd()) == -1) return -1;
if ((h = WSAAccept(fd->handle, addr, (int32_t *)addrsize, 0, 0)) != -1) {
oflags = 0;
if (flags & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
if (flags & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
if (flags & SOCK_NONBLOCK) {
if (__sys_ioctlsocket_nt(g_fds.p[client].handle, FIONBIO,
(uint32_t[]){1}) == -1) {
__winsockerr();
__sys_closesocket_nt(g_fds.p[client].handle);
__releasefd(client);
return -1;
if ((!(flags & SOCK_NONBLOCK) ||
__sys_ioctlsocket_nt(h, FIONBIO, (uint32_t[]){1}) != -1) &&
(sockfd2 = calloc(1, sizeof(struct SockFd)))) {
if ((client = __reservefd()) != -1) {
sockfd2->family = sockfd->family;
sockfd2->type = sockfd->type;
sockfd2->protocol = sockfd->protocol;
sockfd2->event = WSACreateEvent();
g_fds.p[client].kind = kFdSocket;
g_fds.p[client].flags = oflags;
g_fds.p[client].handle = h;
g_fds.p[client].extra = (uintptr_t)sockfd2;
return client;
}
free(sockfd2);
}
sockfd2 = calloc(1, sizeof(struct SockFd));
sockfd2->family = sockfd->family;
sockfd2->type = sockfd->type;
sockfd2->protocol = sockfd->protocol;
sockfd2->event = WSACreateEvent();
g_fds.p[client].kind = kFdSocket;
g_fds.p[client].flags = oflags;
g_fds.p[client].handle = h;
g_fds.p[client].extra = (uintptr_t)sockfd2;
return client;
} else {
__releasefd(client);
return __winsockerr();
__sys_closesocket_nt(h);
}
return __winsockerr();
}
}

View file

@ -26,24 +26,27 @@
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t timeoutms) {
int got;
size_t i;
uint64_t waitfor;
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint64_t ms) {
int i, got, waitfor;
struct sys_pollfd_nt ntfds[64];
if (nfds > 64) return einval();
if (nfds >= ARRAYLEN(ntfds)) return einval();
for (i = 0; i < nfds; ++i) {
if (!__isfdkind(fds[i].fd, kFdSocket)) return ebadf();
ntfds[i].handle = g_fds.p[fds[i].fd].handle;
ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
if (fds[i].fd >= 0) {
if (!__isfdkind(fds[i].fd, kFdSocket)) return enotsock();
ntfds[i].handle = g_fds.p[fds[i].fd].handle;
ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
} else {
ntfds[i].handle = -1;
ntfds[i].events = POLLIN;
}
}
for (;;) {
if (cmpxchg(&__interrupted, true, false)) return eintr();
waitfor = MIN(1000, timeoutms); /* for ctrl+c */
waitfor = MIN(1000, ms); /* for ctrl+c */
if ((got = WSAPoll(ntfds, nfds, waitfor)) != -1) {
if (!got && (timeoutms -= waitfor)) continue;
if (!got && (ms -= waitfor) > 0) continue;
for (i = 0; i < nfds; ++i) {
fds[i].revents = ntfds[i].revents;
fds[i].revents = ntfds[i].handle < 0 ? 0 : ntfds[i].revents;
}
return got;
} else {

View file

@ -18,16 +18,21 @@
*/
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/winsock.h"
#include "libc/nt/iphlpapi.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/yoink.inc"
#include "libc/sysv/consts/fio.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
/* ioctl(SIOCGIFCONFIG) for Windows need to access the following functions through
* weak reference. This ensure those symbols are not stripped during final link
/*
* ioctl(SIOCGIFCONFIG) for Windows need to access the following
* functions through weak reference. This ensure those symbols are not
* stripped during final link.
*/
STATIC_YOINK("GetAdaptersAddresses");
STATIC_YOINK("tprecode16to8");

View file

@ -23,7 +23,9 @@
#include "libc/sysv/errfuns.h"
/**
* Creates new system resource for network communication.
* Creates new system resource for network communication, e.g.
*
* int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
*
* @param family can be AF_UNIX, AF_INET, etc.
* @param type can be SOCK_STREAM (for TCP), SOCK_DGRAM (e.g. UDP), or

View file

@ -67,7 +67,7 @@ struct dirstream {
struct {
unsigned buf_pos;
unsigned buf_end;
uint64_t buf[BUFSIZ / 8];
uint64_t buf[(BUFSIZ + 256) / 8];
};
struct {
bool isdone;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -58,6 +59,7 @@ FILE *fopen(const char *pathname, const char *mode) {
FILE *f;
bool noclose;
int fd, flags;
SYSDEBUG("fopen(%`'s)", pathname);
flags = fopenflags(mode);
pathname = fixpathname(pathname, flags);
if ((fd = openpathname(pathname, flags, &noclose)) != -1) {

View file

@ -2057,7 +2057,7 @@ syscon nr __NR_execve 0x003b 0x200003b 0x003b 0x003b 0x03b 0xfff # D
syscon nr __NR_wait4 0x003d 0x2000007 0x0007 0x000b 0x1c1 0xfff
syscon nr __NR_kill 0x003e 0x2000025 0x0025 0x007a 0x025 0xfff
syscon nr __NR_killpg 0xfff 0xfff 0x0092 0xfff 0xfff 0xfff
syscon nr __NR_clone 0x0038 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_clone 0x0038 0xfff 0xfff 0xfff 0x11f 0xfff
syscon nr __NR_tkill 0x00c8 0xfff 0xfff 0xfff 0xfff 0xfff
syscon nr __NR_futex 0x00ca 0xfff 0xfff 0x0053 0xfff 0xfff
syscon nr __NR_set_robust_list 0x0111 0xfff 0xfff 0xfff 0xfff 0xfff

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon nr,__NR_clone,0x0038,0xfff,0xfff,0xfff,0xfff,0xfff
.syscon nr,__NR_clone,0x0038,0xfff,0xfff,0xfff,0x11f,0xfff

26
libc/sysv/consts/clone.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define CLONE_VM 0x00000100
#define CLONE_FS 0x00000200
#define CLONE_FILES 0x00000400
#define CLONE_SIGHAND 0x00000800
#define CLONE_PTRACE 0x00002000
#define CLONE_VFORK 0x00004000
#define CLONE_PARENT 0x00008000
#define CLONE_THREAD 0x00010000
#define CLONE_NEWNS 0x00020000
#define CLONE_SYSVSEM 0x00040000
#define CLONE_SETTLS 0x00080000
#define CLONE_PARENT_SETTID 0x00100000
#define CLONE_CHILD_CLEARTID 0x00200000
#define CLONE_DETACHED 0x00400000
#define CLONE_UNTRACED 0x00800000
#define CLONE_CHILD_SETTID 0x01000000
#define CLONE_STOPPED 0x02000000
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLONE_H_ */

View file

@ -1,32 +1,32 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_
#define S_ISVTX 01000 /* THE STICKY BIT */
#define S_ISGID 02000 /* the setgid bit */
#define S_ISUID 04000 /* the setuid bit */
#define S_IXUSR 00100 /* user --x; just use octal */
#define S_IWUSR 00200 /* user -w-; just use octal */
#define S_IRUSR 00400 /* user r--; just use octal */
#define S_IRWXU 00700 /* user rwx; just use octal */
#define S_IXGRP 00010 /* group --x; just use octal */
#define S_IWGRP 00020 /* group -w-; just use octal */
#define S_IRGRP 00040 /* group r--; just use octal */
#define S_IRWXG 00070 /* group rwx; just use octal */
#define S_IXOTH 00001 /* other --x; just use octal */
#define S_IWOTH 00002 /* other -w-; just use octal */
#define S_IROTH 00004 /* other r--; just use octal */
#define S_IRWXO 00007 /* other rwx; just use octal */
#define S_IREAD 00400 /* just use octal */
#define S_IEXEC 00100 /* just use octal */
#define S_IWRITE 00200 /* just use octal */
#define S_IFIFO 0010000 /* pipe */
#define S_IFCHR 0020000 /* character device */
#define S_IFDIR 0040000 /* directory */
#define S_IFBLK 0060000 /* block device */
#define S_IFREG 0100000 /* regular file */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
#define S_IFMT 0170000 /* mask of file types above */
#define S_IFIFO (1 << 12) /* pipe */
#define S_IFCHR (2 << 12) /* character device */
#define S_IFDIR (4 << 12) /* directory */
#define S_IFBLK (6 << 12) /* block device */
#define S_IFREG (8 << 12) /* regular file */
#define S_IFLNK (10 << 12) /* symbolic link */
#define S_IFSOCK (12 << 12) /* socket */
#define S_IFMT (15 << 12) /* mask of file types above */
#define S_ISVTX 0001000 /* THE STICKY BIT */
#define S_ISGID 0002000 /* the setgid bit */
#define S_ISUID 0004000 /* the setuid bit */
#define S_IXUSR 0000100 /* user --x; just use octal */
#define S_IWUSR 0000200 /* user -w-; just use octal */
#define S_IRUSR 0000400 /* user r--; just use octal */
#define S_IRWXU 0000700 /* user rwx; just use octal */
#define S_IXGRP 0000010 /* group --x; just use octal */
#define S_IWGRP 0000020 /* group -w-; just use octal */
#define S_IRGRP 0000040 /* group r--; just use octal */
#define S_IRWXG 0000070 /* group rwx; just use octal */
#define S_IXOTH 0000001 /* other --x; just use octal */
#define S_IWOTH 0000002 /* other -w-; just use octal */
#define S_IROTH 0000004 /* other r--; just use octal */
#define S_IRWXO 0000007 /* other rwx; just use octal */
#define S_IREAD 0000400 /* just use octal */
#define S_IEXEC 0000100 /* just use octal */
#define S_IWRITE 0000200 /* just use octal */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_ */

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
@ -35,19 +36,18 @@ static int rmrfdir(const char *dirpath) {
while ((e = readdir(d))) {
if (!strcmp(e->d_name, ".")) continue;
if (!strcmp(e->d_name, "..")) continue;
if (strchr(e->d_name, '/')) abort();
assert(!strchr(e->d_name, '/'));
path = xjoinpaths(dirpath, e->d_name);
if (e->d_type == DT_DIR) {
rc = rmrfdir(path);
} else {
rc = unlink(path);
}
free(path);
if (rc == -1) {
free(path);
closedir(d);
return -1;
}
free(path);
}
rc = closedir(d);
rc |= rmdir(dirpath);

View file

@ -45,7 +45,7 @@ wchar_t *utf8toutf32(const char *p, size_t n, size_t *z) {
if (n == -1) n = p ? strlen(p) : 0;
if ((q = r = malloc(n * sizeof(wchar_t) + sizeof(wchar_t)))) {
for (i = 0; i < n;) {
if (0 && i + 16 < n) { /* 10x speedup for ascii */
if (i + 16 < n) { /* 10x speedup for ascii */
memset(vz, 0, 16);
do {
memcpy(v1, p + i, 16);

View file

@ -66,6 +66,8 @@ int rmrf(const char *);
int makedirs(const char *, unsigned);
char *xdirname(const char *) paramsnonnull() _XMAL;
char *xjoinpaths(const char *, const char *) paramsnonnull() _XMAL;
char *xreadlink(const char *) paramsnonnull() _XMAL;
char *xreadlinkat(int, const char *) paramsnonnull() _XMAL;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § eXtended apis » time

30
libc/x/xreadlink.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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
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/sysv/consts/at.h"
#include "libc/x/x.h"
/**
* Reads symbolic link.
*
* @return nul-terminated string, or null w/ errno
* @see readlink()
*/
char *xreadlink(const char *path) {
return xreadlinkat(AT_FDCWD, path);
}

47
libc/x/xreadlinkat.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- 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
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/calls.h"
#include "libc/mem/mem.h"
#include "libc/sysv/errfuns.h"
#include "libc/x/x.h"
/**
* Reads symbolic link.
*
* @return nul-terminated string, or null w/ errno
* @see readlinkat()
*/
char *xreadlinkat(int dirfd, const char *path) {
ssize_t rc;
size_t n, c;
char *p, *q;
c = PAGESIZE;
p = xmalloc(c);
if ((rc = readlinkat(dirfd, path, p, c)) != -1) {
if ((n = rc) < c) {
p[n] = 0;
if ((q = realloc(p, n + 1))) p = q;
return p;
} else {
enametoolong();
}
}
free(p);
return 0;
}

View file

@ -0,0 +1,60 @@
/*-*- 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
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/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/check.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
char testlib_enable_tmp_setup_teardown;
static textstartup void TestInit(int argc, char **argv) {
int fd;
if (argc == 2 && !strcmp(argv[1], "boop")) {
if ((fd = open("/dev/null", O_RDWR | O_CLOEXEC)) == 3) {
_exit(72);
} else {
_exit(fd + 1);
}
}
}
const void *const TestCtor[] initarray = {TestInit};
TEST(dup, clearsCloexecFlag) {
int ws;
ASSERT_SYS(0, 0, close(creat("file", 0644)));
ASSERT_SYS(0, 3, open("file", O_RDWR | O_CLOEXEC));
ASSERT_NE(-1, (ws = xspawn(0)));
if (ws == -2) {
dup2(3, 0);
execv(program_executable_name,
(char *const[]){program_executable_name, "boop", 0});
_exit(127);
}
ASSERT_EQ(72, WEXITSTATUS(ws));
ASSERT_SYS(0, 0, close(3));
}

View file

@ -22,6 +22,7 @@
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
@ -53,3 +54,12 @@ TEST(fcntl_setfl, testChangeAppendStatus) {
EXPECT_STREQ("foobar", buf);
EXPECT_NE(-1, close(fd));
}
TEST(fcntl, getfd) {
ASSERT_SYS(0, 3, open("/dev/null", O_RDWR));
ASSERT_SYS(0, 0, fcntl(3, F_GETFD));
ASSERT_SYS(0, 4, open("/dev/null", O_RDWR | O_CLOEXEC));
ASSERT_SYS(0, FD_CLOEXEC, fcntl(4, F_GETFD));
ASSERT_SYS(0, 0, close(4));
ASSERT_SYS(0, 0, close(3));
}

View file

@ -0,0 +1,41 @@
/*-*- 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
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/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
char testlib_enable_tmp_setup_teardown;
TEST(fileexists, test) {
EXPECT_SYS(0, 0, fileexists("doge"));
EXPECT_SYS(0, 0, isdirectory("doge"));
EXPECT_SYS(0, 0, close(creat("doge", 0644)));
EXPECT_SYS(0, 1, fileexists("doge"));
EXPECT_SYS(0, 0, isdirectory("doge"));
}
BENCH(fileexists, bench) {
struct stat st;
EZBENCH2("!stat", donothing, stat("doge", &st));
EZBENCH2("!fileexists", donothing, fileexists("doge"));
EXPECT_SYS(0, 0, close(creat("doge", 0644)));
EZBENCH2("stat", donothing, stat("doge", &st));
EZBENCH2("fileexists", donothing, fileexists("doge"));
}

View file

@ -1,10 +1,12 @@
#!/bin/sh
if [ "$MODE" = dbg ]; then
touch o/$MODE/test/libc/release/emulate.ok
exit # TODO
fi
if [ "$MODE" = opt ]; then
touch o/$MODE/test/libc/release/emulate.ok
exit
fi

View file

@ -1,10 +1,12 @@
#!/bin/sh
if [ "$MODE" = dbg ]; then
touch o/$MODE/test/libc/release/metal.ok
exit # TODO
fi
if [ "$MODE" = opt ]; then
touch o/$MODE/test/libc/release/metal.ok
exit
fi

View file

@ -0,0 +1,48 @@
/*-*- 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
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/assert.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/log/backtrace.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/sysv/consts/clone.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
volatile int x;
int thread(void *arg) {
return (x = 42);
}
TEST(clone, test) {
if (!IsLinux() && !IsNetbsd() && !IsWindows()) return;
char *stack;
long double t;
int tid, ptid, ctid, tls, ws;
t = nowl();
stack = gc(malloc(FRAMESIZE));
EXPECT_NE(-1, (tid = clone(thread, stack + FRAMESIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
0, &ptid, &tls, &ctid)));
while ((nowl() - t) < 1 && !x) asm("pause");
ASSERT_EQ(42, x);
}

View file

@ -16,64 +16,33 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/macros.internal.h"
#include "libc/runtime/gc.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/inaddr.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/sock.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#include "tool/decode/lib/flagger.h"
#include "tool/decode/lib/pollnames.h"
#if 0 /* todo(jart): fix me */
#define POLL(FDS, TIMEOUT) \
poll(((struct pollfd[])FDS), ARRAYLEN(((struct pollfd[])FDS)), TIMOUT)
nodiscard char *FormatPollFd(struct pollfd *pol) {
return xasprintf("fd:%d revents:%s", pol->fd,
gc(recreateflags(kPollNames, pol->revents)));
nodiscard char *FormatPollFd(struct pollfd p[2]) {
return xasprintf("fd:%d revents:%s\n"
"fd:%d revents:%s\n",
p[0].fd, gc(RecreateFlags(kPollNames, p[0].revents)),
p[1].fd, gc(RecreateFlags(kPollNames, p[1].revents)));
}
TEST(poll, testNegativeOneFd_completelyIgnored) {
struct pollfd fds[] = {{-1}};
EXPECT_EQ(0, poll(fds, ARRAYLEN(fds), 0));
EXPECT_STREQ("fd:-1 revents:0", gc(FormatPollFd(&fds[0])));
TEST(poll, testNegativeOneFd_isIgnored) {
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
struct sockaddr_in addr = {AF_INET, 0, {htonl(INADDR_LOOPBACK)}};
ASSERT_SYS(0, 0, bind(3, &addr, sizeof(addr)));
ASSERT_SYS(0, 0, listen(3, 10));
struct pollfd fds[] = {{-1}, {3}};
EXPECT_SYS(0, 0, poll(fds, ARRAYLEN(fds), 1));
EXPECT_STREQ("fd:-1 revents:0\n"
"fd:3 revents:0\n",
gc(FormatPollFd(&fds[0])));
ASSERT_SYS(0, 0, close(3));
}
TEST(poll, demo) {
int rw[2];
char buf[2] = "hi";
ASSERT_NE(-1, pipe(rw));
ASSERT_EQ(2, write(rw[1], buf, sizeof(buf))); /* produce */
{
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
EXPECT_EQ(2, poll(fds, ARRAYLEN(fds), 0));
system(gc(xasprintf("ls -l /proc/%d/fd", getpid())));
EXPECT_STREQ("fd:3 revents:POLLIN", gc(FormatPollFd(fds + 0)));
EXPECT_STREQ("fd:4 revents:POLLOUT", gc(FormatPollFd(&fds[1])));
}
ASSERT_EQ(2, read(rw[0], buf, sizeof(buf))); /* consume */
{
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
EXPECT_EQ(1, poll(fds, ARRAYLEN(fds), 0));
EXPECT_STREQ("fd:3 revents:0", gc(FormatPollFd(&fds[0])));
EXPECT_STREQ("fd:4 revents:POLLOUT", gc(FormatPollFd(&fds[1])));
}
ASSERT_NE(-1, close(rw[1])); /* close producer */
{
struct pollfd fds[] = {{rw[0], POLLIN}, {rw[1], POLLOUT}};
EXPECT_EQ(2, poll(fds, ARRAYLEN(fds), 0));
EXPECT_STREQ("fd:3 revents:POLLHUP", gc(FormatPollFd(&fds[0])));
EXPECT_STREQ("fd:4 revents:POLLNVAL", gc(FormatPollFd(&fds[1])));
}
ASSERT_NE(-1, close(rw[0])); /* close consumer */
}
#endif

View file

@ -94,15 +94,18 @@ TEST(highwayhash64, test) {
}
BENCH(highwayhash64, bench) {
EZBENCH2("crc32c small", donothing, crc32c(0, "hello", 5));
EZBENCH2("knuth small", donothing,
EXPROPRIATE(KnuthMultiplicativeHash32(VEIL("r", "hello"), 5)));
EZBENCH2("crc32c small", donothing, crc32c(0, "hello", 5));
EZBENCH2("crc32 small", donothing,
EXPROPRIATE(crc32_z(0, VEIL("r", "hello"), 5)));
EZBENCH2("highwayhash64 small", donothing,
HighwayHash64((void *)"hello", 5, kTestKey1));
EZBENCH2("crc32 big", donothing, crc32_z(0, kHyperion, kHyperionSize));
EZBENCH2("crc32c big", donothing, crc32c(0, kHyperion, kHyperionSize));
EZBENCH2("highwayhash64 big", donothing,
HighwayHash64((void *)kHyperion, kHyperionSize, kTestKey1));
EZBENCH2("knuth big", donothing,
EXPROPRIATE(
KnuthMultiplicativeHash32(VEIL("r", kHyperion), kHyperionSize)));
EZBENCH2("highwayhash64 big", donothing,
HighwayHash64((void *)kHyperion, kHyperionSize, kTestKey1));
}

View file

@ -193,6 +193,13 @@
#include "libc/sysv/consts/fileno.h"
#include "libc/x/x.h"
#include "third_party/linenoise/linenoise.h"
asm(".ident\t\"\\n\\n\
linenoise (BSD-2)\\n\
Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>\n\
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n\
Copyright (c) 2018-2020, Justine Tunney <jtunney at gmail dot com>\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
#define LINENOISE_MAX_LINE 4096

View file

@ -17,10 +17,14 @@
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/nt/runtime.h"
#include "libc/rand/rand.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/symbols.internal.h"
@ -28,6 +32,8 @@
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/nr.h"
#include "libc/x/x.h"
#include "third_party/mbedtls/config.h"
#include "third_party/mbedtls/endian.h"
#include "third_party/mbedtls/error.h"
@ -93,7 +99,7 @@ void mbedtls_test_platform_teardown(void) {
}
wontreturn void exit(int rc) {
if (rc) fwrite(output, 1, appendz(output).i, stderr);
if (rc) xwrite(1, output, appendz(output).i);
free(output);
__cxa_finalize(0);
_Exit(rc);

View file

@ -101,6 +101,7 @@ THIRD_PARTY_MBEDTLS_TEST_DIRECTDEPS = \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_KERNEL32 \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_STDIO \
@ -153,6 +154,10 @@ o/$(MODE)/third_party/mbedtls/test/lib.o: \
o/$(MODE)/third_party/mbedtls/test: \
$(THIRD_PARTY_MBEDTLS_TEST_CHECKS)
.PHONY: o/$(MODE)/third_party/mbedtls/test/TESTS
o/$(MODE)/third_party/mbedtls/test/TESTS: \
$(THIRD_PARTY_MBEDTLS_TEST_TESTS)
o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com: o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com.dbg
o/$(MODE)/third_party/mbedtls/test/test_suite_aes.cbc.com.dbg: \
$(THIRD_PARTY_MBEDTLS_TEST_DEPS) \

View file

@ -811,7 +811,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
if (has_timeout)
timeout = deadline - _PyTime_GetMonotonicClock();
if (err.ssl == SSL_ERROR_WANT_READ) {
if (err.ssl == SSL_ERROR_WANT_READ) {
sockstate = PySSL_select(sock, 0, timeout);
} else if (err.ssl == SSL_ERROR_WANT_WRITE) {
sockstate = PySSL_select(sock, 1, timeout);

View file

@ -1,3 +1,16 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/timeval.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/grnd.h"
#include "libc/time/time.h"
#include "third_party/python/Modules/expat/expat.h"
#include "third_party/python/Modules/expat/expat_config.h"
/* clang-format off */
/* f2d0ab6d1d4422a08cf1cf3bbdfba96b49dea42fb5ff4615e03a2a25c306e769 (2.2.8+)
__ __ _
@ -39,24 +52,7 @@ asm(".include \"libc/disclaimer.inc\"");
#define XML_BUILDING_EXPAT 1
#ifdef HAVE_EXPAT_CONFIG_H
#include "libc/sysv/consts/grnd.h"
#include "libc/rand/rand.h"
#include "libc/errno.h"
#include "libc/calls/struct/timeval.h"
#include "libc/time/time.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/stdio/stdio.h"
#include "libc/stdio/stdio.h"
#include "libc/calls/calls.h"
#include "libc/assert.h"
#include "libc/limits.h"
#include "third_party/python/Modules/expat/expat_config.h"
#endif
#include "third_party/python/Modules/expat/ascii.inc"
#include "third_party/python/Modules/expat/expat.h"
#include "third_party/python/Modules/expat/siphash.inc"
#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
@ -442,7 +438,6 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
static XML_Char *copyString(const XML_Char *s,
const XML_Memory_Handling_Suite *memsuite);
static unsigned long generate_hash_secret_salt(XML_Parser parser);
static XML_Bool startParsing(XML_Parser parser);
static XML_Parser parserCreate(const XML_Char *encodingName,
@ -592,193 +587,6 @@ static const XML_Char implicitContext[] = {
ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e,
'\0'};
/* To avoid warnings about unused functions: */
#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)
#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
/* Obtain entropy on Linux 3.17+ */
static int writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
int success = 0; /* full count bytes written? */
size_t bytesWrittenTotal = 0;
const unsigned int getrandomFlags = GRND_NONBLOCK;
do {
void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
const size_t bytesToWrite = count - bytesWrittenTotal;
const int bytesWrittenMore =
#if defined(HAVE_GETRANDOM)
getrandom(currentTarget, bytesToWrite, getrandomFlags);
#else
syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
#endif
if (bytesWrittenMore > 0) {
bytesWrittenTotal += bytesWrittenMore;
if (bytesWrittenTotal >= count) success = 1;
}
} while (!success && (errno == EINTR));
return success;
}
#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
#if !defined(_WIN32) && defined(XML_DEV_URANDOM)
/* Extract entropy from /dev/urandom */
static int writeRandomBytes_dev_urandom(void *target, size_t count) {
int success = 0; /* full count bytes written? */
size_t bytesWrittenTotal = 0;
const int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
return 0;
}
do {
void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
const size_t bytesToWrite = count - bytesWrittenTotal;
const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
if (bytesWrittenMore > 0) {
bytesWrittenTotal += bytesWrittenMore;
if (bytesWrittenTotal >= count) success = 1;
}
} while (!success && (errno == EINTR));
close(fd);
return success;
}
#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
#if defined(HAVE_ARC4RANDOM) && !defined(HAVE_ARC4RANDOM_BUF)
static void writeRandomBytes_arc4random(void *target, size_t count) {
size_t bytesWrittenTotal = 0;
while (bytesWrittenTotal < count) {
const uint32_t random32 = arc4random();
size_t i = 0;
for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
i++, bytesWrittenTotal++) {
const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
((uint8_t *)target)[bytesWrittenTotal] = random8;
}
}
}
#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
#ifdef _WIN32
/* Obtain entropy on Windows using the rand_s() function which
* generates cryptographically secure random numbers. Internally it
* uses RtlGenRandom API which is present in Windows XP and later.
*/
static int writeRandomBytes_rand_s(void *target, size_t count) {
size_t bytesWrittenTotal = 0;
while (bytesWrittenTotal < count) {
unsigned int random32 = 0;
size_t i = 0;
if (rand_s(&random32)) return 0; /* failure */
for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
i++, bytesWrittenTotal++) {
const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
((uint8_t *)target)[bytesWrittenTotal] = random8;
}
}
return 1; /* success */
}
#endif /* _WIN32 */
#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)
static unsigned long gather_time_entropy(void) {
#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft); /* never fails */
return ft.dwHighDateTime ^ ft.dwLowDateTime;
#else
struct timeval tv;
int gettimeofday_res;
gettimeofday_res = gettimeofday(&tv, NULL);
#if defined(NDEBUG)
(void)gettimeofday_res;
#else
assert(gettimeofday_res == 0);
#endif /* defined(NDEBUG) */
/* Microseconds time is <20 bits entropy */
return tv.tv_usec;
#endif
}
#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
static unsigned long ENTROPY_DEBUG(const char *label, unsigned long entropy) {
const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
if (EXPAT_ENTROPY_DEBUG && !strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
(int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
}
return entropy;
}
static unsigned long generate_hash_secret_salt(XML_Parser parser) {
unsigned long entropy;
(void)parser;
/* "Failproof" high quality providers: */
#if defined(HAVE_ARC4RANDOM_BUF)
arc4random_buf(&entropy, sizeof(entropy));
return ENTROPY_DEBUG("arc4random_buf", entropy);
#elif defined(HAVE_ARC4RANDOM)
writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
return ENTROPY_DEBUG("arc4random", entropy);
#else
/* Try high quality providers first .. */
#ifdef _WIN32
if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("rand_s", entropy);
}
#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("getrandom", entropy);
}
#endif
#if !defined(_WIN32) && defined(XML_DEV_URANDOM)
if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("/dev/urandom", entropy);
}
#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
/* .. and self-made low quality for backup: */
/* Process ID is 0 bits entropy if attacker has local access */
entropy = gather_time_entropy() ^ getpid();
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
if (sizeof(unsigned long) == 4) {
return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
} else {
return ENTROPY_DEBUG("fallback(8)",
entropy * (unsigned long)2305843009213693951ULL);
}
#endif
}
static unsigned long get_hash_secret_salt(XML_Parser parser) {
if (parser->m_parentParser != NULL)
return get_hash_secret_salt(parser->m_parentParser);
@ -789,7 +597,7 @@ static XML_Bool /* only valid for root parser */
startParsing(XML_Parser parser) {
/* hash functions must be initialized before setContext() is called */
if (parser->m_hash_secret_salt == 0)
parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
parser->m_hash_secret_salt = rand64();
if (parser->m_ns) {
/* implicit context only set for root parser, since child
parsers (i.e. external entity parsers) will inherit it

View file

@ -11,6 +11,7 @@
#include "libc/dns/dns.h"
#include "libc/dns/ent.h"
#include "libc/errno.h"
#include "libc/nt/enum/version.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sysv/consts/af.h"
@ -6803,8 +6804,7 @@ PyInit__socket(void)
PyModule_AddIntMacro(m, INADDR_BROADCAST);
PyModule_AddIntMacro(m, INADDR_LOOPBACK);
PyModule_AddIntMacro(m, INADDR_UNSPEC_GROUP);
PyModule_AddIntConstant(m, "INADDR_ALLHOSTS_GROUP",
INADDR_ALLHOSTS_GROUP);
PyModule_AddIntMacro(m, INADDR_ALLHOSTS_GROUP);
PyModule_AddIntMacro(m, INADDR_MAX_LOCAL_GROUP);
PyModule_AddIntMacro(m, INADDR_NONE);
@ -6930,9 +6930,9 @@ PyInit__socket(void)
if (TCP_USER_TIMEOUT) PyModule_AddIntMacro(m, TCP_USER_TIMEOUT);
if (TCP_SAVE_SYN) PyModule_AddIntMacro(m, TCP_SAVE_SYN);
if (TCP_SAVED_SYN) PyModule_AddIntMacro(m, TCP_SAVED_SYN);
if (TCP_KEEPCNT && (!IsWindows() || NtGetVersion() >= 10))
if (TCP_KEEPCNT && (!IsWindows() || NtGetVersion() >= kNtVersionWindows10))
PyModule_AddIntMacro(m, TCP_KEEPCNT);
if (TCP_FASTOPEN && (!IsWindows() || NtGetVersion() >= 10))
if (TCP_FASTOPEN && (!IsWindows() || NtGetVersion() >= kNtVersionWindows10))
PyModule_AddIntMacro(m, TCP_FASTOPEN);
if (TCP_FASTOPEN_CONNECT)
PyModule_AddIntMacro(m, TCP_FASTOPEN_CONNECT);

View file

@ -27,7 +27,7 @@
\n\
/*\n\
* Auto-generated by\n\
* %s \\\n\
* o/third_party/python/freeze \\\n\
* %s \\\n\
* %s\n\
*/\n\
@ -46,6 +46,8 @@ main(int argc, char *argv[])
PyObject *code = NULL, *marshalled = NULL;
int is_bootstrap = 1;
if (argc == 2 && !strcmp(argv[1], "-n")) return 0;
if (argc != 3) {
fprintf(stderr, "need to specify input and output paths\n");
return 2;
@ -115,7 +117,7 @@ main(int argc, char *argv[])
fprintf(stderr, "cannot open '%s' for writing\n", outpath);
goto error;
}
fprintf(outfile, HEADER, argv[0], argv[1], argv[2]);
fprintf(outfile, HEADER, argv[1], argv[2]);
if (is_bootstrap)
fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n");
else

View file

@ -8,7 +8,7 @@
/*
* Auto-generated by
* o/third_party/python/freeze.com \
* o/third_party/python/freeze \
* third_party/python/Lib/importlib/_bootstrap.py \
* third_party/python/Python/importlib.inc
*/

View file

@ -8,7 +8,7 @@
/*
* Auto-generated by
* o/third_party/python/freeze.com \
* o/third_party/python/freeze \
* third_party/python/Lib/importlib/_bootstrap_external.py \
* third_party/python/Python/importlib_external.inc
*/

View file

@ -235,8 +235,6 @@ THIRD_PARTY_PYTHON_INCS = \
third_party/python/Python/wordcode_helpers.inc \
third_party/python/Python/ceval_gil.inc \
third_party/python/Python/thread_nt.inc \
third_party/python/Python/importlib_external.inc \
third_party/python/Python/importlib.inc \
third_party/python/Python/clinic/import.inc \
third_party/python/Python/clinic/bltinmodule.inc \
third_party/python/Modules/expat/asciitab.inc \
@ -2266,6 +2264,16 @@ o/$(MODE)/third_party/python/freeze: \
@cp -f $< $@
@$@ -n
third_party/python/Python/importlib.inc: \
o/$(MODE)/third_party/python/freeze \
third_party/python/Lib/importlib/_bootstrap.py
@$(COMPILE) -AFREEZE $^ $@
third_party/python/Python/importlib_external.inc: \
o/$(MODE)/third_party/python/freeze \
third_party/python/Lib/importlib/_bootstrap_external.py
@$(COMPILE) -AFREEZE $^ $@
$(THIRD_PARTY_PYTHON_STAGE1_A): \
third_party/python \
$(THIRD_PARTY_PYTHON_STAGE1_A).pkg \
@ -2306,41 +2314,27 @@ $(THIRD_PARTY_PYTHON_STAGE2_A_OBJS): \
-DMULTIARCH='"x86_64-cosmo"'
o/$(MODE)/third_party/python/Modules/getbuildinfo.o: \
OVERRIDE_CFLAGS += \
-DGITVERSION='"3.6"' \
-DGITTAG='"3.6"' \
-DGITBRANCH='"cosmo"'
o/$(MODE)/third_party/python/Modules/_elementtree.o: \
OVERRIDE_CFLAGS += \
-DUSE_PYEXPAT_CAPI \
-DHAVE_EXPAT_CONFIG_H
o/$(MODE)/third_party/python/Modules/expat/xmlparse.o \
o/$(MODE)/third_party/python/Modules/expat/xmlrole.o \
o/$(MODE)/third_party/python/Modules/expat/xmltok.o \
o/$(MODE)/third_party/python/Modules/pyexpat.o: \
OVERRIDE_CFLAGS += \
-DXML_POOR_ENTROPY \
-DHAVE_EXPAT_CONFIG_H \
-DUSE_PYEXPAT_CAPI
-DGITVERSION='"3.6"' \
-DGITTAG='"3.6"' \
-DGITBRANCH='"cosmo"'
o/$(MODE)/third_party/python/Modules/_decimal/libmpdec/transpose.o: \
OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED
OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED
# Issue #23654: Turn off ICC's tail call optimization for the
# stack_overflow generator. ICC turns the recursive tail
# call into a loop. [Let's do GCC too, just to be safe.]
o/$(MODE)/third_party/python/Modules/faulthandler.o: \
OVERRIDE_CFLAGS += \
-fno-optimize-sibling-calls
OVERRIDE_CFLAGS += \
-fno-optimize-sibling-calls
$(THIRD_PARTY_PYTHON_STDLIB_PYS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_DIRS_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_DATA_OBJS): ZIPOBJ_FLAGS += -P.python -C3
$(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS): ZIPOBJ_FLAGS += -P.python -C5
.PRECIOUS: $(THIRD_PARTY_PYTHON_STDLIB_PYCS_OBJS)
.PRECIOUS: $(THIRD_PARTY_PYTHON_STDLIB_PYCS)
o/$(MODE)/third_party/python/Python/ceval.o: QUOTA = -M512m
o/$(MODE)/third_party/python/Objects/unicodeobject.o: QUOTA += -C16

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
@ -27,6 +28,7 @@
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/runtime/gc.internal.h"
#include "libc/sock/ipclassify.internal.h"
#include "libc/stdio/stdio.h"
@ -135,7 +137,6 @@ nodiscard char *MakeDeployScript(struct addrinfo *remotenic, size_t combytes) {
const char *ip4 = (const char *)&remotenic->ai_addr4->sin_addr;
return xasprintf("mkdir -p o/ && "
"dd bs=%zu count=%zu of=o/runitd.$$.com 2>/dev/null && "
"exec <&- && "
"chmod +x o/runitd.$$.com && "
"o/runitd.$$.com -rdl%hhu.%hhu.%hhu.%hhu -p %hu && "
"rm -f o/runitd.$$.com",
@ -293,9 +294,10 @@ void SendRequest(void) {
char *p;
size_t i;
ssize_t rc;
uint32_t crc;
struct stat st;
const char *name;
unsigned char *hdr;
unsigned char *hdr, *q;
size_t progsize, namesize, hdrsize;
DEBUGF("running %s on %s", g_prog, g_hostname);
CHECK_NE(-1, (fd = open(g_prog, O_RDONLY)));
@ -303,21 +305,16 @@ void SendRequest(void) {
CHECK_NE(MAP_FAILED, (p = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_LE((namesize = strlen((name = basename(g_prog)))), PATH_MAX);
CHECK_LE((progsize = st.st_size), INT_MAX);
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 4 + 1 + 4 + 4 + namesize)))));
hdr[0 + 0] = (unsigned char)((unsigned)RUNITD_MAGIC >> 030);
hdr[0 + 1] = (unsigned char)((unsigned)RUNITD_MAGIC >> 020);
hdr[0 + 2] = (unsigned char)((unsigned)RUNITD_MAGIC >> 010);
hdr[0 + 3] = (unsigned char)((unsigned)RUNITD_MAGIC >> 000);
hdr[4 + 0] = kRunitExecute;
hdr[5 + 0] = (unsigned char)((unsigned)namesize >> 030);
hdr[5 + 1] = (unsigned char)((unsigned)namesize >> 020);
hdr[5 + 2] = (unsigned char)((unsigned)namesize >> 010);
hdr[5 + 3] = (unsigned char)((unsigned)namesize >> 000);
hdr[9 + 0] = (unsigned char)((unsigned)progsize >> 030);
hdr[9 + 1] = (unsigned char)((unsigned)progsize >> 020);
hdr[9 + 2] = (unsigned char)((unsigned)progsize >> 010);
hdr[9 + 3] = (unsigned char)((unsigned)progsize >> 000);
memcpy(&hdr[4 + 1 + 4 + 4], name, namesize);
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 17 + namesize)))));
crc = crc32_z(0, p, st.st_size);
q = hdr;
q = WRITE32BE(q, RUNITD_MAGIC);
*q++ = kRunitExecute;
q = WRITE32BE(q, namesize);
q = WRITE32BE(q, progsize);
q = WRITE32BE(q, crc);
q = mempcpy(q, name, namesize);
assert(hdrsize == q - hdr);
CHECK_EQ(hdrsize, mbedtls_ssl_write(&ezssl, hdr, hdrsize));
for (i = 0; i < progsize; i += rc) {
CHECK_GT((rc = mbedtls_ssl_write(&ezssl, p + i, progsize - i)), 0);
@ -454,7 +451,7 @@ int RunRemoteTestsInParallel(char *hosts[], int count) {
}
int main(int argc, char *argv[]) {
showcrashreports();
ShowCrashReports();
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT, GetRunitPsk());
/* __log_level = kLogDebug; */
if (argc > 1 &&

View file

@ -23,6 +23,7 @@
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
@ -179,7 +180,16 @@ nodiscard char *DescribeAddress(struct sockaddr_in *addr) {
void StartTcpServer(void) {
int yes = true;
uint32_t asize;
/*
* TODO: How can we make close(serversocket) on Windows go fast?
* That way we can put back SOCK_CLOEXEC.
*/
CHECK_NE(-1, (g_servfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));
CHECK_NE(-1, dup2(g_servfd, 10));
CHECK_NE(-1, close(g_servfd));
g_servfd = 10;
LOGIFNEG1(setsockopt(g_servfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));
LOGIFNEG1(setsockopt(g_servfd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)));
if (bind(g_servfd, &g_servaddr, sizeof(g_servaddr)) == -1) {
@ -194,7 +204,6 @@ void StartTcpServer(void) {
CHECK_NE(-1, listen(g_servfd, 10));
asize = sizeof(g_servaddr);
CHECK_NE(-1, getsockname(g_servfd, &g_servaddr, &asize));
CHECK_NE(-1, fcntl(g_servfd, F_SETFD, FD_CLOEXEC));
LOGF("%s:%s", "listening on tcp", gc(DescribeAddress(&g_servaddr)));
if (g_sendready) {
printf("ready %hu\n", ntohs(g_servaddr.sin_port));
@ -252,15 +261,27 @@ void SetDeadline(int seconds, int micros) {
ITIMER_REAL, &(const struct itimerval){{0, 0}, {seconds, micros}}, NULL));
}
void Recv(void *p, size_t n) {
size_t i, rc;
for (i = 0; i < n; i += rc) {
do {
rc = mbedtls_ssl_read(&ezssl, (char *)p + i, n - i);
DEBUGF("read(%ld)", rc);
} while (rc == MBEDTLS_ERR_SSL_WANT_READ);
if (rc <= 0) TlsDie("read failed", rc);
}
DEBUGF("Recv(%ld)", n);
}
void HandleClient(void) {
const size_t kMinMsgSize = 4 + 1 + 4 + 4;
const size_t kMaxNameSize = 128;
const size_t kMaxFileSize = 10 * 1024 * 1024;
unsigned char *p;
uint32_t crc;
ssize_t got, wrote;
struct sockaddr_in addr;
char *addrstr, *exename;
sigset_t chldmask, savemask;
char *addrstr, *exename, *exe;
unsigned char msg[4 + 1 + 4 + 4 + 4];
struct sigaction ignore, saveint, savequit;
int rc, exitcode, wstatus, child, pipefds[2];
uint32_t addrsize, namesize, filesize, remaining;
@ -276,57 +297,26 @@ void HandleClient(void) {
EzHandshake();
addrstr = gc(DescribeAddress(&addr));
DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr);
while ((got = mbedtls_ssl_read(&ezssl, (p = g_buf), sizeof(g_buf))) < 0) {
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
TlsDie("ssl read failed", got);
}
}
CHECK_GE(got, kMinMsgSize);
CHECK_LE(got, sizeof(g_buf));
CHECK_EQ(RUNITD_MAGIC, READ32BE(p));
p += 4, got -= 4;
CHECK_EQ(kRunitExecute, *p++);
got--;
namesize = READ32BE(p), p += 4, got -= 4;
filesize = READ32BE(p), p += 4, got -= 4;
CHECK_GE(got, namesize);
CHECK_LE(namesize, kMaxNameSize);
CHECK_LE(filesize, kMaxFileSize);
exename = gc(xasprintf("%.*s", namesize, p));
Recv(msg, sizeof(msg));
CHECK_EQ(RUNITD_MAGIC, READ32BE(msg));
CHECK_EQ(kRunitExecute, msg[4]);
namesize = READ32BE(msg + 5);
filesize = READ32BE(msg + 9);
crc = READ32BE(msg + 13);
exename = gc(calloc(1, namesize + 1));
Recv(exename, namesize);
g_exepath = gc(xasprintf("o/%d.%s", getpid(), basename(exename)));
LOGF("%s asked we run %`'s (%,u bytes @ %`'s)", addrstr, exename, filesize,
g_exepath);
p += namesize, got -= namesize;
/* write the file to disk */
remaining = filesize;
exe = malloc(filesize);
Recv(exe, filesize);
if (crc32_z(0, exe, filesize) != crc) {
FATALF("%s crc mismatch! %`'s", addrstr, exename);
}
CHECK_NE(-1, (g_exefd = creat(g_exepath, 0700)));
ftruncate(g_exefd, filesize);
if (got) {
CHECK_EQ(got, write(g_exefd, p, got));
CHECK_LE(got, remaining);
remaining -= got;
}
while (remaining) {
while ((got = mbedtls_ssl_read(&ezssl, g_buf, sizeof(g_buf))) < 0) {
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
TlsDie("ssl read failed", got);
}
}
CHECK_LE(got, remaining);
if (!got) {
LOGF("%s %s %,u/%,u %s", addrstr, "sent", remaining, filesize,
"bytes before hangup");
unlink(g_exepath);
_exit(0);
}
remaining -= got;
p = g_buf;
do {
CHECK_GT((wrote = write(g_exefd, g_buf, got)), 0);
CHECK_LE(wrote, got);
} while ((got -= wrote));
}
LOGIFNEG1(ftruncate(g_exefd, filesize));
CHECK_NE(-1, xwrite(g_exefd, exe, filesize));
LOGIFNEG1(close(g_exefd));
/* run program, tee'ing stderr to both log and client */
@ -346,6 +336,8 @@ void HandleClient(void) {
sigaction(SIGINT, &saveint, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
dup2(g_devnullfd, 0);
dup2(pipefds[1], 1);
dup2(pipefds[1], 2);
execv(g_exepath, (char *const[]){g_exepath, NULL});
_exit(127);
@ -353,7 +345,8 @@ void HandleClient(void) {
LOGIFNEG1(close(pipefds[1]));
DEBUGF("communicating %s[%d]", exename, child);
while (!g_alarmed) {
if ((got = read(pipefds[0], g_buf, sizeof(g_buf))) != -1) {
got = read(pipefds[0], g_buf, sizeof(g_buf));
if (got != -1) {
if (!got) {
close(pipefds[0]);
break;
@ -377,10 +370,14 @@ void HandleClient(void) {
}
}
if (WIFEXITED(wstatus)) {
DEBUGF("%s exited with %d", exename, WEXITSTATUS(wstatus));
if (WEXITSTATUS(wstatus)) {
WARNF("%s exited with %d", exename, WEXITSTATUS(wstatus));
} else {
DEBUGF("%s exited with %d", exename, WEXITSTATUS(wstatus));
}
exitcode = WEXITSTATUS(wstatus);
} else {
DEBUGF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus)));
WARNF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus)));
exitcode = 128 + WTERMSIG(wstatus);
}
LOGIFNEG1(sigaction(SIGINT, &saveint, NULL));
@ -452,11 +449,11 @@ void Daemonize(void) {
}
int main(int argc, char *argv[]) {
showcrashreports();
ShowCrashReports();
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
/* __log_level = kLogDebug; */
GetOpts(argc, argv);
CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR)));
CHECK_EQ(3, (g_devnullfd = open("/dev/null", O_RDWR | O_CLOEXEC)));
defer(close_s, &g_devnullfd);
if (!isdirectory("o")) CHECK_NE(-1, mkdir("o", 0700));
if (g_daemonize) Daemonize();