From d7ac16a9ed56ebdc70481f4a802265ea15619894 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Wed, 27 Jan 2021 19:34:02 -0800 Subject: [PATCH] Work towards improving signals and processes --- README.md | 4 +- ape/ape.lds | 1 + build/bootstrap/zipobj.com | Bin 126976 -> 172032 bytes build/definitions.mk | 3 + build/rules.mk | 4 +- examples/ctrlc.c | 67 ++++----- examples/examples.mk | 1 + examples/sleep.c | 61 ++++++++ examples/unbourne.c | 8 +- libc/calls/atfork.c | 17 ++- libc/calls/fcntl-nt.c | 22 ++- libc/calls/getpid.c | 24 +-- libc/calls/hefty/vfork.S | 3 + libc/calls/internal.h | 39 ++--- libc/calls/kill-nt.c | 56 +++++++ libc/calls/kill.c | 9 +- libc/calls/ntspawn.c | 3 +- libc/calls/onntconsoleevent.c | 2 +- libc/calls/onntconsoleevent_init.S | 2 +- libc/calls/open-nt.c | 10 +- libc/calls/pause.c | 9 +- libc/calls/raise.c | 2 +- libc/calls/sigprocmask.c | 3 +- libc/calls/sigsuspend.c | 8 +- libc/calls/thunks/onntconsoleevent.S | 6 +- libc/calls/waitpid.c | 9 +- libc/calls/write-nt.c | 2 +- libc/log/backtrace2.c | 17 ++- libc/log/backtrace3.c | 6 +- libc/log/checkfail.c | 16 +- libc/log/checkfail_ndebug.c | 2 +- libc/log/perror.c | 14 +- libc/log/vflogf.c | 36 +++-- libc/nt/privilege.h | 4 +- libc/nt/process.h | 4 +- libc/runtime/abort-nt.c | 32 ++++ libc/runtime/abort.S | 3 +- libc/runtime/brk.c | 77 ++++++++++ libc/runtime/ldso.c | 40 +++++ libc/runtime/pthread.c | 50 +++++++ libc/runtime/runtime.h | 4 +- libc/sock/bind-nt.c | 10 -- libc/sock/internal.h | 4 +- libc/sock/shutdown-nt.c | 29 ++++ libc/sock/shutdown.c | 16 +- libc/stdio/fbufsize.c | 27 ++++ libc/stdio/fflush.c | 13 +- libc/stdio/fflush.internal.h | 21 +++ libc/stdio/flbf.c | 27 ++++ libc/stdio/flushlbf.c | 33 +++++ libc/stdio/fpending.c | 26 ++++ libc/{calls/isfdkind.c => stdio/fpurge.c} | 11 +- libc/stdio/freadable.c | 28 ++++ libc/stdio/freading.c | 27 ++++ libc/stdio/freopen.c | 45 +----- libc/stdio/fsetlocking.c | 26 ++++ libc/stdio/fwritable.c | 28 ++++ libc/stdio/fwriting.c | 27 ++++ libc/{calls/isfdopen.c => stdio/g_fflush.c} | 8 +- libc/stdio/internal.h | 1 + libc/stdio/pclose.c | 43 ++++++ libc/stdio/popen.c | 57 +++++++ libc/stdio/stdio.h | 4 + libc/stdio/stdio_ext.h | 25 ++++ libc/stdio/system.c | 51 ++++--- libc/stdio/systemexec.c | 38 +++++ libc/str/iconv.c | 33 +++++ libc/str/str.h | 1 + libc/str/strverscmp.c | 71 +++++++++ libc/sysv/consts.sh | 30 ++-- libc/sysv/consts/SIGBUS.s | 2 +- libc/sysv/consts/SIGCHLD.s | 2 +- libc/sysv/consts/SIGCONT.s | 2 +- libc/sysv/consts/SIGIO.s | 2 +- libc/sysv/consts/SIGPOLL.s | 2 +- libc/sysv/consts/SIGPWR.s | 2 +- libc/sysv/consts/SIGSTKFLT.s | 2 +- libc/sysv/consts/SIGSTKSZ.s | 2 +- libc/sysv/consts/SIGSTOP.s | 2 +- libc/sysv/consts/SIGSYS.s | 2 +- libc/sysv/consts/SIGTSTP.s | 2 +- libc/sysv/consts/SIGUNUSED.s | 2 +- libc/sysv/consts/SIGURG.s | 2 +- libc/sysv/consts/SIGUSR1.s | 2 +- libc/sysv/consts/SIGUSR2.s | 2 +- libc/testlib/showerror_.c | 9 +- libc/time/asctime.c | 10 +- libc/time/asctime_r.c | 7 + test/libc/calls/hefty/vfork_test.c | 6 +- test/libc/calls/sigaction_test.c | 63 ++++++++ test/libc/stdio/popen_test.c | 34 +++++ third_party/chibicc/chibicc.c | 3 +- third_party/chibicc/chibicc.mk | 3 +- tool/build/runit.c | 155 ++++++++++++-------- tool/build/runitd.c | 131 +++++++++-------- tool/build/zipobj.c | 10 +- 96 files changed, 1474 insertions(+), 427 deletions(-) create mode 100644 examples/sleep.c create mode 100644 libc/calls/kill-nt.c create mode 100644 libc/runtime/abort-nt.c create mode 100644 libc/runtime/brk.c create mode 100644 libc/runtime/ldso.c create mode 100644 libc/runtime/pthread.c create mode 100644 libc/sock/shutdown-nt.c create mode 100644 libc/stdio/fbufsize.c create mode 100644 libc/stdio/fflush.internal.h create mode 100644 libc/stdio/flbf.c create mode 100644 libc/stdio/flushlbf.c create mode 100644 libc/stdio/fpending.c rename libc/{calls/isfdkind.c => stdio/fpurge.c} (89%) create mode 100644 libc/stdio/freadable.c create mode 100644 libc/stdio/freading.c create mode 100644 libc/stdio/fsetlocking.c create mode 100644 libc/stdio/fwritable.c create mode 100644 libc/stdio/fwriting.c rename libc/{calls/isfdopen.c => stdio/g_fflush.c} (90%) create mode 100644 libc/stdio/pclose.c create mode 100644 libc/stdio/popen.c create mode 100644 libc/stdio/stdio_ext.h create mode 100644 libc/stdio/systemexec.c create mode 100644 libc/str/iconv.c create mode 100644 libc/str/strverscmp.c create mode 100644 test/libc/calls/sigaction_test.c create mode 100644 test/libc/stdio/popen_test.c diff --git a/README.md b/README.md index 11c43c0ac..7e7ae21e7 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ Fast portable static native textmode executable containers. For an introduction to this project, please read the αcτµαlly pδrταblε -εxεcµταblε blog post and αcτµαlly pδrταblε εxεcµταblε +blog post and cosmopolitan libc website. API documentation is available here. diff --git a/ape/ape.lds b/ape/ape.lds index 6c6e25b93..077ae3f91 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -425,6 +425,7 @@ SECTIONS { *(.xlm) . = ALIGN(0x1000); + . = ALIGN(0x10000); /* for brk()/sbrk() allocation */ HIDDEN(_end = .); PROVIDE_HIDDEN(end = .); } AT>SmallCode :Ram diff --git a/build/bootstrap/zipobj.com b/build/bootstrap/zipobj.com index ca951ab218734d1a2a6cea3b3d0b4df7378ad1bb..f822251ef861efa4b807e36c5984bdbe5b342767 100755 GIT binary patch literal 172032 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↰wi#f#|km$leZ89eu!-y=7>+>B}JP+t%4i5 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 Q1pX%QH-Wzi{HGE4KahSvng9R* diff --git a/build/definitions.mk b/build/definitions.mk index b715438ac..556dcd883 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -185,6 +185,9 @@ DEFAULT_LDFLAGS = \ -z max-page-size=0x1000 \ -Ttext-segment=$(IMAGE_BASE_VIRTUAL) +ZIPOBJ_FLAGS = \ + -b$(IMAGE_BASE_VIRTUAL) + ASONLYFLAGS = \ -g \ --debug-prefix-map="$(PWD)"= diff --git a/build/rules.mk b/build/rules.mk index 9e91caa63..991e95721 100644 --- a/build/rules.mk +++ b/build/rules.mk @@ -34,7 +34,7 @@ o/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(f o/%.h.ok: %.h; @ACTION=CHECK.h build/compile $(COMPILE.c) -x c -g0 -o $@ $< o/%.h.okk: %.h; @ACTION=CHECK.h build/compile $(COMPILE.cxx) -x c++ -g0 -o $@ $< o/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg build/compile $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< -o/%.zip.o: o/%; @build/zipobj $(OUTPUT_OPTION) $< +o/%.zip.o: o/%; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< o/$(MODE)/%.a:; @$(ARCHIVE) $@ $^ o/$(MODE)/%: o/$(MODE)/%.dbg; @ACTION=OBJCOPY TARGET=$@ build/do $(OBJCOPY) -SO binary $< $@ @@ -75,7 +75,7 @@ o/$(MODE)/%.ncabi.o: %.ncabi.c; @ACTION=OBJECTIFY.nc build/compile $(OBJECTIFY.n o/$(MODE)/%.real.o: %.c; @ACTION=OBJECTIFY.real build/compile $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.runs: o/$(MODE)/%; @ACTION=CHECK.runs TARGET=$< build/runcom $< $(TESTARGS) && touch $@ o/$(MODE)/%.pkg:; @build/package $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^) -o/$(MODE)/%.zip.o: %; @build/zipobj $(OUTPUT_OPTION) $< +o/$(MODE)/%.zip.o: %; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< o/$(MODE)/%-gcc.asm: %.c; @ACTION=OBJECTIFY.c build/compile $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-clang.asm: CC = $(CLANG) diff --git a/examples/ctrlc.c b/examples/ctrlc.c index fa3e79cb8..3e2d1404a 100644 --- a/examples/ctrlc.c +++ b/examples/ctrlc.c @@ -8,10 +8,12 @@ ╚─────────────────────────────────────────────────────────────────*/ #endif #include "libc/calls/calls.h" +#include "libc/errno.h" #include "libc/log/check.h" #include "libc/log/color.internal.h" #include "libc/log/log.h" #include "libc/mem/mem.h" +#include "libc/nt/thread.h" #include "libc/runtime/gc.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" @@ -20,48 +22,41 @@ #include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/sig.h" -#define kTutorialMessage "This echos stdio until Ctrl+C is pressed.\n" -#define kVictoryMessage "\rGot Ctrl+C and longjmp() ran dtors (>'.')>\n" - -jmp_buf jb; +volatile bool gotctrlc; void GotCtrlC(int sig) { - gclongjmp(jb, 1); - unreachable; -} - -size_t HowManyBytesOfHeapMemoryAreAllocated(void) { - return mallinfo().uordblks; -} - -void ReadAndPrintLinesLoop(void) { - ssize_t got; - unsigned char *buf; - buf = gc(malloc(BUFSIZ)); - CHECK_NE(0, HowManyBytesOfHeapMemoryAreAllocated()); - for (;;) { - CHECK_NE(-1, (got = read(STDIN_FILENO, buf, BUFSIZ))); - CHECK_EQ(got, write(STDOUT_FILENO, buf, got)); - } + gotctrlc = true; } int main(int argc, char *argv[]) { - int rc; - rc = 0; - showcrashreports(); - if (cancolor()) { - CHECK_EQ(0 /* cosmo runtime doesn't link malloc */, - HowManyBytesOfHeapMemoryAreAllocated()); - puts("This echos stdio until Ctrl+C is pressed."); - if (!(rc = setjmp(jb))) { - CHECK_NE(SIG_ERR, signal(SIGINT, GotCtrlC)); - ReadAndPrintLinesLoop(); - unreachable; + ssize_t rc; + size_t got, wrote; + unsigned char buf[512]; + fprintf(stderr, "This echos stdio until Ctrl+C is pressed.\n"); + CHECK_NE( + -1, sigaction(SIGINT, &(struct sigaction){.sa_handler = GotCtrlC}, NULL)); + for (;;) { + rc = read(0, buf, BUFSIZ); + if (rc != -1) { + got = rc; } else { - --rc; + CHECK_EQ(EINTR, errno); + break; } - CHECK_EQ(0, HowManyBytesOfHeapMemoryAreAllocated()); - puts("\rGot Ctrl+C and longjmp() ran dtors (>'.')>"); + if (!got) break; + rc = write(1, buf, got); + if (rc != -1) { + wrote = rc; + } else { + CHECK_EQ(EINTR, errno); + break; + } + CHECK_EQ(got, wrote); } - return rc; + if (gotctrlc) { + fprintf(stderr, "Got Ctrl+C\n"); + } else { + fprintf(stderr, "Got EOF\n"); + } + return 0; } diff --git a/examples/examples.mk b/examples/examples.mk index 1dfe4fe18..58d4554ed 100644 --- a/examples/examples.mk +++ b/examples/examples.mk @@ -51,6 +51,7 @@ EXAMPLES_DIRECTDEPS = \ LIBC_LOG_ASAN \ LIBC_MEM \ LIBC_NEXGEN32E \ + LIBC_NT_KERNEL32 \ LIBC_NT_NTDLL \ LIBC_NT_USER32 \ LIBC_NT_WS2_32 \ diff --git a/examples/sleep.c b/examples/sleep.c new file mode 100644 index 000000000..565ab8e68 --- /dev/null +++ b/examples/sleep.c @@ -0,0 +1,61 @@ +#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" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/time/time.h" +#include "libc/x/x.h" + +/** + * 16kb sleep executable that runs on all operating systems. + * https://justine.lol/cosmopolitan/demos/sleep.c + * https://justine.lol/cosmopolitan/demos/sleep.com + * https://justine.lol/cosmopolitan/index.html + */ + +#define WRITE(s) write(2, s, strlen(s)) + +int main(int argc, char *argv[]) { + char *p; + long double x, y; + if (argc != 2) { + WRITE("Usage: "); + WRITE(argv[0]); + WRITE(" SECONDS\n"); + exit(1); + } + x = 0; + for (p = argv[1]; isdigit(*p); ++p) { + x *= 10; + x += *p - '0'; + } + if (*p == '.') { + y = 1; + for (++p; isdigit(*p); ++p) { + x += (*p - '0') * (y /= 10); + } + } + switch (*p) { + case 'm': + x *= 60; + break; + case 'h': + x *= 60 * 60; + break; + case 'd': + x *= 60 * 60 * 24; + break; + default: + break; + } + dsleep(x); + return 0; +} diff --git a/examples/unbourne.c b/examples/unbourne.c index 61cc71c0b..2bc18f370 100644 --- a/examples/unbourne.c +++ b/examples/unbourne.c @@ -617,10 +617,10 @@ #define setlocate(l, s) 0 #define equal(s1, s2) (strcmp(s1, s2) == 0) -#define getenv(p) bltinlookup((p), 0) -#define isodigit(c) ((c) >= '0' && (c) <= '7') -#define octtobin(c) ((c) - '0') -#define scopy(s1, s2) ((void)strcpy(s2, s1)) +/* #define getenv(p) bltinlookup((p), 0) */ +#define isodigit(c) ((c) >= '0' && (c) <= '7') +#define octtobin(c) ((c) - '0') +#define scopy(s1, s2) ((void)strcpy(s2, s1)) #define TRACE(param) /* #define TRACE(param) \ */ diff --git a/libc/calls/atfork.c b/libc/calls/atfork.c index 3e047554a..528e2745c 100644 --- a/libc/calls/atfork.c +++ b/libc/calls/atfork.c @@ -16,12 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" #include "libc/macros.h" #include "libc/runtime/runtime.h" #include "libc/sysv/errfuns.h" static struct AtFork { - size_t i; + volatile size_t i; struct AtForkCallback { void (*fn)(void *); void *arg; @@ -33,17 +34,25 @@ static struct AtFork { * * @return 0 on success, or -1 w/ errno * @note vfork() won't invoke callbacks + * @asyncsignalsafe */ int atfork(void *fn, void *arg) { - if (g_atfork.i == ARRAYLEN(g_atfork.p)) return enomem(); - g_atfork.p[g_atfork.i++] = (struct AtForkCallback){.fn = fn, .arg = arg}; - return 0; + size_t i; + for (;;) { + i = g_atfork.i; + if (i == ARRAYLEN(g_atfork.p)) return enomem(); + if (cmpxchg(&g_atfork.i, i, i + 1)) { + g_atfork.p[i] = (struct AtForkCallback){.fn = fn, .arg = arg}; + return 0; + } + } } /** * Triggers callbacks registered by atfork(). * * @note only fork() should call this + * @asyncsignalsafe */ void __onfork(void) { size_t i; diff --git a/libc/calls/fcntl-nt.c b/libc/calls/fcntl-nt.c index cd45e4b76..05f34bd70 100644 --- a/libc/calls/fcntl-nt.c +++ b/libc/calls/fcntl-nt.c @@ -17,6 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" +#include "libc/nt/enum/accessmask.h" +#include "libc/nt/enum/fileflagandattributes.h" +#include "libc/nt/enum/filesharemode.h" #include "libc/nt/files.h" #include "libc/sysv/consts/f.h" #include "libc/sysv/consts/fd.h" @@ -30,7 +33,22 @@ textwindows int fcntl$nt(int fd, int cmd, unsigned arg) { case F_GETFL: return g_fds.p[fd].flags; case F_SETFL: - return (g_fds.p[fd].flags = arg); + if (ReOpenFile( + g_fds.p[fd].handle, + (arg & O_APPEND) + ? kNtFileAppendData + : (arg & O_ACCMODE) == O_RDONLY + ? kNtGenericExecute | kNtFileGenericRead + : kNtGenericExecute | kNtFileGenericRead | + kNtFileGenericWrite, + (arg & O_EXCL) == O_EXCL + ? kNtFileShareExclusive + : kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, + kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal)) { + return (g_fds.p[fd].flags = arg); + } else { + return __winerr(); + } case F_GETFD: if (g_fds.p[fd].flags & O_CLOEXEC) { return FD_CLOEXEC; @@ -38,7 +56,7 @@ textwindows int fcntl$nt(int fd, int cmd, unsigned arg) { return 0; } case F_SETFD: - if (arg & O_CLOEXEC) { + if (arg & FD_CLOEXEC) { g_fds.p[fd].flags |= O_CLOEXEC; return FD_CLOEXEC; } else { diff --git a/libc/calls/getpid.c b/libc/calls/getpid.c index f75be2c35..ce9ad3689 100644 --- a/libc/calls/getpid.c +++ b/libc/calls/getpid.c @@ -17,15 +17,16 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/bits.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/dce.h" #include "libc/nt/process.h" #include "libc/runtime/runtime.h" -static int g_pid; +static int __pid; -static int __get_pid(void) { +static int __getpid(void) { if (!IsWindows()) { return getpid$sysv(); } else { @@ -33,20 +34,25 @@ static int __get_pid(void) { } } -static void __update_pid(void) { - g_pid = __get_pid(); +static void __updatepid(void) { + __pid = __getpid(); } /** * Returns process id. * @asyncsignalsafe + * @vforksafe */ int getpid(void) { static bool once; - if (!once) { - __update_pid(); - atfork(__update_pid, NULL); - once = true; + if (__vforked) { + return getpid$sysv(); } - return g_pid; + if (!once) { + __updatepid(); + if (cmpxchg(&once, false, true)) { + atfork(__updatepid, NULL); + } + } + return __pid; } diff --git a/libc/calls/hefty/vfork.S b/libc/calls/hefty/vfork.S index 40f6ecfda..4821a69fb 100644 --- a/libc/calls/hefty/vfork.S +++ b/libc/calls/hefty/vfork.S @@ -27,6 +27,9 @@ / call read() safely but you can call pread(). Call _exit() but / don't call exit(). Look for the vforksafe function annotation / +/ Do not make the assumption that the parent is suspended until +/ the child terminates since this impl calls fork() on Windows. +/ / @return pid of child process or 0 if forked process / @returnstwice / @vforksafe diff --git a/libc/calls/internal.h b/libc/calls/internal.h index f1db931a1..d7189eb01 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -70,8 +70,14 @@ hidden extern const struct NtSecurityAttributes kNtIsInheritable; ssize_t __getemptyfd(void) hidden; int __ensurefds(int) hidden; void __removefd(int) hidden; -bool __isfdopen(int) hidden nosideeffect; -bool __isfdkind(int, enum FdKind) hidden nosideeffect; + +forceinline bool __isfdopen(int fd) { + return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty; +} + +forceinline bool __isfdkind(int fd, enum FdKind kind) { + return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind; +} forceinline size_t clampio(size_t size) { if (!IsTrustworthy()) { @@ -214,46 +220,46 @@ void xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *, │ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -int gettimeofday$nt(struct timeval *, struct timezone *) hidden; bool32 isatty$nt(int) hidden; char *getcwd$nt(char *, size_t) hidden; -int fork$nt(void) hidden; +i64 lseek$nt(int, i64, int) hidden; int chdir$nt(const char *) hidden; int close$nt(int) hidden; int dup$nt(int, int, int) hidden; +int execve$nt(const char *, char *const[], char *const[]) hidden; +int faccessat$nt(int, const char *, int, uint32_t) hidden; int fadvise$nt(int, u64, u64, int) hidden; int fcntl$nt(int, int, unsigned) hidden; -int getpriority$nt(int) hidden; -int setpriority$nt(int) hidden; int fdatasync$nt(int) hidden; int flock$nt(int, int) hidden; +int fork$nt(void) hidden; int fstat$nt(i64, struct stat *) hidden; int ftruncate$nt(int, u64) hidden; -int kill$nt(i64, int) hidden; +int getpriority$nt(int) hidden; +int getrusage$nt(int, struct rusage *) hidden; +int gettimeofday$nt(struct timeval *, struct timezone *) hidden; +int kill$nt(int, int) hidden; int link$nt(const char *, const char *) hidden; int lstat$nt(const char *, struct stat *) hidden; int madvise$nt(void *, size_t, int) hidden; int msync$nt(void *, size_t, int) hidden; -ssize_t open$nt(const char *, u32, i32) nodiscard hidden; +int nanosleep$nt(const struct timespec *, struct timespec *) hidden; int pipe$nt(int[hasatleast 2], unsigned) hidden; int rename$nt(const char *, const char *) hidden; int rmdir$nt(const char *) hidden; int sched_yield$nt(void) hidden; +int setitimer$nt(int, const struct itimerval *, struct itimerval *) hidden; +int setpriority$nt(int) hidden; int stat$nt(const char *, struct stat *) hidden; -int sync$nt(void) hidden; int symlink$nt(const char *, const char *) hidden; +int sync$nt(void) hidden; int sysinfo$nt(struct sysinfo *) hidden; int truncate$nt(const char *, u64) hidden; int unlink$nt(const char *) hidden; -i64 lseek$nt(int, i64, int) hidden; +int utimensat$nt(int, const char *, const struct timespec *, int) hidden; +ssize_t open$nt(const char *, u32, i32) nodiscard hidden; ssize_t read$nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden; ssize_t write$nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden; -int utimensat$nt(int, const char *, const struct timespec *, int) hidden; -int getrusage$nt(int, struct rusage *) hidden; -int setitimer$nt(int, const struct itimerval *, struct itimerval *) hidden; -int nanosleep$nt(const struct timespec *, struct timespec *) hidden; -int faccessat$nt(int, const char *, int, uint32_t) hidden; -int execve$nt(const char *, char *const[], char *const[]) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » windows nt » support ─╬─│┼ @@ -266,7 +272,6 @@ int getsetpriority$nt(int, unsigned, int, int (*)(int)); void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden; struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden; bool32 ntsetprivilege(i64, const char16_t *, u32) hidden; -bool32 onntconsoleevent$nt(u32) hidden; void __winalarm(void *, uint32_t, uint32_t) hidden; int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden; int64_t __winerr(void) nocallback privileged; diff --git a/libc/calls/kill-nt.c b/libc/calls/kill-nt.c new file mode 100644 index 000000000..d09f908cb --- /dev/null +++ b/libc/calls/kill-nt.c @@ -0,0 +1,56 @@ +/*-*- 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 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/calls/internal.h" +#include "libc/dce.h" +#include "libc/macros.h" +#include "libc/nt/console.h" +#include "libc/nt/enum/ctrlevent.h" +#include "libc/nt/process.h" +#include "libc/sysv/errfuns.h" + +textwindows int kill$nt(int pid, int sig) { + int target; + uint32_t event; + if (!pid) return raise(sig); + if ((pid > 0 && __isfdkind(pid, kFdProcess)) || + (pid < 0 && __isfdkind(-pid, kFdProcess))) { + target = GetProcessId(g_fds.p[ABS(pid)].handle); + } else { + target = pid; + } + if (target == GetCurrentProcessId()) { + return raise(sig); + } else { + switch (sig) { + case SIGINT: + event = kNtCtrlCEvent; + case SIGHUP: + event = kNtCtrlCloseEvent; + case SIGQUIT: + event = kNtCtrlBreakEvent; + default: + return einval(); + } + if (GenerateConsoleCtrlEvent(event, target)) { + return 0; + } else { + return __winerr(); + } + } +} diff --git a/libc/calls/kill.c b/libc/calls/kill.c index aafab4075..60fbd1627 100644 --- a/libc/calls/kill.c +++ b/libc/calls/kill.c @@ -19,7 +19,6 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/dce.h" -#include "libc/sysv/errfuns.h" /** * Sends signal to process. @@ -39,15 +38,9 @@ * @asyncsignalsafe */ int kill(int pid, int sig) { - int me; if (!IsWindows()) { return kill$sysv(pid, sig, 1); } else { - me = getpid(); - if (!pid || pid == me || pid == -me) { - return raise(sig); - } else { - return enosys(); - } + return kill$nt(pid, sig); } } diff --git a/libc/calls/ntspawn.c b/libc/calls/ntspawn.c index cbb2a7995..ae6a51abd 100644 --- a/libc/calls/ntspawn.c +++ b/libc/calls/ntspawn.c @@ -84,7 +84,8 @@ textwindows int ntspawn( mkntenvblock(block->envvars, envp) != -1) { if (CreateProcess(NULL, block->cmdline, opt_lpProcessAttributes, opt_lpThreadAttributes, bInheritHandles, - dwCreationFlags | kNtCreateUnicodeEnvironment, + dwCreationFlags | kNtCreateNewProcessGroup | + kNtCreateUnicodeEnvironment, block->envvars, opt_lpCurrentDirectory, lpStartupInfo, opt_out_lpProcessInformation)) { rc = 0; diff --git a/libc/calls/onntconsoleevent.c b/libc/calls/onntconsoleevent.c index 481a3b3c5..b03347aee 100644 --- a/libc/calls/onntconsoleevent.c +++ b/libc/calls/onntconsoleevent.c @@ -23,7 +23,7 @@ #include "libc/str/str.h" #include "libc/sysv/consts/sig.h" -textwindows bool32 onntconsoleevent(uint32_t CtrlType) { +textwindows bool32 __onntconsoleevent(uint32_t CtrlType) { int sig; siginfo_t info; switch (CtrlType) { diff --git a/libc/calls/onntconsoleevent_init.S b/libc/calls/onntconsoleevent_init.S index 68dc806d3..024c04b5a 100644 --- a/libc/calls/onntconsoleevent_init.S +++ b/libc/calls/onntconsoleevent_init.S @@ -20,7 +20,7 @@ .source __FILE__ .init.start 300,_init_onntconsoleevent - ezlea onntconsoleevent$nt,cx + ezlea __onntconsoleevent$nt,cx pushpop 1,%rdx ntcall __imp_SetConsoleCtrlHandler .init.end 300,_init_onntconsoleevent,globl,hidden diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c index a13db563d..f405adb68 100644 --- a/libc/calls/open-nt.c +++ b/libc/calls/open-nt.c @@ -45,10 +45,12 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags, (flags & 0xf000000f) | (/* this is needed if we mmap(rwx+cow) nt is choosy about open() access */ - (flags & O_ACCMODE) == O_RDONLY - ? kNtGenericExecute | kNtFileGenericRead - : kNtGenericExecute | kNtFileGenericRead | - kNtFileGenericWrite), + (flags & O_APPEND) + ? kNtFileAppendData + : (flags & O_ACCMODE) == O_RDONLY + ? kNtGenericExecute | kNtFileGenericRead + : kNtGenericExecute | kNtFileGenericRead | + kNtFileGenericWrite), (flags & O_EXCL) ? kNtFileShareExclusive : kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, diff --git a/libc/calls/pause.c b/libc/calls/pause.c index 06ad55495..0a721dad1 100644 --- a/libc/calls/pause.c +++ b/libc/calls/pause.c @@ -25,15 +25,18 @@ /** * Waits for signal. * - * @return should be -1 w/ EINTR + * This suspends execution until an unmasked signal is delivered + * and its callback function has been called. It's a better idea + * to use sigsuspend() w/ sigprocmask() to avoid race conditions + * + * @return should always be -1 w/ EINTR * @see sigsuspend() */ int pause(void) { int rc, olderr; sigset_t oldmask; olderr = errno; - rc = pause$sysv(); - if (rc == -1 && errno == ENOSYS) { + if ((rc = pause$sysv()) == -1 && errno == ENOSYS) { errno = olderr; if (sigprocmask(SIG_BLOCK, NULL, &oldmask) == -1) return -1; rc = sigsuspend(&oldmask); diff --git a/libc/calls/raise.c b/libc/calls/raise.c index a20e9dc05..2236518da 100644 --- a/libc/calls/raise.c +++ b/libc/calls/raise.c @@ -23,7 +23,7 @@ #include "libc/nt/runtime.h" #include "libc/sysv/consts/sig.h" -static uint32_t GetCtrlEvent(int sig) { +static textwindows uint32_t GetCtrlEvent(int sig) { switch (sig) { case SIGINT: return kNtCtrlCEvent; diff --git a/libc/calls/sigprocmask.c b/libc/calls/sigprocmask.c index 7d0b35a0b..02185798f 100644 --- a/libc/calls/sigprocmask.c +++ b/libc/calls/sigprocmask.c @@ -34,11 +34,12 @@ * @param oldset will receive the old mask (optional) and can't overlap * @return 0 on success, or -1 w/ errno * @asyncsignalsafe + * @vforksafe */ int sigprocmask(int how, const sigset_t *opt_set, sigset_t *opt_out_oldset) { if (!IsWindows()) { return sigprocmask$sysv(how, opt_set, opt_out_oldset, 8); } else { - return enosys(); /* TODO(jart): Implement me! */ + return 0; /* TODO(jart): Implement me! */ } } diff --git a/libc/calls/sigsuspend.c b/libc/calls/sigsuspend.c index cee0a3995..96b526f29 100644 --- a/libc/calls/sigsuspend.c +++ b/libc/calls/sigsuspend.c @@ -25,14 +25,14 @@ /** * Blocks until SIG ∉ MASK is delivered to process. * - * @param mask is a bitset of signals to block temporarily + * @param ignore is a bitset of signals to block temporarily * @return -1 w/ EINTR * @asyncsignalsafe */ -int sigsuspend(const sigset_t *mask) { - if (!mask) return efault(); +int sigsuspend(const sigset_t *ignore) { + if (!ignore) return efault(); if (!IsWindows()) { - return sigsuspend$sysv(mask, 8); + return sigsuspend$sysv(ignore, 8); } else { return enosys(); /* TODO(jart): Implement me! */ } diff --git a/libc/calls/thunks/onntconsoleevent.S b/libc/calls/thunks/onntconsoleevent.S index 92c4caf6f..1126da796 100644 --- a/libc/calls/thunks/onntconsoleevent.S +++ b/libc/calls/thunks/onntconsoleevent.S @@ -20,7 +20,7 @@ .text.windows .source __FILE__ -onntconsoleevent$nt: - ezlea onntconsoleevent,ax +__onntconsoleevent$nt: + ezlea __onntconsoleevent,ax jmp __nt2sysv - .endfn onntconsoleevent$nt,globl,hidden + .endfn __onntconsoleevent$nt,globl,hidden diff --git a/libc/calls/waitpid.c b/libc/calls/waitpid.c index e3d25d65f..a5fb7d70e 100644 --- a/libc/calls/waitpid.c +++ b/libc/calls/waitpid.c @@ -17,9 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/internal.h" -#include "libc/calls/wait4.h" -#include "libc/dce.h" /** * Waits for status to change on process. @@ -33,9 +30,5 @@ * @asyncsignalsafe */ int waitpid(int pid, int *opt_out_wstatus, int options) { - if (!IsWindows()) { - return wait4$sysv(pid, opt_out_wstatus, options, NULL); - } else { - return wait4$nt(pid, opt_out_wstatus, options, NULL); - } + return wait4(pid, opt_out_wstatus, options, NULL); } diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index aab0c4efc..a7e1d0818 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -41,7 +41,7 @@ textwindows ssize_t write$nt(struct Fd *fd, const struct iovec *iov, if (WriteFile(fd->handle, iovlen ? iov[0].iov_base : NULL, iovlen ? clampio(iov[0].iov_len) : 0, &wrote, offset2overlap(opt_offset, &overlap))) { - if (!wrote) assert(SumIovecLen(iov, iovlen) > 0); + if (!wrote) assert(!SumIovecLen(iov, iovlen)); FlushFileBuffers(fd->handle); return wrote; } else { diff --git a/libc/log/backtrace2.c b/libc/log/backtrace2.c index b45c4fb23..5ad1775d7 100644 --- a/libc/log/backtrace2.c +++ b/libc/log/backtrace2.c @@ -22,6 +22,7 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/dce.h" +#include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/log/backtrace.internal.h" @@ -40,7 +41,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { ssize_t got; intptr_t addr; size_t i, j, gi; - int rc, pid, pipefds[2]; + int ws, pid, pipefds[2]; struct Garbages *garbage; const struct StackFrame *frame; const char *debugbin, *p1, *p2, *p3, *addr2line; @@ -73,7 +74,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { close(pipefds[0]); close(pipefds[1]); execvp(addr2line, argv); - abort(); + _exit(127); } close(pipefds[1]); while ((got = read(pipefds[0], buf, kBacktraceBufSize)) > 0) { @@ -99,9 +100,15 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { } } close(pipefds[0]); - if (waitpid(pid, &rc, 0) == -1) return -1; - if (WEXITSTATUS(rc) != 0) return -1; - return 0; + while (waitpid(pid, &ws, 0) == -1) { + if (errno == EINTR) continue; + return -1; + } + if (WIFEXITED(ws) && !WEXITSTATUS(ws)) { + return 0; + } else { + return -1; + } } static int PrintBacktrace(int fd, const struct StackFrame *bp) { diff --git a/libc/log/backtrace3.c b/libc/log/backtrace3.c index dd239e144..17f5eabd2 100644 --- a/libc/log/backtrace3.c +++ b/libc/log/backtrace3.c @@ -50,7 +50,6 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp, char buf[256], ibuf[21]; const struct Symbol *symbol; const struct StackFrame *frame; - if (!st) return -1; if (!bp) bp = __builtin_frame_address(0); garbage = weaken(__garbage); gi = garbage ? garbage->i : 0; @@ -66,8 +65,9 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp, *p++ = ' '; p = mempcpy(p, ibuf, uint64toarray_fixed16(addr, ibuf, 48)); *p++ = ' '; - if (st->count && ((intptr_t)addr >= (intptr_t)&_base && - (intptr_t)addr <= (intptr_t)&_end)) { + if (st && st->count && + ((intptr_t)addr >= (intptr_t)&_base && + (intptr_t)addr <= (intptr_t)&_end)) { symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols, st->count, addr - st->addr_base - 1)]; p = stpcpy(p, &st->name_base[symbol->name_rva]); diff --git a/libc/log/checkfail.c b/libc/log/checkfail.c index 8e5a010ed..37caa6e63 100644 --- a/libc/log/checkfail.c +++ b/libc/log/checkfail.c @@ -56,10 +56,10 @@ relegated void __check_fail(const char *suffix, const char *opstr, gethostname(hostname, sizeof(hostname)); (dprintf)(STDERR_FILENO, - "check failed on %s pid %d\r\n" - "\tCHECK_%s(%s, %s);\r\n" - "\t\t → %#lx (%s)\r\n" - "\t\t%s %#lx (%s)\r\n", + "check failed on %s pid %d\n" + "\tCHECK_%s(%s, %s);\n" + "\t\t → %#lx (%s)\n" + "\t\t%s %#lx (%s)\n", hostname, getpid(), sufbuf, wantstr, gotstr, want, wantstr, opstr, got, gotstr); @@ -68,19 +68,19 @@ relegated void __check_fail(const char *suffix, const char *opstr, va_start(va, fmt); (vdprintf)(STDERR_FILENO, fmt, va); va_end(va); - (dprintf)(STDERR_FILENO, "\r\n"); + (dprintf)(STDERR_FILENO, "\n"); } - (dprintf)(STDERR_FILENO, "\t%s\r\n\t%s%s%s%s\r\n", strerror(lasterr), SUBTLE, + (dprintf)(STDERR_FILENO, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE, getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET); for (i = 1; i < g_argc; ++i) { - (dprintf)(STDERR_FILENO, "\t\t%s%s\r\n", g_argv[i], + (dprintf)(STDERR_FILENO, "\t\t%s%s\n", g_argv[i], i < g_argc - 1 ? " \\" : ""); } if (!IsTiny() && lasterr == ENOMEM) { - (dprintf)(STDERR_FILENO, "\r\n"); + (dprintf)(STDERR_FILENO, "\n"); PrintMemoryIntervals(STDERR_FILENO, &_mmi); } diff --git a/libc/log/checkfail_ndebug.c b/libc/log/checkfail_ndebug.c index b232a73e0..a3a1a18c6 100644 --- a/libc/log/checkfail_ndebug.c +++ b/libc/log/checkfail_ndebug.c @@ -46,5 +46,5 @@ relegated void ___check_fail_ndebug(uint64_t want, uint64_t got, __print(bx, uint64toarray_radix16(got, bx)); __print_string(" ("); __print(bx, int64toarray_radix10(lasterr, bx)); - __print_string(")\r\n"); + __print_string(")\n"); } diff --git a/libc/log/perror.c b/libc/log/perror.c index dba0e01f8..7523a2cda 100644 --- a/libc/log/perror.c +++ b/libc/log/perror.c @@ -18,13 +18,21 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" #include "libc/fmt/fmt.h" -#include "libc/log/color.internal.h" #include "libc/log/internal.h" #include "libc/log/log.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" +/** + * Writes error messages to standard error. + */ void perror(const char *message) { - fprintf(stderr, "%s%s%s: %s: %s: %s\r\n", RED2, "error", RESET, - program_invocation_name, strerror(errno), message); + int err; + err = errno; + if (message && *message) { + fputs(message, stderr); + fputs(": ", stderr); + } + fputs(strerror(err), stderr); + fputc('\n', stderr); } diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index b9653ae51..2809abf53 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -41,7 +41,9 @@ STATIC_YOINK("ntoa"); STATIC_YOINK("stoa"); STATIC_YOINK("ftoa"); -static int loglevel2char(unsigned level) { +static struct timespec vflogf_ts; + +static int vflogf_loglevel2char(unsigned level) { switch (level) { case kLogInfo: return 'I'; @@ -78,34 +80,46 @@ void vflogf_onfail(FILE *f) { /** * Writes formatted message w/ timestamp to log. + * + * Timestamps are hyphenated out when multiple events happen within the + * same second in the same process. When timestamps are crossed out, it + * will display microseconsd as a delta elapsed time. This is useful if + * you do something like: + * + * LOGF("connecting to foo"); + * connect(...) + * LOGF("connected to foo"); + * + * In that case, the second log entry will always display the amount of + * time that it took to connect. This is great in forking applications. */ void(vflogf)(unsigned level, const char *file, int line, FILE *f, const char *fmt, va_list va) { - static struct timespec ts; struct tm tm; long double t2; const char *prog; - int64_t secs, nsec, dots; + bool issamesecond; char buf32[32], *buf32p; + int64_t secs, nsec, dots; if (!f) f = g_logfile; if (fileno(f) == -1) return; t2 = nowl(); secs = t2; - nsec = rem1000000000int64(t2 * 1e9L); - if (secs > ts.tv_sec) { + nsec = (t2 - secs) * 1e9L; + issamesecond = secs == vflogf_ts.tv_sec; + dots = issamesecond ? nsec - vflogf_ts.tv_nsec : nsec; + vflogf_ts.tv_sec = secs; + vflogf_ts.tv_nsec = nsec; + if (!issamesecond) { localtime_r(&secs, &tm); strftime(buf32, sizeof(buf32), "%Y-%m-%dT%H:%M:%S.", &tm); buf32p = buf32; - dots = nsec; } else { buf32p = "--------------------"; - dots = nsec - ts.tv_nsec; } - ts.tv_sec = secs; - ts.tv_nsec = nsec; prog = basename(program_invocation_name); - if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", loglevel2char(level), buf32p, - rem1000000int64(div1000int64(dots)), file, line, + if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", vflogf_loglevel2char(level), + buf32p, rem1000000int64(div1000int64(dots)), file, line, strchrnul(prog, '.') - prog, prog, getpid()) <= 0) { vflogf_onfail(f); } diff --git a/libc/nt/privilege.h b/libc/nt/privilege.h index 043c2e3d1..0f49ba915 100644 --- a/libc/nt/privilege.h +++ b/libc/nt/privilege.h @@ -1,6 +1,7 @@ #ifndef COSMOPOLITAN_LIBC_NT_PRIVILEGE_H_ #define COSMOPOLITAN_LIBC_NT_PRIVILEGE_H_ #include "libc/nt/struct/luid.h" +#include "libc/nt/struct/tokenprivileges.h" /* ░░░░ ▒▒▒░░░▒▒▒▒▒▒▒▓▓▓░ ▒▒▒▒░░░▒▒▒▒▒▒▓▓▓▓▓▓░ @@ -34,9 +35,6 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -struct NtLuid; -struct NtTokenPrivileges; - bool32 LookupPrivilegeValue(const char16_t *opt_lpSystemName, const char16_t *lpName, struct NtLuid *out_lpLuid); diff --git a/libc/nt/process.h b/libc/nt/process.h index 6fe89c151..02ff6d4b1 100644 --- a/libc/nt/process.h +++ b/libc/nt/process.h @@ -43,8 +43,8 @@ bool32 CreateProcess(const char16_t *opt_lpApplicationName, struct NtProcessInformation *opt_out_lpProcessInformation) paramsnonnull((2, 9)); -uint32_t GetThreadId(int64_t Thread); /* cf. NT_TID */ -uint32_t GetProcessId(int64_t Process); /* cf. NT_PID */ +uint32_t GetThreadId(int64_t hThread); /* cf. NT_TID */ +uint32_t GetProcessId(int64_t hProcess); /* cf. NT_PID */ void SetLastError(uint32_t dwErrCode); uint32_t FormatMessage(uint32_t dwFlags, const void *lpSource, uint32_t dwMessageId, uint32_t dwLanguageId, diff --git a/libc/runtime/abort-nt.c b/libc/runtime/abort-nt.c new file mode 100644 index 000000000..4491d2bb5 --- /dev/null +++ b/libc/runtime/abort-nt.c @@ -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 2020 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/bits/pushpop.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/siginfo.h" +#include "libc/nt/enum/ctrlevent.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/sig.h" + +textwindows wontreturn void abort$nt(void) { + siginfo_t info; + memset(&info, 0, sizeof(info)); + info.si_signo = SIGABRT; + __sigenter(SIGABRT, &info, NULL); + _Exit(128 + SIGABRT); +} diff --git a/libc/runtime/abort.S b/libc/runtime/abort.S index de1bc818a..36164db63 100644 --- a/libc/runtime/abort.S +++ b/libc/runtime/abort.S @@ -56,6 +56,5 @@ abort: push %rbp mov SIGABRT,%esi mov __NR_kill,%eax syscall # avoid hook and less bt noise -2: mov $134,%edi # exit(128+SIGABRT) [bash-ism] - call _Exit +2: call abort$nt .endfn abort,globl,protected diff --git a/libc/runtime/brk.c b/libc/runtime/brk.c new file mode 100644 index 000000000..6e95b6841 --- /dev/null +++ b/libc/runtime/brk.c @@ -0,0 +1,77 @@ +/*-*- 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 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/assert.h" +#include "libc/calls/calls.h" +#include "libc/macros.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" +#include "libc/sysv/errfuns.h" + +uintptr_t __break; + +/** + * Sets end of data section. + * + * This can be used to allocate and deallocate memory. It won't + * conflict with malloc() and mmap(NULL, ...) allocations since + * APE binaries load the image at 0x400000 and does allocations + * starting at 0x100080000000. You should consult _end, or call + * sbrk(NULL), to figure out where the existing break is first. + * + * @return 0 on success or -1 w/ errno + * @see mmap(), sbrk(), _end + */ +int brk(void *end) { + int rc; + uintptr_t x; + if (!__break) __break = (uintptr_t)_end; + x = (uintptr_t)end; + if (x < (uintptr_t)_end) x = (uintptr_t)_end; + x = ROUNDUP(x, FRAMESIZE); + if (x == __break) return 0; + /* allocate one frame at a time due to nt pickiness */ + for (; x > __break; __break += FRAMESIZE) { + if (mmap((void *)__break, FRAMESIZE, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) { + return -1; + } + } + for (rc = 0; x < __break; __break -= FRAMESIZE) { + rc |= munmap((void *)(__break - FRAMESIZE), FRAMESIZE); + } + return 0; +} + +/** + * Adjusts end of data section. + * + * This shrinks or increases the program break by delta bytes. On + * success, the previous program break is returned. It's possible + * to pass zero to this function to get the current program break + * + * @return old break on success or -1 w/ errno + * @see mmap(), brk(), _end + */ +void *sbrk(intptr_t delta) { + uintptr_t oldbreak; + if (!__break) __break = (uintptr_t)_end; + oldbreak = __break; + return (void *)(brk((void *)(__break + delta)) != -1 ? oldbreak : -1); +} diff --git a/libc/runtime/ldso.c b/libc/runtime/ldso.c new file mode 100644 index 000000000..4034dfb34 --- /dev/null +++ b/libc/runtime/ldso.c @@ -0,0 +1,40 @@ +/*-*- 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 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/runtime/runtime.h" + +char *dlerror(void) { + return "cosmopolitan doesn't support dsos"; +} + +void *dlopen(const char *file, int mode) { + return NULL; +} + +void *dlsym(void *handle, const char *name) { + return NULL; +} + +int dlclose(void *handle) { + return -1; +} + +int dl_iterate_phdr(int callback(void *info, size_t size, void *data), + void *data) { + return -1; +} diff --git a/libc/runtime/pthread.c b/libc/runtime/pthread.c new file mode 100644 index 000000000..62fda4684 --- /dev/null +++ b/libc/runtime/pthread.c @@ -0,0 +1,50 @@ +/*-*- 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 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/bits/bits.h" +#include "libc/errno.h" +#include "libc/runtime/runtime.h" + +typedef void *pthread_t; +typedef bool pthread_once_t; +typedef int pthread_mutex_t; + +int pthread_once(pthread_once_t *once, void init(void)) { + if (lockcmpxchg(once, 0, 1)) init(); + return 0; +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) { + return EINVAL; +} + +int pthread_mutex_trylock(pthread_mutex_t *mutex) { + return EINVAL; +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) { + return EPERM; +} + +int pthread_cancel(pthread_t thread) { + return ESRCH; +} + +void *__tls_get_addr(size_t v[2]) { + return NULL; +} diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 423a3e325..015b02592 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -23,7 +23,7 @@ extern unsigned char _base[] forcealign(PAGESIZE); /* αpε */ extern unsigned char _ehead[] forcealign(PAGESIZE); /* αpε */ extern unsigned char _etext[] forcealign(PAGESIZE); /* αpε */ extern unsigned char _edata[] forcealign(PAGESIZE); /* αpε */ -extern unsigned char _end[] forcealign(PAGESIZE); /* αpε */ +extern unsigned char _end[] forcealign(FRAMESIZE); /* αpε */ extern unsigned char _ereal; /* αpε */ extern unsigned char __privileged_start; /* αpε */ extern unsigned char __test_start; /* αpε */ @@ -70,6 +70,8 @@ int msync(void *, size_t, int); void __print(const void *, size_t); void __print_string(const char *); void __fast_math(void); +void *sbrk(intptr_t); +int brk(void *); /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § runtime » optimizations ─╬─│┼ diff --git a/libc/sock/bind-nt.c b/libc/sock/bind-nt.c index 846ef449d..75c6ea5e8 100644 --- a/libc/sock/bind-nt.c +++ b/libc/sock/bind-nt.c @@ -23,16 +23,6 @@ #include "libc/sock/yoink.inc" #include "libc/sysv/errfuns.h" -/** - * Assigns local address and port number to socket. - * - * @param fd is the file descriptor returned by socket() - * @param addr is usually the binary-encoded ip:port on which to listen - * @param addrsize is the byte-length of addr's true polymorphic form - * @return socket file descriptor or -1 w/ errno - * @error ENETDOWN, EPFNOSUPPORT, etc. - * @asyncsignalsafe - */ textwindows int bind$nt(struct Fd *fd, const void *addr, uint32_t addrsize) { assert(fd->kind == kFdSocket); if (__bind$nt(fd->handle, addr, addrsize) != -1) { diff --git a/libc/sock/internal.h b/libc/sock/internal.h index c951c5d4b..6aaeefd58 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -58,8 +58,6 @@ int32_t __socket$sysv(int32_t, int32_t, int32_t) hidden; int32_t __getsockname$sysv(int32_t, void *, uint32_t *) hidden; int32_t __getpeername$sysv(int32_t, void *, uint32_t *) hidden; -int32_t setsockopt$sysv(int32_t, int32_t, int32_t, const void *, - uint32_t) hidden; int32_t accept4$sysv(int32_t, void *, uint32_t *, int) nodiscard hidden; int32_t accept$sysv(int32_t, void *, uint32_t *) hidden; int32_t bind$sysv(int32_t, const void *, uint32_t) hidden; @@ -78,6 +76,7 @@ ssize_t sendto$sysv(int, const void *, size_t, int, const void *, uint32_t) hidden; int32_t select$sysv(int32_t, fd_set *, fd_set *, fd_set *, struct timeval *) hidden; +int setsockopt$sysv(int, int, int, const void *, uint32_t) hidden; int32_t epoll_create$sysv(int32_t) hidden; int32_t epoll_ctl$sysv(int32_t, int32_t, int32_t, void *) hidden; int32_t epoll_wait$sysv(int32_t, void *, int32_t, int32_t) hidden; @@ -93,6 +92,7 @@ int accept$nt(struct Fd *, void *, uint32_t *, int) hidden; int closesocket$nt(int) hidden; int socket$nt(int, int, int) hidden; int select$nt(int, fd_set *, fd_set *, fd_set *, struct timeval *) hidden; +int shutdown$nt(struct Fd *, int) hidden; size_t iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t) hidden; diff --git a/libc/sock/shutdown-nt.c b/libc/sock/shutdown-nt.c new file mode 100644 index 000000000..3dde5fb15 --- /dev/null +++ b/libc/sock/shutdown-nt.c @@ -0,0 +1,29 @@ +/*-*- 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 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/calls/internal.h" +#include "libc/nt/winsock.h" +#include "libc/sock/internal.h" + +textwindows int shutdown$nt(struct Fd *fd, int how) { + if (__shutdown$nt(fd->handle, how) != -1) { + return 0; + } else { + return __winsockerr(); + } +} diff --git a/libc/sock/shutdown.c b/libc/sock/shutdown.c index fa47c9528..c0f2ca868 100644 --- a/libc/sock/shutdown.c +++ b/libc/sock/shutdown.c @@ -18,19 +18,10 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/dce.h" -#include "libc/nt/winsock.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" #include "libc/sysv/errfuns.h" -static int shutdown$nt(struct Fd *fd, int how) { - if (__shutdown$nt(fd->handle, how) != -1) { - return 0; - } else { - return __winsockerr(); - } -} - /** * Disables sends or receives on a socket, without closing. * @@ -41,12 +32,7 @@ static int shutdown$nt(struct Fd *fd, int how) { */ int shutdown(int fd, int how) { if (!IsWindows()) { - if (!IsXnu()) { - return shutdown$sysv(fd, how); - } else { - /* TODO(jart): What's wrong with XNU shutdown()? */ - return 0; - } + return shutdown$sysv(fd, how); } else if (__isfdkind(fd, kFdSocket)) { return shutdown$nt(&g_fds.p[fd], how); } else { diff --git a/libc/stdio/fbufsize.c b/libc/stdio/fbufsize.c new file mode 100644 index 000000000..254276b64 --- /dev/null +++ b/libc/stdio/fbufsize.c @@ -0,0 +1,27 @@ +/*-*- 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 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/assert.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Returns capacity of stdio stream buffer. + */ +size_t __fbufsize(FILE *f) { + return f->size; +} diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c index 69c491f69..cfbce4f56 100644 --- a/libc/stdio/fflush.c +++ b/libc/stdio/fflush.c @@ -23,22 +23,11 @@ #include "libc/macros.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" +#include "libc/stdio/fflush.internal.h" #include "libc/stdio/internal.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/o.h" -struct StdioFlushHandles { - size_t i, n; - FILE **p; -}; - -struct StdioFlush { - struct StdioFlushHandles handles; - FILE *handles_initmem[8]; -}; - -static struct StdioFlush g_fflush; - /** * Blocks until data from stream buffer is written out. * diff --git a/libc/stdio/fflush.internal.h b/libc/stdio/fflush.internal.h new file mode 100644 index 000000000..e5c8bd710 --- /dev/null +++ b/libc/stdio/fflush.internal.h @@ -0,0 +1,21 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ +#define COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ +#include "libc/stdio/stdio.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct StdioFlushHandles { + size_t i, n; + FILE **p; +}; + +struct StdioFlush { + struct StdioFlushHandles handles; + FILE *handles_initmem[8]; +}; + +extern struct StdioFlush g_fflush; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ */ diff --git a/libc/stdio/flbf.c b/libc/stdio/flbf.c new file mode 100644 index 000000000..661e09a73 --- /dev/null +++ b/libc/stdio/flbf.c @@ -0,0 +1,27 @@ +/*-*- 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 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/calls/calls.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Returns nonzero if stream is line buffered. + */ +int __flbf(FILE *f) { + return f->bufmode == _IOLBF; +} diff --git a/libc/stdio/flushlbf.c b/libc/stdio/flushlbf.c new file mode 100644 index 000000000..01166e0b2 --- /dev/null +++ b/libc/stdio/flushlbf.c @@ -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 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/calls/calls.h" +#include "libc/stdio/fflush.internal.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Flushes all line-buffered streams. + */ +void _flushlbf(void) { + int i; + for (i = 0; i < g_fflush.handles.i; ++i) { + if (g_fflush.handles.p[i]->bufmode == _IOLBF) { + fflush(g_fflush.handles.p[i]); + } + } +} diff --git a/libc/stdio/fpending.c b/libc/stdio/fpending.c new file mode 100644 index 000000000..1d540711a --- /dev/null +++ b/libc/stdio/fpending.c @@ -0,0 +1,26 @@ +/*-*- 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 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/stdio/stdio_ext.h" + +/** + * Returns number of pending output bytes. + */ +size_t __fpending(FILE *f) { + return f->end - f->beg; +} diff --git a/libc/calls/isfdkind.c b/libc/stdio/fpurge.c similarity index 89% rename from libc/calls/isfdkind.c rename to libc/stdio/fpurge.c index 6b2a2312a..ae87dd1ed 100644 --- a/libc/calls/isfdkind.c +++ b/libc/stdio/fpurge.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,8 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/internal.h" +#include "libc/stdio/stdio_ext.h" -bool __isfdkind(int fd, enum FdKind kind) { - return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind; +/** + * Discards contents of stream buffer. + */ +void __fpurge(FILE *f) { + f->beg = f->end = 0; } diff --git a/libc/stdio/freadable.c b/libc/stdio/freadable.c new file mode 100644 index 000000000..23281cb61 --- /dev/null +++ b/libc/stdio/freadable.c @@ -0,0 +1,28 @@ +/*-*- 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 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/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream allows reading. + */ +int __freadable(FILE *f) { + return (f->iomode & O_ACCMODE) == O_RDONLY || + (f->iomode & O_ACCMODE) == O_RDWR; +} diff --git a/libc/stdio/freading.c b/libc/stdio/freading.c new file mode 100644 index 000000000..07f2f2284 --- /dev/null +++ b/libc/stdio/freading.c @@ -0,0 +1,27 @@ +/*-*- 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 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/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream is read only. + */ +int __freading(FILE *f) { + return (f->iomode & O_ACCMODE) == O_RDONLY; +} diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c index 048b45510..275f65de4 100644 --- a/libc/stdio/freopen.c +++ b/libc/stdio/freopen.c @@ -17,18 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/internal.h" -#include "libc/dce.h" -#include "libc/errno.h" -#include "libc/nt/enum/accessmask.h" -#include "libc/nt/enum/fileflagandattributes.h" -#include "libc/nt/enum/filesharemode.h" -#include "libc/nt/files.h" -#include "libc/nt/runtime.h" #include "libc/stdio/stdio.h" #include "libc/sysv/consts/f.h" #include "libc/sysv/consts/fd.h" -#include "libc/sysv/consts/fileno.h" #include "libc/sysv/consts/o.h" /** @@ -52,42 +43,16 @@ FILE *freopen(const char *pathname, const char *mode, FILE *stream) { if (pathname) { /* open new stream, overwriting existing alloc */ if ((fd = open(pathname, flags, 0666)) != -1) { - if (!IsWindows()) { - dup3(fd, stream->fd, (flags & O_CLOEXEC)); - close(fd); - } else { - g_fds.p[stream->fd].handle = g_fds.p[fd].handle; - g_fds.p[fd].kind = kFdEmpty; - } + dup3(fd, stream->fd, flags & O_CLOEXEC); + close(fd); stream->iomode = flags; return stream; } else { return NULL; } } else { - /* change mode of open file */ - if (!IsWindows()) { - if (flags & O_CLOEXEC) { - if (fcntl$sysv(stream->fd, F_SETFD, FD_CLOEXEC) == -1) return NULL; - flags &= ~O_CLOEXEC; - } - if (flags) { - if (fcntl$sysv(stream->fd, F_SETFL, flags) == -1) return NULL; - } - return stream; - } else { - if (ReOpenFile( - stream->fd, - (flags & O_RDWR) == O_RDWR ? kNtGenericWrite : kNtGenericRead, - (flags & O_EXCL) == O_EXCL - ? kNtFileShareExclusive - : kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, - kNtFileAttributeNormal)) { - return stream; - } else { - __winerr(); - return NULL; - } - } + fcntl(stream->fd, F_SETFD, !!(flags & O_CLOEXEC)); + fcntl(stream->fd, F_SETFL, flags & ~O_CLOEXEC); + return stream; } } diff --git a/libc/stdio/fsetlocking.c b/libc/stdio/fsetlocking.c new file mode 100644 index 000000000..2dd880e79 --- /dev/null +++ b/libc/stdio/fsetlocking.c @@ -0,0 +1,26 @@ +/*-*- 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 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/stdio/stdio_ext.h" + +/** + * Does nothing and returns `FSETLOCKING_BYCALLER`. + */ +int __fsetlocking(FILE *f, int type) { + return FSETLOCKING_BYCALLER; +} diff --git a/libc/stdio/fwritable.c b/libc/stdio/fwritable.c new file mode 100644 index 000000000..04562f467 --- /dev/null +++ b/libc/stdio/fwritable.c @@ -0,0 +1,28 @@ +/*-*- 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 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/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream allows reading. + */ +int __fwritable(FILE *f) { + return (f->iomode & O_ACCMODE) == O_WRONLY || + (f->iomode & O_ACCMODE) == O_RDWR; +} diff --git a/libc/stdio/fwriting.c b/libc/stdio/fwriting.c new file mode 100644 index 000000000..18209496d --- /dev/null +++ b/libc/stdio/fwriting.c @@ -0,0 +1,27 @@ +/*-*- 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 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/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream is write only. + */ +int __fwriting(FILE *f) { + return (f->iomode & O_ACCMODE) == O_WRONLY; +} diff --git a/libc/calls/isfdopen.c b/libc/stdio/g_fflush.c similarity index 90% rename from libc/calls/isfdopen.c rename to libc/stdio/g_fflush.c index b1d134723..80139bd9b 100644 --- a/libc/calls/isfdopen.c +++ b/libc/stdio/g_fflush.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,8 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/internal.h" +#include "libc/stdio/fflush.internal.h" -bool __isfdopen(int fd) { - return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty; -} +struct StdioFlush g_fflush; diff --git a/libc/stdio/internal.h b/libc/stdio/internal.h index 56b28dab3..745b94a0a 100644 --- a/libc/stdio/internal.h +++ b/libc/stdio/internal.h @@ -17,6 +17,7 @@ int __fwritebuf(FILE *) hidden; long __fseteof(FILE *) hidden; long __fseterrno(FILE *) hidden; long __fseterr(FILE *, int) hidden; +void __fclosepid(FILE *) hidden; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/stdio/pclose.c b/libc/stdio/pclose.c new file mode 100644 index 000000000..911855ad1 --- /dev/null +++ b/libc/stdio/pclose.c @@ -0,0 +1,43 @@ +/*-*- 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 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/assert.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +/** + * Closes stream created by popen(). + * @return termination status of subprocess, or -1 w/ ECHILD + */ +int pclose(FILE *f) { + int ws, pid; + pid = f->pid; + fclose(f); + assert(pid); + if (!pid) return 0; +TryAgain: + if (wait4(pid, &ws, 0, 0) != -1) { + return ws; + } else if (errno == EINTR) { + goto TryAgain; + } else { + return echild(); + } +} diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c new file mode 100644 index 000000000..50abc39c5 --- /dev/null +++ b/libc/stdio/popen.c @@ -0,0 +1,57 @@ +/*-*- 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 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/calls/calls.h" +#include "libc/errno.h" +#include "libc/paths.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/fd.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * Spawns subprocess and returns pipe stream. + * @see pclose() + */ +FILE *popen(const char *cmdline, const char *mode) { + FILE *f; + int dir, flags, pipefds[2]; + flags = fopenflags(mode); + if ((flags & O_ACCMODE) == O_RDONLY) { + dir = 0; + } else if ((flags & O_ACCMODE) == O_WRONLY) { + dir = 1; + } else { + errno = EINVAL; + return NULL; + } + if (pipe(pipefds) == -1) return NULL; + fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC); + if (!(f = fdopen(pipefds[dir], mode))) abort(); + if ((f->pid = vfork()) == -1) abort(); + if (!f->pid) { + dup2(pipefds[!dir], !dir); + systemexec(cmdline); + _exit(127); + } + close(pipefds[!dir]); + return f; +} diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h index 0bc2b42d8..a0f4f1f18 100644 --- a/libc/stdio/stdio.h +++ b/libc/stdio/stdio.h @@ -22,6 +22,7 @@ typedef struct FILE { uint32_t nofree; // 0x24 int (*reader)(struct FILE *); // 0x28 int (*writer)(struct FILE *); // 0x30 + int pid; // 0x34 } FILE; extern FILE *stdin; @@ -69,6 +70,8 @@ unsigned favail(FILE *); void setbuf(FILE *, char *); void setbuffer(FILE *, char *, size_t); int setvbuf(FILE *, char *, int, size_t); +FILE *popen(const char *, const char *); +int pclose(FILE *); typedef uint64_t fpos_t; compatfn char *gets(char *) paramsnonnull(); @@ -78,6 +81,7 @@ compatfn int64_t fseeko(FILE *, long, int) paramsnonnull(); compatfn int64_t ftello(FILE *) paramsnonnull(); int system(const char *); +int systemexec(const char *); int systemecho(const char *); /*───────────────────────────────────────────────────────────────────────────│─╗ diff --git a/libc/stdio/stdio_ext.h b/libc/stdio/stdio_ext.h new file mode 100644 index 000000000..ea8b67136 --- /dev/null +++ b/libc/stdio/stdio_ext.h @@ -0,0 +1,25 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ +#define COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ +#include "libc/stdio/stdio.h" + +#define FSETLOCKING_QUERY 0 +#define FSETLOCKING_INTERNAL 1 +#define FSETLOCKING_BYCALLER 2 + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +size_t __fbufsize(FILE *); +size_t __fpending(FILE *); +int __flbf(FILE *); +int __freadable(FILE *); +int __fwritable(FILE *); +int __freading(FILE *); +int __fwriting(FILE *); +int __fsetlocking(FILE *, int); +void _flushlbf(void); +void __fpurge(FILE *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ */ diff --git a/libc/stdio/system.c b/libc/stdio/system.c index a01c7fdb4..ea69be8e6 100644 --- a/libc/stdio/system.c +++ b/libc/stdio/system.c @@ -18,12 +18,15 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigaction.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/paths.h" #include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/sysv/consts/sig.h" /** * Launches program with system command interpreter. @@ -34,26 +37,36 @@ */ int system(const char *cmdline) { int pid, wstatus; - char comspec[128]; - const char *prog, *arg; - if (weaken(fflush)) weaken(fflush)(NULL); - if (cmdline) { - if ((pid = vfork()) == -1) return -1; - if (!pid) { - strcpy(comspec, kNtSystemDirectory); - strcat(comspec, "cmd.exe"); - prog = !IsWindows() ? _PATH_BSHELL : comspec; - arg = !IsWindows() ? "-c" : "/C"; - execv(prog, (char *const[]){prog, arg, cmdline, NULL}); - _exit(errno); - } else if (wait4(pid, &wstatus, 0, NULL) != -1) { - return wstatus; - } else { - return -1; + sigset_t chldmask, savemask; + struct sigaction ignore, saveint, savequit; + if (!cmdline) return 1; + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + sigaction(SIGINT, &ignore, &saveint); + sigaction(SIGQUIT, &ignore, &savequit); + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); + pid = fork(); + if (!pid) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); + systemexec(cmdline); + _exit(127); + } else if (pid != -1) { + while (wait4(pid, &wstatus, 0, NULL) == -1) { + if (errno != EINTR) { + wstatus = -1; + break; + } } - } else if (IsWindows()) { - return true; } else { - return fileexists(_PATH_BSHELL); + wstatus = -1; } + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); + return wstatus; } diff --git a/libc/stdio/systemexec.c b/libc/stdio/systemexec.c new file mode 100644 index 000000000..cb9b3fd76 --- /dev/null +++ b/libc/stdio/systemexec.c @@ -0,0 +1,38 @@ +/*-*- 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 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/calls/calls.h" +#include "libc/dce.h" +#include "libc/paths.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +/** + * Executes system command replacing current process. + * @vforksafe + */ +int systemexec(const char *cmdline) { + char comspec[128]; + const char *prog, *arg; + strcpy(comspec, kNtSystemDirectory); + strcat(comspec, "cmd.exe"); + prog = !IsWindows() ? _PATH_BSHELL : comspec; + arg = !IsWindows() ? "-c" : "/C"; + return execv(prog, (char *const[]){prog, arg, cmdline, NULL}); +} diff --git a/libc/str/iconv.c b/libc/str/iconv.c new file mode 100644 index 000000000..f490fd365 --- /dev/null +++ b/libc/str/iconv.c @@ -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 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/str/str.h" + +typedef void *iconv_t; + +iconv_t iconv_open(const char *to, const char *from) { + return NULL; +} + +int iconv_close(iconv_t cd) { + return -1; +} + +size_t iconv(iconv_t cd, char **in, size_t *inb, char **out, size_t *outb) { + return -1; +} diff --git a/libc/str/str.h b/libc/str/str.h index 8f814355a..9684dd26b 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -169,6 +169,7 @@ bool endswith(const char *, const char *) strlenesque; bool endswith16(const char16_t *, const char16_t *) strlenesque; bool wcsendswith(const wchar_t *, const wchar_t *) strlenesque; const char *IndexDoubleNulString(const char *, unsigned) strlenesque; +int strverscmp(const char *, const char *); wchar_t *wmemset(wchar_t *, wchar_t, size_t) memcpyesque; char16_t *memset16(char16_t *, char16_t, size_t) memcpyesque; compatfn wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t) memcpyesque; diff --git a/libc/str/strverscmp.c b/libc/str/strverscmp.c new file mode 100644 index 000000000..153eeca83 --- /dev/null +++ b/libc/str/strverscmp.c @@ -0,0 +1,71 @@ +/*-*- 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│ +╚──────────────────────────────────────────────────────────────────────────────╝ +│ │ +│ Musl Libc │ +│ Copyright © 2005-2014 Rich Felker, et al. │ +│ │ +│ Permission is hereby granted, free of charge, to any person obtaining │ +│ a copy of this software and associated documentation files (the │ +│ "Software"), to deal in the Software without restriction, including │ +│ without limitation the rights to use, copy, modify, merge, publish, │ +│ distribute, sublicense, and/or sell copies of the Software, and to │ +│ permit persons to whom the Software is furnished to do so, subject to │ +│ the following conditions: │ +│ │ +│ The above copyright notice and this permission notice shall be │ +│ included in all copies or substantial portions of the Software. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ +│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ +│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ +│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ +│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ +│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │ +│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ +│ │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/str/str.h" + +asm(".ident\t\"\\n\\n\ +Musl libc (MIT License)\\n\ +Copyright 2005-2014 Rich Felker, et. al.\""); +asm(".include \"libc/disclaimer.inc\""); + +/** + * Compares two version strings. + */ +int strverscmp(const char *l0, const char *r0) { + const unsigned char *l = (const void *)l0; + const unsigned char *r = (const void *)r0; + size_t i, dp, j; + int z = 1; + /* Find maximal matching prefix and track its maximal digit + * suffix and whether those digits are all zeros. */ + for (dp = i = 0; l[i] == r[i]; i++) { + int c = l[i]; + if (!c) return 0; + if (!isdigit(c)) { + dp = i + 1, z = 1; + } else if (c != '0') { + z = 0; + } + } + if (l[dp] != '0' && r[dp] != '0') { + /* If we're not looking at a digit sequence that began + * with a zero, longest digit string is greater. */ + for (j = i; isdigit(l[j]); j++) { + if (!isdigit(r[j])) { + return 1; + } + } + if (isdigit(r[j])) { + return -1; + } + } else if (z && dp < i && (isdigit(l[i]) || isdigit(r[i]))) { + /* Otherwise, if common prefix of digit sequence is + * all zeros, digits order less than non-digits. */ + return (unsigned char)(l[i] - '0') - (unsigned char)(r[i] - '0'); + } + return l[i] - r[i]; +} diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 0278edbe6..04b7d49c5 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -180,21 +180,21 @@ syscon sig SIGXFSZ 25 25 25 25 25 # unix consensus & faked on nt syscon sig SIGVTALRM 26 26 26 26 26 # unix consensus & faked on nt syscon sig SIGPROF 27 27 27 27 27 # unix consensus & faked on nt syscon sig SIGWINCH 28 28 28 28 28 # unix consensus & faked on nt -syscon sig SIGBUS 7 10 10 10 0 # bsd consensus -syscon sig SIGUSR1 10 30 30 30 0 # bsd consensus -syscon sig SIGCHLD 17 20 20 20 0 # bsd consensus -syscon sig SIGCONT 18 19 19 19 0 # bsd consensus -syscon sig SIGIO 29 23 23 23 0 # bsd consensus -syscon sig SIGSTOP 19 17 17 17 0 # bsd consensus -syscon sig SIGSYS 31 12 12 12 0 # bsd consensus -syscon sig SIGTSTP 20 18 18 18 0 # bsd consensus -syscon sig SIGURG 23 0x10 0x10 0x10 0 # bsd consensus -syscon sig SIGUSR2 12 31 31 31 0 # bsd consensus -syscon sig SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0 -syscon sig SIGPOLL 29 0 0 0 0 -syscon sig SIGPWR 30 0 0 0 0 -syscon sig SIGSTKFLT 0x10 0 0 0 0 -syscon sig SIGUNUSED 31 0 0 0 0 +syscon sig SIGBUS 7 10 10 10 7 # bsd consensus +syscon sig SIGUSR1 10 30 30 30 10 # bsd consensus +syscon sig SIGCHLD 17 20 20 20 17 # bsd consensus +syscon sig SIGCONT 18 19 19 19 18 # bsd consensus +syscon sig SIGIO 29 23 23 23 29 # bsd consensus +syscon sig SIGSTOP 19 17 17 17 19 # bsd consensus +syscon sig SIGSYS 31 12 12 12 31 # bsd consensus +syscon sig SIGTSTP 20 18 18 18 20 # bsd consensus +syscon sig SIGURG 23 0x10 0x10 0x10 23 # bsd consensus +syscon sig SIGUSR2 12 31 31 31 12 # bsd consensus +syscon sig SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x2000 +syscon sig SIGPOLL 29 0 0 0 29 +syscon sig SIGPWR 30 0 0 0 30 +syscon sig SIGSTKFLT 0x10 0 0 0 0x10 +syscon sig SIGUNUSED 31 0 0 0 31 syscon sig SIGRTMAX 0 0 126 0 0 syscon sig SIGRTMIN 0 0 65 0 0 diff --git a/libc/sysv/consts/SIGBUS.s b/libc/sysv/consts/SIGBUS.s index b34442fcd..b0331dfab 100644 --- a/libc/sysv/consts/SIGBUS.s +++ b/libc/sysv/consts/SIGBUS.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGBUS 7 10 10 10 0 +.syscon sig SIGBUS 7 10 10 10 7 diff --git a/libc/sysv/consts/SIGCHLD.s b/libc/sysv/consts/SIGCHLD.s index 3a25f5ccf..4fd02e67d 100644 --- a/libc/sysv/consts/SIGCHLD.s +++ b/libc/sysv/consts/SIGCHLD.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGCHLD 17 20 20 20 0 +.syscon sig SIGCHLD 17 20 20 20 17 diff --git a/libc/sysv/consts/SIGCONT.s b/libc/sysv/consts/SIGCONT.s index 004525779..4cc74b898 100644 --- a/libc/sysv/consts/SIGCONT.s +++ b/libc/sysv/consts/SIGCONT.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGCONT 18 19 19 19 0 +.syscon sig SIGCONT 18 19 19 19 18 diff --git a/libc/sysv/consts/SIGIO.s b/libc/sysv/consts/SIGIO.s index 8a64d2bc4..ded429b3c 100644 --- a/libc/sysv/consts/SIGIO.s +++ b/libc/sysv/consts/SIGIO.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGIO 29 23 23 23 0 +.syscon sig SIGIO 29 23 23 23 29 diff --git a/libc/sysv/consts/SIGPOLL.s b/libc/sysv/consts/SIGPOLL.s index 7f88e1a27..36c6e42c3 100644 --- a/libc/sysv/consts/SIGPOLL.s +++ b/libc/sysv/consts/SIGPOLL.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGPOLL 29 0 0 0 0 +.syscon sig SIGPOLL 29 0 0 0 29 diff --git a/libc/sysv/consts/SIGPWR.s b/libc/sysv/consts/SIGPWR.s index 9fcfab49d..eb7f8ed98 100644 --- a/libc/sysv/consts/SIGPWR.s +++ b/libc/sysv/consts/SIGPWR.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGPWR 30 0 0 0 0 +.syscon sig SIGPWR 30 0 0 0 30 diff --git a/libc/sysv/consts/SIGSTKFLT.s b/libc/sysv/consts/SIGSTKFLT.s index fbc256189..e986d404a 100644 --- a/libc/sysv/consts/SIGSTKFLT.s +++ b/libc/sysv/consts/SIGSTKFLT.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGSTKFLT 0x10 0 0 0 0 +.syscon sig SIGSTKFLT 0x10 0 0 0 0x10 diff --git a/libc/sysv/consts/SIGSTKSZ.s b/libc/sysv/consts/SIGSTKSZ.s index c0410eae5..e02067c62 100644 --- a/libc/sysv/consts/SIGSTKSZ.s +++ b/libc/sysv/consts/SIGSTKSZ.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0 +.syscon sig SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x2000 diff --git a/libc/sysv/consts/SIGSTOP.s b/libc/sysv/consts/SIGSTOP.s index 239996633..1438f22c2 100644 --- a/libc/sysv/consts/SIGSTOP.s +++ b/libc/sysv/consts/SIGSTOP.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGSTOP 19 17 17 17 0 +.syscon sig SIGSTOP 19 17 17 17 19 diff --git a/libc/sysv/consts/SIGSYS.s b/libc/sysv/consts/SIGSYS.s index 67768e78a..d13c13909 100644 --- a/libc/sysv/consts/SIGSYS.s +++ b/libc/sysv/consts/SIGSYS.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGSYS 31 12 12 12 0 +.syscon sig SIGSYS 31 12 12 12 31 diff --git a/libc/sysv/consts/SIGTSTP.s b/libc/sysv/consts/SIGTSTP.s index c70d3b33a..cfa45fbd2 100644 --- a/libc/sysv/consts/SIGTSTP.s +++ b/libc/sysv/consts/SIGTSTP.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGTSTP 20 18 18 18 0 +.syscon sig SIGTSTP 20 18 18 18 20 diff --git a/libc/sysv/consts/SIGUNUSED.s b/libc/sysv/consts/SIGUNUSED.s index 2a5c092c5..ba71f6857 100644 --- a/libc/sysv/consts/SIGUNUSED.s +++ b/libc/sysv/consts/SIGUNUSED.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGUNUSED 31 0 0 0 0 +.syscon sig SIGUNUSED 31 0 0 0 31 diff --git a/libc/sysv/consts/SIGURG.s b/libc/sysv/consts/SIGURG.s index f07d8610e..d57f6f772 100644 --- a/libc/sysv/consts/SIGURG.s +++ b/libc/sysv/consts/SIGURG.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGURG 23 0x10 0x10 0x10 0 +.syscon sig SIGURG 23 0x10 0x10 0x10 23 diff --git a/libc/sysv/consts/SIGUSR1.s b/libc/sysv/consts/SIGUSR1.s index bf64e7336..07faf27a0 100644 --- a/libc/sysv/consts/SIGUSR1.s +++ b/libc/sysv/consts/SIGUSR1.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGUSR1 10 30 30 30 0 +.syscon sig SIGUSR1 10 30 30 30 10 diff --git a/libc/sysv/consts/SIGUSR2.s b/libc/sysv/consts/SIGUSR2.s index 16792d049..e4bacc8c8 100644 --- a/libc/sysv/consts/SIGUSR2.s +++ b/libc/sysv/consts/SIGUSR2.s @@ -1,2 +1,2 @@ .include "libc/sysv/consts/syscon.inc" -.syscon sig SIGUSR2 12 31 31 31 0 +.syscon sig SIGUSR2 12 31 31 31 12 diff --git a/libc/testlib/showerror_.c b/libc/testlib/showerror_.c index f0d61c09a..3fce21950 100644 --- a/libc/testlib/showerror_.c +++ b/libc/testlib/showerror_.c @@ -30,8 +30,6 @@ #include "libc/str/str.h" #include "libc/testlib/testlib.h" -STATIC_YOINK("__isfdkind"); - const char *testlib_showerror_errno; const char *testlib_showerror_file; const char *testlib_showerror_func; @@ -85,9 +83,10 @@ testonly void testlib_showerror_(int line, const char *wantcode, strcpy(hostname, "unknown"); gethostname(hostname, sizeof(hostname)); fprintf(stderr, - "\t%s%s\n" - "\t%s @ %s%s\n", - SUBTLE, strerror(err), program_invocation_name, hostname, RESET); + "\t%s%s%s\n" + "\t%s%s @ %s%s\n", + SUBTLE, strerror(err), RESET, SUBTLE, program_invocation_name, + hostname, RESET); free_s(&FREED_want); free_s(&FREED_got); diff --git a/libc/time/asctime.c b/libc/time/asctime.c index 0e8ebb9eb..b17b44e6f 100644 --- a/libc/time/asctime.c +++ b/libc/time/asctime.c @@ -20,4 +20,12 @@ static char g_asctime_buf[64]; -char *asctime(const struct tm *date) { return asctime_r(date, g_asctime_buf); } +/** + * Converts date time to string. + * + * @return date time string in statically allocated buffer + * @see asctime_r for reentrant version + */ +char *asctime(const struct tm *date) { + return asctime_r(date, g_asctime_buf); +} diff --git a/libc/time/asctime_r.c b/libc/time/asctime_r.c index 1dfe8cc70..e3e71d0cc 100644 --- a/libc/time/asctime_r.c +++ b/libc/time/asctime_r.c @@ -27,6 +27,13 @@ static unsigned clip(unsigned index, unsigned count) { return index < count ? index : 0; } +/** + * Converts date time to string. + * + * @param buf needs to have 64 bytes + * @return pointer to buf + * @see asctime_r for reentrant version + */ char *asctime_r(const struct tm *date, char buf[hasatleast 64]) { (snprintf)(buf, 64, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", kWeekdayNameShort[clip(date->tm_wday, 7)], diff --git a/test/libc/calls/hefty/vfork_test.c b/test/libc/calls/hefty/vfork_test.c index 1ce18ab5f..1c5bc6155 100644 --- a/test/libc/calls/hefty/vfork_test.c +++ b/test/libc/calls/hefty/vfork_test.c @@ -33,14 +33,18 @@ TEST(vfork, test) { ASSERT_NE(-1, lseek(fd, 0, SEEK_SET)); if (!vfork()) { EXPECT_EQ(5, pread(fd, buf, 5, 0)); + /* + * TODO(jart): DOES PREAD IN CHILD REALLY CHANGE PARENT HANDLE POSITION? + */ + ASSERT_NE(-1, lseek(fd, 0, SEEK_SET)); EXPECT_STREQ("hello", buf); EXPECT_NE(-1, close(fd)); _exit(0); } EXPECT_EQ(0, __vforked); + EXPECT_NE(-1, wait(0)); EXPECT_EQ(5, read(fd, buf, 5)); EXPECT_STREQ("hello", buf); EXPECT_NE(-1, close(fd)); - EXPECT_NE(-1, wait(0)); unlink(PATH); } diff --git a/test/libc/calls/sigaction_test.c b/test/libc/calls/sigaction_test.c new file mode 100644 index 000000000..44c58b051 --- /dev/null +++ b/test/libc/calls/sigaction_test.c @@ -0,0 +1,63 @@ +/*-*- 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 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/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigaction.h" +#include "libc/dce.h" +#include "libc/errno.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/sa.h" +#include "libc/sysv/consts/sig.h" +#include "libc/testlib/testlib.h" + +bool gotsigint; + +void OnSigInt(int sig) { + gotsigint = true; +} + +TEST(sigaction, test) { + /* TODO(jart): Why does RHEL5 behave differently? */ + /* TODO(jart): Windows needs huge signal overhaul */ + if (IsWindows()) return; + int pid, status; + sigset_t block, ignore, oldmask; + struct sigaction saint = {.sa_handler = OnSigInt}; + sigemptyset(&block); + sigaddset(&block, SIGINT); + EXPECT_NE(-1, sigprocmask(SIG_BLOCK, &block, &oldmask)); + sigfillset(&ignore); + sigdelset(&ignore, SIGINT); + EXPECT_NE(-1, sigaction(SIGINT, &saint, NULL)); + ASSERT_NE(-1, (pid = fork())); + if (!pid) { + EXPECT_NE(-1, kill(getppid(), SIGINT)); + EXPECT_EQ(-1, sigsuspend(&ignore)); + EXPECT_EQ(EINTR, errno); + EXPECT_TRUE(gotsigint); + _exit(0); + } + EXPECT_EQ(-1, sigsuspend(&ignore)); + EXPECT_NE(-1, kill(pid, SIGINT)); + EXPECT_NE(-1, waitpid(pid, &status, 0)); + EXPECT_EQ(1, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); + EXPECT_EQ(0, WTERMSIG(status)); + EXPECT_NE(-1, sigprocmask(SIG_BLOCK, &oldmask, NULL)); +} diff --git a/test/libc/stdio/popen_test.c b/test/libc/stdio/popen_test.c new file mode 100644 index 000000000..c7d37b8ea --- /dev/null +++ b/test/libc/stdio/popen_test.c @@ -0,0 +1,34 @@ +/*-*- 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 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/log/check.h" +#include "libc/stdio/stdio.h" +#include "libc/testlib/testlib.h" + +TEST(popen, test) { + int ws; + FILE *f; + f = popen("echo hi", "r"); + ASSERT_NE(NULL, f); + EXPECT_EQ('h', fgetc(f)); + EXPECT_EQ('i', fgetc(f)); + ws = pclose(f); + EXPECT_NE(-1, ws); + EXPECT_TRUE(WIFEXITED(ws)); + EXPECT_EQ(0, WEXITSTATUS(ws)); +} diff --git a/third_party/chibicc/chibicc.c b/third_party/chibicc/chibicc.c index d430b091a..cf4d69f10 100644 --- a/third_party/chibicc/chibicc.c +++ b/third_party/chibicc/chibicc.c @@ -1,5 +1,6 @@ #include "libc/calls/struct/siginfo.h" #include "libc/calls/ucontext.h" +#include "libc/x/x.h" #include "third_party/chibicc/chibicc.h" asm(".ident\t\"\\n\\n\ @@ -606,7 +607,7 @@ static void run_linker(StringArray *inputs, char *output) { strarray_push(&arr, "--gc-sections"); strarray_push(&arr, "--build-id=none"); strarray_push(&arr, "--no-dynamic-linker"); - strarray_push(&arr, "-Ttext-segment=0x400000"); + strarray_push(&arr, xasprintf("-Ttext-segment=%#x", IMAGE_BASE_VIRTUAL)); strarray_push(&arr, "-T"); strarray_push(&arr, LDS); strarray_push(&arr, APE); diff --git a/third_party/chibicc/chibicc.mk b/third_party/chibicc/chibicc.mk index c7cb18fee..2dad14334 100644 --- a/third_party/chibicc/chibicc.mk +++ b/third_party/chibicc/chibicc.mk @@ -14,7 +14,8 @@ CHIBICC = o/$(MODE)/third_party/chibicc/chibicc.com.dbg CHIBICC2 = o/$(MODE)/third_party/chibicc/chibicc2.com.dbg CHIBICC_FLAGS = \ -fno-common \ - -include libc/integral/normalize.inc + -include libc/integral/normalize.inc \ + -DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) PKGS += THIRD_PARTY_CHIBICC THIRD_PARTY_CHIBICC_ARTIFACTS += THIRD_PARTY_CHIBICC_A diff --git a/tool/build/runit.c b/tool/build/runit.c index 3650a1ce9..6cd5fcffc 100644 --- a/tool/build/runit.c +++ b/tool/build/runit.c @@ -20,6 +20,7 @@ #include "libc/bits/bits.h" #include "libc/bits/safemacros.h" #include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" #include "libc/calls/struct/flock.h" #include "libc/calls/struct/itimerval.h" #include "libc/calls/struct/sigaction.h" @@ -119,7 +120,7 @@ char g_hostname[128]; uint16_t g_runitdport; volatile bool alarmed; -static void OnAlarm(void) { +static void OnAlarm(int sig) { alarmed = true; } @@ -170,7 +171,9 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { struct stat st; char linebuf[32]; struct timeval now, then; + sigset_t chldmask, savemask; int sshpid, wstatus, binfd, pipefds[2][2]; + struct sigaction ignore, saveint, savequit; mkdir("o", 0755); CHECK_NE(-1, (lock = open(gc(xasprintf("o/lock.%s", g_hostname)), O_RDWR | O_CREAT, 0644))); @@ -179,7 +182,7 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { if (!read(lock, &then, 16) || ((now.tv_sec * 1000 + now.tv_usec / 1000) - (then.tv_sec * 1000 + then.tv_usec / 1000)) >= (RUNITD_TIMEOUT_MS >> 1)) { - DEBUGF("spawning %s on %s:%hu", g_runitd, g_hostname, g_runitdport); + DEBUGF("ssh %s:%hu to spawn %s", g_hostname, g_runitdport, g_runitd); CHECK_NE(-1, (binfd = open(g_runitd, O_RDONLY | O_CLOEXEC))); CHECK_NE(-1, fstat(binfd, &st)); args[0] = "ssh"; @@ -189,16 +192,28 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { args[4] = g_hostname; args[5] = gc(MakeDeployScript(ai, st.st_size)); args[6] = NULL; + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + LOGIFNEG1(sigemptyset(&ignore.sa_mask)); + LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint)); + LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit)); + LOGIFNEG1(sigemptyset(&chldmask)); + LOGIFNEG1(sigaddset(&chldmask, SIGCHLD)); + LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask)); CHECK_NE(-1, pipe2(pipefds[0], O_CLOEXEC)); CHECK_NE(-1, pipe2(pipefds[1], O_CLOEXEC)); - if (!(sshpid = vfork())) { + CHECK_NE(-1, (sshpid = fork())); + if (!sshpid) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); dup2(pipefds[0][0], 0); dup2(pipefds[1][1], 1); execv(g_ssh, args); - abort(); + _exit(127); } - close(pipefds[0][0]); - close(pipefds[1][1]); + LOGIFNEG1(close(pipefds[0][0])); + LOGIFNEG1(close(pipefds[1][1])); Upload(pipefds[0][1], binfd, &st); LOGIFNEG1(close(pipefds[0][1])); CHECK_NE(-1, (got = read(pipefds[1][0], linebuf, sizeof(linebuf)))); @@ -212,7 +227,16 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { g_runitdport = (uint16_t)atoi(&linebuf[6]); LOGIFNEG1(close(pipefds[1][0])); CHECK_NE(-1, waitpid(sshpid, &wstatus, 0)); - CHECK_EQ(0, WEXITSTATUS(wstatus)); + LOGIFNEG1(sigaction(SIGINT, &saveint, NULL)); + LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL)); + LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL)); + if (WIFEXITED(wstatus)) { + DEBUGF("ssh %s exited with %d", g_hostname, WEXITSTATUS(wstatus)); + } else { + DEBUGF("ssh %s terminated with %s", g_hostname, + strsignal(WTERMSIG(wstatus))); + } + CHECK(WIFEXITED(wstatus) && !WEXITSTATUS(wstatus), "wstatus=%#x", wstatus); CHECK_NE(-1, gettimeofday(&now, 0)); CHECK_NE(-1, lseek(lock, 0, SEEK_SET)); CHECK_NE(-1, write(lock, &now, 16)); @@ -223,7 +247,11 @@ void DeployEphemeralRunItDaemonRemotelyViaSsh(struct addrinfo *ai) { } void SetDeadline(int micros) { - setitimer(ITIMER_REAL, &(const struct itimerval){{0, 0}, {0, micros}}, NULL); + alarmed = false; + LOGIFNEG1( + sigaction(SIGALRM, &(struct sigaction){.sa_handler = OnAlarm}, NULL)); + LOGIFNEG1(setitimer(ITIMER_REAL, + &(const struct itimerval){{0, 0}, {0, micros}}, NULL)); } void Connect(void) { @@ -242,28 +270,32 @@ void Connect(void) { g_hostname, ip4[0], ip4[1], ip4[2], ip4[3]); unreachable; } - DEBUGF("connecting to %s (%hhu.%hhu.%hhu.%hhu) to run %s", g_hostname, ip4[0], - ip4[1], ip4[2], ip4[3], g_prog); CHECK_NE(-1, (g_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol))); expo = 1; -TryAgain: - alarmed = false; +Reconnect: + DEBUGF("connecting to %s (%hhu.%hhu.%hhu.%hhu) to run %s", g_hostname, ip4[0], + ip4[1], ip4[2], ip4[3], g_prog); SetDeadline(100000); +TryAgain: rc = connect(g_sock, ai->ai_addr, ai->ai_addrlen); err = errno; SetDeadline(0); if (rc == -1) { - if ((err == ECONNREFUSED || err == EHOSTUNREACH || err == ECONNRESET || - err == EINTR)) { + if (err == EINTR) goto TryAgain; + if (err == ECONNREFUSED || err == EHOSTUNREACH || err == ECONNRESET) { + DEBUGF("got %s from %s (%hhu.%hhu.%hhu.%hhu)", strerror(err), g_hostname, + ip4[0], ip4[1], ip4[2], ip4[3]); usleep((expo *= 2)); DeployEphemeralRunItDaemonRemotelyViaSsh(ai); - goto TryAgain; + goto Reconnect; } else { FATALF("%s(%s:%hu): %s", "connect", g_hostname, g_runitdport, strerror(err)); unreachable; } + } else { + DEBUGF("connected to %s", g_hostname); } freeaddrinfo(ai); } @@ -275,6 +307,7 @@ void SendRequest(void) { const char *name; unsigned char *hdr; size_t progsize, namesize, hdrsize; + DEBUGF("running %s on %s", g_prog, g_hostname); CHECK_NE(-1, (fd = open(g_prog, O_RDONLY))); CHECK_NE(-1, fstat(fd, &st)); CHECK_LE((namesize = strlen((name = basename(g_prog)))), PATH_MAX); @@ -370,8 +403,7 @@ int RunOnHost(char *spec) { do { Connect(); SendRequest(); - rc = ReadResponse(); - } while (rc == -1); + } while ((rc = ReadResponse()) == -1); return rc; } @@ -384,59 +416,56 @@ bool ShouldRunInParralel(void) { return !IsWindows() && IsParallelBuild(); } -int RunRemoteTestsInSerial(char *hosts[], int count) { - int i, exitcode; - for (i = 0; i < count; ++i) { - if ((exitcode = RunOnHost(hosts[i]))) { - return exitcode; - } - } - return 0; -} - -void OnInterrupt(int sig) { - static bool once; - if (!once) { - once = true; - gclongjmp(g_jmpbuf, 128 + sig); - } else { - abort(); - } -} - int RunRemoteTestsInParallel(char *hosts[], int count) { - const struct sigaction onsigterm = {.sa_handler = (void *)OnInterrupt}; - struct sigaction onsigint = {.sa_handler = (void *)OnInterrupt}; - int i, rc, exitcode; - int64_t leader, *pids; - leader = getpid(); - pids = gc(xcalloc(count, sizeof(char *))); - if (!(exitcode = setjmp(g_jmpbuf))) { - sigaction(SIGINT, &onsigint, NULL); - sigaction(SIGTERM, &onsigterm, NULL); - for (i = 0; i < count; ++i) { - CHECK_NE(-1, (pids[i] = fork())); - if (!pids[i]) { - return RunOnHost(hosts[i]); - } + sigset_t chldmask, savemask; + int i, rc, ws, pid, *pids, exitcode; + struct sigaction ignore, saveint, savequit; + pids = calloc(count, sizeof(char *)); + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + LOGIFNEG1(sigemptyset(&ignore.sa_mask)); + LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint)); + LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit)); + LOGIFNEG1(sigemptyset(&chldmask)); + LOGIFNEG1(sigaddset(&chldmask, SIGCHLD)); + LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask)); + for (i = 0; i < count; ++i) { + CHECK_NE(-1, (pids[i] = fork())); + if (!pids[i]) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); + _exit(RunOnHost(hosts[i])); } - for (i = 0; i < count; ++i) { - CHECK_NE(-1, waitpid(pids[i], &rc, 0)); - exitcode |= WEXITSTATUS(rc); - } - } else if (getpid() == leader) { - onsigint.sa_handler = SIG_IGN; - sigaction(SIGINT, &onsigint, NULL); - kill(0, SIGINT); - while (waitpid(-1, NULL, 0) > 0) donothing; } + for (exitcode = 0;;) { + if ((pid = wait(&ws)) == -1) { + if (errno == EINTR) continue; + if (errno == ECHILD) break; + FATALF("wait failed"); + } + for (i = 0; i < count; ++i) { + if (pids[i] != pid) continue; + if (WIFEXITED(ws)) { + DEBUGF("%s exited with %d", hosts[i], WEXITSTATUS(ws)); + if (!exitcode) exitcode = WEXITSTATUS(ws); + } else { + DEBUGF("%s terminated with %s", hosts[i], strsignal(WTERMSIG(ws))); + if (!exitcode) exitcode = 128 + WTERMSIG(ws); + } + break; + } + } + LOGIFNEG1(sigaction(SIGINT, &saveint, NULL)); + LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL)); + LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL)); + free(pids); return exitcode; } int main(int argc, char *argv[]) { showcrashreports(); /* g_loglevel = kLogDebug; */ - const struct sigaction onsigalrm = {.sa_handler = (void *)OnAlarm}; if (argc > 1 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) { ShowUsage(stdout, 0); @@ -447,9 +476,7 @@ int main(int argc, char *argv[]) { CheckExists((g_runitd = argv[1])); CheckExists((g_prog = argv[2])); if (argc == 1 + 2) return 0; /* hosts list empty */ - sigaction(SIGALRM, &onsigalrm, NULL); g_sshport = 22; g_runitdport = RUNITD_PORT; - return (ShouldRunInParralel() ? RunRemoteTestsInParallel - : RunRemoteTestsInSerial)(&argv[3], argc - 3); + return RunRemoteTestsInParallel(&argv[3], argc - 3); } diff --git a/tool/build/runitd.c b/tool/build/runitd.c index 949ae13b7..b5dca0fc2 100644 --- a/tool/build/runitd.c +++ b/tool/build/runitd.c @@ -19,6 +19,7 @@ #include "libc/bits/bits.h" #include "libc/bits/safemacros.h" #include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" #include "libc/dce.h" @@ -96,32 +97,30 @@ #define kLogFile "o/runitd.log" #define kLogMaxBytes (2 * 1000 * 1000) -jmp_buf g_jb; char *g_exepath; -volatile bool g_childterm; -volatile int g_childstatus; struct sockaddr_in g_servaddr; unsigned char g_buf[PAGESIZE]; bool g_daemonize, g_sendready; int g_timeout, g_devnullfd, g_servfd, g_clifd, g_exefd; -void OnInterrupt(int sig) { - static bool once; - if (once) abort(); - once = true; - kill(0, sig); - for (;;) { - if (waitpid(-1, NULL, 0) == -1) { - break; - } - } - gclongjmp(g_jb, sig); - unreachable; -} - void OnChildTerminated(int sig) { - while (waitpid(-1, &g_childstatus, WNOHANG) > 0) { - g_childterm = true; + int ws, pid; + for (;;) { + if ((pid = waitpid(-1, &ws, WNOHANG)) != -1) { + if (pid) { + if (WIFEXITED(ws)) { + DEBUGF("worker %d exited with %d", pid, WEXITSTATUS(ws)); + } else { + DEBUGF("worker %d terminated with %s", pid, strsignal(WTERMSIG(ws))); + } + } else { + break; + } + } else { + if (errno == EINTR) continue; + if (errno == ECHILD) break; + FATALF("waitpid failed in sigchld"); + } } } @@ -190,14 +189,14 @@ void StartTcpServer(void) { CHECK_NE(-1, listen(g_servfd, 10)); asize = sizeof(g_servaddr); CHECK_NE(-1, getsockname(g_servfd, &g_servaddr, &asize)); + CHECK_NE(-1, fcntl(g_servfd, F_SETFD, FD_CLOEXEC)); + LOGF("%s:%s", "listening on tcp", gc(DescribeAddress(&g_servaddr))); if (g_sendready) { printf("ready %hu\n", ntohs(g_servaddr.sin_port)); fflush(stdout); fclose(stdout); - stdout->fd = g_devnullfd; + dup2(g_devnullfd, stdout->fd); } - CHECK_NE(-1, fcntl(g_servfd, F_SETFD, FD_CLOEXEC)); - LOGF("%s:%s", "listening on tcp", gc(DescribeAddress(&g_servaddr))); } void SendExitMessage(int sock, int rc) { @@ -242,7 +241,9 @@ void HandleClient(void) { ssize_t got, wrote; struct sockaddr_in addr; char *addrstr, *exename; - int rc, wstatus, child, pipefds[2]; + sigset_t chldmask, savemask; + int exitcode, wstatus, child, pipefds[2]; + struct sigaction ignore, saveint, savequit; uint32_t addrsize, namesize, filesize, remaining; /* read request to run program */ @@ -252,7 +253,6 @@ void HandleClient(void) { close(g_clifd); return; } - g_childterm = false; addrstr = gc(DescribeAddress(&addr)); DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr); got = recv(g_clifd, (p = &g_buf[0]), sizeof(g_buf), 0); @@ -303,13 +303,25 @@ void HandleClient(void) { /* run program, tee'ing stderr to both log and client */ DEBUGF("spawning %s", exename); + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + LOGIFNEG1(sigemptyset(&ignore.sa_mask)); + LOGIFNEG1(sigaction(SIGINT, &ignore, &saveint)); + LOGIFNEG1(sigaction(SIGQUIT, &ignore, &savequit)); + LOGIFNEG1(sigemptyset(&chldmask)); + LOGIFNEG1(sigaddset(&chldmask, SIGCHLD)); + LOGIFNEG1(sigprocmask(SIG_BLOCK, &chldmask, &savemask)); CHECK_NE(-1, pipe2(pipefds, O_CLOEXEC)); - if (!(child = vfork())) { + CHECK_NE(-1, (child = fork())); + if (!child) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); dup2(pipefds[1], 2); execv(g_exepath, (char *const[]){g_exepath, NULL}); - abort(); + _exit(127); } - close(pipefds[1]); + LOGIFNEG1(close(pipefds[1])); DEBUGF("communicating %s[%d]", exename, child); for (;;) { CHECK_NE(-1, (got = read(pipefds[0], g_buf, sizeof(g_buf)))); @@ -320,23 +332,24 @@ void HandleClient(void) { fwrite(g_buf, got, 1, stderr); SendOutputFragmentMessage(g_clifd, kRunitStderr, g_buf, got); } - - if ((rc = waitpid(child, &wstatus, 0)) != -1) { - g_childstatus = wstatus; - } else { - CHECK_EQ(ECHILD, errno); - CHECK(g_childterm); + while (waitpid(child, &wstatus, 0) == -1) { + if (errno == EINTR) continue; + FATALF("waitpid failed"); } - if (WIFSIGNALED(g_childstatus)) { - rc = 128 + WTERMSIG(g_childstatus); + if (WIFEXITED(wstatus)) { + DEBUGF("%s exited with %d", exename, WEXITSTATUS(wstatus)); + exitcode = WEXITSTATUS(wstatus); } else { - rc = WEXITSTATUS(g_childstatus); + DEBUGF("%s terminated with %s", exename, strsignal(WTERMSIG(wstatus))); + exitcode = 128 + WTERMSIG(wstatus); } - DEBUGF("exited %s[%d] -> %d", exename, child, rc); + LOGIFNEG1(sigaction(SIGINT, &saveint, NULL)); + LOGIFNEG1(sigaction(SIGQUIT, &savequit, NULL)); + LOGIFNEG1(sigprocmask(SIG_SETMASK, &savemask, NULL)); /* let client know how it went */ LOGIFNEG1(unlink(g_exepath)); - SendExitMessage(g_clifd, rc); + SendExitMessage(g_clifd, exitcode); LOGIFNEG1(shutdown(g_clifd, SHUT_RDWR)); LOGIFNEG1(close(g_clifd)); _exit(0); @@ -363,29 +376,17 @@ TryAgain: } int Serve(void) { - int rc; - const struct sigaction onsigint = {.sa_handler = (void *)OnInterrupt, - .sa_flags = SA_NODEFER}; - const struct sigaction onsigterm = {.sa_handler = (void *)OnInterrupt, - .sa_flags = SA_NODEFER}; - const struct sigaction onsigchld = {.sa_handler = (void *)OnChildTerminated, - .sa_flags = SA_RESTART}; StartTcpServer(); - defer(close_s, &g_servfd); - if (!(rc = setjmp(g_jb))) { - sigaction(SIGINT, &onsigint, NULL); - sigaction(SIGTERM, &onsigterm, NULL); - sigaction(SIGCHLD, &onsigchld, NULL); - for (;;) { - if (!Poll() && !g_timeout) break; - } - LOGF("timeout expired, shutting down"); - } else { - if (isatty(fileno(stderr))) fputc('\r', stderr); - LOGF("got %s, shutting down", strsignal(rc)); - rc += 128; + sigaction(SIGCHLD, + (&(struct sigaction){.sa_handler = (void *)OnChildTerminated, + .sa_flags = SA_RESTART}), + NULL); + for (;;) { + if (!Poll() && !g_timeout) break; } - return rc; + close(g_servfd); + LOGF("timeout expired, shutting down"); + return 0; } void Daemonize(void) { @@ -393,15 +394,17 @@ void Daemonize(void) { if (fork() > 0) _exit(0); setsid(); if (fork() > 0) _exit(0); - stdin->fd = g_devnullfd; - if (!g_sendready) stdout->fd = g_devnullfd; - if (stat(kLogFile, &st) != -1 && st.st_size > kLogMaxBytes) unlink(kLogFile); - freopen(kLogFile, "a", stderr); + dup2(g_devnullfd, stdin->fd); + if (!g_sendready) dup2(g_devnullfd, stdout->fd); + freopen(kLogFile, "ae", stderr); + if (fstat(fileno(stderr), &st) != -1 && st.st_size > kLogMaxBytes) { + ftruncate(fileno(stderr), 0); + } } int main(int argc, char *argv[]) { showcrashreports(); - g_loglevel = kLogDebug; + /* g_loglevel = kLogDebug; */ GetOpts(argc, argv); CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR))); defer(close_s, &g_devnullfd); diff --git a/tool/build/zipobj.c b/tool/build/zipobj.c index df28b9a88..30584bc1d 100644 --- a/tool/build/zipobj.c +++ b/tool/build/zipobj.c @@ -23,6 +23,7 @@ #include "libc/calls/struct/stat.h" #include "libc/calls/struct/timespec.h" #include "libc/elf/def.h" +#include "libc/fmt/conv.h" #include "libc/limits.h" #include "libc/log/check.h" #include "libc/log/log.h" @@ -68,6 +69,7 @@ char *symbol_; char *outpath_; char *yoink_; +int64_t image_base_; const size_t kMinCompressSize = 32; const char kNoCompressExts[][8] = {".gz", ".xz", ".jpg", ".png", @@ -83,7 +85,8 @@ wontreturn void PrintUsage(int rc, FILE *f) { void GetOpts(int *argc, char ***argv) { int opt; yoink_ = "__zip_start"; - while ((opt = getopt(*argc, *argv, "?ho:s:y:")) != -1) { + image_base_ = IMAGE_BASE_VIRTUAL; + while ((opt = getopt(*argc, *argv, "?ho:s:y:b:")) != -1) { switch (opt) { case 'o': outpath_ = optarg; @@ -94,6 +97,9 @@ void GetOpts(int *argc, char ***argv) { case 'y': yoink_ = optarg; break; + case 'b': + image_base_ = strtol(optarg, NULL, 0); + break; case '?': case 'h': PrintUsage(EXIT_SUCCESS, stdout); @@ -261,7 +267,7 @@ void EmitZip(struct ElfWriter *elf, const char *name, size_t namesize, ELF64_ST_INFO(STB_LOCAL, STT_OBJECT), STV_DEFAULT, 0, kZipCdirHdrLinkableSize); elfwriter_appendrela(elf, kZipCfileOffsetOffset, lfilesym, R_X86_64_32, - -IMAGE_BASE_VIRTUAL); + -image_base_); elfwriter_commit(elf, kZipCdirHdrLinkableSize); elfwriter_finishsection(elf); }