Make improvements

- Add GetCpuCount() API to redbean
- Add unix.gmtime() API to redbean
- Add unix.readlink() API to redbean
- Add unix.localtime() API to redbean
- Perfect the new redbean UNIX module APIs
- Integrate with Linux clock_gettime() vDSO
- Run Lua garbage collector when malloc() fails
- Fix another regression quirk with linenoise repl
- Fix GetProgramExecutableName() for systemwide installs
- Fix a build flake with test/libc/mem/test.mk SRCS list
This commit is contained in:
Justine Tunney 2022-04-25 21:16:05 -07:00
parent 860ea18a87
commit d57b81aac7
51 changed files with 3096 additions and 1395 deletions

32
tool/decode/dumpvdso.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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/elf/struct/ehdr.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
noasan int main(int argc, char *argv[]) {
int i = 0;
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);
if (isatty(1)) exit(1);
for (;;) {
write(1, ((char *)ehdr) + i++, 1);
}
return 0;
}

View file

@ -27,8 +27,10 @@
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
@ -231,6 +233,21 @@ static void printelfsymboltable(void) {
}
}
static void printelfdynsymboltable(void) {
size_t i, symcount = 0;
Elf64_Sym *symtab = GetElfDynSymbolTable(elf, st->st_size, &symcount);
char *strtab = GetElfDynStringTable(elf, st->st_size);
char *shstrtab = GetElfSectionNameStringTable(elf, st->st_size);
if (symtab && strtab) {
printf("\n\n");
printf("\t.org\t%#x\n", (intptr_t)symtab - (intptr_t)elf);
for (i = 0; i < symcount; ++i) {
printf(".Lsym%d:\n", i);
printelfsymbol(&symtab[i], strtab, shstrtab);
}
}
}
static char *getelfsymbolname(const Elf64_Ehdr *elf, size_t mapsize,
const char *strtab, const char *shstrtab,
const Elf64_Sym *sym) {
@ -324,12 +341,14 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "error: not an elf executable: %'s\n", path);
exit(1);
}
elf = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);
startfile();
printelfehdr();
printelfsegmentheaders();
printelfsectionheaders();
printelfrelocations();
printelfsymboltable();
printelfdynsymboltable();
munmap(elf, st->st_size);
close(fd);
return 0;

2
tool/net/demo/script.lua Executable file
View file

@ -0,0 +1,2 @@
#!/usr/bin/redbean -i
print('hello world')

View file

@ -0,0 +1,93 @@
Write('<!doctype html>\r\n')
Write('<title>redbean</title>\r\n')
Write('<style>\r\n')
Write('td,th { padding: 2px 5px; }\r\n')
Write('td { white-space: nowrap; }\r\n')
Write('.l { text-align: left; }\r\n')
Write('.r { text-align: right; }\r\n')
Write('</style>\r\n')
Write('<h3>UNIX Directory Stream Demo</h3>\r\n')
Write('<table>\r\n')
Write('<thead>\r\n')
Write('<tr>\r\n')
Write('<th class=l>name\r\n')
Write('<th>type\r\n')
Write('<th class=r>ino\r\n')
Write('<th class=r>off\r\n')
Write('<th class=r>size\r\n')
Write('<th class=r>blocks\r\n')
Write('<th class=r>mode\r\n')
Write('<th class=r>uid\r\n')
Write('<th class=r>gid\r\n')
Write('<th class=r>dev\r\n')
Write('<th class=r>rdev\r\n')
Write('<th class=r>nlink\r\n')
Write('<th class=r>blksize\r\n')
Write('<th class=r>gen\r\n')
Write('<th class=r>flags\r\n')
Write('<th class=r>birthtim\r\n')
Write('<th class=r>mtim\r\n')
Write('<th class=r>atim\r\n')
Write('<th class=r>ctim\r\n')
Write('<tbody>\r\n')
dir = '.'
for name, kind, ino, off in assert(unix.opendir(dir)) do
Write('<tr>\r\n')
Write('<td>')
Write(EscapeHtml(name))
if kind == unix.DT_DIR then
Write('/')
end
Write('\r\n')
Write('<td>')
if kind == unix.DT_REG then Write('DT_REG')
elseif kind == unix.DT_DIR then Write('DT_DIR')
elseif kind == unix.DT_FIFO then Write('DT_FIFO')
elseif kind == unix.DT_CHR then Write('DT_CHR')
elseif kind == unix.DT_BLK then Write('DT_BLK')
elseif kind == unix.DT_LNK then Write('DT_LNK')
elseif kind == unix.DT_SOCK then Write('DT_SOCK')
else Write('DT_UNKNOWN')
end
Write('\r\n')
Write('<td class=r>%d\r\n' % {ino})
Write('<td class=r>%d\r\n' % {off})
st,err = unix.stat(dir..'/'..name, unix.AT_SYMLINK_NOFOLLOW)
if st then
Write('<td class=r>%d\r\n' % {st:size()})
Write('<td class=r>%d\r\n' % {st:blocks()})
Write('<td class=r>%.7o\r\n' % {st:mode()})
Write('<td class=r>%d\r\n' % {st:uid()})
Write('<td class=r>%d\r\n' % {st:gid()})
Write('<td class=r>%d\r\n' % {st:dev()})
Write('<td class=r>%d,%d\r\n' % {unix.major(st:rdev()), unix.minor(st:rdev())})
Write('<td class=r>%d\r\n' % {st:nlink()})
Write('<td class=r>%d\r\n' % {st:blksize()})
Write('<td class=r>%d\r\n' % {st:gen()})
Write('<td class=r>%#x\r\n' % {st:flags()})
function WriteTime(unixsec,nanos)
year,mon,mday,hour,min,sec,gmtoffsec = unix.localtime(unixsec)
Write('<td class=r>%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.9d%+.2d%.2d\r\n' % {
year, mon, mday, hour, min, sec, nanos,
gmtoffsec / (60 * 60), math.abs(gmtoffsec) % 60})
end
WriteTime(st:birthtim())
WriteTime(st:mtim())
WriteTime(st:atim())
WriteTime(st:ctim())
else
Write('<td class=l colspan=15>%s\r\n' % {err})
end
end
Write('</table>\r\n')

View file

@ -26,7 +26,7 @@ sid, errno = unix.getsid(0)
if sid then
Write('<dd>%d\r\n' % {sid})
else
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {tostring(errno)})
end
Write('<dt>unix.gethostname()\r\n')
@ -54,7 +54,7 @@ function PrintResourceLimit(name, id)
end
Write('\r\n')
else
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
end
end
PrintResourceLimit('RLIMIT_AS', unix.RLIMIT_AS)
@ -77,13 +77,13 @@ if ifs then
Write('%s %s/%d<br>\r\n' % {EscapeHtml(ifs[i].name), FormatIp(ifs[i].ip), cidr})
end
else
Write('%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('%s\r\n' % {EscapeHtml(tostring(errno))})
end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_DEBUG)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_DEBUG)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -91,7 +91,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_ACCEPTCONN)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_ACCEPTCONN)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -99,7 +99,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_REUSEADDR)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_REUSEADDR)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -107,7 +107,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_REUSEPORT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_REUSEPORT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -115,7 +115,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_KEEPALIVE)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_KEEPALIVE)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -123,7 +123,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_NODELAY)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_NODELAY)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -131,7 +131,7 @@ end
secs, errno, micros = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVTIMEO)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVTIMEO)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d sec %d µs\r\n' % {secs, micros})
end
@ -139,7 +139,7 @@ end
secs, errno, micros = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDTIMEO)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDTIMEO)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d sec %d µs\r\n' % {secs, micros})
end
@ -147,7 +147,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_DONTROUTE)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_DONTROUTE)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -155,7 +155,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDBUF)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDBUF)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -163,7 +163,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVBUF)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVBUF)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -171,7 +171,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_FASTOPEN)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_FASTOPEN)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -179,7 +179,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_BROADCAST)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_BROADCAST)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -187,7 +187,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_CORK)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_CORK)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -195,7 +195,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_QUICKACK)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_QUICKACK)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -203,7 +203,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_DEFER_ACCEPT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_DEFER_ACCEPT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -211,7 +211,7 @@ end
enabled, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_FASTOPEN_CONNECT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_FASTOPEN_CONNECT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%s\r\n' % {enabled})
end
@ -219,7 +219,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDLOWAT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_SNDLOWAT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -227,7 +227,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVLOWAT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_SOCKET, unix.SO_RCVLOWAT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -235,7 +235,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPCNT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPCNT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -243,7 +243,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_MAXSEG)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_MAXSEG)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -251,7 +251,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_SYNCNT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_SYNCNT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -259,7 +259,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_NOTSENT_LOWAT)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_NOTSENT_LOWAT)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -267,7 +267,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_WINDOW_CLAMP)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_WINDOW_CLAMP)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -275,7 +275,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPIDLE)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPIDLE)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end
@ -283,7 +283,7 @@ end
bytes, errno = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPINTVL)
Write('<dt>unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_KEEPINTVL)\r\n')
if errno then
Write('<dd>%s\r\n' % {EscapeHtml(unix.strerrno(errno))})
Write('<dd>%s\r\n' % {EscapeHtml(tostring(errno))})
else
Write('<dd>%d\r\n' % {bytes})
end

