mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 14:09:12 +00:00
Make more fixes and improvements
This commit is contained in:
parent
01b25e267b
commit
1599b818d9
24 changed files with 858 additions and 538 deletions
|
@ -45,6 +45,7 @@ static const struct sock_filter kSandboxFilter[] = {
|
|||
_SECCOMP_ALLOW_SYSCALL(0x008), // lseek
|
||||
_SECCOMP_ALLOW_SYSCALL(0x009), // mmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00b), // munmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x04f), // getcwd
|
||||
_SECCOMP_ALLOW_SYSCALL(0x003), // close
|
||||
_SECCOMP_ALLOW_SYSCALL(0x010), // ioctl todo
|
||||
_SECCOMP_ALLOW_SYSCALL(0x016), // pipe
|
||||
|
@ -60,6 +61,15 @@ static const struct sock_filter kSandboxFilter[] = {
|
|||
_SECCOMP_ALLOW_SYSCALL(0x127), // preadv
|
||||
_SECCOMP_ALLOW_SYSCALL(0x128), // pwritev
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0d9), // getdents
|
||||
_SECCOMP_ALLOW_SYSCALL(0x027), // getpid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x066), // getuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x068), // getgid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06e), // getppid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06f), // getpgrp
|
||||
_SECCOMP_ALLOW_SYSCALL(0x07c), // getsid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06b), // geteuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06c), // getegid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x061), // getrlimit
|
||||
_SECCOMP_ALLOW_SYSCALL(0x028), // sendfile
|
||||
_SECCOMP_ALLOW_SYSCALL(0x02d), // recvfrom
|
||||
_SECCOMP_ALLOW_SYSCALL(0x033), // getsockname
|
||||
|
@ -67,7 +77,6 @@ static const struct sock_filter kSandboxFilter[] = {
|
|||
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
|
||||
_SECCOMP_ALLOW_SYSCALL(0x060), // gettimeofday
|
||||
_SECCOMP_ALLOW_SYSCALL(0x027), // getpid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
|
||||
_SECCOMP_ALLOW_SYSCALL(0x03c), // exit
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e7), // exit_group
|
||||
|
|
80
tool/net/demo/unix-info.lua
Normal file
80
tool/net/demo/unix-info.lua
Normal file
|
@ -0,0 +1,80 @@
|
|||
local unix = require 'unix'
|
||||
|
||||
Write('<!doctype html>\r\n')
|
||||
Write('<title>redbean</title>\r\n')
|
||||
Write('<h3>UNIX Information Demo</h3>\r\n')
|
||||
|
||||
Write('<dl>\r\n')
|
||||
Write('<dt>getuid()\r\n')
|
||||
Write(string.format('<dd>%d\r\n', unix.getuid()))
|
||||
Write('<dt>getgid()\r\n')
|
||||
Write(string.format('<dd>%d\r\n', unix.getgid()))
|
||||
Write('<dt>getpid()\r\n')
|
||||
Write(string.format('<dd>%d\r\n', unix.getpid()))
|
||||
Write('<dt>getppid()\r\n')
|
||||
Write(string.format('<dd>%d\r\n', unix.getppid()))
|
||||
Write('<dt>getpgrp()\r\n')
|
||||
Write(string.format('<dd>%d\r\n', unix.getpgrp()))
|
||||
|
||||
Write('<dt>getsid(0)\r\n')
|
||||
sid, errno = unix.getsid(0)
|
||||
if sid then
|
||||
Write(string.format('<dd>%d\r\n', sid))
|
||||
else
|
||||
Write(string.format('<dd>%s\r\n', EscapeHtml(unix.strerrno(errno))))
|
||||
end
|
||||
|
||||
Write('<dt>gethostname()\r\n')
|
||||
Write(string.format('<dd>%s\r\n', EscapeHtml(unix.gethostname())))
|
||||
Write('<dt>getcwd()\r\n')
|
||||
Write(string.format('<dd>%s\r\n', EscapeHtml(unix.getcwd())))
|
||||
|
||||
function PrintResourceLimit(name, id)
|
||||
soft, hard, errno = unix.getrlimit(id)
|
||||
Write(string.format('<dt>getrlimit(%s)\r\n', name))
|
||||
if soft then
|
||||
Write('<dd>')
|
||||
Write('soft ')
|
||||
if soft == -1 then
|
||||
Write('∞')
|
||||
else
|
||||
Write(string.format('%d', soft))
|
||||
end
|
||||
Write('<br>\r\n')
|
||||
Write('hard ')
|
||||
if hard == -1 then
|
||||
Write('∞')
|
||||
else
|
||||
Write(string.format('%d', hard))
|
||||
end
|
||||
Write('\r\n')
|
||||
else
|
||||
Write(string.format('<dd>%s\r\n', EscapeHtml(unix.strerrno(errno))))
|
||||
end
|
||||
end
|
||||
PrintResourceLimit('RLIMIT_AS', unix.RLIMIT_AS)
|
||||
PrintResourceLimit('RLIMIT_RSS', unix.RLIMIT_RSS)
|
||||
PrintResourceLimit('RLIMIT_CPU', unix.RLIMIT_CPU)
|
||||
PrintResourceLimit('RLIMIT_FSIZE', unix.RLIMIT_FSIZE)
|
||||
PrintResourceLimit('RLIMIT_NPROC', unix.RLIMIT_NPROC)
|
||||
PrintResourceLimit('RLIMIT_NOFILE', unix.RLIMIT_NOFILE)
|
||||
|
||||
Write('<dt>siocgifconf()\r\n')
|
||||
Write('<dd>\r\n')
|
||||
ifs, errno = unix.siocgifconf()
|
||||
if ifs then
|
||||
for i = 1,#ifs do
|
||||
if ifs[i].netmask ~= 0 then
|
||||
cidr = 32 - Bsf(ifs[i].netmask)
|
||||
else
|
||||
cidr = 0
|
||||
end
|
||||
Write(string.format('%s %s/%d<br>\r\n',
|
||||
EscapeHtml(ifs[i].name),
|
||||
FormatIp(ifs[i].ip),
|
||||
cidr))
|
||||
end
|
||||
else
|
||||
Write(string.format('%s\r\n', EscapeHtml(unix.strerrno(errno))))
|
||||
end
|
||||
Write('</dl>\r\n')
|
44
tool/net/demo/unix-subprocess.lua
Normal file
44
tool/net/demo/unix-subprocess.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
-- example of how to run the ls command
|
||||
-- and pipe its output to the http user
|
||||
local unix = require "unix"
|
||||
function main()
|
||||
syscall = 'commandv'
|
||||
ls, errno = unix.commandv("ls")
|
||||
if ls then
|
||||
syscall = 'pipe'
|
||||
reader, writer, errno = unix.pipe()
|
||||
if reader then
|
||||
syscall = 'fork'
|
||||
child, errno = unix.fork()
|
||||
if child then
|
||||
if child == 0 then
|
||||
unix.close(1)
|
||||
unix.dup(writer)
|
||||
unix.close(writer)
|
||||
unix.close(reader)
|
||||
unix.execve(ls, {ls, "-Shal"})
|
||||
unix.exit(127)
|
||||
else
|
||||
unix.close(writer)
|
||||
SetStatus(200)
|
||||
SetHeader('Content-Type', 'text/plain')
|
||||
while true do
|
||||
data = unix.read(reader)
|
||||
if data ~= "" then
|
||||
Write(data)
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
unix.close(reader)
|
||||
unix.wait(-1)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
SetStatus(200)
|
||||
SetHeader('Content-Type', 'text/plain')
|
||||
Write(string.format('error %s calling %s()', unix.strerrno(errno), syscall))
|
||||
end
|
||||
main()
|
|
@ -1,26 +0,0 @@
|
|||
-- example of how to run the ls command
|
||||
-- and pipe its output to the http user
|
||||
local unix = require "unix"
|
||||
ls = unix.commandv("ls")
|
||||
reader, writer = unix.pipe()
|
||||
if unix.fork() == 0 then
|
||||
unix.close(1)
|
||||
unix.dup(writer)
|
||||
unix.close(writer)
|
||||
unix.close(reader)
|
||||
unix.execve(ls, {ls, "-Shal"})
|
||||
unix.exit(127)
|
||||
else
|
||||
unix.close(writer)
|
||||
SetHeader('Content-Type', 'text/plain')
|
||||
while true do
|
||||
data = unix.read(reader)
|
||||
if data ~= "" then
|
||||
Write(data)
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
unix.close(reader)
|
||||
unix.wait(-1)
|
||||
end
|
|
@ -47,15 +47,16 @@ void PrintUsage(char **argv) {
|
|||
}
|
||||
|
||||
void UdpServer(void) {
|
||||
int ip;
|
||||
ssize_t rc;
|
||||
struct sockaddr_in addr2;
|
||||
uint32_t addrsize2 = sizeof(struct sockaddr_in);
|
||||
CHECK_NE(-1, (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)));
|
||||
CHECK_NE(-1, bind(sock, &addr, addrsize));
|
||||
CHECK_NE(-1, getsockname(sock, &addr2, &addrsize2));
|
||||
kprintf("udp server %hhu.%hhu.%hhu.%hhu %hu%n", addr2.sin_addr.s_addr >> 24,
|
||||
addr2.sin_addr.s_addr >> 16, addr2.sin_addr.s_addr >> 8,
|
||||
addr2.sin_addr.s_addr, addr2.sin_port);
|
||||
ip = ntohl(addr2.sin_addr.s_addr);
|
||||
kprintf("udp server %hhu.%hhu.%hhu.%hhu %hu%n", ip >> 24, ip >> 16, ip >> 8,
|
||||
ip, ntohs(addr2.sin_port));
|
||||
for (;;) {
|
||||
CHECK_NE(-1,
|
||||
(rc = recvfrom(sock, buf, sizeof(buf), 0, &addr2, &addrsize2)));
|
||||
|
@ -73,23 +74,23 @@ void UdpClient(void) {
|
|||
}
|
||||
|
||||
void TcpServer(void) {
|
||||
int client;
|
||||
ssize_t rc;
|
||||
int ip, client;
|
||||
struct sockaddr_in addr2;
|
||||
uint32_t addrsize2 = sizeof(struct sockaddr_in);
|
||||
CHECK_NE(-1, (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));
|
||||
CHECK_NE(-1, bind(sock, &addr, addrsize));
|
||||
CHECK_NE(-1, listen(sock, 10));
|
||||
CHECK_NE(-1, getsockname(sock, &addr2, &addrsize2));
|
||||
kprintf("tcp server %hhu.%hhu.%hhu.%hhu %hu%n", addr2.sin_addr.s_addr >> 24,
|
||||
addr2.sin_addr.s_addr >> 16, addr2.sin_addr.s_addr >> 8,
|
||||
addr2.sin_addr.s_addr, addr2.sin_port);
|
||||
ip = ntohl(addr2.sin_addr.s_addr);
|
||||
kprintf("tcp server %hhu.%hhu.%hhu.%hhu %hu%n", ip >> 24, ip >> 16, ip >> 8,
|
||||
ip, ntohs(addr2.sin_port));
|
||||
for (;;) {
|
||||
addrsize2 = sizeof(struct sockaddr_in);
|
||||
CHECK_NE(-1, (client = accept(sock, &addr2, &addrsize2)));
|
||||
kprintf("got client %hhu.%hhu.%hhu.%hhu %hu%n", addr2.sin_addr.s_addr >> 24,
|
||||
addr2.sin_addr.s_addr >> 16, addr2.sin_addr.s_addr >> 8,
|
||||
addr2.sin_addr.s_addr, addr2.sin_port);
|
||||
ip = ntohl(addr2.sin_addr.s_addr);
|
||||
kprintf("got client %hhu.%hhu.%hhu.%hhu %hu%n", ip >> 24, ip >> 16, ip >> 8,
|
||||
ip, ntohs(addr2.sin_port));
|
||||
for (;;) {
|
||||
CHECK_NE(-1, (rc = read(client, buf, sizeof(buf))));
|
||||
if (!rc) break;
|
||||
|
|
|
@ -1440,7 +1440,7 @@ UNIX MODULE
|
|||
end
|
||||
end
|
||||
unix.close(reader)
|
||||
unix.wait(-1)
|
||||
unix.wait()
|
||||
end
|
||||
|
||||
unix.wait([pid:int, options:int])
|
||||
|
@ -1705,6 +1705,28 @@ UNIX MODULE
|
|||
Further note that calling `unix.bind(sock)` is equivalent to not
|
||||
calling bind() at all, since the above behavior is the default.
|
||||
|
||||
unix.siocgifconf() → {{name:str,ip:uint32,netmask:uint32}, ...}[, errno:int]
|
||||
|
||||
Returns list of network adapter addresses.
|
||||
|
||||
unix.poll({fd:int=events:int, ...}[, timeoutms:int])
|
||||
→ {fd:int=revents:int, ...}[, errno:int]
|
||||
|
||||
Checks for events on a set of file descriptors.
|
||||
|
||||
The table of file descriptors to poll uses sparse integer keys. Any
|
||||
pairs with non-integer keys will be ignored. Pairs with negative
|
||||
keys are ignored by poll(). The returned table will be a subset of
|
||||
the supplied file descriptors.
|
||||
|
||||
`timeoutms` is the number of seconds to block. If this is set to -1
|
||||
then that means block as long as it takes until there's an event or
|
||||
an interrupt. If the timeout expires, an empty table is returned.
|
||||
|
||||
unix.gethostname() → host:str[, errno:int]
|
||||
|
||||
Returns hostname of system.
|
||||
|
||||
unix.listen(fd:int[, backlog]) → rc:int[, errno:int]
|
||||
|
||||
Begins listening for incoming connections on a socket.
|
||||
|
@ -1802,20 +1824,6 @@ UNIX MODULE
|
|||
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
|
||||
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
|
||||
|
||||
unix.reboot(how:int) → str
|
||||
|
||||
Changes power status of system.
|
||||
|
||||
`how` may be `RB_AUTOBOOT` to reboot, `RB_POWER_OFF` to power
|
||||
down, `RB_HALT_SYSTEM` to literally just stop the processor, or
|
||||
`RB_SW_SUSPEND` to put the machine into a suspend state. These
|
||||
magnums will be set to -1 if the method isn't supported on the
|
||||
host platform.
|
||||
|
||||
By default, an implicit sync() is performed. That's to help
|
||||
prevent you from losing data. If you don't want to shutdown
|
||||
gracefully, then you can bitwise or `RB_NOSYNC` into `how`.
|
||||
|
||||
unix.strerrno(errno:int) → str
|
||||
|
||||
Turns `errno` code into its symbolic name, e.g. `"EINTR"`.
|
||||
|
@ -1829,6 +1837,41 @@ UNIX MODULE
|
|||
Turns platform-specific `sig` code into its name, e.g.
|
||||
`strsignal(9)` always returns `"SIGKILL"`.
|
||||
|
||||
unix.setrlimit(resource:int, soft:int[, hard:int]) → rc:int[, errno:int]
|
||||
|
||||
Changes resource limit.
|
||||
|
||||
`resource` may be one of:
|
||||
|
||||
- `RLIMIT_AS` limits the size of the virtual address space. This
|
||||
will work on all platforms. It's emulated on XNU and Windows which
|
||||
means it won't propagate across execve() currently.
|
||||
|
||||
- `RLIMIT_CPU` causes `SIGXCPU` to be sent to the process when the
|
||||
soft limit on CPU time is exceeded, and the process is destroyed
|
||||
when the hard limit is exceeded. It works everywhere but Windows
|
||||
where it should be possible to poll getrusage() with setitimer()
|
||||
|
||||
- `RLIMIT_FSIZE` causes `SIGXFSZ` to sent to the process when the
|
||||
soft limit on file size is exceeded and the process is destroyed
|
||||
when the hard limit is exceeded. It works everywhere but Windows
|
||||
|
||||
- `RLIMIT_NPROC` limits the number of simultaneous processes and it
|
||||
should work on all platforms except Windows. Please be advised it
|
||||
limits the process, with respect to the activities of the user id
|
||||
as a whole.
|
||||
|
||||
- `RLIMIT_NOFILE` limits the number of open file descriptors and it
|
||||
should work on all platforms except Windows (TODO)
|
||||
|
||||
If a limit isn't supported by the host platform, it'll be set to
|
||||
127. On most platforms these limits are enforced by the kernel and
|
||||
as such are inherited by subprocesses.
|
||||
|
||||
unix.getrlimit(resource:int) → soft:int, hard:int[, errno:int]
|
||||
|
||||
Returns information about resource limit.
|
||||
|
||||
unix.stat(x) → UnixStat*, errno:int
|
||||
|
||||
Gets information about file or directory. `x` may be a file or
|
||||
|
|
166
tool/net/lunix.c
166
tool/net/lunix.c
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/kerrornames.internal.h"
|
||||
|
@ -52,13 +54,15 @@
|
|||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/reboot.h"
|
||||
#include "libc/sysv/consts/rlim.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/lua/lauxlib.h"
|
||||
|
@ -104,14 +108,6 @@ static dontinline int ReturnTimespec(lua_State *L, struct timespec *ts) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
static int ReturnRc(lua_State *L, int64_t rc, int olderr) {
|
||||
lua_pushinteger(L, rc);
|
||||
if (rc != -1) return 1;
|
||||
lua_pushinteger(L, errno);
|
||||
errno = olderr;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int ReturnErrno(lua_State *L, int nils, int olderr) {
|
||||
int i;
|
||||
for (i = 0; i < nils; ++i) {
|
||||
|
@ -122,6 +118,15 @@ static int ReturnErrno(lua_State *L, int nils, int olderr) {
|
|||
return nils + 1;
|
||||
}
|
||||
|
||||
static int ReturnRc(lua_State *L, int64_t rc, int olderr) {
|
||||
if (rc != -1) {
|
||||
lua_pushinteger(L, rc);
|
||||
return 1;
|
||||
} else {
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
}
|
||||
|
||||
static char **ConvertLuaArrayToStringList(lua_State *L, int i) {
|
||||
int j, n;
|
||||
char **p;
|
||||
|
@ -146,7 +151,7 @@ static char **ConvertLuaTableToEnvList(lua_State *L, int i) {
|
|||
lua_pushnil(L);
|
||||
for (n = 0; lua_next(L, i);) {
|
||||
if (lua_type(L, -2) == LUA_TSTRING) {
|
||||
p = xrealloc(p, (++n + 1) * sizeof(char *));
|
||||
p = xrealloc(p, (++n + 1) * sizeof(*p));
|
||||
p[n - 1] = xasprintf("%s=%s", lua_tostring(L, -2), lua_tostring(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
@ -322,12 +327,16 @@ static int LuaUnixChmod(lua_State *L) {
|
|||
|
||||
// unix.getcwd(path:str, mode:int) → rc:int[, errno:int]
|
||||
static int LuaUnixGetcwd(lua_State *L) {
|
||||
int olderr;
|
||||
char *path;
|
||||
path = getcwd(0, 0);
|
||||
assert(path);
|
||||
lua_pushstring(L, path);
|
||||
free(path);
|
||||
return 1;
|
||||
olderr = errno;
|
||||
if ((path = getcwd(0, 0))) {
|
||||
lua_pushstring(L, path);
|
||||
free(path);
|
||||
return 1;
|
||||
} else {
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
}
|
||||
|
||||
// unix.fork() → childpid|0:int[, errno:int]
|
||||
|
@ -374,9 +383,7 @@ static int LuaUnixExecve(lua_State *L) {
|
|||
execve(prog, argv, envp);
|
||||
FreeStringList(freeme1);
|
||||
FreeStringList(freeme2);
|
||||
lua_pushinteger(L, errno);
|
||||
errno = olderr;
|
||||
return 1;
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
|
||||
// unix.commandv(prog:str) → path:str[, errno:int]
|
||||
|
@ -450,8 +457,8 @@ static int LuaUnixGetrlimit(lua_State *L) {
|
|||
olderr = errno;
|
||||
resource = luaL_checkinteger(L, 1);
|
||||
if (!getrlimit(resource, &rlim)) {
|
||||
lua_pushinteger(L, rlim.rlim_cur);
|
||||
lua_pushinteger(L, rlim.rlim_max);
|
||||
lua_pushinteger(L, rlim.rlim_cur < RLIM_INFINITY ? rlim.rlim_cur : -1);
|
||||
lua_pushinteger(L, rlim.rlim_max < RLIM_INFINITY ? rlim.rlim_max : -1);
|
||||
return 2;
|
||||
} else {
|
||||
return ReturnErrno(L, 2, olderr);
|
||||
|
@ -931,7 +938,7 @@ static int LuaUnixGetsockname(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
// unix.getpeername(fd) → ip, port, errno
|
||||
// unix.getpeername(fd:int) → ip:uint32, port:uint16[, errno:int]
|
||||
static int LuaUnixGetpeername(lua_State *L) {
|
||||
int fd, olderr;
|
||||
uint32_t addrsize;
|
||||
|
@ -948,7 +955,72 @@ static int LuaUnixGetpeername(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
// unix.accept(serverfd:int) → clientfd:int, ip:uint32, port:uint16, errno
|
||||
// unix.siocgifconf() → {{name:str,ip:uint32,netmask:uint32}, ...}[, errno:int]
|
||||
static int LuaUnixSiocgifconf(lua_State *L) {
|
||||
size_t n;
|
||||
char *data;
|
||||
int i, fd, olderr;
|
||||
struct ifreq *ifr;
|
||||
struct ifconf conf;
|
||||
olderr = errno;
|
||||
if (!(data = malloc((n = 4096)))) {
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||
free(data);
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
conf.ifc_buf = data;
|
||||
conf.ifc_len = n;
|
||||
if (ioctl(fd, SIOCGIFCONF, &conf) == -1) {
|
||||
close(fd);
|
||||
free(data);
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
lua_newtable(L);
|
||||
i = 0;
|
||||
for (ifr = (struct ifreq *)data; (char *)ifr < data + conf.ifc_len; ++ifr) {
|
||||
if (ifr->ifr_addr.sa_family != AF_INET) continue;
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushstring(L, "name");
|
||||
lua_pushstring(L, ifr->ifr_name);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "ip");
|
||||
lua_pushinteger(
|
||||
L, ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr));
|
||||
lua_settable(L, -3);
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifr) != -1) {
|
||||
lua_pushstring(L, "netmask");
|
||||
lua_pushinteger(
|
||||
L, ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr));
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
close(fd);
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// unix.gethostname() → host:str[, errno:int]
|
||||
static int LuaUnixGethostname(lua_State *L) {
|
||||
int rc, olderr;
|
||||
char buf[DNS_NAME_MAX + 1];
|
||||
olderr = errno;
|
||||
if ((rc = gethostname(buf, sizeof(buf))) != -1) {
|
||||
if (strnlen(buf, sizeof(buf)) < sizeof(buf)) {
|
||||
lua_pushstring(L, buf);
|
||||
return 1;
|
||||
} else {
|
||||
enomem();
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
} else {
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
}
|
||||
|
||||
// unix.accept(serverfd:int) → clientfd:int, ip:uint32, port:uint16[, errno:int]
|
||||
static int LuaUnixAccept(lua_State *L) {
|
||||
uint32_t addrsize;
|
||||
struct sockaddr_in sa;
|
||||
|
@ -967,6 +1039,40 @@ static int LuaUnixAccept(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
// unix.poll({fd:int=events:int, ...}[, timeoutms:int])
|
||||
// → {fd:int=revents:int, ...}[, errno:int]
|
||||
static int LuaUnixPoll(lua_State *L) {
|
||||
size_t nfds;
|
||||
struct pollfd *fds;
|
||||
int i, fd, olderr, events, timeoutms;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_pushnil(L);
|
||||
for (fds = 0, nfds = 0; lua_next(L, 1);) {
|
||||
if (lua_isinteger(L, -2)) {
|
||||
fds = xrealloc(fds, ++nfds * sizeof(*fds));
|
||||
fds[nfds - 1].fd = lua_tointeger(L, -2);
|
||||
fds[nfds - 1].events = lua_tointeger(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
timeoutms = luaL_optinteger(L, 2, -1);
|
||||
olderr = errno;
|
||||
if ((events = poll(fds, nfds, timeoutms)) != -1) {
|
||||
lua_createtable(L, events, 0);
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
if (fds[i].revents && fds[i].fd >= 0) {
|
||||
lua_pushinteger(L, fds[i].revents);
|
||||
lua_rawseti(L, -2, fds[i].fd);
|
||||
}
|
||||
}
|
||||
free(fds);
|
||||
return 1;
|
||||
} else {
|
||||
free(fds);
|
||||
return ReturnErrno(L, 1, olderr);
|
||||
}
|
||||
}
|
||||
|
||||
// unix.recvfrom(fd[, bufsiz[, flags]]) → data, ip, port[, errno]
|
||||
// flags can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
|
||||
static int LuaUnixRecvfrom(lua_State *L) {
|
||||
|
@ -1286,11 +1392,6 @@ static int LuaUnixWtermsig(lua_State *L) {
|
|||
return ReturnInteger(L, WTERMSIG(luaL_checkinteger(L, 1)));
|
||||
}
|
||||
|
||||
// unix.reboot(how:int) → rc:int[, errno:int]
|
||||
static int LuaUnixReboot(lua_State *L) {
|
||||
return ReturnInteger(L, reboot(luaL_checkinteger(L, 1)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UnixStat* object
|
||||
|
||||
|
@ -1568,10 +1669,12 @@ static const luaL_Reg kLuaUnix[] = {
|
|||
{"setuid", LuaUnixSetuid}, // set real user id of process
|
||||
{"getgid", LuaUnixGetgid}, // get real group id of process
|
||||
{"setgid", LuaUnixSetgid}, // set real group id of process
|
||||
{"gethostname", LuaUnixGethostname}, // get hostname of this machine
|
||||
{"clock_gettime", LuaUnixGettime}, // get timestamp w/ nano precision
|
||||
{"nanosleep", LuaUnixNanosleep}, // sleep w/ nano precision
|
||||
{"socket", LuaUnixSocket}, // create network communication fd
|
||||
{"socketpair", LuaUnixSocketpair}, // create bidirectional pipe
|
||||
{"poll", LuaUnixPoll}, // waits for file descriptor events
|
||||
{"bind", LuaUnixBind}, // reserve network interface address
|
||||
{"listen", LuaUnixListen}, // begin listening for clients
|
||||
{"accept", LuaUnixAccept}, // create client fd for client
|
||||
|
@ -1583,11 +1686,11 @@ static const luaL_Reg kLuaUnix[] = {
|
|||
{"shutdown", LuaUnixShutdown}, // make socket half empty or full
|
||||
{"getpeername", LuaUnixGetpeername}, // get address of remote end
|
||||
{"getsockname", LuaUnixGetsockname}, // get address of local end
|
||||
{"siocgifconf", LuaUnixSiocgifconf}, // get list of network interfaces
|
||||
{"sigaction", LuaUnixSigaction}, // install signal handler
|
||||
{"sigprocmask", LuaUnixSigprocmask}, // change signal mask
|
||||
{"sigsuspend", LuaUnixSigsuspend}, // wait for signal
|
||||
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
||||
{"reboot", LuaUnixReboot}, // reboots system
|
||||
{"strerror", LuaUnixStrerror}, // turn errno into string
|
||||
{"strerrno", LuaUnixStrerrno}, // turn errno into string
|
||||
{"strsignal", LuaUnixStrsignal}, // turn signal into string
|
||||
|
@ -1765,12 +1868,5 @@ int LuaUnix(lua_State *L) {
|
|||
LuaSetIntField(L, "LOG_INFO", LOG_INFO);
|
||||
LuaSetIntField(L, "LOG_DEBUG", LOG_DEBUG);
|
||||
|
||||
// reboot() howto
|
||||
LuaSetIntField(L, "RB_AUTOBOOT", RB_AUTOBOOT);
|
||||
LuaSetIntField(L, "RB_POWER_OFF", RB_POWER_OFF);
|
||||
LuaSetIntField(L, "RB_HALT_SYSTEM", RB_HALT_SYSTEM);
|
||||
LuaSetIntField(L, "RB_SW_SUSPEND", RB_SW_SUSPEND);
|
||||
LuaSetIntField(L, "RB_NOSYNC", RB_NOSYNC);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,9 @@ o/tinylinux/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/unix-rawsocket.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-info.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 \
|
||||
|
@ -213,8 +215,9 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
|||
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/unix2.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-rawsocket.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
|
||||
o/$(MODE)/tool/net/demo/unix-info.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 \
|
||||
|
|
|
@ -6608,45 +6608,65 @@ static int ExitWorker(void) {
|
|||
static const struct sock_filter kSandboxOnline[] = {
|
||||
_SECCOMP_MACHINE(AUDIT_ARCH_X86_64), //
|
||||
_SECCOMP_LOAD_SYSCALL_NR(), //
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0013), // readv
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0014), // writev
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0009), // mmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000b), // munmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0000), // read
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0001), // write
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0003), // close
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0008), // lseek
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000f), // rt_sigreturn
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00e7), // exit_group
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0106), // newfstatat
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00e4), // clock_gettime
|
||||
_SECCOMP_ALLOW_SYSCALL(0x003f), // uname
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0048), // fcntl
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0029), // socket
|
||||
_SECCOMP_ALLOW_SYSCALL(0x002a), // connect
|
||||
_SECCOMP_ALLOW_SYSCALL(0x002c), // sendto
|
||||
_SECCOMP_ALLOW_SYSCALL(0x002d), // recvfrom
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0036), // setsockopt
|
||||
_SECCOMP_ALLOW_SYSCALL(0x013), // readv
|
||||
_SECCOMP_ALLOW_SYSCALL(0x014), // writev
|
||||
_SECCOMP_ALLOW_SYSCALL(0x009), // mmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00b), // munmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000), // read
|
||||
_SECCOMP_ALLOW_SYSCALL(0x001), // write
|
||||
_SECCOMP_ALLOW_SYSCALL(0x003), // close
|
||||
_SECCOMP_ALLOW_SYSCALL(0x008), // lseek
|
||||
_SECCOMP_ALLOW_SYSCALL(0x04f), // getcwd
|
||||
_SECCOMP_ALLOW_SYSCALL(0x027), // getpid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x066), // getuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x068), // getgid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06e), // getppid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06f), // getpgrp
|
||||
_SECCOMP_ALLOW_SYSCALL(0x07c), // getsid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06b), // geteuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06c), // getegid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x061), // getrlimit
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e7), // exit_group
|
||||
_SECCOMP_ALLOW_SYSCALL(0x106), // newfstatat
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
|
||||
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
|
||||
_SECCOMP_ALLOW_SYSCALL(0x048), // fcntl
|
||||
_SECCOMP_ALLOW_SYSCALL(0x029), // socket
|
||||
_SECCOMP_ALLOW_SYSCALL(0x02a), // connect
|
||||
_SECCOMP_ALLOW_SYSCALL(0x02c), // sendto
|
||||
_SECCOMP_ALLOW_SYSCALL(0x02d), // recvfrom
|
||||
_SECCOMP_ALLOW_SYSCALL(0x036), // setsockopt
|
||||
_SECCOMP_LOG_AND_RETURN_ERRNO(1), // EPERM
|
||||
};
|
||||
|
||||
static const struct sock_filter kSandboxOffline[] = {
|
||||
_SECCOMP_MACHINE(AUDIT_ARCH_X86_64), //
|
||||
_SECCOMP_LOAD_SYSCALL_NR(), //
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0013), // readv
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0014), // writev
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0000), // read
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0001), // write
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0009), // mmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000b), // munmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0003), // close
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0008), // lseek
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000f), // rt_sigreturn
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00e7), // exit_group
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0106), // newfstatat
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00e4), // clock_gettime
|
||||
_SECCOMP_ALLOW_SYSCALL(0x003f), // uname
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0048), // fcntl
|
||||
_SECCOMP_ALLOW_SYSCALL(0x013), // readv
|
||||
_SECCOMP_ALLOW_SYSCALL(0x014), // writev
|
||||
_SECCOMP_ALLOW_SYSCALL(0x000), // read
|
||||
_SECCOMP_ALLOW_SYSCALL(0x001), // write
|
||||
_SECCOMP_ALLOW_SYSCALL(0x009), // mmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00b), // munmap
|
||||
_SECCOMP_ALLOW_SYSCALL(0x003), // close
|
||||
_SECCOMP_ALLOW_SYSCALL(0x008), // lseek
|
||||
_SECCOMP_ALLOW_SYSCALL(0x04f), // getcwd
|
||||
_SECCOMP_ALLOW_SYSCALL(0x027), // getpid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x066), // getuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x068), // getgid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06e), // getppid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06f), // getpgrp
|
||||
_SECCOMP_ALLOW_SYSCALL(0x07c), // getsid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06b), // geteuid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x06c), // getegid
|
||||
_SECCOMP_ALLOW_SYSCALL(0x061), // getrlimit
|
||||
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e7), // exit_group
|
||||
_SECCOMP_ALLOW_SYSCALL(0x106), // newfstatat
|
||||
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
|
||||
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
|
||||
_SECCOMP_ALLOW_SYSCALL(0x048), // fcntl
|
||||
_SECCOMP_LOG_AND_RETURN_ERRNO(1), // EPERM
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue