Make improvements

- Expand redbean UNIX module
- Expand redbean documentation
- Ensure Lua copyright is embedded in binary
- Increase the PATH_MAX limit especially on NT
- Use column major sorting for linenoise completions
- Fix some suboptimalities in redbean's new UNIX API
- Figured out right flags for Multics newline in raw mode
This commit is contained in:
Justine Tunney 2022-04-24 09:59:22 -07:00
parent cf3174dc74
commit 2046c0d2ae
305 changed files with 6602 additions and 4221 deletions

View file

@ -0,0 +1,33 @@
/*-*- 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/fmt/itoa.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes setsockopt() level arguments.
*/
const char *DescribeSockLevel(int x) {
static char buf[12];
if (x == SOL_IP) return "SOL_IP";
if (x == SOL_TCP) return "SOL_TCP";
if (x == SOL_UDP) return "SOL_UDP";
if (x == SOL_SOCKET) return "SOL_SOCKET";
FormatInt32(buf, x);
return buf;
}

View file

@ -0,0 +1,45 @@
/*-*- 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/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes setsockopt() optname arguments.
*/
const char *DescribeSockOptname(int l, int x) {
int i;
static char buf[12], *s;
const struct MagnumStr *ms = 0;
if (x) {
if (l == SOL_SOCKET) {
ms = kSockOptnames;
} else if (l == SOL_TCP) {
ms = kTcpOptnames;
} else if (l == SOL_IP) {
ms = kIpOptnames;
}
}
if (ms && (s = GetMagnumStr(ms, x))) {
return s;
} else {
FormatInt32(buf, x);
return buf;
}
}

View file

@ -17,20 +17,54 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/timeval.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/yoink.inc"
#include "libc/str/str.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
void *out_opt_optval, uint32_t *out_optlen) {
/* TODO(jart): Use WSAIoctl? */
void *out_opt_optval,
uint32_t *inout_optlen) {
uint64_t ms;
uint32_t in_optlen;
assert(fd->kind == kFdSocket);
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval,
out_optlen) != -1) {
return 0;
if (out_opt_optval && inout_optlen) {
in_optlen = *inout_optlen;
} else {
in_optlen = 0;
}
// TODO(jart): Use WSAIoctl?
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) {
return __winsockerr();
}
if (level == SOL_SOCKET) {
if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) &&
in_optlen == sizeof(struct timeval) &&
*inout_optlen == sizeof(uint32_t)) {
ms = *(uint32_t *)out_opt_optval;
((struct timeval *)out_opt_optval)->tv_sec = ms / 1000;
((struct timeval *)out_opt_optval)->tv_usec = ms % 1000 * 1000;
*inout_optlen = sizeof(struct timeval);
}
}
if (in_optlen == 4 && *inout_optlen == 1) {
// handle cases like this
// getsockopt(8, SOL_TCP, TCP_FASTOPEN, [u"☺"], [1]) → 0
int32_t wut = *(signed char *)out_opt_optval;
memcpy(out_opt_optval, &wut, 4);
*inout_optlen = 4;
}
return 0;
}

View file

@ -19,6 +19,8 @@
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sysv/errfuns.h"
@ -36,10 +38,15 @@
int getsockopt(int fd, int level, int optname, void *out_opt_optval,
uint32_t *out_optlen) {
int rc;
if (!level || !optname) {
rc = enoprotoopt(); /* our sysvconsts definition */
} else if (optname == -1) {
rc = 0; /* our sysvconsts definition */
} else if (IsAsan() && (out_opt_optval && out_optlen &&
(!__asan_is_valid(out_optlen, sizeof(uint32_t)) ||
!__asan_is_valid(out_opt_optval, *out_optlen)))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_getsockopt(fd, level, optname, out_opt_optval, out_optlen);
} else if (__isfdkind(fd, kFdSocket)) {
@ -48,7 +55,18 @@ int getsockopt(int fd, int level, int optname, void *out_opt_optval,
} else {
rc = ebadf();
}
STRACE("getsockopt(%d, %#x, %#x, %p, %p) → %d% lm", fd, level, optname,
out_opt_optval, out_optlen, rc);
#ifdef SYSDEBUG
if (out_opt_optval && out_optlen && rc != -1) {
STRACE("getsockopt(%d, %s, %s, [%#.*hhs], [%d]) → %d% lm", fd,
DescribeSockLevel(level), DescribeSockOptname(level, optname),
*out_optlen, out_opt_optval, *out_optlen, rc);
} else {
STRACE("getsockopt(%d, %s, %s, %p, %p) → %d% lm", fd,
DescribeSockLevel(level), DescribeSockOptname(level, optname),
out_opt_optval, out_optlen, rc);
}
#endif
return rc;
}

39
libc/sock/kipoptnames.S Normal file
View file

@ -0,0 +1,39 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.macro .e e
.long \e - kIpOptnames
.long 1f - kIpOptnames
.rodata.str1.1
1: .string "\e"
.previous
.endm
.section .rodata
.align 4
.underrun
kIpOptnames:
.e IP_TOS # int
.e IP_MTU # int
.e IP_TTL # int
.e IP_HDRINCL # bool32
.long -123
.endobj kIpOptnames,globl,hidden
.overrun

49
libc/sock/ksockoptnames.S Normal file
View file

@ -0,0 +1,49 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.macro .e e
.long \e - kSockOptnames
.long 1f - kSockOptnames
.rodata.str1.1
1: .string "\e"
.previous
.endm
.section .rodata
.align 4
.underrun
kSockOptnames:
.e SO_DEBUG # bool32
.e SO_BROADCAST # bool32
.e SO_REUSEADDR # bool32
.e SO_REUSEPORT # bool32
.e SO_KEEPALIVE # bool32
.e SO_DONTROUTE # bool32
.e SO_RCVTIMEO # timeval
.e SO_SNDTIMEO # timeval
.e SO_LINGER # linger
.e SO_SNDBUF # int
.e SO_RCVBUF # int
.e SO_RCVLOWAT # int
.e SO_SNDLOWAT # int
.e SO_ERROR # int
.long -123
.endobj kSockOptnames,globl,hidden
.overrun

48
libc/sock/ktcpoptnames.S Normal file
View file

@ -0,0 +1,48 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.macro .e e
.long \e - kTcpOptnames
.long 1f - kTcpOptnames
.rodata.str1.1
1: .string "\e"
.previous
.endm
.section .rodata
.align 4
.underrun
kTcpOptnames:
.e TCP_NODELAY # bool32
.e TCP_CORK # bool32
.e TCP_QUICKACK # bool32
.e TCP_FASTOPEN_CONNECT # bool32
.e TCP_DEFER_ACCEPT # bool32
.e TCP_KEEPIDLE # int (seconds)
.e TCP_KEEPINTVL # int (seconds)
.e TCP_FASTOPEN # int
.e TCP_KEEPCNT # int
.e TCP_MAXSEG # int
.e TCP_SYNCNT # int
.e TCP_NOTSENT_LOWAT # int
.e TCP_WINDOW_CLAMP # int
.long -123
.endobj kTcpOptnames,globl,hidden
.overrun

View file

@ -88,7 +88,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
kprintf(".iov=", fd);
__strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
kprintf("}], %#x) → %'ld% m%n", flags, rc);
kprintf("}], %#x) → %'ld% m\n", flags, rc);
}
}
#endif

View file

@ -90,7 +90,7 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags);
kprintf(".iov=", fd);
__strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0);
kprintf("}, %#x) → %'ld% m%n", flags, rc);
kprintf("}, %#x) → %'ld% m\n", flags, rc);
}
}
#endif

View file

@ -17,9 +17,11 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timeval.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h"
struct linger_nt { /* Linux+XNU+BSD ABI */
@ -29,27 +31,34 @@ struct linger_nt { /* Linux+XNU+BSD ABI */
textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
const void *optval, uint32_t optlen) {
int64_t ms;
struct timeval *tv;
struct linger *linger;
union {
uint32_t millis;
struct linger_nt linger;
} nt;
} u;
if (optname == SO_LINGER && optval && optlen == sizeof(struct linger)) {
linger = optval;
nt.linger.l_onoff = linger->l_onoff;
nt.linger.l_linger = MIN(0xFFFF, MAX(0, linger->l_linger));
optval = &nt.linger;
optlen = sizeof(nt.linger);
}
if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) && optval &&
optlen == sizeof(struct timeval)) {
tv = optval;
nt.millis = MIN(0xFFFFFFFF, MAX(0, tv->tv_sec * 1000 + tv->tv_usec / 1000));
optval = &nt.millis;
optlen = sizeof(nt.millis);
if (level == SOL_SOCKET) {
if (optname == SO_LINGER && optval && optlen == sizeof(struct linger)) {
linger = optval;
u.linger.l_onoff = linger->l_onoff;
u.linger.l_linger = MIN(0xFFFF, MAX(0, linger->l_linger));
optval = &u.linger;
optlen = sizeof(u.linger);
} else if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) && optval &&
optlen == sizeof(struct timeval)) {
tv = optval;
if (__builtin_mul_overflow(tv->tv_sec, 1000, &ms) ||
__builtin_add_overflow(ms, tv->tv_usec / 1000, &ms) ||
(ms < 0 || ms > 0xffffffff)) {
u.millis = 0xffffffff;
} else {
u.millis = ms;
}
optval = &u.millis;
optlen = sizeof(u.millis);
}
}
if (__sys_setsockopt_nt(fd->handle, level, optname, optval, optlen) != -1) {

View file

@ -20,6 +20,8 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
@ -52,12 +54,12 @@ static bool setsockopt_polyfill(int *optname) {
int setsockopt(int fd, int level, int optname, const void *optval,
uint32_t optlen) {
int e, rc;
if (!optval) {
if (!optname) {
rc = enosys(); /* see libc/sysv/consts.sh */
} else if ((!optval && optlen) ||
(IsAsan() && !__asan_is_valid(optval, optlen))) {
rc = efault();
} else if (!level || !optname) {
rc = enoprotoopt(); /* our sysvconsts definition */
} else if (optname == -1) {
rc = 0; /* our sysvconsts definition */
} else if (!IsWindows()) {
rc = -1;
e = errno;
@ -73,7 +75,18 @@ int setsockopt(int fd, int level, int optname, const void *optval,
} else {
rc = ebadf();
}
STRACE("setsockopt(%d, %#x, %#x, %p, %'u) → %d% lm", fd, level, optname,
optval, optlen, rc);
#ifdef SYSDEBUG
if (!(rc == -1 && errno == EFAULT)) {
STRACE("setsockopt(%d, %s, %s, %#.*hhs, %'u) → %d% lm", fd,
DescribeSockLevel(level), DescribeSockOptname(level, optname),
optlen, optval, optlen, rc);
} else {
STRACE("setsockopt(%d, %s, %s, %p, %'u) → %d% lm", fd,
DescribeSockLevel(level), DescribeSockOptname(level, optname),
optval, optlen, rc);
}
#endif
return rc;
}

View file

@ -9,10 +9,16 @@ LIBC_SOCK_A = o/$(MODE)/libc/sock/sock.a
LIBC_SOCK_A_FILES := $(wildcard libc/sock/*)
LIBC_SOCK_A_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_INCS = $(filter %.inc,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS = $(filter %.c,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS_C = $(filter %.c,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS_S = $(filter %.S,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS = \
$(LIBC_SOCK_A_SRCS_C) \
$(LIBC_SOCK_A_SRCS_S)
LIBC_SOCK_A_OBJS = \
$(LIBC_SOCK_A_SRCS:%.c=o/$(MODE)/%.o)
$(LIBC_SOCK_A_SRCS_C:%.c=o/$(MODE)/%.o) \
$(LIBC_SOCK_A_SRCS_S:%.S=o/$(MODE)/%.o)
LIBC_SOCK_A_CHECKS = \
$(LIBC_SOCK_A).pkg \

View file

@ -48,6 +48,10 @@ const char *__describe_socket_type(int type) {
p = stpcpy(p, "SOCK_DGRAM");
} else if (x == SOCK_RAW) {
p = stpcpy(p, "SOCK_RAW");
} else if (x == SOCK_RDM) {
p = stpcpy(p, "SOCK_RDM");
} else if (x == SOCK_SEQPACKET) {
p = stpcpy(p, "SOCK_SEQPACKET");
} else {
p = FormatInt32(p, x);
}