Make improvements

- Fix build flakes
- Polyfill SIGWINCH on Windows
- Fix an execve issue on Windows
- Make strerror show more information
- Improve cmd.exe setup/teardown on Windows
- Support bracketed paste mode in Blinkenlights
- Show keyboard shortcuts in Blinkenlights status bar
- Fixed copy_file_range() and copyfile() w/ zip filesystem
- Size optimize GetDosArgv() to keep life.com 12kb in size
- Improve Blinkenlights ability to load weird ELF executables
- Fix program_executable_name and add GetInterpreterExecutableName
- Make Python in tiny mode fail better if docstrings are requested
- Update Python test exclusions in tiny* modes such as tinylinux
- Add bulletproof unbreakable kprintf() troubleshooting function
- Remove "oldskool" keyword from ape.S for virus scanners
- Fix issue that caused backtraces to not print sometimes
- Improve Blinkenlights serial uart character i/o
- Make clock_gettime() not clobber errno on xnu
- Improve sha256 cpuid check for old computers
- Integrate some bestline linenoise fixes
- Show runit process names better in htop
- Remove SIGPIPE from ShowCrashReports()
- Make realpath() not clobber errno
- Avoid attaching GDB on non-Linux
- Improve img.com example
This commit is contained in:
Justine Tunney 2022-03-16 13:33:13 -07:00
parent 2a938b3eaa
commit b45d50b690
194 changed files with 4881 additions and 2966 deletions

View file

@ -28,9 +28,11 @@
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/log/color.internal.h"
#include "libc/log/log.h"
@ -43,6 +45,7 @@
#include "libc/stdio/append.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/o.h"
@ -95,8 +98,8 @@ FLAGS\n\
-T TARGET specifies target name for V=0 logging\n\
-A ACTION specifies short command name for V=0 logging\n\
-V NUMBER specifies compiler version\n\
-C SECS set cpu limit [default 8]\n\
-L SECS set lat limit [default 64]\n\
-C SECS set cpu limit [default 16]\n\
-L SECS set lat limit [default 90]\n\
-M BYTES set mem limit [default 512m]\n\
-F BYTES set fsz limit [default 100m]\n\
-O BYTES set out limit [default 1m]\n\
@ -194,6 +197,7 @@ const char *const kSafeEnv[] = {
"MODE", // needed by test scripts
"PATH", // needed by clang
"PWD", // just seems plain needed
"STRACE", // useful for troubleshooting
"TERM", // needed by IsTerminalInarticulate
"TMPDIR", // needed by compiler
};
@ -223,6 +227,7 @@ const char *const kGccOnlyFlags[] = {
"-fno-gnu-unique",
"-fno-gnu-unique",
"-fno-instrument-functions",
"-fno-schedule-insns2",
"-fno-whole-program",
"-fopt-info-vec",
"-fopt-info-vec-missed",
@ -324,10 +329,14 @@ int GetTerminalWidth(void) {
}
}
int GetLineWidth(void) {
int GetLineWidth(bool *isineditor) {
char *s;
struct winsize ws = {0};
if ((s = getenv("COLUMNS"))) {
s = getenv("COLUMNS");
if (isineditor) {
*isineditor = !!s;
}
if (s) {
return atoi(s);
} else if (ioctl(2, TIOCGWINSZ, &ws) != -1) {
if (ws.ws_col && ws.ws_row) {
@ -398,11 +407,20 @@ bool FileExistsAndIsNewerThan(const char *filepath, const char *thanpath) {
return st1.st_mtim.tv_nsec >= st2.st_mtim.tv_nsec;
}
static size_t TallyArgs(char **p) {
size_t n;
for (n = 0; *p; ++p) {
n += sizeof(*p);
n += strlen(*p) + 1;
}
return n;
}
void AddStr(struct Strings *l, char *s) {
l->p = realloc(l->p, (++l->n + 1) * sizeof(*l->p));
l->p[l->n - 1] = s;
l->p[l->n - 0] = 0;
};
}
void AddEnv(char *s) {
AddStr(&env, s);
@ -433,7 +451,15 @@ void AddArg(char *s) {
} else {
appends(&shortened, s);
}
} else if (s[0] == '-' && (!s[1] || s[1] == 'o' || (s[1] == '-' && !s[2]) ||
} else if (/*
* a in ('-', '--') or
* a.startswith('-o') or
* c == 'ld' and a == '-T' or
* c == 'cc' and a.startswith('-O') or
* c == 'cc' and a.startswith('-x') or
* c == 'cc' and a in ('-c', '-E', '-S')
*/
s[0] == '-' && (!s[1] || s[1] == 'o' || (s[1] == '-' && !s[2]) ||
(isbfd && (s[1] == 'T' && !s[2])) ||
(iscc && (s[1] == 'O' || s[1] == 'x' ||
(!s[2] && (s[1] == 'c' || s[1] == 'E' ||
@ -486,6 +512,56 @@ void SetMemLimit(long n) {
setrlimit(RLIMIT_AS, &rlim);
}
bool ArgNeedsShellQuotes(const char *s) {
if (*s) {
for (;;) {
switch (*s++ & 255) {
case 0:
return false;
case '-':
case '.':
case '/':
case '_':
case '=':
case ':':
case '0' ... '9':
case 'A' ... 'Z':
case 'a' ... 'z':
break;
default:
return true;
}
}
} else {
return true;
}
}
char *AddShellQuotes(const char *s) {
char *p, *q;
size_t i, j, n;
n = strlen(s);
p = malloc(1 + n * 5 + 1 + 1);
j = 0;
p[j++] = '\'';
for (i = 0; i < n; ++i) {
if (s[i] != '\'') {
p[j++] = s[i];
} else {
p[j + 0] = '\'';
p[j + 1] = '"';
p[j + 2] = '\'';
p[j + 3] = '"';
p[j + 4] = '\'';
j += 5;
}
}
p[j++] = '\'';
p[j] = 0;
if ((q = realloc(p, j + 1))) p = q;
return p;
}
int Launch(void) {
size_t got;
ssize_t rc;
@ -499,7 +575,19 @@ int Launch(void) {
timer.it_interval.tv_sec = timeout;
setitimer(ITIMER_REAL, &timer, 0);
}
if ((pid = vfork()) == -1) exit(errno);
pid = fork();
#if 0
int fd;
size_t n;
char b[1024], *p;
size_t t = strlen(cmd) + 1 + TallyArgs(args.p) + 9 + TallyArgs(env.p) + 9;
n = ksnprintf(b, sizeof(b), "%ld %s %s\n", t, cmd, outpath);
fd = open("o/argmax.txt", O_APPEND | O_CREAT | O_WRONLY, 0644);
write(fd, b, n);
close(fd);
#endif
if (!pid) {
SetCpuLimit(cpuquota);
SetFszLimit(fszquota);
@ -508,7 +596,7 @@ int Launch(void) {
dup2(pipefds[1], 2);
sigprocmask(SIG_SETMASK, &savemask, 0);
execve(cmd, args.p, env.p);
_exit(127);
_Exit(127);
}
close(pipefds[1]);
for (;;) {
@ -609,21 +697,42 @@ void ReportResources(void) {
appendw(&output, '\n');
}
bool IsNativeExecutable(const char *path) {
bool res;
char buf[4];
int got, fd;
res = false;
if ((fd = open(path, O_RDONLY)) != -1) {
if ((got = read(fd, buf, 4)) == 4) {
if (IsWindows()) {
res = READ16LE(buf) == READ16LE("MZ");
} else if (IsXnu()) {
res = READ32LE(buf) == 0xFEEDFACEu + 1;
} else {
res = READ32LE(buf) == READ32LE("\177ELF");
}
}
close(fd);
}
return res;
}
int main(int argc, char *argv[]) {
int columns;
uint64_t us;
bool isineditor;
size_t i, j, n, m;
bool isproblematic;
char *s, *p, **envp;
int ws, opt, exitcode;
char *s, *p, *q, **envp;
/*
* parse prefix arguments
*/
mode = MODE;
verbose = 4;
timeout = 64; /* secs */
cpuquota = 8; /* secs */
timeout = 90; /* secs */
cpuquota = 16; /* secs */
fszquota = 100 * 1000 * 1000; /* bytes */
memquota = 512 * 1024 * 1024; /* bytes */
if ((s = getenv("V"))) verbose = atoi(s);
@ -876,6 +985,8 @@ int main(int argc, char *argv[]) {
if (wantframe) {
AddArg("-fno-omit-frame-pointer");
AddArg("-D__FNO_OMIT_FRAME_POINTER__");
} else {
AddArg("-fomit-frame-pointer");
}
}
@ -938,6 +1049,7 @@ int main(int argc, char *argv[]) {
exit(97);
}
}
args.p[0] = cmd;
}
/*
@ -991,7 +1103,8 @@ int main(int argc, char *argv[]) {
* cleanup temporary copy of ape executable
*/
if (originalcmd) {
if (cachedcmd && WIFEXITED(ws) && !WEXITSTATUS(ws)) {
if (cachedcmd && WIFEXITED(ws) && !WEXITSTATUS(ws) &&
IsNativeExecutable(cmd)) {
makedirs(xdirname(cachedcmd), 0755);
rename(cmd, cachedcmd);
} else {
@ -1036,6 +1149,17 @@ int main(int argc, char *argv[]) {
appends(&output, strsignal(WTERMSIG(ws)));
PrintReset();
appendw(&output, READ16LE(":\n"));
appends(&output, "env -i ");
for (i = 0; i < env.n; ++i) {
if (ArgNeedsShellQuotes(env.p[i])) {
q = AddShellQuotes(env.p[i]);
appends(&output, q);
free(q);
} else {
appends(&output, env.p[i]);
}
appendw(&output, ' ');
}
}
} else {
exitcode = 89;
@ -1170,10 +1294,19 @@ int main(int argc, char *argv[]) {
if (verbose < 2 || verbose == 3) {
command = shortened;
}
m = GetLineWidth();
m = GetLineWidth(&isineditor);
if (m > n + 3 && appendz(command).i > m - n) {
appendd(&output, command, m - n - 3);
appendw(&output, READ32LE("..."));
if (isineditor) {
if (m > n + 3 && appendz(shortened).i > m - n) {
appendd(&output, shortened, m - n - 3);
appendw(&output, READ32LE("..."));
} else {
appendd(&output, shortened, appendz(shortened).i);
}
} else {
appendd(&output, command, m - n - 3);
appendw(&output, READ32LE("..."));
}
} else {
appendd(&output, command, appendz(command).i);
}