mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Implement raw system call for redbean lua code
You can now call functions like fork() from Lua and it'll work across all supported platforms, including Windows. This gives you a level of control of the system that Lua traditionally hasn't been able to have due to its focus on old portable stdio rather modern POSIX APIs. Demo code has been added to redbean-demo.com to show how it works. This change also modifies Lua so that integer literals with a leading zero will be interpreted as octal. That should help avoid shooting in the foot with POSIX APIs that frequently use octal mode bits. This change fixes a bug in opendir(".") on New Technology. Lastly, redbean will now serve crash reports to private network IPs. This is consistent with other frameworks. However that isn't served to public IPs unless the -E flag is passed to redbean at startup.
This commit is contained in:
parent
f684e348d4
commit
281a0f2730
39 changed files with 2044 additions and 84 deletions
|
@ -229,7 +229,7 @@ uint32_t getgid(void) nosideeffect;
|
|||
uint32_t getpgrp(void) nosideeffect;
|
||||
uint32_t getsid(int) nosideeffect;
|
||||
uint32_t getuid(void) nosideeffect;
|
||||
uint32_t umask(int32_t);
|
||||
uint32_t umask(uint32_t);
|
||||
void rewinddir(DIR *);
|
||||
void sync(void);
|
||||
int getloadavg(double *, int);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* @param oldfd isn't closed afterwards
|
||||
* @param newfd if already assigned, is silently closed beforehand;
|
||||
* unless it's equal to oldfd, in which case dup2() is a no-op
|
||||
* @flags can have O_CLOEXEC
|
||||
* @param flags can have O_CLOEXEC
|
||||
* @see dup(), dup2()
|
||||
*/
|
||||
int dup3(int oldfd, int newfd, int flags) {
|
||||
|
|
|
@ -17,19 +17,23 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Returns parent process id.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int getppid(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
if (!IsNetbsd()) {
|
||||
return sys_getppid();
|
||||
rc = sys_getppid();
|
||||
} else {
|
||||
return sys_getpid().dx;
|
||||
rc = sys_getpid().dx;
|
||||
}
|
||||
} else {
|
||||
return sys_getppid_nt();
|
||||
rc = sys_getppid_nt();
|
||||
}
|
||||
STRACE("getppid() → %d% m", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Returns nice value of thing.
|
||||
|
@ -28,9 +29,12 @@
|
|||
* @see setpriority(), nice()
|
||||
*/
|
||||
int getpriority(int which, unsigned who) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
return sys_getpriority(which, who) - 20;
|
||||
rc = sys_getpriority(which, who) - 20;
|
||||
} else {
|
||||
return sys_getsetpriority_nt(which, who, 0, sys_getpriority_nt);
|
||||
rc = sys_getsetpriority_nt(which, who, 0, sys_getpriority_nt);
|
||||
}
|
||||
STRACE("getpriority(%d, %u) → %d% m", which, who, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -220,6 +220,7 @@ u32 sys_getgid(void) hidden;
|
|||
u32 sys_getsid(int) hidden;
|
||||
u32 sys_gettid(void) hidden;
|
||||
u32 sys_getuid(void) hidden;
|
||||
u32 sys_umask(u32) hidden;
|
||||
void *__sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden;
|
||||
void *sys_mremap(void *, u64, u64, i32, void *) hidden;
|
||||
void sys_exit(int) hidden;
|
||||
|
|
|
@ -17,10 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective group ID.
|
||||
*/
|
||||
int setegid(unsigned gid) {
|
||||
return setregid(-1, gid);
|
||||
int setegid(unsigned egid) {
|
||||
int rc;
|
||||
rc = setregid(-1, egid);
|
||||
STRACE("%s(%u) → %d% m", "setegid", egid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Sets effective user ID.
|
||||
*/
|
||||
int seteuid(unsigned euid) {
|
||||
return setreuid(-1, euid);
|
||||
int rc;
|
||||
rc = setreuid(-1, euid);
|
||||
STRACE("%s(%u) → %d% m", "seteuid", euid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Creates session and sets the process group id.
|
||||
* @return new session id, or -1 w/ errno
|
||||
*/
|
||||
int setsid(void) {
|
||||
return sys_setsid();
|
||||
int rc;
|
||||
rc = sys_setsid();
|
||||
STRACE("setsid() → %d% m", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
40
libc/calls/umask.c
Normal file
40
libc/calls/umask.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Sets file mode creation mask.
|
||||
*
|
||||
* @return previous mask
|
||||
* @note always succeeds
|
||||
*/
|
||||
unsigned umask(unsigned newmask) {
|
||||
unsigned oldmask;
|
||||
if (!IsWindows()) {
|
||||
oldmask = sys_umask(newmask);
|
||||
} else {
|
||||
// TODO(jart): what should we do with this?
|
||||
oldmask = newmask;
|
||||
}
|
||||
STRACE("umask(%#o) → %#o", oldmask);
|
||||
return oldmask;
|
||||
}
|
16
libc/fmt/kerrornames.internal.h
Normal file
16
libc/fmt/kerrornames.internal.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct ErrorName {
|
||||
int x, s;
|
||||
};
|
||||
|
||||
extern const struct ErrorName kStrSignal[];
|
||||
extern const struct ErrorName kErrorNames[];
|
||||
extern const struct ErrorName kErrorNamesLong[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_ */
|
|
@ -17,8 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
extern const struct { int x, s; } kErrorNamesLong[];
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to descriptive sentence.
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
extern const struct { int x, s; } kErrorNames[];
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to symbolic name.
|
||||
|
|
|
@ -17,6 +17,7 @@ const char *DescribeRemapFlags(int);
|
|||
|
||||
const char *DescribeNtPageFlags(uint32_t);
|
||||
const char *DescribeNtFileMapFlags(uint32_t);
|
||||
const char *DescribeNtFiletypeFlags(uint32_t);
|
||||
const char *DescribeNtFileFlagsAndAttributes(uint32_t);
|
||||
const char *DescribeNtFileShareFlags(uint32_t);
|
||||
const char *DescribeNtFileAccessFlags(uint32_t);
|
||||
|
|
35
libc/intrin/describentfiletypeflags.greg.c
Normal file
35
libc/intrin/describentfiletypeflags.greg.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/sysv/consts/mremap.h"
|
||||
|
||||
static const struct DescribeFlags kFiletypeFlags[] = {
|
||||
{kNtFileTypeRemote, "Remote"}, //
|
||||
{kNtFileTypePipe, "Pipe"}, // order matters
|
||||
{kNtFileTypeDisk, "Disk"}, //
|
||||
{kNtFileTypeChar, "Char"}, //
|
||||
};
|
||||
|
||||
const char *DescribeNtFiletypeFlags(uint32_t x) {
|
||||
static char filetypeflags[64];
|
||||
return DescribeFlags(filetypeflags, sizeof(filetypeflags), kFiletypeFlags,
|
||||
ARRAYLEN(kFiletypeFlags), "kNtFileType", x);
|
||||
}
|
52
libc/intrin/findfirstfile.greg.c
Normal file
52
libc/intrin/findfirstfile.greg.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/struct/win32finddata.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(FindFirstFile) *const __imp_FindFirstFileW __msabi;
|
||||
|
||||
/**
|
||||
* Finds first file in directory.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows int64_t FindFirstFile(const char16_t *lpFileName,
|
||||
struct NtWin32FindData *out_lpFindFileData) {
|
||||
int64_t hFindFile;
|
||||
hFindFile = __imp_FindFirstFileW(lpFileName, out_lpFindFileData);
|
||||
if (hFindFile != -1) {
|
||||
STRACE(
|
||||
"FindFirstFile(%#hs, [{"
|
||||
".cFileName=%#hs, "
|
||||
".dwFileAttributes=%s, "
|
||||
".dwFileType=%s"
|
||||
"}]) → %ld% m",
|
||||
lpFileName, out_lpFindFileData->cFileName,
|
||||
DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
|
||||
DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), hFindFile);
|
||||
} else {
|
||||
__winerr();
|
||||
STRACE("FindFirstFile(%#hs, [n/a]) → %ld% m", lpFileName, hFindFile);
|
||||
}
|
||||
return hFindFile;
|
||||
}
|
52
libc/intrin/findnextfile.greg.c
Normal file
52
libc/intrin/findnextfile.greg.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/struct/win32finddata.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
||||
extern typeof(FindNextFile) *const __imp_FindNextFileW __msabi;
|
||||
|
||||
/**
|
||||
* Finds more files in directory.
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows bool32 FindNextFile(int64_t hFindFile,
|
||||
struct NtWin32FindData *out_lpFindFileData) {
|
||||
bool32 ok;
|
||||
ok = __imp_FindNextFileW(hFindFile, out_lpFindFileData);
|
||||
if (ok) {
|
||||
STRACE(
|
||||
"FindNextFile(%ld, [{"
|
||||
".cFileName=%#hs, "
|
||||
".dwFileAttributes=%s, "
|
||||
".dwFileType=%s"
|
||||
"}]) → %hhhd% m",
|
||||
hFindFile, out_lpFindFileData->cFileName,
|
||||
DescribeNtFileFlagsAndAttributes(out_lpFindFileData->dwFileAttributes),
|
||||
DescribeNtFiletypeFlags(out_lpFindFileData->dwFileType), ok);
|
||||
} else {
|
||||
__winerr();
|
||||
STRACE("FindNextFile(%ld, [n/a]) → %hhhd% m", hFindFile, ok);
|
||||
}
|
||||
return ok;
|
||||
}
|
|
@ -70,7 +70,9 @@ o/$(MODE)/libc/intrin/createpipe.greg.o \
|
|||
o/$(MODE)/libc/intrin/closehandle.greg.o \
|
||||
o/$(MODE)/libc/intrin/openprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/createthread.greg.o \
|
||||
o/$(MODE)/libc/intrin/findnextfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/createprocess.greg.o \
|
||||
o/$(MODE)/libc/intrin/findfirstfile.greg.o \
|
||||
o/$(MODE)/libc/intrin/describeflags.greg.o \
|
||||
o/$(MODE)/libc/intrin/removedirectory.greg.o \
|
||||
o/$(MODE)/libc/intrin/createnamedpipe.greg.o \
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_FindFirstFileW,FindFirstFileW,0
|
||||
|
||||
.text.windows
|
||||
FindFirstFile:
|
||||
__FindFirstFile:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_FindFirstFileW(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn FindFirstFile,globl
|
||||
.endfn __FindFirstFile,globl
|
||||
.previous
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
.imp kernel32,__imp_FindNextFileW,FindNextFileW,0
|
||||
|
||||
.text.windows
|
||||
FindNextFile:
|
||||
__FindNextFile:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov __imp_FindNextFileW(%rip),%rax
|
||||
jmp __sysv2nt
|
||||
.endfn FindNextFile,globl
|
||||
.endfn __FindNextFile,globl
|
||||
.previous
|
||||
|
|
|
@ -327,7 +327,6 @@ imp 'FindClose' FindClose kernel32 0 1
|
|||
imp 'FindCloseChangeNotification' FindCloseChangeNotification kernel32 0
|
||||
imp 'FindFirstChangeNotification' FindFirstChangeNotificationW kernel32 0
|
||||
imp 'FindFirstChangeNotificationA' FindFirstChangeNotificationA kernel32 0
|
||||
imp 'FindFirstFile' FindFirstFileW kernel32 0 2
|
||||
imp 'FindFirstFileA' FindFirstFileA kernel32 0 2
|
||||
imp 'FindFirstFileEx' FindFirstFileExW kernel32 0 6
|
||||
imp 'FindFirstFileExA' FindFirstFileExA kernel32 0 6
|
||||
|
@ -344,7 +343,6 @@ imp 'FindFirstVolumeMountPointA' FindFirstVolumeMountPointA kernel32 393
|
|||
imp 'FindNLSString' FindNLSString kernel32 0
|
||||
imp 'FindNLSStringEx' FindNLSStringEx kernel32 0
|
||||
imp 'FindNextChangeNotification' FindNextChangeNotification kernel32 0
|
||||
imp 'FindNextFile' FindNextFileW kernel32 0 2
|
||||
imp 'FindNextFileA' FindNextFileA kernel32 0 2
|
||||
imp 'FindNextFileName' FindNextFileNameW kernel32 0
|
||||
imp 'FindNextStream' FindNextStreamW kernel32 0
|
||||
|
@ -1359,6 +1357,8 @@ imp '__CreateProcess' CreateProcessW kernel32 0 10
|
|||
imp '__CreateThread' CreateThread kernel32 0 6
|
||||
imp '__DeleteFile' DeleteFileW kernel32 0 1
|
||||
imp '__DeviceIoControl' DeviceIoControl kernel32 0 8
|
||||
imp '__FindFirstFile' FindFirstFileW kernel32 0 2
|
||||
imp '__FindNextFile' FindNextFileW kernel32 0 2
|
||||
imp '__FlushFileBuffers' FlushFileBuffers kernel32 0 1
|
||||
imp '__FlushViewOfFile' FlushViewOfFile kernel32 0 2
|
||||
imp '__GenerateConsoleCtrlEvent' GenerateConsoleCtrlEvent kernel32 0 2
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_CXAATEXIT_H_
|
||||
#include "libc/stdio/stdio.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
struct CxaAtexitBlocks {
|
||||
struct CxaAtexitBlock {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
* @param fd is the file descriptor returned by socket()
|
||||
* @param addr is usually the binary-encoded ip:port on which to listen
|
||||
* @param addrsize is the byte-length of addr's true polymorphic form
|
||||
* @return socket file descriptor or -1 w/ errno
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @error ENETDOWN, EPFNOSUPPORT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
* Creates bidirectional pipe.
|
||||
*
|
||||
* @param family should be AF_UNIX or synonymously AF_LOCAL
|
||||
* @param type may be or'd with SOCK_CLOEXEC
|
||||
* @param type can be SOCK_STREAM (for TCP), SOCK_DGRAM (e.g. UDP), or
|
||||
* SOCK_RAW (IP) so long as IP_HDRINCL was passed to setsockopt();
|
||||
* and additionally, may be or'd with SOCK_NONBLOCK, SOCK_CLOEXEC
|
||||
* @param sv a vector of 2 integers to store the created sockets
|
||||
* @return 0 if success, -1 in case of error
|
||||
* @error EFAULT, EPFNOSUPPORT, etc.
|
||||
|
|
|
@ -116,16 +116,18 @@ struct dirent_netbsd {
|
|||
static textwindows DIR *opendir_nt_impl(char16_t *name, size_t len) {
|
||||
DIR *res;
|
||||
if (len + 2 + 1 <= PATH_MAX) {
|
||||
if (len > 1 && name[len - 1] != u'\\') {
|
||||
name[len++] = u'\\';
|
||||
if (len == 1 && name[0] == '.') {
|
||||
name[0] = '*';
|
||||
} else {
|
||||
if (len > 1 && name[len - 1] != u'\\') {
|
||||
name[len++] = u'\\';
|
||||
}
|
||||
name[len++] = u'*';
|
||||
}
|
||||
name[len++] = u'*';
|
||||
name[len] = u'\0';
|
||||
if ((res = calloc(1, sizeof(DIR)))) {
|
||||
if ((res->fd = FindFirstFile(name, &res->windata)) != -1) {
|
||||
return res;
|
||||
} else {
|
||||
__winerr();
|
||||
}
|
||||
free(res);
|
||||
}
|
||||
|
@ -342,6 +344,7 @@ struct dirent *readdir(DIR *dir) {
|
|||
if (dir->buf_pos >= dir->buf_end) {
|
||||
basep = dir->tell; /* TODO(jart): what does xnu do */
|
||||
rc = getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep);
|
||||
STRACE("getdents(%d) → %d% m", dir->fd, rc);
|
||||
if (!rc || rc == -1) return NULL;
|
||||
dir->buf_pos = 0;
|
||||
dir->buf_end = rc;
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
extern const struct { int x, s; } kStrSignal[];
|
||||
|
||||
static char g_strsignal[12];
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall umask,0x03c03c03c203c05f,globl
|
||||
.scall sys_umask,0x03c03c03c203c05f,globl
|
|
@ -619,9 +619,9 @@ syscon clock CLOCK_REALTIME_COARSE 5 -1 -1 -1 -1 -1 # Linux 2.6.32
|
|||
syscon clock CLOCK_MONOTONIC_COARSE 6 -1 -1 -1 -1 -1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
|
||||
syscon clock CLOCK_PROF -1 -1 2 -1 2 -1 #
|
||||
syscon clock CLOCK_BOOTTIME 7 -1 -1 6 6 -1 #
|
||||
syscon clock CLOCK_REALTIME_ALARM 8 -1 -1 -1 -1 -1 # bsd consensus
|
||||
syscon clock CLOCK_BOOTTIME_ALARM 9 -1 -1 -1 -1 -1 # bsd consensus
|
||||
syscon clock CLOCK_TAI 11 -1 -1 -1 -1 -1 # bsd consensus
|
||||
syscon clock CLOCK_REALTIME_ALARM 8 -1 -1 -1 -1 -1 #
|
||||
syscon clock CLOCK_BOOTTIME_ALARM 9 -1 -1 -1 -1 -1 #
|
||||
syscon clock CLOCK_TAI 11 -1 -1 -1 -1 -1 #
|
||||
|
||||
# poll()
|
||||
#
|
||||
|
|
|
@ -134,7 +134,7 @@ scall sys_fchmod 0x07c07c07c207c05b globl hidden
|
|||
scall sys_chown 0x010010010201005c globl hidden # impl. w/ fchownat() @asyncsignalsafe
|
||||
scall sys_fchown 0x07b07b07b207b05d globl hidden # @asyncsignalsafe
|
||||
scall sys_lchown 0x1130fe0fe216c05e globl hidden # impl. w/ fchownat()
|
||||
scall umask 0x03c03c03c203c05f globl
|
||||
scall sys_umask 0x03c03c03c203c05f globl
|
||||
scall sys_gettimeofday 0x1a20430742074060 globl hidden # xnu esi/edx=0
|
||||
scall sys_getrlimit 0x0c20c20c220c2061 globl hidden
|
||||
scall __sys_getrusage 0x1bd0130752075062 globl hidden
|
||||
|
|
18
third_party/infozip/zip/fileio.c
vendored
18
third_party/infozip/zip/fileio.c
vendored
|
@ -1934,24 +1934,6 @@ int bfcopy(n)
|
|||
}
|
||||
|
||||
|
||||
|
||||
#ifdef NO_RENAME
|
||||
int rename(from, to)
|
||||
ZCONST char *from;
|
||||
ZCONST char *to;
|
||||
{
|
||||
unlink(to);
|
||||
if (link(from, to) == -1)
|
||||
return -1;
|
||||
if (unlink(from) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NO_RENAME */
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
* Split archives
|
||||
*/
|
||||
|
|
14
third_party/infozip/zip/unix/unix.c
vendored
14
third_party/infozip/zip/unix/unix.c
vendored
|
@ -56,20 +56,6 @@ typedef FILE DIR;
|
|||
** Cleaned up and modified by James W. Birdsall.
|
||||
*/
|
||||
|
||||
struct dirent *readdir(dirp)
|
||||
DIR *dirp;
|
||||
{
|
||||
static struct dirent entry;
|
||||
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
for (;;)
|
||||
if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)
|
||||
return NULL;
|
||||
else if (entry.d_ino)
|
||||
return (&entry);
|
||||
} /* end of readdir() */
|
||||
|
||||
#define closedir(dirp) fclose(dirp)
|
||||
#endif /* NO_DIR */
|
||||
|
||||
|
|
2
third_party/lua/README.cosmo
vendored
2
third_party/lua/README.cosmo
vendored
|
@ -20,6 +20,8 @@ PROVENANCE
|
|||
|
||||
LOCAL MODIFICATIONS
|
||||
|
||||
Integer literals such as `033` will now be interpreted as octal.
|
||||
|
||||
The `\e` string literal escape sequence has been added, which is
|
||||
equivalent to `\27` (the Lua version of `\033`) or the ASCII ESC
|
||||
character. It may be used for teletypewriter control like having
|
||||
|
|
1
third_party/lua/llex.c
vendored
1
third_party/lua/llex.c
vendored
|
@ -414,6 +414,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
|
|||
goto no_save;
|
||||
}
|
||||
default: {
|
||||
// TODO(jart): this is highly irregular it must become octal
|
||||
esccheck(ls, lisdigit(ls->current), "invalid escape sequence");
|
||||
c = readdecesc(ls); /* digital escape '\ddd' */
|
||||
goto only_save;
|
||||
|
|
12
third_party/lua/lobject.c
vendored
12
third_party/lua/lobject.c
vendored
|
@ -7,6 +7,7 @@
|
|||
#define lobject_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "third_party/lua/lctype.h"
|
||||
#include "third_party/lua/ldebug.h"
|
||||
#include "third_party/lua/ldo.h"
|
||||
|
@ -242,7 +243,9 @@ static const char *l_str2d (const char *s, lua_Number *result) {
|
|||
|
||||
|
||||
#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10)
|
||||
#define MAXBY8 cast(lua_Unsigned, LUA_MAXINTEGER / 8)
|
||||
#define MAXLASTD cast_int(LUA_MAXINTEGER % 10)
|
||||
#define MAXLASTD8 cast_int(LUA_MAXINTEGER % 8)
|
||||
|
||||
static const char *l_str2int (const char *s, lua_Integer *result) {
|
||||
lua_Unsigned a = 0;
|
||||
|
@ -258,6 +261,15 @@ static const char *l_str2int (const char *s, lua_Integer *result) {
|
|||
empty = 0;
|
||||
}
|
||||
}
|
||||
else if (s[0] == '0') { /* [jart] octal is the best radix */
|
||||
for (s += 1; lisdigit(cast_uchar(*s)); s++) {
|
||||
int d = *s - '0';
|
||||
if (a >= MAXBY8 && (a > MAXBY8 || d > MAXLASTD8 + neg)) /* overflow? */
|
||||
return NULL; /* do not accept it (as integer) */
|
||||
a = a * 8 + d;
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
else { /* decimal */
|
||||
for (; lisdigit(cast_uchar(*s)); s++) {
|
||||
int d = *s - '0';
|
||||
|
|
8
third_party/make/misc.c
vendored
8
third_party/make/misc.c
vendored
|
@ -360,14 +360,6 @@ char *mktemp (char *template);
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UMASK
|
||||
mode_t
|
||||
umask (mode_t mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *
|
||||
get_tmpfile (char **name, const char *template)
|
||||
{
|
||||
|
|
116
tool/net/demo/unix.lua
Normal file
116
tool/net/demo/unix.lua
Normal file
|
@ -0,0 +1,116 @@
|
|||
local unix = require "unix"
|
||||
|
||||
local function main()
|
||||
if GetMethod() ~= 'GET' and GetMethod() ~= 'HEAD' then
|
||||
ServeError(405)
|
||||
SetHeader('Allow', 'GET, HEAD')
|
||||
return
|
||||
end
|
||||
if IsClientUsingSsl() then
|
||||
SetStatus(400)
|
||||
SetHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
Write('<!doctype html>\r\n')
|
||||
Write('<title>redbean unix module</title>\r\n')
|
||||
Write('<h1>\r\n')
|
||||
Write('<img style="vertical-align:middle" src="data:image/png;base64,\r\n')
|
||||
Write(EncodeBase64(LoadAsset('/redbean.png')))
|
||||
Write('">\r\n')
|
||||
Write('redbean unix demo\r\n')
|
||||
Write('<span style="color:red"> error</span>\r\n')
|
||||
Write('</h1>\r\n')
|
||||
Write([[
|
||||
<p>
|
||||
The redbean unix module demo needs to intercept a raw unix
|
||||
socket. It's hard to do that if your file descriptor is
|
||||
encrypted with TLS. Please reload this page using http://
|
||||
rather than https://.
|
||||
</p>
|
||||
]])
|
||||
Write('</h1>\r\n')
|
||||
return
|
||||
end
|
||||
|
||||
-- steal client from redbean
|
||||
fd = GetClientFd()
|
||||
rc = unix.fork()
|
||||
if rc ~= 0 then
|
||||
unix.close(fd)
|
||||
return
|
||||
end
|
||||
|
||||
-- turn into a daemon
|
||||
unix.umask(0)
|
||||
unix.setsid()
|
||||
if unix.fork() > 0 then unix.exit(0) end
|
||||
unix.close(0)
|
||||
unix.open('/dev/null', unix.O_RDONLY)
|
||||
unix.close(1)
|
||||
unix.open('/dev/null', unix.O_WRONLY)
|
||||
efd = unix.open('/tmp/redbean-unix.log', unix.O_WRONLY | unix.O_CREAT | unix.O_TRUNC, 0600)
|
||||
unix.dup(efd, 2)
|
||||
unix.close(efd)
|
||||
unix.sigaction(unix.SIGHUP, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGINT, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGQUIT, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGTERM, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGUSR1, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGUSR2, unix.SIG_DFL)
|
||||
unix.sigaction(unix.SIGCHLD, unix.SIG_DFL)
|
||||
|
||||
-- communicate with client
|
||||
unix.write(fd, 'HTTP/1.0 200 OK\r\n' ..
|
||||
'Connection: close\r\n' ..
|
||||
'Date: '.. FormatHttpDateTime(GetDate()) ..'\r\n' ..
|
||||
'Content-Type: text/html; charset=utf-8\r\n' ..
|
||||
'Server: redbean unix\r\n' ..
|
||||
'\r\n')
|
||||
unix.write(fd, '<!doctype html>\n')
|
||||
unix.write(fd, '<title>redbean unix module</title>')
|
||||
unix.write(fd, '<h1>\r\n')
|
||||
unix.write(fd, '<img style="vertical-align:middle" src="data:image/png;base64,\r\n')
|
||||
unix.write(fd, EncodeBase64(LoadAsset('/redbean.png')))
|
||||
unix.write(fd, '">\r\n')
|
||||
unix.write(fd, 'redbean unix demo\r\n')
|
||||
unix.write(fd, '<span style="color:green"> success</span>\r\n')
|
||||
unix.write(fd, '</h1>\r\n')
|
||||
unix.write(fd, '<p>\r\n')
|
||||
unix.write(fd, 'your lua code just stole control of your http client\r\n')
|
||||
unix.write(fd, 'socket file descriptor from redbean server, and then\r\n')
|
||||
unix.write(fd, 'became an autonomous daemon reparented on your init!\r\n')
|
||||
unix.write(fd, '</p>\r\n')
|
||||
|
||||
unix.write(fd, '<h2>listing of current directory</h2>\r\n')
|
||||
dir, err = unix.opendir('.')
|
||||
if dir then
|
||||
unix.write(fd, '<ul>\r\n')
|
||||
while true do
|
||||
name, kind, ino, off = dir:read()
|
||||
if not name then
|
||||
break
|
||||
end
|
||||
unix.write(fd, '<li>')
|
||||
unix.write(fd, EscapeHtml(VisualizeControlCodes(name)))
|
||||
if kind == unix.DT_DIR then
|
||||
unix.write(fd, '/')
|
||||
else
|
||||
st, err = unix.stat(name)
|
||||
if st then
|
||||
unix.write(fd, string.format(' (%d bytes)', st:size()))
|
||||
end
|
||||
end
|
||||
unix.write(fd, '\r\n')
|
||||
end
|
||||
unix.write(fd, '</ul>\r\n')
|
||||
else
|
||||
unix.write(fd, '<p>\r\n')
|
||||
unix.write(fd, string.format('failed: %s\r\n', EscapeHtml(VisualizeControlCodes(unix:strerror(err)))))
|
||||
unix.write(fd, '</p>\r\n')
|
||||
end
|
||||
|
||||
-- terminate
|
||||
unix.close(fd)
|
||||
unix.exit(0)
|
||||
|
||||
end
|
||||
|
||||
main()
|
|
@ -35,6 +35,7 @@ FLAGS
|
|||
-a log resource usage
|
||||
-g log handler latency
|
||||
-e run specified Lua command
|
||||
-E show crash reports to public ips
|
||||
-j enable ssl client verify
|
||||
-k disable ssl fetch verify
|
||||
-f log worker function calls
|
||||
|
@ -585,6 +586,15 @@ FUNCTIONS
|
|||
instead, since the latter takes into consideration reverse proxy
|
||||
scenarios.
|
||||
|
||||
GetClientFd() → int
|
||||
Returns file descriptor being used for client connection.
|
||||
This is useful for scripts that want to use unix:fork().
|
||||
|
||||
IsClientUsingSsl() → bool
|
||||
Returns true if client connection has begun being managed by
|
||||
the MbedTLS security layer. This is an important thing to
|
||||
consider if a script is taking control of GetClientFd()
|
||||
|
||||
GetServerAddr() → ip:uint32,port:uint16
|
||||
Returns address to which listening server socket is bound, e.g.
|
||||
0x01020304,8080 would represent 1.2.3.4:8080. If -p 0 was supplied
|
||||
|
@ -734,6 +744,11 @@ FUNCTIONS
|
|||
Returns true if the client IP address (returned by GetRemoteAddr)
|
||||
is part of the localhost network (127.0.0.0/8).
|
||||
|
||||
IsPrivateClient() → bool
|
||||
Returns true if the client IP address (returned by GetRemoteAddr)
|
||||
is part of the localhost network (127.0.0.0/8) or a private network
|
||||
(10.0.0.0/8, etc.)
|
||||
|
||||
IsLoopbackIp(uint32) → bool
|
||||
Returns true if IP address is part of the localhost network
|
||||
(127.0.0.0/8).
|
||||
|
@ -1045,6 +1060,46 @@ FUNCTIONS
|
|||
Popcnt(x:int) → int
|
||||
Returns number of bits set in integer.
|
||||
|
||||
Rdtsc() → int
|
||||
Returns CPU timestamp counter.
|
||||
|
||||
Lemur64() → int
|
||||
Returns fastest pseudorandom non-cryptographic random number. This
|
||||
linear congruential generator passes practrand and bigcrush.
|
||||
|
||||
Rand64() → int
|
||||
Returns nondeterministic pseudorandom non-cryptographic number. This
|
||||
linear congruential generator passes practrand and bigcrush. This
|
||||
generator is safe across fork(), threads, and signal handlers.
|
||||
|
||||
Rdrand() → int
|
||||
Returns 64-bit hardware random integer from RDRND instruction, with
|
||||
automatic fallback to getrandom() if not available.
|
||||
|
||||
Rdseed() → int
|
||||
Returns 64-bit hardware random integer from RDSEED instruction, with
|
||||
automatic fallback to RDRND and getrandom() if not available.
|
||||
|
||||
GetCpuCore() → int
|
||||
Returns 0-indexed CPU core on which process is currently scheduled.
|
||||
|
||||
GetCpuNode() → int
|
||||
Returns 0-indexed NUMA node on which process is currently scheduled.
|
||||
|
||||
Decimate(data) → int
|
||||
Shrinks byte buffer in half using John Costella's magic kernel.
|
||||
This downscales data 2x using an eight-tap convolution, e.g.
|
||||
|
||||
>: Decimate(b'\\xff\\xff\\x00\\x00\\xff\\xff\\x00\\x00\\xff\\xff\\x00\\x00')
|
||||
b'\\xff\\x00\\xff\\x00\\xff\\x00'
|
||||
|
||||
This is very fast if SSSE3 is available (Intel 2004+ / AMD 2011+).
|
||||
|
||||
MeasureEntropy(data) → float
|
||||
Returns Shannon entropy of array. This gives you an idea of
|
||||
the density of information. Cryptographic random should be in
|
||||
the ballpark of 7.9 whereas plaintext will be more like 4.5.
|
||||
|
||||
LSQLITE3 MODULE
|
||||
|
||||
Please refer to the LuaSQLite3 Documentation.
|
||||
|
@ -1168,6 +1223,159 @@ MAXMIND MODULE
|
|||
|
||||
For further details, please see maxmind.lua in redbean-demo.com.
|
||||
|
||||
UNIX MODULE
|
||||
|
||||
This module exports the best raw system calls from Cosmopolitan Libc.
|
||||
These UNIX APIs are supported across all supported operating systems,
|
||||
and that includes Windows.
|
||||
|
||||
fork exit stat open close seek read write access fcntl chdir chown
|
||||
chmod getcwd kill raise wait pipe dup mkdir rmdir opendir rename
|
||||
link unlink symlink sync fsync fdatasync truncate umask getppid
|
||||
getpgid setpgid getsid setsid getpid getuid getgid gettime
|
||||
nanosleep socket socketpair bind listen accept connect recvfrom
|
||||
sendto shutdown getpeername getsockname sigaction sigprocmask
|
||||
strerror
|
||||
|
||||
This module also provides the following magic numbers:
|
||||
|
||||
O_RDONLY O_WRONLY O_RDWR O_ACCMODE O_CREAT O_EXCL O_TRUNC
|
||||
O_CLOEXEC O_APPEND O_TMPFILE O_NOFOLLOW O_SYNC O_ASYNC O_NOCTTY
|
||||
O_NOATIME O_EXEC O_SEARCH O_DSYNC O_RSYNC O_PATH O_VERIFY O_SHLOCK
|
||||
O_EXLOCK O_RANDOM O_SEQUENTIAL O_COMPRESSED O_INDEXED SEEK_SET
|
||||
SEEK_CUR SEEK_END F_GETFD F_SETFD F_GETFL F_SETFL F_UNLCK F_RDLCK
|
||||
F_WRLCK F_SETLK F_SETLKW FD_CLOEXEC R_OK W_OK X_OK F_OK WNOHANG
|
||||
CLOCK_REALTIME CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
|
||||
CLOCK_REALTIME_COARSE CLOCK_MONOTONIC_COARSE
|
||||
CLOCK_PROCESS_CPUTIME_ID CLOCK_TAI CLOCK_PROF CLOCK_BOOTTIME
|
||||
CLOCK_REALTIME_ALARM CLOCK_BOOTTIME_ALARM AF_UNSPEC AF_UNIX
|
||||
AF_INET SOCK_STREAM SOCK_DGRAM SOCK_CLOEXEC IPPROTO_TCP
|
||||
IPPROTO_UDP SHUT_RD SHUT_WR SHUT_RDWR MSG_WAITALL MSG_DONTROUTE
|
||||
MSG_PEEK MSG_OOB MSG_NOSIGNAL DT_UNKNOWN DT_REG DT_DIR DT_BLK
|
||||
DT_LNK DT_CHR DT_FIFO DT_SOCK AT_FDCWD AT_SYMLINK_NOFOLLOW
|
||||
SIG_BLOCK SIG_UNBLOCK SIG_SETMASK SIG_DFL SIG_IGN
|
||||
|
||||
Please see the Cosmopolitan Libc documentation for further details.
|
||||
There's also a /unix.lua file in redbean-demo.com that provides a
|
||||
glimpse of how these powerful APIs can be used. Here's a synopsis:
|
||||
|
||||
unix.fork() → childpid|0, errno
|
||||
unix.exit([exitcode]) → ⊥
|
||||
unix.access(path, mode) → rc, errno
|
||||
mode can be: R_OK, W_OK, X_OK, F_OK
|
||||
unix.mkdir(path, mode) → rc, errno
|
||||
mode should be octal
|
||||
unix.chdir(path) → rc, errno
|
||||
unix.unlink(path) → rc, errno
|
||||
unix.rmdir(path) → rc, errno
|
||||
unix.rename(oldpath, newpath) → rc, errno
|
||||
unix.link(existingpath, newpath) → rc, errno
|
||||
unix.symlink(target, linkpath) → rc, errno
|
||||
unix.chown(path, uid, gid) → rc, errno
|
||||
unix.chmod(path, mode) → rc, errno
|
||||
unix.getcwd(path, mode) → rc, errno
|
||||
unix.getpid() → pid
|
||||
unix.getppid() → pid
|
||||
unix.kill(pid, sig) → rc, errno
|
||||
unix.raise(sig) → rc, errno
|
||||
unix.wait(pid[, options]) → pid, wstatus, nil, errno
|
||||
unix.fcntl(fd, cmd[, arg]) → rc, errno
|
||||
unix.dup(oldfd[, newfd[, flags]]) → newfd, errno
|
||||
flags can have O_CLOEXEC
|
||||
unix.pipe([flags]) → reader, writer, errno
|
||||
flags can have O_CLOEXEC
|
||||
unix.getsid(pid) → sid, errno
|
||||
unix.getpgid(pid) → pgid, errno
|
||||
unix.umask(mask) → rc, errno
|
||||
unix.setpgid(pid, pgid) → pgid, errno
|
||||
unix.setsid() → sid, errno
|
||||
unix.getuid() → uid, errno
|
||||
unix.getgid() → gid, errno
|
||||
unix.gettime([clock]) → seconds, nanos, errno
|
||||
unix.nanosleep(seconds, nanos) → remseconds, remnanos, errno
|
||||
unix.sync(fd)
|
||||
unix.fsync(fd) → rc, errno
|
||||
unix.fdatasync(fd) → rc, errno
|
||||
unix.open(path, flags[, mode]) → fd, errno
|
||||
unix.close(fd) → rc, errno
|
||||
unix.seek(fd, offset, whence) → newpos, errno
|
||||
where whence ∈ {SEEK_SET, SEEK_CUR, SEEK_END}
|
||||
whence defaults to SEEK_SET
|
||||
unix.truncate(path, length) → rc, errno
|
||||
unix.truncate(fd, length) → rc, errno
|
||||
unix.read(fd[, bufsiz, offset]) → data, errno
|
||||
unix.write(fd, data[, offset]) → rc, errno
|
||||
unix.socket([family[, type[, protocol]]]) → fd, errno
|
||||
SOCK_CLOEXEC may be or'd into type
|
||||
family defaults to AF_INET
|
||||
type defaults to SOCK_STREAM
|
||||
protocol defaults to IPPROTO_TCP
|
||||
unix.socketpair([family[, type[, protocol]]]) → fd1, fd2, errno
|
||||
SOCK_CLOEXEC may be or'd into type
|
||||
family defaults to AF_INET
|
||||
type defaults to SOCK_STREAM
|
||||
protocol defaults to IPPROTO_TCP
|
||||
unix.bind(fd, ip, port) → rc, errno
|
||||
SOCK_CLOEXEC may be or'd into type
|
||||
family defaults to AF_INET
|
||||
type defaults to SOCK_STREAM
|
||||
protocol defaults to IPPROTO_TCP
|
||||
unix.connect(fd, ip, port) → rc, errno
|
||||
SOCK_CLOEXEC may be or'd into type
|
||||
family defaults to AF_INET
|
||||
type defaults to SOCK_STREAM
|
||||
protocol defaults to IPPROTO_TCP
|
||||
unix.listen(fd[, backlog]) → rc, errno
|
||||
unix.getsockname(fd) → ip, port, errno
|
||||
unix.getpeername(fd) → ip, port, errno
|
||||
unix.accept(serverfd) → clientfd, ip, port, errno
|
||||
unix.recvfrom(fd[, bufsiz[, flags]]) → data, ip, port, errno
|
||||
flags can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
|
||||
unix.sendto(fd, data, ip, port[, flags]) → sent, errno
|
||||
flags MSG_OOB, MSG_DONTROUTE, MSG_NOSIGNAL, etc.
|
||||
unix.shutdown(fd, how) → rc, errno
|
||||
how can be SHUT_RD, SHUT_WR, or SHUT_RDWR
|
||||
unix.sigprocmask(how, mask) → oldmask, errno
|
||||
how can be SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
|
||||
unix.sigaction(sig, handler[, flags[, mask]]) → rc, errno
|
||||
sig can be SIGINT, SIGQUIT, SIGTERM, SIGUSR1, etc.
|
||||
handler can be SIG_IGN or SIG_DFL for time being
|
||||
note: this api will be changed in the future
|
||||
unix.strerror(errno) → str
|
||||
|
||||
Here's your UnixStat* object.
|
||||
|
||||
unix.stat(path) → UnixStat*, errno
|
||||
unix.stat(fd) → UnixStat*, errno
|
||||
UnixStat:size() → bytes:int
|
||||
UnixStat:mode() → mode:int
|
||||
UnixStat:dev() → int
|
||||
UnixStat:ino() → int
|
||||
UnixStat:rdev() → int
|
||||
UnixStat:uid() → int
|
||||
UnixStat:gid() → int
|
||||
UnixStat:atim() → secs:int, nanosint
|
||||
UnixStat:mtim() → secs:int, nanosint
|
||||
UnixStat:ctim() → secs:int, nanosint
|
||||
UnixStat:blocks() → int
|
||||
UnixStat:blksize() → int
|
||||
|
||||
Here's your UnixDir* object.
|
||||
|
||||
unix.opendir(path) → UnixDir*, errno
|
||||
unix.opendir(fd) → UnixDir*, errno
|
||||
UnixDir:close()
|
||||
may be called multiple times
|
||||
called by the garbage collector too
|
||||
UnixDir:read() → name, kind, ino, off
|
||||
returns nil if no more entries
|
||||
kind can be DT_UNKNOWN/REG/DIR/BLK/LNK/CHR/FIFO/SOCK
|
||||
UnixDir:fd() → fd, errno
|
||||
EOPNOTSUPP if using /zip/
|
||||
EOPNOTSUPP if IsWindows()
|
||||
UnixDir:tell() → off
|
||||
UnixDir:rewind()
|
||||
|
||||
CONSTANTS
|
||||
|
||||
kLogDebug
|
||||
|
|
1326
tool/net/lunix.c
Normal file
1326
tool/net/lunix.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,7 @@ TOOL_NET_COMS = \
|
|||
o/$(MODE)/tool/net/wb.com
|
||||
|
||||
TOOL_NET_DIRECTDEPS = \
|
||||
DSP_SCALE \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
|
@ -88,6 +89,7 @@ o/$(MODE)/tool/net/redbean.com.dbg: \
|
|||
$(TOOL_NET_DEPS) \
|
||||
o/$(MODE)/tool/net/redbean.o \
|
||||
o/$(MODE)/tool/net/lre.o \
|
||||
o/$(MODE)/tool/net/lunix.o \
|
||||
o/$(MODE)/tool/net/lmaxmind.o \
|
||||
o/$(MODE)/tool/net/lsqlite3.o \
|
||||
o/$(MODE)/tool/net/largon2.o \
|
||||
|
@ -126,6 +128,7 @@ o/$(MODE)/tool/net/redbean.com: \
|
|||
o/$(MODE)/tool/net/demo/.init.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/.reload.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/hello.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/maxmind.lua.zip.o \
|
||||
|
@ -160,11 +163,13 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
|||
$(TOOL_NET_DEPS) \
|
||||
o/$(MODE)/tool/net/redbean.o \
|
||||
o/$(MODE)/tool/net/lre.o \
|
||||
o/$(MODE)/tool/net/lunix.o \
|
||||
o/$(MODE)/tool/net/lmaxmind.o \
|
||||
o/$(MODE)/tool/net/lsqlite3.o \
|
||||
o/$(MODE)/tool/net/largon2.o \
|
||||
o/$(MODE)/tool/net/net.pkg \
|
||||
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/hello.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
||||
|
@ -271,6 +276,7 @@ o/$(MODE)/tool/net/redbean-unsecure.com.dbg: \
|
|||
$(TOOL_NET_DEPS) \
|
||||
o/$(MODE)/tool/net/redbean-unsecure.o \
|
||||
o/$(MODE)/tool/net/lre.o \
|
||||
o/$(MODE)/tool/net/lunix.o \
|
||||
o/$(MODE)/tool/net/lmaxmind.o \
|
||||
o/$(MODE)/tool/net/lsqlite3.o \
|
||||
o/$(MODE)/tool/net/net.pkg \
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/scale/cdecimate2xuint8x8.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/popcnt.h"
|
||||
|
@ -46,6 +47,8 @@
|
|||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/rdtscp.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
|
@ -360,12 +363,13 @@ static bool isinitialized;
|
|||
static bool checkedmethod;
|
||||
static bool sslinitialized;
|
||||
static bool sslfetchverify;
|
||||
static bool hascontenttype;
|
||||
static bool sslclientverify;
|
||||
static bool connectionclose;
|
||||
static bool hasonworkerstop;
|
||||
static bool hasonworkerstart;
|
||||
static bool leakcrashreports;
|
||||
static bool hasonhttprequest;
|
||||
static bool hascontenttype;
|
||||
static bool ishandlingrequest;
|
||||
static bool listeningonport443;
|
||||
static bool hasonprocesscreate;
|
||||
|
@ -2978,13 +2982,25 @@ static char *GetLuaResponse(void) {
|
|||
return luaheaderp ? luaheaderp : SetStatus(200, "OK");
|
||||
}
|
||||
|
||||
static bool IsLoopbackClient() {
|
||||
static bool IsLoopbackClient(void) {
|
||||
uint32_t ip;
|
||||
uint16_t port;
|
||||
GetRemoteAddr(&ip, &port);
|
||||
return IsLoopbackIp(ip);
|
||||
}
|
||||
|
||||
static bool IsPrivateClient(void) {
|
||||
uint32_t ip;
|
||||
uint16_t port;
|
||||
GetRemoteAddr(&ip, &port);
|
||||
return IsLoopbackIp(ip) || IsPrivateIp(ip);
|
||||
}
|
||||
|
||||
static bool ShouldServeCrashReportDetails(void) {
|
||||
if (leakcrashreports) return true;
|
||||
return IsPrivateClient();
|
||||
}
|
||||
|
||||
static char *LuaOnHttpRequest(void) {
|
||||
char *error;
|
||||
lua_State *L = GL;
|
||||
|
@ -2996,9 +3012,9 @@ static char *LuaOnHttpRequest(void) {
|
|||
return CommitOutput(GetLuaResponse());
|
||||
} else {
|
||||
LogLuaError("OnHttpRequest", lua_tostring(L, -1));
|
||||
error =
|
||||
ServeErrorWithDetail(500, "Internal Server Error",
|
||||
IsLoopbackClient() ? lua_tostring(L, -1) : NULL);
|
||||
error = ServeErrorWithDetail(
|
||||
500, "Internal Server Error",
|
||||
ShouldServeCrashReportDetails() ? lua_tostring(L, -1) : NULL);
|
||||
lua_pop(L, 1); // pop error
|
||||
AssertLuaStackIsEmpty(L);
|
||||
return error;
|
||||
|
@ -3021,9 +3037,9 @@ static char *ServeLua(struct Asset *a, const char *s, size_t n) {
|
|||
} else {
|
||||
char *error;
|
||||
LogLuaError("lua code", lua_tostring(L, -1));
|
||||
error =
|
||||
ServeErrorWithDetail(500, "Internal Server Error",
|
||||
IsLoopbackClient() ? lua_tostring(L, -1) : NULL);
|
||||
error = ServeErrorWithDetail(
|
||||
500, "Internal Server Error",
|
||||
ShouldServeCrashReportDetails() ? lua_tostring(L, -1) : NULL);
|
||||
lua_pop(L, 1); // pop error
|
||||
return error;
|
||||
}
|
||||
|
@ -4109,6 +4125,12 @@ static int LuaIsLoopbackClient(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int LuaIsPrivateClient(lua_State *L) {
|
||||
OnlyCallDuringRequest(L, "IsPrivateClient");
|
||||
lua_pushboolean(L, IsPrivateClient());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaCategorizeIp(lua_State *L) {
|
||||
lua_pushstring(L, GetIpCategoryName(CategorizeIp(luaL_checkinteger(L, 1))));
|
||||
return 1;
|
||||
|
@ -5282,12 +5304,83 @@ static bool LuaRunAsset(const char *path, bool mandatory) {
|
|||
return !!a;
|
||||
}
|
||||
|
||||
static int LuaRdtsc(lua_State *L) {
|
||||
lua_pushinteger(L, rdtsc());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaGetCpuNode(lua_State *L) {
|
||||
lua_pushinteger(L, TSC_AUX_NODE(rdpid()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaGetCpuCore(lua_State *L) {
|
||||
lua_pushinteger(L, TSC_AUX_CORE(rdpid()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaRand(lua_State *L, uint64_t impl(void)) {
|
||||
lua_pushinteger(L, impl());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaLemur64(lua_State *L) {
|
||||
return LuaRand(L, lemur64);
|
||||
}
|
||||
|
||||
static int LuaRand64(lua_State *L) {
|
||||
return LuaRand(L, rand64);
|
||||
}
|
||||
|
||||
static int LuaRdrand(lua_State *L) {
|
||||
return LuaRand(L, rdrand);
|
||||
}
|
||||
|
||||
static int LuaRdseed(lua_State *L) {
|
||||
return LuaRand(L, rdseed);
|
||||
}
|
||||
|
||||
static int LuaDecimate(lua_State *L) {
|
||||
size_t n, m;
|
||||
const char *s;
|
||||
unsigned char *p;
|
||||
s = luaL_checklstring(L, 1, &n);
|
||||
m = ROUNDUP(n, 16);
|
||||
p = xmalloc(m);
|
||||
bzero(p + n, m - n);
|
||||
cDecimate2xUint8x8(m, p, (signed char[8]){-1, -3, 3, 17, 17, 3, -3, -1});
|
||||
lua_pushlstring(L, (char *)p, (n + 1) >> 1);
|
||||
free(p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaMeasureEntropy(lua_State *L) {
|
||||
size_t n;
|
||||
const char *s;
|
||||
s = luaL_checklstring(L, 1, &n);
|
||||
lua_pushnumber(L, MeasureEntropy(s, n));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaGetClientFd(lua_State *L) {
|
||||
OnlyCallDuringConnection(L, "GetClientFd");
|
||||
lua_pushinteger(L, client);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaIsClientUsingSsl(lua_State *L) {
|
||||
OnlyCallDuringConnection(L, "IsClientUsingSsl");
|
||||
lua_pushboolean(L, usessl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg kLuaFuncs[] = {
|
||||
{"Bsf", LuaBsf}, //
|
||||
{"Bsr", LuaBsr}, //
|
||||
{"CategorizeIp", LuaCategorizeIp}, //
|
||||
{"Crc32", LuaCrc32}, //
|
||||
{"Crc32c", LuaCrc32c}, //
|
||||
{"Decimate", LuaDecimate}, //
|
||||
{"DecodeBase64", LuaDecodeBase64}, //
|
||||
{"DecodeLatin1", LuaDecodeLatin1}, //
|
||||
{"EncodeBase64", LuaEncodeBase64}, //
|
||||
|
@ -5312,8 +5405,11 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
{"GetAssetSize", LuaGetAssetSize}, //
|
||||
{"GetBody", LuaGetBody}, //
|
||||
{"GetClientAddr", LuaGetClientAddr}, //
|
||||
{"GetClientFd", LuaGetClientFd}, //
|
||||
{"GetComment", LuaGetAssetComment}, //
|
||||
{"GetCookie", LuaGetCookie}, //
|
||||
{"GetCpuCore", LuaGetCpuCore}, //
|
||||
{"GetCpuNode", LuaGetCpuNode}, //
|
||||
{"GetCryptoHash", LuaGetCryptoHash}, //
|
||||
{"GetDate", LuaGetDate}, //
|
||||
{"GetEffectivePath", LuaGetEffectivePath}, //
|
||||
|
@ -5352,20 +5448,24 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
{"IsAcceptableHost", LuaIsAcceptableHost}, //
|
||||
{"IsAcceptablePath", LuaIsAcceptablePath}, //
|
||||
{"IsAcceptablePort", LuaIsAcceptablePort}, //
|
||||
{"IsClientUsingSsl", LuaIsClientUsingSsl}, //
|
||||
{"IsCompressed", LuaIsCompressed}, //
|
||||
{"IsDaemon", LuaIsDaemon}, //
|
||||
{"IsHeaderRepeatable", LuaIsHeaderRepeatable}, //
|
||||
{"IsHiddenPath", LuaIsHiddenPath}, //
|
||||
{"IsLoopbackClient", LuaIsLoopbackClient}, //
|
||||
{"IsLoopbackIp", LuaIsLoopbackIp}, //
|
||||
{"IsPrivateClient", LuaIsPrivateClient}, //
|
||||
{"IsPrivateIp", LuaIsPrivateIp}, //
|
||||
{"IsPublicIp", LuaIsPublicIp}, //
|
||||
{"IsReasonablePath", LuaIsReasonablePath}, //
|
||||
{"IsValidHttpToken", LuaIsValidHttpToken}, //
|
||||
{"LaunchBrowser", LuaLaunchBrowser}, //
|
||||
{"Lemur64", LuaLemur64}, //
|
||||
{"LoadAsset", LuaLoadAsset}, //
|
||||
{"Log", LuaLog}, //
|
||||
{"Md5", LuaMd5}, //
|
||||
{"MeasureEntropy", LuaMeasureEntropy}, //
|
||||
{"ParseHost", LuaParseHost}, //
|
||||
{"ParseHttpDateTime", LuaParseHttpDateTime}, //
|
||||
{"ParseIp", LuaParseIp}, //
|
||||
|
@ -5389,6 +5489,10 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
{"ProgramTimeout", LuaProgramTimeout}, //
|
||||
{"ProgramUid", LuaProgramUid}, //
|
||||
{"ProgramUniprocess", LuaProgramUniprocess}, //
|
||||
{"Rand64", LuaRand64}, //
|
||||
{"Rdrand", LuaRdrand}, //
|
||||
{"Rdseed", LuaRdseed}, //
|
||||
{"Rdtsc", LuaRdtsc}, //
|
||||
{"Route", LuaRoute}, //
|
||||
{"RouteHost", LuaRouteHost}, //
|
||||
{"RoutePath", LuaRoutePath}, //
|
||||
|
@ -5434,11 +5538,13 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
|
||||
int LuaMaxmind(lua_State *);
|
||||
int LuaRe(lua_State *);
|
||||
int LuaUnix(lua_State *);
|
||||
int luaopen_argon2(lua_State *);
|
||||
int luaopen_lsqlite3(lua_State *);
|
||||
|
||||
static const luaL_Reg kLuaLibs[] = {
|
||||
{"re", LuaRe}, //
|
||||
{"unix", LuaUnix}, //
|
||||
{"maxmind", LuaMaxmind}, //
|
||||
{"lsqlite3", luaopen_lsqlite3}, //
|
||||
#ifndef UNSECURE
|
||||
|
@ -6874,6 +6980,7 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
CASE('M', ProgramMaxPayloadSize(ParseInt(optarg)));
|
||||
#ifndef STATIC
|
||||
CASE('e', LuaRunCode(optarg));
|
||||
CASE('E', leakcrashreports = true);
|
||||
CASE('A', storeasset = true; StorePath(optarg));
|
||||
#endif
|
||||
#ifndef UNSECURE
|
||||
|
|
Loading…
Reference in a new issue