11
tool/net/demo/unix-raise.lua Executable file
View file

@ -0,0 +1,11 @@
#!/home/jart/bin/redbean -i
assert(unix.sigaction(unix.SIGUSR1, function(sig)
gotsigusr1 = true
end))
gotsigusr1 = false
assert(unix.raise(unix.SIGUSR1))
if gotsigusr1 then
print('hooray the signal was delivered')
else
print('oh no some other signal was handled')
end

View file

@ -1,4 +1,4 @@
local unix = require "unix"
local unix = require 'unix'
local function main()
if GetMethod() ~= 'GET' and GetMethod() ~= 'HEAD' then
@ -45,7 +45,7 @@ local function main()
Write(EncodeBase64(LoadAsset('/redbean.png')))
Write('">\r\n')
Write('redbean unix demo\r\n')
Write('<span style="color:red">&nbsp;%s</span>\r\n' % {unix.strerrno(errno)})
Write('<span style="color:red">&nbsp;%s</span>\r\n' % {EscapeHtml(tostring(errno))})
Write('</h1>\r\n')
Write([[
<p>
@ -63,7 +63,6 @@ local function main()
unix.close(fd)
return
end
-- if pid is zero then we're the child
-- turn into a daemon
unix.umask(0)
@ -106,34 +105,6 @@ local function main()
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, errno, 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, ' (%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, 'failed: %s\r\n' % {EscapeHtml(VisualizeControlCodes(unix:strerror(err)))})
unix.write(fd, '</p>\r\n')
end
-- terminate
unix.close(fd)
unix.exit(0)

View file

@ -9,55 +9,48 @@ function main()
end
syscall = 'commandv'
ls = assert(unix.commandv(cmd))
if ls then
syscall = 'pipe'
reader, writer, errno = unix.pipe()
if reader then
-- oldint = assert(unix.sigaction(unix.SIGINT, unix.SIG_IGN))
-- oldquit = assert(unix.sigaction(unix.SIGQUIT, unix.SIG_IGN))
-- oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, (1 << (unix.SIGCHLD - 1))))
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.sigaction(unix.SIGINT, oldint)
-- unix.sigaction(unix.SIGQUIT, oldquit)
-- unix.sigprocmask(unix.SIG_SETMASK, oldmask)
unix.execve(ls, {ls, '-Shal'})
unix.exit(127)
syscall = 'pipe'
reader, writer = assert(unix.pipe(unix.O_CLOEXEC))
oldint = assert(unix.sigaction(unix.SIGINT, unix.SIG_IGN))
oldquit = assert(unix.sigaction(unix.SIGQUIT, unix.SIG_IGN))
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGCHLD)))
syscall = 'fork'
child = assert(unix.fork())
if child == 0 then
unix.close(0)
unix.open("/dev/null", unix.O_RDONLY)
unix.close(1)
unix.dup(writer)
unix.close(2)
unix.open("/dev/null", unix.O_RDONLY)
unix.sigaction(unix.SIGINT, oldint)
unix.sigaction(unix.SIGQUIT, oldquit)
unix.sigprocmask(unix.SIG_SETMASK, oldmask)
unix.execve(ls, {ls, '-Shal'})
unix.exit(127)
else
unix.close(writer)
SetStatus(200)
SetHeader('Content-Type', 'text/plain')
while true do
data, err = unix.read(reader)
if data then
if data ~= '' then
Write(data)
else
unix.close(writer)
SetStatus(200)
SetHeader('Content-Type', 'text/plain')
while true do
data, errno = unix.read(reader)
if data then
if data ~= '' then
Write(data)
else
break
end
elseif errno ~= unix.EINTR then
Log(kLogWarn, 'read() failed: %s' % {unix.strerror(errno)})
break
end
end
unix.close(reader)
unix.wait(-1)
-- unix.sigaction(unix.SIGINT, oldint)
-- unix.sigaction(unix.SIGQUIT, oldquit)
-- unix.sigprocmask(unix.SIG_SETMASK, oldmask)
return
break
end
elseif err:errno() ~= unix.EINTR then
Log(kLogWarn, 'read() failed: %s' % {tostring(err)})
break
end
end
unix.close(reader)
unix.wait(-1)
unix.sigaction(unix.SIGINT, oldint)
unix.sigaction(unix.SIGQUIT, oldquit)
unix.sigprocmask(unix.SIG_SETMASK, oldmask)
return
end
SetStatus(200)
SetHeader('Content-Type', 'text/plain')
Write('error %s calling %s()' % {unix.strerrno(errno), syscall})
end
main()

View file

@ -45,7 +45,7 @@ function main()
server = unix.socket()
unix.bind(server, ifs[i].ip)
unix.listen(server)
ip, errno, port = unix.getsockname(server)
ip, port = assert(unix.getsockname(server))
addr = '%s:%d' % {FormatIp(ip), port}
url = 'http://%s' % {addr}
Log(kLogInfo, 'listening on %s' % {addr})
@ -65,7 +65,7 @@ function main()
if fd == mainfd then
data, errno = unix.read(mainfd)
if not data then
Log(kLogInfo, 'got %s from parent client' % {unix.strerrno(errno)})
Log(kLogInfo, 'got %s from parent client' % {tostring(errno)})
-- prevent redbean core from writing a response
unix.exit(1)
end
@ -79,8 +79,7 @@ function main()
unix.write(mainfd, data)
elseif servers[fd] then
unix.write(mainfd, 'preparing to accept from %d<br>\r\n' % {fd})
client, errno, clientip, clientport = unix.accept(fd)
unix.write(mainfd, 'preparing to accept from %d<br>\r\n' % {fd})
client, clientip, clientport = assert(unix.accept(fd))
addr = '%s:%d' % {FormatIp(clientip), clientport}
addrs[client] = addr
unix.write(mainfd, 'got client %s<br>\r\n' % {addr})

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,7 @@
#include "libc/nexgen32e/rdtscp.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/sysconf.h"
#include "libc/sock/sock.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/rusage.h"
@ -82,6 +83,11 @@ int LuaGetCpuCore(lua_State *L) {
return 1;
}
int LuaGetCpuCount(lua_State *L) {
lua_pushinteger(L, GetCpuCount());
return 1;
}
int LuaGetLogLevel(lua_State *L) {
lua_pushinteger(L, __log_level);
return 1;

View file

@ -35,6 +35,7 @@ int LuaEscapeUser(lua_State *);
int LuaFormatHttpDateTime(lua_State *);
int LuaFormatIp(lua_State *);
int LuaGetCpuCore(lua_State *);
int LuaGetCpuCount(lua_State *);
int LuaGetCpuNode(lua_State *);
int LuaGetCryptoHash(lua_State *);
int LuaGetHostOs(lua_State *);

File diff suppressed because it is too large Load diff

View file

@ -175,6 +175,7 @@ o/$(MODE)/tool/net/demo/sql.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-webserver.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-dir.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 \
@ -221,6 +222,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
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-webserver.lua.zip.o \
o/$(MODE)/tool/net/demo/unix-dir.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 \

View file

@ -63,6 +63,7 @@
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
@ -196,6 +197,8 @@ STATIC_YOINK("zip_uri_support");
// puncts not used: !"#$%&'()*+,-./;<=>@[\]^_`{|}~
#define GETOPTS "BSVZabdfghijkmsuvzA:C:D:F:G:H:K:L:M:P:R:T:U:c:e:l:p:r:t:"
extern unsigned long long __kbirth;
static const uint8_t kGzipHeader[] = {
0x1F, // MAGNUM
0x8B, // MAGNUM
@ -4956,6 +4959,7 @@ static const luaL_Reg kLuaFuncs[] = {
{"GetComment", LuaGetAssetComment}, //
{"GetCookie", LuaGetCookie}, //
{"GetCpuCore", LuaGetCpuCore}, //
{"GetCpuCount", LuaGetCpuCount}, //
{"GetCpuNode", LuaGetCpuNode}, //
{"GetCryptoHash", LuaGetCryptoHash}, //
{"GetDate", LuaGetDate}, //
@ -5192,6 +5196,7 @@ static void LuaPrint(lua_State *L) {
static void LuaInterpreter(lua_State *L) {
int i, n, sig, status;
const char *script;
if (funtrace) ftrace_install();
if (optind < __argc) {
script = __argv[optind];
if (!strcmp(script, "-")) script = 0;
@ -5201,7 +5206,11 @@ static void LuaInterpreter(lua_State *L) {
luaL_checkstack(L, n + 3, "too many script args");
for (i = 1; i <= n; i++) lua_rawgeti(L, -i, i);
lua_remove(L, -i); // remove arg table from stack
if (funtrace) ++g_ftrace;
if (systrace) ++__strace;
status = lua_runchunk(L, n, LUA_MULTRET);
if (systrace) --__strace;
if (funtrace) --g_ftrace;
}
lua_report(L, status);
} else {
@ -5225,7 +5234,9 @@ static void LuaInterpreter(lua_State *L) {
exit(1);
}
if (status == LUA_OK) {
if (funtrace) ++g_ftrace;
status = lua_runchunk(GL, 0, LUA_MULTRET);
if (funtrace) --g_ftrace;
}
if (status == LUA_OK) {
LuaPrint(GL);
@ -6358,7 +6369,6 @@ static int HandleConnection(size_t i) {
connectionclose = false;
if (!IsTiny()) {
if (systrace) {
extern unsigned long long __kbirth;
__strace = 1;
__kbirth = rdtsc();
}
@ -6474,18 +6484,20 @@ static void RestoreApe(void) {
if (endswith(zpath, ".com.dbg")) return;
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
close(zfd);
if ((zfd = OpenExecutable()) == -1 || WRITE(zfd, p, n) == -1)
if ((zfd = OpenExecutable()) == -1 || WRITE(zfd, p, n) == -1) {
WARNF("(srvr) can't restore .ape");
}
free(p);
} else {
INFOF("(srvr) /.ape not found");
DEBUGF("(srvr) /.ape not found");
}
}
static int HandleReadline(void) {
int status;
lua_State *L = GL;
for (;;) {
status = lua_loadline(GL);
status = lua_loadline(L);
if (status < 0) {
if (status == -1) {
OnTerm(SIGHUP); // eof
@ -6508,12 +6520,12 @@ static int HandleReadline(void) {
linenoiseDisableRawMode();
LUA_REPL_LOCK;
if (status == LUA_OK) {
status = lua_runchunk(GL, 0, LUA_MULTRET);
status = lua_runchunk(L, 0, LUA_MULTRET);
}
if (status == LUA_OK) {
LuaPrint(GL);
LuaPrint(L);
} else {
lua_report(GL, status);
lua_report(L, status);
}
LUA_REPL_UNLOCK;
if (lua_repl_isterminal) {
@ -6683,26 +6695,28 @@ static int EventLoop(int ms) {
}
static void ReplEventLoop(void) {
lua_State *L = GL;
DEBUGF("ReplEventLoop()");
polls[0].fd = 0;
lua_repl_completions_callback = HandleCompletions;
lua_initrepl(GL, "redbean");
lua_initrepl(L, "redbean");
if (lua_repl_isterminal) {
linenoiseEnableRawMode(0);
}
EventLoop(100);
linenoiseDisableRawMode();
lua_freerepl();
lua_settop(GL, 0); // clear stack
lua_settop(L, 0); // clear stack
polls[0].fd = -1;
}
static uint32_t WindowsReplThread(void *arg) {
int sig;
lua_State *L = GL;
DEBUGF("WindowsReplThread()");
lua_repl_blocking = true;
lua_repl_completions_callback = HandleCompletions;
lua_initrepl(GL, "redbean");
lua_initrepl(L, "redbean");
if (lua_repl_isterminal) {
linenoiseEnableRawMode(0);
}
@ -6714,7 +6728,7 @@ static uint32_t WindowsReplThread(void *arg) {
linenoiseDisableRawMode();
lua_freerepl();
LUA_REPL_LOCK;
lua_settop(GL, 0); // clear stack
lua_settop(L, 0); // clear stack
LUA_REPL_UNLOCK;
if ((sig = linenoiseGetInterrupt())) {
raise(sig);
@ -6896,7 +6910,7 @@ void RedBean(int argc, char *argv[]) {
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
-1, 0)));
zpath = program_executable_name;
zpath = GetProgramExecutableName();
CHECK_NE(-1, (zfd = open(zpath, O_RDONLY)));
CHECK_NE(-1, fstat(zfd, &zst));
OpenZip(true);