mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 05:59:10 +00:00
Fix XNU / FreeBSD / OpenBSD / RHEL5 / NT bugs
For the first time ever, all tests in this codebase now pass, when run automatically on macos, freebsd, openbsd, rhel5, rhel7, alpine and windows via the network using the runit and runitd build tools - Fix vfork exec path etc. - Add XNU opendir() support - Add OpenBSD opendir() support - Add Linux history to syscalls.sh - Use copy_file_range on FreeBSD 13+ - Fix system calls with 7+ arguments - Fix Windows with greater than 16 FDs - Fix RUNIT.COM and RUNITD.COM flakiness - Fix OpenBSD munmap() when files are mapped - Fix long double so it's actually long on Windows - Fix OpenBSD truncate() and ftruncate() thunk typo - Let Windows fcntl() be used on socket files descriptors - Fix Windows fstat() which had an accidental printf statement - Fix RHEL5 CLOCK_MONOTONIC by not aliasing to CLOCK_MONOTONIC_RAW This is wonderful. I never could have dreamed it would be possible to get it working so well on so many platforms with tiny binaries. Fixes #31 Fixes #25 Fixes #14
This commit is contained in:
parent
c20dad3534
commit
45b72485ad
1032 changed files with 6083 additions and 2348 deletions
|
@ -1,102 +0,0 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/copyfile.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/gc.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/clock.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Overcommit tutorial.
|
||||
* You can allocate memory like a central banker prints money.
|
||||
*/
|
||||
|
||||
/* #define kHugeAmount (10LU * 1024LU * 1024LU * 1024LU * 1024LU) */
|
||||
#define kHugeAmount (1LU * 1024LU * 1024LU * 1024LU)
|
||||
|
||||
int copyfile2(const char *frompath, const char *topath, bool dontoverwrite) {
|
||||
struct stat st;
|
||||
ssize_t transferred;
|
||||
int rc, fromfd, tofd;
|
||||
int64_t inoffset, outoffset;
|
||||
rc = -1;
|
||||
if ((fromfd = open(frompath, O_RDONLY | O_DIRECT, 0)) != -1) {
|
||||
if (fstat(fromfd, &st) != -1 &&
|
||||
(tofd =
|
||||
open(topath,
|
||||
O_WRONLY | O_CREAT | O_DIRECT | (dontoverwrite ? O_EXCL : 0),
|
||||
st.st_mode & 0777)) != -1) {
|
||||
inoffset = 0;
|
||||
outoffset = 0;
|
||||
while (st.st_size &&
|
||||
(transferred = copy_file_range(fromfd, &inoffset, tofd, &outoffset,
|
||||
st.st_size, 0)) != -1) {
|
||||
st.st_size -= transferred;
|
||||
}
|
||||
if (!st.st_size) rc = 0;
|
||||
rc |= close(tofd);
|
||||
}
|
||||
rc |= close(fromfd);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int fd, pid;
|
||||
size_t size;
|
||||
long double t1, t2;
|
||||
const char *core, *core2, *core3;
|
||||
volatile unsigned char *mem;
|
||||
size = ROUNDUP(kHugeAmount, PAGESIZE);
|
||||
core = gc(xasprintf("%s.%s", getauxval(AT_EXECFN), "core"));
|
||||
core2 = gc(xasprintf("%s.%s", getauxval(AT_EXECFN), "core2"));
|
||||
core3 = gc(xasprintf("%s.%s", getauxval(AT_EXECFN), "core3"));
|
||||
CHECK_NE(-1, (fd = open(core, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600)));
|
||||
CHECK_NE(-1, ftruncate(fd, size));
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)));
|
||||
strcpy(&mem[0], "hello\n\n\n\n\n\n\n\n\n\n");
|
||||
strcpy(&mem[kHugeAmount / 2], "hello\n\n\n\n\n\n\n\n\n\n");
|
||||
CHECK_NE(-1, munmap(mem, size));
|
||||
CHECK_NE(-1,
|
||||
(pid = spawnve(
|
||||
0, (int[3]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO},
|
||||
"o/examples/stat.com",
|
||||
(char *const[]){"o/examples/stat.com", core, NULL}, environ)));
|
||||
CHECK_NE(-1, waitpid(pid, NULL, 0));
|
||||
CHECK_NE(-1, close(fd));
|
||||
|
||||
t1 = dtime(CLOCK_REALTIME);
|
||||
CHECK_NE(-1, copyfile(core, core2, 0));
|
||||
t2 = dtime(CLOCK_REALTIME);
|
||||
printf("%.6Lf\n", t2 - t1);
|
||||
|
||||
t1 = dtime(CLOCK_REALTIME);
|
||||
CHECK_NE(-1, copyfile2(core, core3, false));
|
||||
t2 = dtime(CLOCK_REALTIME);
|
||||
printf("%.6Lf\n", t2 - t1);
|
||||
|
||||
/* CHECK_NE(-1, unlink(core)); */
|
||||
return 0;
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
|
@ -42,48 +43,52 @@ int main(int argc, char *argv[]) {
|
|||
showcrashreports();
|
||||
res = 0;
|
||||
|
||||
asm volatile(
|
||||
"mov\t$0x1111111111111111,%rax\n\t"
|
||||
"mov\t$0x3333333333333333,%rcx\n\t"
|
||||
"mov\t$0x4444444444444444,%rdx\n\t"
|
||||
"mov\t$0x8888888888888888,%r8\n\t"
|
||||
"mov\t$0x9999999999999999,%r9d\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%r10d\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%r11d\n\t"
|
||||
"mov\t$0x0000000000000000,%rax\n\t"
|
||||
"movd\t%rax,%xmm0\n\t"
|
||||
"mov\t$0x1111111111111111,%rax\n\t"
|
||||
"movd\t%rax,%xmm1\n\t"
|
||||
"mov\t$0x2222222222222222,%rax\n\t"
|
||||
"movd\t%rax,%xmm2\n\t"
|
||||
"mov\t$0x3333333333333333,%rax\n\t"
|
||||
"movd\t%rax,%xmm3\n\t"
|
||||
"mov\t$0x4444444444444444,%rax\n\t"
|
||||
"movd\t%rax,%xmm4\n\t"
|
||||
"mov\t$0x5555555555555555,%rax\n\t"
|
||||
"movd\t%rax,%xmm5\n\t"
|
||||
"mov\t$0x6666666666666666,%rax\n\t"
|
||||
"movd\t%rax,%xmm6\n\t"
|
||||
"mov\t$0x7777777777777777,%rax\n\t"
|
||||
"movd\t%rax,%xmm7\n\t"
|
||||
"mov\t$0x8888888888888888,%rax\n\t"
|
||||
"movd\t%rax,%xmm8\n\t"
|
||||
"mov\t$0x9999999999999999,%rax\n\t"
|
||||
"movd\t%rax,%xmm9\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%rax\n\t"
|
||||
"movd\t%rax,%xmm10\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%rax\n\t"
|
||||
"movd\t%rax,%xmm11\n\t"
|
||||
"mov\t$0xcccccccccccccccc,%rax\n\t"
|
||||
"movd\t%rax,%xmm12\n\t"
|
||||
"mov\t$0xdddddddddddddddd,%rax\n\t"
|
||||
"movd\t%rax,%xmm13\n\t"
|
||||
"mov\t$0xeeeeeeeeeeeeeeee,%rax\n\t"
|
||||
"movd\t%rax,%xmm14\n\t"
|
||||
"mov\t$0xffffffffffffffff,%rax\n\t"
|
||||
"movd\t%rax,%xmm15\n\t"
|
||||
"fldlg2\n\t");
|
||||
asm volatile("mov\t$0x1111111111111111,%rax\n\t"
|
||||
"mov\t$0x3333333333333333,%rcx\n\t"
|
||||
"mov\t$0x4444444444444444,%rdx\n\t"
|
||||
"mov\t$0x8888888888888888,%r8\n\t"
|
||||
"mov\t$0x9999999999999999,%r9d\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%r10d\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%r11d\n\t"
|
||||
"mov\t$0x0000000000000000,%rax\n\t"
|
||||
"movd\t%rax,%xmm0\n\t"
|
||||
"mov\t$0x1111111111111111,%rax\n\t"
|
||||
"push\t%rax\n\t"
|
||||
"push\t%rax\n\t"
|
||||
"movdqu\t(%rsp),%xmm1\n\t"
|
||||
"pop\t%rax\n\t"
|
||||
"pop\t%rax\n\t"
|
||||
"mov\t$0x2222222222220022,%rax\n\t"
|
||||
"movd\t%rax,%xmm2\n\t"
|
||||
"mov\t$0x3333333333333333,%rax\n\t"
|
||||
"movd\t%rax,%xmm3\n\t"
|
||||
"mov\t$0x4444444444444444,%rax\n\t"
|
||||
"movd\t%rax,%xmm4\n\t"
|
||||
"mov\t$0x5555555555555555,%rax\n\t"
|
||||
"movd\t%rax,%xmm5\n\t"
|
||||
"mov\t$0x6666666666666666,%rax\n\t"
|
||||
"movd\t%rax,%xmm6\n\t"
|
||||
"mov\t$0x7777777777777777,%rax\n\t"
|
||||
"movd\t%rax,%xmm7\n\t"
|
||||
"mov\t$0x8888888888888888,%rax\n\t"
|
||||
"movd\t%rax,%xmm8\n\t"
|
||||
"mov\t$0x9999999999999999,%rax\n\t"
|
||||
"movd\t%rax,%xmm9\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%rax\n\t"
|
||||
"movd\t%rax,%xmm10\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%rax\n\t"
|
||||
"movd\t%rax,%xmm11\n\t"
|
||||
"mov\t$0xcccccccccccccccc,%rax\n\t"
|
||||
"movd\t%rax,%xmm12\n\t"
|
||||
"mov\t$0xdddddddddddddddd,%rax\n\t"
|
||||
"movd\t%rax,%xmm13\n\t"
|
||||
"mov\t$0xeeeeeeeeeeeeeeee,%rax\n\t"
|
||||
"movd\t%rax,%xmm14\n\t"
|
||||
"mov\t$0xffffffffffffffff,%rax\n\t"
|
||||
"movd\t%rax,%xmm15\n\t"
|
||||
"fldpi\n\t");
|
||||
|
||||
res = *(int *)(intptr_t)boo / boo;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
29
examples/echo.c
Normal file
29
examples/echo.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i, j;
|
||||
bool wantnewline;
|
||||
if (argc > 1 && !strcmp(argv[1], "-n")) {
|
||||
i = 2;
|
||||
wantnewline = false;
|
||||
} else {
|
||||
i = 1;
|
||||
wantnewline = true;
|
||||
}
|
||||
for (j = 0; i + j < argc; ++j) {
|
||||
if (j) fputc(' ', stdout);
|
||||
fputs(argv[i + j], stdout);
|
||||
}
|
||||
if (wantnewline) fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
17
examples/exec.c
Normal file
17
examples/exec.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) return 1;
|
||||
execv(argv[1], argv + 1);
|
||||
abort();
|
||||
}
|
18
examples/fork.c
Normal file
18
examples/fork.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid;
|
||||
pid = fork();
|
||||
fprintf(stderr, "fork returned %d\n", pid);
|
||||
return 0;
|
||||
}
|
19
examples/hostname.c
Normal file
19
examples/hostname.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char hostname[254];
|
||||
CHECK_NE(-1, gethostname(hostname, sizeof(hostname)));
|
||||
puts(hostname);
|
||||
return 0;
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -148,7 +147,6 @@ struct ZipGames {
|
|||
static int frame_;
|
||||
static int drain_;
|
||||
static int playfd_;
|
||||
static int devnull_;
|
||||
static int playpid_;
|
||||
static bool exited_;
|
||||
static bool timeout_;
|
||||
|
@ -308,21 +306,6 @@ void GetTermSize(void) {
|
|||
WriteStringNow("\e[0m\e[H\e[J");
|
||||
}
|
||||
|
||||
bool TrySpeaker(const char* prog, char* const* args) {
|
||||
int rc;
|
||||
int fds[3];
|
||||
fds[0] = -1;
|
||||
fds[1] = devnull_;
|
||||
fds[2] = devnull_;
|
||||
if ((rc = spawnve(0, fds, prog, args, environ)) != -1) {
|
||||
playpid_ = rc;
|
||||
playfd_ = fds[0];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void IoInit(void) {
|
||||
GetTermSize();
|
||||
xsigaction(SIGINT, (void*)OnCtrlC, 0, 0, NULL);
|
||||
|
@ -1700,6 +1683,8 @@ char* GetLine(void) {
|
|||
|
||||
int PlayGame(const char* romfile, const char* opt_tasfile) {
|
||||
FILE* fp;
|
||||
int devnull;
|
||||
int pipefds[2];
|
||||
inputfn_ = opt_tasfile;
|
||||
|
||||
if (!(fp = fopen(romfile, "rb"))) {
|
||||
|
@ -1716,13 +1701,23 @@ int PlayGame(const char* romfile, const char* opt_tasfile) {
|
|||
|
||||
// open speaker
|
||||
// todo: this needs plenty of work
|
||||
devnull_ = open("/dev/null", O_WRONLY);
|
||||
if ((ffplay_ = commandvenv("FFPLAY", "ffplay"))) {
|
||||
const char* args[] = {
|
||||
"ffplay", "-nodisp", "-loglevel", "quiet", "-fflags", "nobuffer", "-ac",
|
||||
"1", "-ar", "1789773", "-f", "s16le", "pipe:", NULL,
|
||||
};
|
||||
TrySpeaker(ffplay_, (char* const*)args);
|
||||
devnull = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
pipe2(pipefds, O_CLOEXEC);
|
||||
if (!(playpid_ = vfork())) {
|
||||
const char* const args[] = {
|
||||
"ffplay", "-nodisp", "-loglevel", "quiet", "-fflags",
|
||||
"nobuffer", "-ac", "1", "-ar", "1789773",
|
||||
"-f", "s16le", "pipe:", NULL,
|
||||
};
|
||||
dup2(pipefds[0], 0);
|
||||
dup2(devnull, 1);
|
||||
dup2(devnull, 2);
|
||||
execv(ffplay_, (char* const*)args);
|
||||
abort();
|
||||
}
|
||||
close(pipefds[0]);
|
||||
playfd_ = pipefds[1];
|
||||
} else {
|
||||
fputs("\nWARNING\n\
|
||||
\n\
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -23,26 +22,30 @@ void Show(const char *name, long measurement, const char *unit) {
|
|||
fprintf(stderr, "%-*s%,*d %s\n", 32, name, 32, measurement, unit);
|
||||
}
|
||||
|
||||
long TvToUs(struct timeval tv) {
|
||||
return 1000000l * tv.tv_usec + tv.tv_sec;
|
||||
long TvToNs(struct timeval tv) {
|
||||
return tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *exe;
|
||||
int pid, wstatus;
|
||||
long double ts1, ts2;
|
||||
struct rusage rusage;
|
||||
char pathbuf[PATH_MAX];
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s PROG [ARGS...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
memset(&rusage, -1, sizeof(rusage));
|
||||
CHECK_GT(argc, 1);
|
||||
CHECK_NOTNULL((exe = commandv(argv[1], pathbuf)));
|
||||
ts1 = nowl();
|
||||
CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ)));
|
||||
if (!(pid = vfork())) {
|
||||
execvp(argv[1], argv + 1);
|
||||
abort();
|
||||
}
|
||||
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));
|
||||
ts2 = nowl();
|
||||
Show("wall time", lroundl((ts2 - ts1) * 1e9l), "ns");
|
||||
Show("user time", TvToUs(rusage.ru_utime), "µs");
|
||||
Show("sys time", TvToUs(rusage.ru_stime), "µs");
|
||||
Show("user time", TvToNs(rusage.ru_utime), "ns");
|
||||
Show("sys time", TvToNs(rusage.ru_stime), "ns");
|
||||
Show("maximum resident set size", rusage.ru_maxrss, "");
|
||||
Show("integral shared memory size", rusage.ru_ixrss, "");
|
||||
Show("integral unshared data size", rusage.ru_idrss, "");
|
||||
|
@ -57,5 +60,9 @@ int main(int argc, char *argv[]) {
|
|||
Show("signals received", rusage.ru_nsignals, "");
|
||||
Show("voluntary context switches", rusage.ru_nvcsw, "");
|
||||
Show("involuntary context switches", rusage.ru_nivcsw, "");
|
||||
return WEXITSTATUS(wstatus);
|
||||
if (WIFEXITED(wstatus)) {
|
||||
return WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
return 128 + WTERMSIG(wstatus);
|
||||
}
|
||||
}
|
||||
|
|
23
examples/spawn.c
Normal file
23
examples/spawn.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid, wstatus;
|
||||
if (argc < 2) return 1;
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
execv(argv[1], argv + 1);
|
||||
abort();
|
||||
}
|
||||
waitpid(pid, &wstatus, 0);
|
||||
return WEXITSTATUS(wstatus);
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
const char kProgram[] = "o/default/examples/hello.com";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/**
|
||||
* Runs make if hello.com doesn't exist.
|
||||
*
|
||||
* 1. gc() automates calling free() on return.
|
||||
* 2. xasprintf("foo %s", "bar") is our version of "foo %s" % ("bar")
|
||||
* 3. Demonstrates correct escaping for bourne shell
|
||||
*/
|
||||
if (!fileexists(kProgram)) {
|
||||
system(gc(xasprintf("%s '%s'", "make -j4",
|
||||
gc(replacestr(kProgram, "'", "'\"'\"'")))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Our version of subprocess.Popen
|
||||
* 1. Doesn't require fork() so pain-free on NT
|
||||
* 2. Google checks are like assert() but better
|
||||
*/
|
||||
ssize_t transferred;
|
||||
int child, wstatus, procfds[3] = {STDIN_FILENO, -1, STDERR_FILENO};
|
||||
CHECK_NE(-1,
|
||||
(child = spawnve(0, procfds, /* run w/o shell */ kProgram,
|
||||
(char *const[]){/* argv[0] */ basename(kProgram),
|
||||
/* argv[1] */ "boop",
|
||||
/* sentinel */ NULL},
|
||||
environ)));
|
||||
printf("%s %s: ", kProgram, "says");
|
||||
fflush(stdout);
|
||||
for (;;) {
|
||||
transferred = copyfd(procfds[1], NULL, fileno(stdout), NULL, INT_MAX, 0);
|
||||
CHECK_NE(-1, transferred);
|
||||
if (!transferred) break;
|
||||
}
|
||||
CHECK_NE(-1, waitpid(child, &wstatus, 0));
|
||||
CHECK_EQ(0, WEXITSTATUS(wstatus));
|
||||
|
||||
return 0;
|
||||
}
|
15
examples/system.c
Normal file
15
examples/system.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
system("notepad");
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue