mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 15:38:22 +00:00
Improve redbean ctrl-c handling
This commit is contained in:
parent
1599b818d9
commit
c39d6111f2
3 changed files with 89 additions and 21 deletions
26
third_party/linenoise/linenoise.c
vendored
26
third_party/linenoise/linenoise.c
vendored
|
@ -580,8 +580,9 @@ static char abGrow(struct abuf *a, int need) {
|
||||||
int cap;
|
int cap;
|
||||||
char *b;
|
char *b;
|
||||||
cap = a->cap;
|
cap = a->cap;
|
||||||
do cap += cap / 2;
|
do {
|
||||||
while (cap < need);
|
cap += cap / 2;
|
||||||
|
} while (cap < need);
|
||||||
if (!(b = realloc(a->b, cap * sizeof(*a->b)))) return 0;
|
if (!(b = realloc(a->b, cap * sizeof(*a->b)))) return 0;
|
||||||
a->cap = cap;
|
a->cap = cap;
|
||||||
a->b = b;
|
a->b = b;
|
||||||
|
@ -824,8 +825,9 @@ static char linenoiseGrow(struct linenoiseState *ls, size_t n) {
|
||||||
size_t m;
|
size_t m;
|
||||||
m = ls->buflen;
|
m = ls->buflen;
|
||||||
if (m >= n) return 1;
|
if (m >= n) return 1;
|
||||||
do m += m >> 1;
|
do {
|
||||||
while (m < n);
|
m += m >> 1;
|
||||||
|
} while (m < n);
|
||||||
if (!(p = realloc(ls->buf, m * sizeof(*ls->buf)))) return 0;
|
if (!(p = realloc(ls->buf, m * sizeof(*ls->buf)))) return 0;
|
||||||
ls->buf = p;
|
ls->buf = p;
|
||||||
ls->buflen = m;
|
ls->buflen = m;
|
||||||
|
@ -855,8 +857,9 @@ static size_t Forward(struct linenoiseState *l, size_t pos) {
|
||||||
|
|
||||||
static size_t Backward(struct linenoiseState *l, size_t pos) {
|
static size_t Backward(struct linenoiseState *l, size_t pos) {
|
||||||
if (pos) {
|
if (pos) {
|
||||||
do --pos;
|
do {
|
||||||
while (pos && (l->buf[pos] & 0300) == 0200);
|
--pos;
|
||||||
|
} while (pos && (l->buf[pos] & 0300) == 0200);
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -1461,8 +1464,9 @@ static size_t EscapeWord(struct linenoiseState *l) {
|
||||||
if (iswseparator(r.c)) break;
|
if (iswseparator(r.c)) break;
|
||||||
}
|
}
|
||||||
if ((j = i)) {
|
if ((j = i)) {
|
||||||
do --j;
|
do {
|
||||||
while (j && (l->buf[j] & 0300) == 0200);
|
--j;
|
||||||
|
} while (j && (l->buf[j] & 0300) == 0200);
|
||||||
r = GetUtf8(l->buf + j, l->len - j);
|
r = GetUtf8(l->buf + j, l->len - j);
|
||||||
if (iswseparator(r.c)) break;
|
if (iswseparator(r.c)) break;
|
||||||
}
|
}
|
||||||
|
@ -1477,8 +1481,9 @@ static void linenoiseEditLeft(struct linenoiseState *l) {
|
||||||
|
|
||||||
static void linenoiseEditRight(struct linenoiseState *l) {
|
static void linenoiseEditRight(struct linenoiseState *l) {
|
||||||
if (l->pos == l->len) return;
|
if (l->pos == l->len) return;
|
||||||
do l->pos++;
|
do {
|
||||||
while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200);
|
l->pos++;
|
||||||
|
} while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200);
|
||||||
linenoiseRefreshLine(l);
|
linenoiseRefreshLine(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2268,6 +2273,7 @@ char *linenoiseRaw(const char *prompt, int infd, int outfd) {
|
||||||
buf = 0;
|
buf = 0;
|
||||||
raise(gotint);
|
raise(gotint);
|
||||||
errno = EINTR;
|
errno = EINTR;
|
||||||
|
gotint = 0;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
if (rc != -1) {
|
if (rc != -1) {
|
||||||
|
|
|
@ -17,9 +17,13 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/sigbits.h"
|
||||||
#include "libc/calls/struct/filter.h"
|
#include "libc/calls/struct/filter.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/calls/struct/siginfo.h"
|
||||||
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/calls/struct/user_regs_struct.h"
|
#include "libc/calls/struct/user_regs_struct.h"
|
||||||
|
#include "libc/calls/ucontext.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
@ -28,6 +32,7 @@
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sysv/consts/pr.h"
|
#include "libc/sysv/consts/pr.h"
|
||||||
#include "libc/sysv/consts/ptrace.h"
|
#include "libc/sysv/consts/ptrace.h"
|
||||||
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "tool/net/sandbox.h"
|
#include "tool/net/sandbox.h"
|
||||||
|
|
||||||
|
@ -75,6 +80,7 @@ static const struct sock_filter kSandboxFilter[] = {
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x033), // getsockname
|
_SECCOMP_ALLOW_SYSCALL(0x033), // getsockname
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x034), // getpeername
|
_SECCOMP_ALLOW_SYSCALL(0x034), // getpeername
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
|
_SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn
|
||||||
|
_SECCOMP_ALLOW_SYSCALL(0x082), // rt_sigsuspend
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
|
_SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x060), // gettimeofday
|
_SECCOMP_ALLOW_SYSCALL(0x060), // gettimeofday
|
||||||
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
|
_SECCOMP_ALLOW_SYSCALL(0x03f), // uname
|
||||||
|
@ -110,7 +116,12 @@ static const struct sock_fprog kSandbox = {
|
||||||
.filter = kSandboxFilter,
|
.filter = kSandboxFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void OnSys(int sig, siginfo_t *si, ucontext_t *ctx) {
|
||||||
|
kprintf("Got SIGSYS%n");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
sigset_t mask, origmask;
|
||||||
struct user_regs_struct regs;
|
struct user_regs_struct regs;
|
||||||
int child, evpid, signal, wstatus;
|
int child, evpid, signal, wstatus;
|
||||||
|
|
||||||
|
@ -122,30 +133,68 @@ int main(int argc, char *argv[]) {
|
||||||
kprintf("Usage: %s PROGRAM [ARGS...]%n", argv[0]);
|
kprintf("Usage: %s PROGRAM [ARGS...]%n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ShowCrashReports();
|
/* ShowCrashReports(); */
|
||||||
|
|
||||||
CHECK_NE(-1, (child = fork()));
|
|
||||||
if (!child) {
|
|
||||||
if (ptrace(PTRACE_TRACEME) == -1) _Exit(124);
|
|
||||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) _Exit(125);
|
|
||||||
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) _Exit(126);
|
|
||||||
execvp(argv[1], argv + 1);
|
|
||||||
_Exit(127);
|
|
||||||
}
|
|
||||||
|
|
||||||
sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
|
sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
|
||||||
sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
|
sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_IGN}, 0);
|
||||||
|
sigaction(SIGSYS,
|
||||||
|
&((struct sigaction){
|
||||||
|
.sa_sigaction = OnSys,
|
||||||
|
.sa_flags = SA_SIGINFO,
|
||||||
|
}),
|
||||||
|
0);
|
||||||
|
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGCHLD);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, &origmask);
|
||||||
|
|
||||||
|
CHECK_NE(-1, (child = fork()));
|
||||||
|
if (!child) {
|
||||||
|
sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
|
||||||
|
sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
|
||||||
|
kprintf("CHILD ptrace(PTRACE_TRACEME)%n");
|
||||||
|
if (ptrace(PTRACE_TRACEME) == -1) {
|
||||||
|
kprintf("CHILD ptrace(PTRACE_TRACEME) failed %m%n");
|
||||||
|
_Exit(124);
|
||||||
|
}
|
||||||
|
kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS)%n");
|
||||||
|
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
|
||||||
|
kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS) failed %m%n");
|
||||||
|
_Exit(125);
|
||||||
|
}
|
||||||
|
kprintf("CHILD prctl(PR_SET_SECCOMP)%n");
|
||||||
|
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) {
|
||||||
|
kprintf("CHILD prctl(PR_SET_SECCOMP) failed %m%n");
|
||||||
|
_Exit(126);
|
||||||
|
}
|
||||||
|
kprintf("CHILD sigsuspend()%n");
|
||||||
|
if (sigsuspend(0) == -1) {
|
||||||
|
kprintf("CHILD sigsuspend() failed %m%n");
|
||||||
|
}
|
||||||
|
sigaction(SIGSYS, &(struct sigaction){.sa_handler = SIG_DFL}, 0);
|
||||||
|
sigprocmask(SIG_SETMASK, &origmask, 0);
|
||||||
|
execv(argv[1], argv + 1);
|
||||||
|
kprintf("CHILD execve(%#s) failed %m%n", argv[1]);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
// wait for ptrace(PTRACE_TRACEME) to be called
|
// wait for ptrace(PTRACE_TRACEME) to be called
|
||||||
|
kprintf("PARENT waitpid(child, &wstatus)%n");
|
||||||
CHECK_EQ(child, waitpid(child, &wstatus, 0));
|
CHECK_EQ(child, waitpid(child, &wstatus, 0));
|
||||||
|
|
||||||
// configure linux process tracing
|
// configure linux process tracing
|
||||||
|
kprintf("PARENT ptrace(PTRACE_SETOPTIONS)%n");
|
||||||
CHECK_NE(-1, ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESECCOMP));
|
CHECK_NE(-1, ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESECCOMP));
|
||||||
|
|
||||||
// continue child process
|
// continue child process
|
||||||
|
kprintf("PARENT ptrace(PTRACE_CONT)%n");
|
||||||
CHECK_NE(-1, ptrace(PTRACE_CONT, child, 0, 0));
|
CHECK_NE(-1, ptrace(PTRACE_CONT, child, 0, 0));
|
||||||
|
|
||||||
|
kprintf("PARENT kill(child, SIGSYS)%n");
|
||||||
|
kill(child, SIGSYS);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
kprintf("PARENT waitpid()%n");
|
||||||
CHECK_NE(-1, (evpid = waitpid(-1, &wstatus, __WALL)));
|
CHECK_NE(-1, (evpid = waitpid(-1, &wstatus, __WALL)));
|
||||||
if (WIFSTOPPED(wstatus)) {
|
if (WIFSTOPPED(wstatus)) {
|
||||||
signal = (wstatus >> 8) & 0xffff;
|
signal = (wstatus >> 8) & 0xffff;
|
||||||
|
|
|
@ -6986,13 +6986,26 @@ static int EventLoop(int fd, int ms) {
|
||||||
|
|
||||||
static void ReplEventLoop(void) {
|
static void ReplEventLoop(void) {
|
||||||
int status;
|
int status;
|
||||||
|
long double t;
|
||||||
lua_State *L = GL;
|
lua_State *L = GL;
|
||||||
polls[0].fd = 0;
|
polls[0].fd = 0;
|
||||||
__nomultics = 2;
|
__nomultics = 2;
|
||||||
__replmode = true;
|
__replmode = true;
|
||||||
lua_initrepl("redbean");
|
lua_initrepl("redbean");
|
||||||
linenoiseSetPollCallback(EventLoop);
|
linenoiseSetPollCallback(EventLoop);
|
||||||
while ((status = lua_loadline(L)) != -1) {
|
for (;;) {
|
||||||
|
if ((status = lua_loadline(L)) == -1) {
|
||||||
|
if (errno = EINTR) {
|
||||||
|
LockInc(&shared->c.pollinterrupts);
|
||||||
|
if (terminated) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (status == LUA_OK) {
|
if (status == LUA_OK) {
|
||||||
status = lua_runchunk(L, 0, LUA_MULTRET);
|
status = lua_runchunk(L, 0, LUA_MULTRET);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue