diff --git a/.gitignore b/.gitignore index 3412f6af2..4c767cd51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # -*- conf -*- /o -/.prompt.jtlp +/cosmocc +/.cosmocc # TODO: Find some way to have Python write to o/ __pycache__ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eaca3537c..1db711677 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,23 +2,41 @@ We'd love to accept your patches! Please read this guide first. +## Identity Disclosure + +This project does not accept anonymous contributions. Justine Tunney +won't merge pull requests from strangers. In order to change the Cosmo +codebase, and have your changes be upstreamed, she has to know who you +are. You're encouraged to disclose your full name and email address to +the public too, by including them in your git commit messages; however +that's not a requirement; as we're happy to respect the wishes of +contributors who prefer to remain anonymous to the public. + ## Copyright Assignment -Please send an email to Justine Tunney stating that -you intend to assign her the copyright to the changes you contribute to -Cosmopolitan. Please use the same email address you use for git commits -which should only contain original source code from you or other people -who are also assigning copyright. Please note that, if you're employed, -you may need to get your employer's approval beforehand. If you can not -assign copyright due to local laws, then you may alternatively consider -disclaiming it using the language in [Unlicense](https://unlicense.org) -or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0) +The first time you send a pull request, you need to send an email to +Justine Tunney stating that you intend to assign her +the copyright to the changes you contribute to Cosmopolitan. This only +applies to the code you *choose* to contribute. It only has to happen +once. The email should be sent from an email address associated with +your identity. Your email should link to your pull request. -This is important because we can't produce 12kb single-file executables -that comply with license requirements if we have to embed lots of them. -Although that's less of an issue depending on the purpose of the files. -For example, ownership is much less of a concern in the unit test files -so you're encouraged to put your copyright on those, provided it's ISC. +Please note that in order to give Justine the copyright, it has to be +yours to give in the first place. If you're employed, then you should +get your employer's approval to do this beforehand. Even with big +companies like Google, this process is quick and painless. Usually we +see employers granting authorization in less than one day. + +If you live in a country that doesn't recognize one's ability to assign +copyright, then you may alternatively consider disclaiming it using the +language in [Unlicense](https://unlicense.org) or +[CC-0](http://creativecommons.org/share-your-work/public-domain/cc0). + +If you're checking-in third party code, then you need to have headers at +the top of each source file (but never header files) documenting its +owners and the code should go in the `third_party/` folder. Every third +party project should have a `README.cosmo` file that documents its +provenance as well as any local changes you've made. ## Style Guide diff --git a/Makefile b/Makefile index 498227f4d..46e0b69d9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # # SYNOPSIS # @@ -73,10 +73,13 @@ MODE := $(m) endif endif +COMMA := , +PWD := $(shell pwd) + # detect wsl2 running cosmopolitan binaries on the host by checking whether: # - user ran build/bootstrap/make.com, in which case make's working directory is in wsl # - user ran make, in which case cocmd.com's working directory is in wsl -ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(shell pwd)),) +ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(PWD)),) $(warning wsl2 interop is enabled) $(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop') endif @@ -89,14 +92,33 @@ ifeq ($(MAKE_VERSION), 3.81) $(error please use build/bootstrap/make.com) endif -# provide instructions to non-linux users on unbundling gcc -ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined -ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled -ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux -$(error please run tool/cosmocc/fetch.sh) -endif -endif -endif +LC_ALL = C +SOURCE_DATE_EPOCH = 0 + +ARFLAGS = rcsD +ZFLAGS ?= +XARGS ?= xargs -P4 -rs8000 +DOT ?= dot +CLANG = clang +TMPDIR = o/tmp + +AR = build/bootstrap/ar.com +CP = build/bootstrap/cp.com +RM = build/bootstrap/rm.com -f +GZIP = build/bootstrap/gzip.com +ECHO = build/bootstrap/echo.com +CHMOD = build/bootstrap/chmod.com +TOUCH = build/bootstrap/touch.com +PKG = build/bootstrap/package.com +MKDEPS = build/bootstrap/mkdeps.com +ZIPOBJ = build/bootstrap/zipobj.com +ZIPCOPY = build/bootstrap/zipcopy.com +PECHECK = build/bootstrap/pecheck.com +FIXUPOBJ = build/bootstrap/fixupobj.com +MKDIR = build/bootstrap/mkdir.com -p +COMPILE = build/bootstrap/compile.com -V9 -M2048m -P8192 $(QUOTA) + +IGNORE := $(shell $(MKDIR) $(TMPDIR)) # the default build modes is empty string # on x86_64 hosts, MODE= is the same as MODE=x86_64 @@ -110,6 +132,44 @@ MODE := aarch64 endif endif +ifneq ($(findstring aarch64,$(MODE)),) +ARCH = aarch64 +HOSTS ?= pi studio freebsdarm +else +ARCH = x86_64 +HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd +endif + +ZIPOBJ_FLAGS += -a$(ARCH) +IGNORE := $(shell $(MKDIR) $(TMPDIR)) + +export ADDR2LINE +export LC_ALL +export MKDIR +export MODE +export SOURCE_DATE_EPOCH +export TMPDIR + +COSMOCC = .cosmocc/3.2 +TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo- +DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.2 28b48682595f0f46b45ab381118cdffdabc8fcfa29aa54e301fe6ffe35269f5e) + +AS = $(TOOLCHAIN)as +CC = $(TOOLCHAIN)gcc +CXX = $(TOOLCHAIN)g++ +CXXFILT = $(TOOLCHAIN)c++filt +LD = $(TOOLCHAIN)ld.bfd +NM = $(TOOLCHAIN)nm +GCC = $(TOOLCHAIN)gcc +STRIP = $(TOOLCHAIN)strip +OBJCOPY = $(TOOLCHAIN)objcopy +OBJDUMP = $(TOOLCHAIN)objdump +ifneq ($(wildcard $(PWD)/$(TOOLCHAIN)addr2line),) +ADDR2LINE = $(PWD)/$(TOOLCHAIN)addr2line +else +ADDR2LINE = $(TOOLCHAIN)addr2line +endif + # primary build rules all: o o: o/$(MODE) @@ -138,7 +198,7 @@ $(warning please run ape/apeinstall.sh if you intend to use landlock make) $(shell sleep .5) endif endif -ifeq ($(USE_SYSTEM_TOOLCHAIN),) +ifneq ($(TOOLCHAIN),) .STRICT = 1 endif endif @@ -149,8 +209,8 @@ endif libc/stdbool.h \ libc/disclaimer.inc \ rwc:/dev/shm \ + rx:cosmocc \ rx:build/bootstrap \ - rx:o/third_party/gcc \ r:build/portcosmo.h \ /proc/stat \ rw:/dev/null \ @@ -189,7 +249,6 @@ include libc/calls/BUILD.mk #─┐ include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME include third_party/nsync/BUILD.mk # │ You can issue system calls include libc/runtime/BUILD.mk # │ -include third_party/double-conversion/BUILD.mk # │ include libc/crt/BUILD.mk # │ include third_party/dlmalloc/BUILD.mk #─┘ include libc/mem/BUILD.mk #─┐ @@ -198,9 +257,9 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio include libc/proc/BUILD.mk # │ You can now use threads include libc/dlopen/BUILD.mk # │ You can now use processes include libc/thread/BUILD.mk # │ You can finally call malloc() -include tool/hello/BUILD.mk # │ include third_party/zlib/BUILD.mk # │ include libc/stdio/BUILD.mk # │ +include tool/hello/BUILD.mk # │ include libc/time/BUILD.mk # │ include net/BUILD.mk # │ include third_party/vqsort/BUILD.mk # │ @@ -213,9 +272,8 @@ include third_party/intel/BUILD.mk # │ include third_party/aarch64/BUILD.mk # │ include libc/BUILD.mk #─┘ include libc/sock/BUILD.mk #─┐ -include libc/dns/BUILD.mk # ├──ONLINE RUNTIME -include net/http/BUILD.mk # │ You can communicate with the network -include third_party/musl/BUILD.mk # │ +include net/http/BUILD.mk # ├──ONLINE RUNTIME +include third_party/musl/BUILD.mk # │ You can communicate with the network include libc/x/BUILD.mk # │ include dsp/scale/BUILD.mk # │ include dsp/mpeg/BUILD.mk # │ @@ -223,11 +281,18 @@ include dsp/tty/BUILD.mk # │ include dsp/BUILD.mk # │ include third_party/stb/BUILD.mk # │ include third_party/mbedtls/BUILD.mk # │ +include third_party/ncurses/BUILD.mk # │ +include third_party/readline/BUILD.mk # │ +include third_party/libunwind/BUILD.mk # | +include third_party/libcxxabi/BUILD.mk # | include third_party/libcxx/BUILD.mk # │ -include third_party/ggml/BUILD.mk # │ -include third_party/radpajama/BUILD.mk # │ +include third_party/openmp/BUILD.mk # │ +include third_party/double-conversion/BUILD.mk # │ +include third_party/pcre/BUILD.mk # │ +include third_party/less/BUILD.mk # │ include net/https/BUILD.mk # │ -include third_party/regex/BUILD.mk #─┘ +include third_party/regex/BUILD.mk # │ +include third_party/bash/BUILD.mk #─┘ include third_party/tidy/BUILD.mk include third_party/BUILD.mk include third_party/nsync/testing/BUILD.mk @@ -235,6 +300,7 @@ include libc/testlib/BUILD.mk include tool/viz/lib/BUILD.mk include tool/args/BUILD.mk include test/posix/BUILD.mk +include test/libcxx/BUILD.mk include test/tool/args/BUILD.mk include third_party/linenoise/BUILD.mk include third_party/maxmind/BUILD.mk @@ -254,7 +320,6 @@ include third_party/argon2/BUILD.mk include third_party/smallz4/BUILD.mk include third_party/sqlite3/BUILD.mk include third_party/mbedtls/test/BUILD.mk -include third_party/quickjs/BUILD.mk include third_party/lz4cli/BUILD.mk include third_party/zip/BUILD.mk include third_party/xxhash/BUILD.mk @@ -266,6 +331,7 @@ include third_party/python/BUILD.mk include tool/build/BUILD.mk include tool/curl/BUILD.mk include third_party/qemu/BUILD.mk +include third_party/libcxxabi/test/BUILD.mk include examples/BUILD.mk include examples/pyapp/BUILD.mk include examples/pylife/BUILD.mk @@ -294,7 +360,6 @@ include test/libc/calls/BUILD.mk include test/libc/x/BUILD.mk include test/libc/xed/BUILD.mk include test/libc/fmt/BUILD.mk -include test/libc/dns/BUILD.mk include test/libc/time/BUILD.mk include test/libc/proc/BUILD.mk include test/libc/stdio/BUILD.mk @@ -370,7 +435,6 @@ loc: o/$(MODE)/tool/build/summy.com COSMOPOLITAN_OBJECTS = \ TOOL_ARGS \ NET_HTTP \ - LIBC_DNS \ LIBC_SOCK \ LIBC_NT_WS2_32 \ LIBC_NT_IPHLPAPI \ @@ -378,8 +442,11 @@ COSMOPOLITAN_OBJECTS = \ THIRD_PARTY_GETOPT \ LIBC_LOG \ LIBC_TIME \ + THIRD_PARTY_OPENMP \ THIRD_PARTY_MUSL \ THIRD_PARTY_ZLIB_GZ \ + THIRD_PARTY_LIBCXXABI \ + THIRD_PARTY_LIBUNWIND \ LIBC_STDIO \ THIRD_PARTY_GDTOA \ THIRD_PARTY_REGEX \ @@ -421,7 +488,6 @@ COSMOPOLITAN_H_PKGS = \ APE \ LIBC \ LIBC_CALLS \ - LIBC_DNS \ LIBC_ELF \ LIBC_FMT \ LIBC_DLOPEN \ @@ -450,12 +516,16 @@ COSMOPOLITAN_H_PKGS = \ THIRD_PARTY_GETOPT \ THIRD_PARTY_MUSL \ THIRD_PARTY_ZLIB \ + THIRD_PARTY_ZLIB_GZ \ THIRD_PARTY_REGEX COSMOCC_PKGS = \ $(COSMOPOLITAN_H_PKGS) \ THIRD_PARTY_AARCH64 \ THIRD_PARTY_LIBCXX \ + THIRD_PARTY_LIBCXXABI \ + THIRD_PARTY_LIBUNWIND \ + THIRD_PARTY_OPENMP \ THIRD_PARTY_INTEL o/$(MODE)/cosmopolitan.a: \ @@ -480,18 +550,15 @@ o/cosmopolitan.h: o/cosmopolitan.h.txt \ $(wildcard libc/integral/*) \ $(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS)) \ $(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_INCS)) - @$(ECHO) '#ifndef __STRICT_ANSI__' >$@ - @$(ECHO) '#define _COSMO_SOURCE' >>$@ - @$(ECHO) '#endif' >>$@ @$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup.com @$< >>$@ o/cosmopolitan.html: private .UNSANDBOXED = 1 o/cosmopolitan.html: \ o/$(MODE)/third_party/chibicc/chibicc.com.dbg \ $(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \ - $(SRCS) \ + $(filter-out %.cc,$(SRCS)) \ $(HDRS) - $(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))) + $(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))) o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \ -fno-common -include libc/integral/normalize.inc -o $@ \ -DCOSMO @$(TMPDIR)/$(subst /,_,$@) diff --git a/README.md b/README.md index e29e4493a..7132420ca 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,11 @@ possible performance and the tiniest footprint imaginable. ## Background -For an introduction to this project, please read the [αcτµαlly pδrταblε -εxεcµταblε](https://justine.lol/ape.html) blog post and [cosmopolitan +For an introduction to this project, please read the [actually portable +executable](https://justine.lol/ape.html) blog post and [cosmopolitan libc](https://justine.lol/cosmopolitan/index.html) website. We also have -[API documentation](https://justine.lol/cosmopolitan/documentation.html). +[API +documentation](https://justine.lol/cosmopolitan/documentation.html). ## Getting Started @@ -75,18 +76,7 @@ make install ## Cosmopolitan Source Builds Cosmopolitan can be compiled from source on any of our supported -platforms. First, you need to download or clone the repository. If -you're not using x86-64 Linux then you'll need cosmocc too. - -```sh -git clone https://github.com/jart/cosmopolitan cosmo -cd cosmo -mkdir -p o/third_party/gcc -pushd o/third_party/gcc -wget https://cosmo.zip/pub/cosmocc/cosmocc.zip -unzip cosmocc.zip -popd -``` +platforms. The Makefile will download cosmocc automatically. It's recommended that you install a systemwide APE Loader. This command requires `sudo` access to copy the `ape` command to a system folder and @@ -102,7 +92,7 @@ guaranteed to be compatible and furthermore includes our extensions for doing build system sandboxing. ```sh -o//third_party/gcc/bin/make -j8 +build/bootstrap/make.com -j8 o//examples/hello.com ``` @@ -113,7 +103,7 @@ depends on core LIBC packages. ```sh rm -rf o//libc o//test -o//third_party/gcc/bin/make o//test/posix/signal_test.com +build/bootstrap/make.com o//test/posix/signal_test.com o//test/posix/signal_test.com ``` @@ -122,21 +112,21 @@ list out each individual one. For example if you wanted to build and run all the unit tests in the `TEST_POSIX` package, you could say: ```sh -o//third_party/gcc/bin/make o//test/posix +build/bootstrap/make.com o//test/posix ``` Cosmopolitan provides a variety of build modes. For example, if you want really tiny binaries (as small as 12kb in size) then you'd say: ```sh -o//third_party/gcc/bin/make m=tiny +build/bootstrap/make.com m=tiny ``` You can furthermore cut out the bloat of other operating systems, and have Cosmopolitan become much more similar to Musl Libc. ```sh -o//third_party/gcc/bin/make m=tinylinux +build/bootstrap/make.com m=tinylinux ``` For further details, see [//build/config.mk](build/config.mk). diff --git a/ape/BUILD.mk b/ape/BUILD.mk index 7eb64bc5a..106504d02 100644 --- a/ape/BUILD.mk +++ b/ape/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # OVERVIEW # @@ -78,7 +78,8 @@ APE_LOADER_FLAGS = \ $< o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg - $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@ + @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@ + @$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@ o/$(MODE)/ape/ape.elf.dbg: \ o/$(MODE)/ape/start.o \ @@ -88,7 +89,7 @@ o/$(MODE)/ape/ape.elf.dbg: \ @$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^) o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h - @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS) + @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=33 -g $(APE_LOADER_FLAGS) o/$(MODE)/ape/start.o: ape/start.S @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< o/$(MODE)/ape/launch.o: ape/launch.S @@ -167,14 +168,11 @@ o/$(MODE)/ape/ape-no-modify-self.o: \ libc/macros.internal.h \ libc/nexgen32e/uart.internal.h \ libc/calls/metalfile.internal.h \ - libc/nexgen32e/vidya.internal.h \ libc/nt/pedef.internal.h \ libc/runtime/e820.internal.h \ libc/runtime/mman.internal.h \ libc/runtime/pc.internal.h \ libc/sysv/consts/prot.h \ - ape/blink-linux-aarch64.gz \ - ape/blink-xnu-aarch64.gz \ o/$(MODE)/ape/ape.elf @$(COMPILE) \ -AOBJECTIFY.S \ @@ -198,14 +196,11 @@ o/$(MODE)/ape/ape-copy-self.o: \ libc/macros.internal.h \ libc/nexgen32e/uart.internal.h \ libc/calls/metalfile.internal.h \ - libc/nexgen32e/vidya.internal.h \ libc/nt/pedef.internal.h \ libc/runtime/e820.internal.h \ libc/runtime/mman.internal.h \ libc/runtime/pc.internal.h \ - libc/sysv/consts/prot.h \ - ape/blink-linux-aarch64.gz \ - ape/blink-xnu-aarch64.gz + libc/sysv/consts/prot.h @$(COMPILE) \ -AOBJECTIFY.S \ $(OBJECTIFY.S) \ @@ -264,10 +259,6 @@ endif o/$(MODE)/ape/ape.o: ape/ape.S @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< -o/$(MODE)/ape/ape.o: \ - ape/blink-linux-aarch64.gz \ - ape/blink-xnu-aarch64.gz - o/$(MODE)/ape/ape.lds: \ ape/ape.lds \ ape/macros.internal.h \ diff --git a/ape/aarch64.lds b/ape/aarch64.lds index 3bf1792f9..9866ac748 100644 --- a/ape/aarch64.lds +++ b/ape/aarch64.lds @@ -1,5 +1,5 @@ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ -│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ +│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/thread/tls.h" diff --git a/ape/ape-m1.c b/ape/ape-m1.c index 677bf3545..82c98feaa 100644 --- a/ape/ape-m1.c +++ b/ape/ape-m1.c @@ -35,9 +35,7 @@ #include #include -#define pagesz 16384 -#define VARNAME "COSMOPOLITAN_PROGRAM_EXECUTABLE=" -#define VARSIZE (sizeof(VARNAME) - 1) +#define pagesz 16384 /* maximum path size that cosmo can take */ #define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024) #define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24) @@ -105,36 +103,39 @@ struct Syslib { char *(*dlerror)(void); }; -#define ELFCLASS32 1 -#define ELFDATA2LSB 1 -#define EM_AARCH64 183 -#define ET_EXEC 2 -#define ET_DYN 3 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define PF_X 1 -#define PF_W 2 -#define PF_R 4 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_BASE 7 -#define AT_ENTRY 9 -#define AT_UID 11 -#define AT_EUID 12 -#define AT_GID 13 -#define AT_EGID 14 -#define AT_HWCAP 16 -#define AT_HWCAP2 16 -#define AT_SECURE 23 -#define AT_RANDOM 25 -#define AT_EXECFN 31 +#define ELFCLASS32 1 +#define ELFDATA2LSB 1 +#define EM_AARCH64 183 +#define ET_EXEC 2 +#define ET_DYN 3 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define PF_X 1 +#define PF_W 2 +#define PF_R 4 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_FLAGS_PRESERVE_ARGV0_BIT 0 +#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT) +#define AT_ENTRY 9 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 +#define AT_HWCAP 16 +#define AT_HWCAP2 16 +#define AT_SECURE 23 +#define AT_RANDOM 25 +#define AT_EXECFN 31 -#define AUXV_WORDS 29 +#define AUXV_WORDS 31 /* from the xnu codebase */ #define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul @@ -203,11 +204,8 @@ struct PathSearcher { unsigned long namelen; const char *name; const char *syspath; - char varname[VARSIZE]; char path[PATHSIZE]; }; -_Static_assert(offsetof(struct PathSearcher, varname) + VARSIZE == - offsetof(struct PathSearcher, path), "struct layout"); struct ApeLoader { struct PathSearcher ps; @@ -321,28 +319,13 @@ __attribute__((__noreturn__)) static void Pexit(const char *c, int failed, } static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) { - if (!pathlen && *ps->name != '/') { - if (!getcwd(ps->path, sizeof(ps->path) - 1 - ps->namelen)) { - Pexit("getcwd", -errno, "failed"); - } - pathlen = strlen(ps->path); - } else if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) { + if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) { return 0; } if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/'; memmove(ps->path + pathlen, ps->name, ps->namelen); ps->path[pathlen + ps->namelen] = 0; - if (!access(ps->path, X_OK)) { - if (ps->indirect) { - ps->namelen -= 4; - ps->path[pathlen + ps->namelen] = 0; - if (access(ps->path, X_OK) < 0) { - Pexit(ps->path, -errno, "access(X_OK)"); - } - } - return 1; - } - return 0; + return !access(ps->path, X_OK); } static char SearchPath(struct PathSearcher *ps) { @@ -368,12 +351,8 @@ static char FindCommand(struct PathSearcher *ps) { ps->path[0] = 0; /* paths are always 100% taken literally when a slash exists - $ ape foo/bar.com arg1 arg2 */ - if (memchr(ps->name, '/', ps->namelen)) { - return AccessCommand(ps, 0); - } - - /* we don't run files in the current directory + $ ape foo/bar.com arg1 arg2 + we don't run files in the current directory $ ape foo.com arg1 arg2 unless $PATH has an empty string entry, e.g. $ expert PATH=":/bin" @@ -381,8 +360,8 @@ static char FindCommand(struct PathSearcher *ps) { however we will execute this $ ape - foo.com foo.com arg1 arg2 because cosmo's execve needs it */ - if (ps->literally && AccessCommand(ps, 0)) { - return 1; + if (ps->literally || memchr(ps->name, '/', ps->namelen)) { + return AccessCommand(ps, 0); } /* otherwise search for name on $PATH */ @@ -392,7 +371,8 @@ static char FindCommand(struct PathSearcher *ps) { static char *Commandv(struct PathSearcher *ps, const char *name, const char *syspath) { ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin"; - if (!(ps->namelen = StrLen((ps->name = name)))) return 0; + ps->name = name; + if (!(ps->namelen = ps->indirect ? ps->indirect : StrLen(ps->name))) return 0; if (ps->namelen + 1 > sizeof(ps->path)) return 0; if (FindCommand(ps)) { return ps->path; @@ -563,7 +543,8 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, long *sp, struct ElfEhdr *e, struct ElfPhdr *p, - struct Syslib *lib) { + struct Syslib *lib, + char *path) { long rc; int prot; int flags; @@ -734,11 +715,11 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, close(fd); register long *x0 __asm__("x0") = sp; + register char *x2 __asm__("x2") = path; + register int x3 __asm__("x3") = 8; /* _HOSTXNU */ register struct Syslib *x15 __asm__("x15") = lib; register long x16 __asm__("x16") = e->e_entry; __asm__ volatile("mov\tx1,#0\n\t" - "mov\tx2,#0\n\t" - "mov\tx3,#0\n\t" "mov\tx4,#0\n\t" "mov\tx5,#0\n\t" "mov\tx6,#0\n\t" @@ -767,7 +748,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, "mov\tx0,#0\n\t" "br\tx16" : /* no outputs */ - : "r"(x0), "r"(x15), "r"(x16) + : "r"(x0), "r"(x2), "r"(x3), "r"(x15), "r"(x16) : "memory"); __builtin_unreachable(); } @@ -870,28 +851,30 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf, auxv[7] = ebuf->ehdr.e_entry; auxv[8] = AT_PAGESZ; auxv[9] = pagesz; - auxv[10] = AT_UID; - auxv[11] = getuid(); - auxv[12] = AT_EUID; - auxv[13] = geteuid(); - auxv[14] = AT_GID; - auxv[15] = getgid(); - auxv[16] = AT_EGID; - auxv[17] = getegid(); - auxv[18] = AT_HWCAP; - auxv[19] = 0xffb3ffffu; - auxv[20] = AT_HWCAP2; - auxv[21] = 0x181; - auxv[22] = AT_SECURE; - auxv[23] = issetugid(); - auxv[24] = AT_RANDOM; - auxv[25] = (long)M->rando; - auxv[26] = AT_EXECFN; - auxv[27] = (long)execfn; - auxv[28] = 0; + auxv[10] = AT_FLAGS; + auxv[11] = M->ps.literally ? AT_FLAGS_PRESERVE_ARGV0 : 0; + auxv[12] = AT_UID; + auxv[13] = getuid(); + auxv[14] = AT_EUID; + auxv[15] = geteuid(); + auxv[16] = AT_GID; + auxv[17] = getgid(); + auxv[18] = AT_EGID; + auxv[19] = getegid(); + auxv[20] = AT_HWCAP; + auxv[21] = 0xffb3ffffu; + auxv[22] = AT_HWCAP2; + auxv[23] = 0x181; + auxv[24] = AT_SECURE; + auxv[25] = issetugid(); + auxv[26] = AT_RANDOM; + auxv[27] = (long)M->rando; + auxv[28] = AT_EXECFN; + auxv[29] = (long)execfn; + auxv[30] = 0; /* we're now ready to load */ - Spawn(exe, fd, sp, e, p, &M->lib); + Spawn(exe, fd, sp, e, p, &M->lib, M->ps.path); } int main(int argc, char **argv, char **envp) { @@ -900,8 +883,7 @@ int main(int argc, char **argv, char **envp) { struct ApeLoader *M; long *sp, *sp2, *auxv; union ElfEhdrBuf *ebuf; - char *p, *pe, *exe, *prog, - *execfn, *shell, **varpos; + char *p, *pe, *exe, *prog, *execfn; /* allocate loader memory in program's arg block */ n = sizeof(struct ApeLoader); @@ -964,16 +946,16 @@ int main(int argc, char **argv, char **envp) { M->lib.dlerror = dlerror; /* getenv("_") is close enough to at_execfn */ - execfn = argc > 0 ? argv[0] : 0; - varpos = 0; + execfn = 0; for (i = 0; envp[i]; ++i) { if (envp[i][0] == '_' && envp[i][1] == '=') { execfn = envp[i] + 2; - } else if (!memcmp(VARNAME, envp[i], VARSIZE)) { - assert(!varpos); - varpos = envp + i; } } + prog = GetEnv(envp + i + 1, "executable_path"); + if (!execfn) { + execfn = prog; + } /* sneak the system five abi back out of args */ sp = (long *)(argv - 1); @@ -982,7 +964,7 @@ int main(int argc, char **argv, char **envp) { /* create new bottom of stack for spawned program system v abi aligns this on a 16-byte boundary grows down the alloc by poking the guard pages */ - n = (auxv - sp + !varpos + AUXV_WORDS + 1) * sizeof(long); + n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long); sp2 = (long *)__builtin_alloca(n); if ((long)sp2 & 15) ++sp2; for (; n > 0; n -= pagesz) { @@ -991,18 +973,12 @@ int main(int argc, char **argv, char **envp) { memmove(sp2, sp, (auxv - sp) * sizeof(long)); argv = (char **)(sp2 + 1); envp = (char **)(sp2 + 1 + argc + 1); - if (varpos) { - varpos = (char **)((long *)varpos - sp + sp2); - } else { - varpos = envp + i++; - *(envp + i) = 0; - } auxv = (long *)(envp + i + 1); sp = sp2; /* interpret command line arguments */ - if ((M->ps.indirect = argc > 0 ? GetIndirectOffset(argv[0]) : 0)) { - /* if argv[0] is $prog.ape, then we strip off the .ape and run + if ((M->ps.indirect = GetIndirectOffset(prog))) { + /* if called as $prog.ape, then strip off the .ape and run the $prog. This allows you to use symlinks to trick the OS when a native executable is required. For example, let's say you want to use the APE binary /opt/cosmos/bin/bash as a system @@ -1011,13 +987,7 @@ int main(int argc, char **argv, char **envp) { but it will if you say: ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape and then use #!/opt/cosmos/bin/bash.ape instead. */ - M->ps.literally = 0; - if (*argv[0] == '-' && (shell = GetEnv(envp, "SHELL")) && - !StrCmp(argv[0] + 1, BaseName(shell))) { - execfn = prog = shell; - } else { - prog = (char *)sp[1]; - } + M->ps.literally = 1; argc = sp[0]; argv = (char **)(sp + 1); } else if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) { @@ -1031,9 +1001,9 @@ int main(int argc, char **argv, char **envp) { } else if (argc < 2) { Emit("usage: ape PROG [ARGV1,ARGV2,...]\n" " ape - PROG [ARGV0,ARGV1,...]\n" - " ($0 = PROG.ape) [ARGV1,ARGV2,...]\n" - "actually portable executable loader silicon 1.9\n" - "copyright 2023 justine alexandra roberts tunney\n" + " PROG.ape [ARGV1,ARGV2,...]\n" + "actually portable executable loader silicon 1.10\n" + "copyrights 2023 justine alexandra roberts tunney\n" "https://justine.lol/ape.html\n"); _exit(1); } else { @@ -1061,12 +1031,6 @@ int main(int argc, char **argv, char **envp) { } pe = ebuf->buf + rc; - /* inject program executable as first environment variable, - swapping the old first variable for it. */ - memmove(M->ps.varname, VARNAME, VARSIZE); - *varpos = *envp; - *envp = M->ps.varname; - /* generate some hard random data */ if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) { Pexit(argv[0], rc, "getentropy"); diff --git a/ape/ape.S b/ape/ape.S index 70b3d709c..80e788570 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -592,9 +592,7 @@ ape_disk: #ifdef APE_IS_SHELL_SCRIPT apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang - .ascii "m=$(/bin/uname -m 2>/dev/null) || " - .ascii "m=$(/usr/bin/uname -m 2>/dev/null) || " - .ascii "m=x86_64\n" + .ascii "m=$(uname -m 2>/dev/null) || m=x86_64\n" .ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n" // Until all operating systems can be updated to support APE, @@ -617,15 +615,15 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang .ascii APE_VERSION_STR .ascii "\"\n" .ascii "[ -x \"$t\" ] || {\n" - .ascii "/bin/mkdir -p \"${t%/*}\" &&\n" - .ascii "/bin/dd if=\"$o\" of=\"$t.$$\" skip=" + .ascii "mkdir -p \"${t%/*}\" &&\n" + .ascii "dd if=\"$o\" of=\"$t.$$\" skip=" .shstub ape_loader_dd_skip,2 .ascii " count=" .shstub ape_loader_dd_count,2 .ascii " bs=64 2>/dev/null\n" #if SupportsXnu() .ascii "[ -d /Applications ] && " - .ascii "/bin/dd if=\"$t.$$\"" + .ascii "dd if=\"$t.$$\"" .ascii " of=\"$t.$$\"" .ascii " skip=5" .ascii " count=8" @@ -633,8 +631,8 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang .ascii " conv=notrunc" .ascii " 2>/dev/null\n" #endif /* SupportsXnu() */ - .ascii "/bin/chmod 755 \"$t.$$\"\n" - .ascii "/bin/mv -f \"$t.$$\" \"$t\"\n" + .ascii "chmod 755 \"$t.$$\"\n" + .ascii "mv -f \"$t.$$\" \"$t\"\n" .ascii "}\n" .ascii "exec \"$t\" \"$o\" \"$@\"\n" .ascii "}\n" @@ -650,9 +648,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang .ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n" .ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n" .ascii "[ x\"$1\" != x--assimilate ] && {\n" - .ascii "/bin/mkdir -p \"${t%/*}\" 2>/dev/null\n" - .ascii "/bin/cp -f \"$o\" \"$t.$$\" &&\n" - .ascii "/bin/mv -f \"$t.$$\" \"$t\" || exit 120\n" + .ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n" + .ascii "cp -f \"$o\" \"$t.$$\" &&\n" + .ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n" .ascii "o=\"$t\"\n" .ascii "}\n" #endif /* APE_NO_MODIFY_SELF */ @@ -683,7 +681,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang .ascii "exec 7<&-\n" #if SupportsXnu() .ascii "[ -d /Applications ] && " - .ascii "/bin/dd if=\"$o\"" + .ascii "dd if=\"$o\"" .ascii " of=\"$o\"" .ascii " bs=8" .ascii " skip=" @@ -702,38 +700,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang #endif /* APE_NO_MODIFY_SELF */ .ascii "exit $?\n" .ascii "fi\n" // x86_64 -// ... -// decentralized section (.apesh) -// ... - .ascii "PHDRS='' <<'@'\n" - .endobj apesh - -// elf program headers get inserted here -// because they need to be in the first 4096 bytes - .section .emushprologue,"a",@progbits -emush: .ascii "\n@\n#'\"\n" - .ascii "s=$(/bin/uname -s 2>/dev/null) || " - .ascii "s=$(/usr/bin/uname -s 2>/dev/null) || " - .ascii "s=Darwin\n" -// our script is running on a non-x86_64 architecture -// 1. `dd` out the appropriate blink vm blob -// 2. gunzip the blink virtual machine executable -// 3. relaunch this program inside the blink vm - .ascii "o=\"$(command -v \"$0\")\"\n" - .ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n" - .previous -// ... -// decentralized section (.emush) -// - __static_yoink("blink_linux_aarch64"); // for raspberry pi -// - __static_yoink("blink_xnu_aarch64"); // is apple silicon -// ... - .section .emushepilogue,"a",@progbits - .ascii "echo \"$0: this ape binary lacks $m support\" >&2\n" - .rept 16 - .ascii "exit 127\n" - .endr + .ascii "echo error: this ape binary only supports x86_64 >&2\n" .ascii "exit 1\n" - .previous + .endobj apesh #ifdef APE_LOADER .section .ape.loader,"a",@progbits diff --git a/ape/ape.h b/ape/ape.h index 68ab61b0a..d2f589612 100644 --- a/ape/ape.h +++ b/ape/ape.h @@ -2,7 +2,7 @@ #define COSMOPOLITAN_APE_APE_H_ #define APE_VERSION_MAJOR 1 -#define APE_VERSION_MINOR 9 +#define APE_VERSION_MINOR 10 #define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR) #define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR) diff --git a/ape/ape.lds b/ape/ape.lds index 6df89eeb3..288d798d4 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -1,5 +1,5 @@ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ -│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ +│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -229,7 +229,6 @@ SECTIONS { /* Real Mode */ KEEP(*(.head)) - KEEP(*(.apesh)) KEEP(*(.text.head)) /* Executable & Linkable Format */ @@ -238,10 +237,6 @@ SECTIONS { KEEP(*(.elf.phdrs)) ape_phdrs_end = .; - KEEP(*(.emushprologue)) - KEEP(*(.emush)) - KEEP(*(.emushepilogue)) - /* OpenBSD */ . = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0); ape_note = .; @@ -301,7 +296,6 @@ SECTIONS { KEEP(*(.textwindowsprologue)) *(.text.windows) KEEP(*(.textwindowsepilogue)) - KEEP(*(.blink)) *(SORT_BY_ALIGNMENT(.text.modernity)) *(SORT_BY_ALIGNMENT(.text.modernity.*)) *(SORT_BY_ALIGNMENT(.text.hot)) @@ -613,29 +607,6 @@ SHSTUB2(ape_loader_dd_count, ? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64 : 0); -#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny() - -#define IDENTITY(X) X - -#define APE_DECLARE_FIXED_DECIMAL(F, X) \ - X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \ - (F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \ - (F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \ - (F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \ - (F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \ - (F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \ - (F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \ - (F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \ - X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \ - (F(X) % 10 + 48) << 010) : 0 - -APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64); -APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size); -APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64); -APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size); - -#endif /* APE_IS_SHELL_SCRIPT */ - #if SupportsMetal() v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512; v_ape_realbytes = v_ape_realsectors * 512; diff --git a/ape/apeinstall.sh b/ape/apeinstall.sh index bb71c98e2..37771820d 100755 --- a/ape/apeinstall.sh +++ b/ape/apeinstall.sh @@ -10,73 +10,98 @@ if [ ! -f ape/loader.c ]; then cd "$COSMO" || exit fi +if [ -x build/bootstrap/make.com ]; then + MAKE=build/bootstrap/make.com +else + MAKE=make +fi + if [ "$(id -u)" -eq 0 ]; then SUDO= -else +elif command -v sudo >/dev/null 2>&1; then SUDO=sudo +elif command -v doas >/dev/null 2>&1; then + SUDO=doas +else + echo "need root or sudo" >&2 + exit +fi + +if command -v install >/dev/null 2>&1; then + if [ x"$(uname -s)" = xLinux ]; then + INSTALL="install -o root -g root -m 755" + else + INSTALL="install -o root -g wheel -m 755" + fi +else + INSTALL="cp -f" fi echo "Actually Portable Executable (APE) Installer" >&2 echo "Author: Justine Tunney " >&2 # special installation process for apple silicon -if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "arm64" ]; then +if [ x"$(uname -s)" = xDarwin ] && [ x"$(uname -m)" = xarm64 ]; then echo "cc -O -o $TMPDIR/ape.$$ ape/ape-m1.c" >&2 cc -O -o "$TMPDIR/ape.$$" ape/ape-m1.c || exit + trap 'rm "$TMPDIR/ape.$$"' EXIT if [ ! -d /usr/local/bin ]; then echo "$SUDO mkdir -p /usr/local/bin" >&2 $SUDO mkdir -p /usr/local/bin || exit fi - echo "$SUDO mv -f $TMPDIR/ape.$$ /usr/local/bin/ape" >&2 - $SUDO mv -f "$TMPDIR/ape.$$" /usr/local/bin/ape || exit + echo "$SUDO $INSTALL $TMPDIR/ape.$$ /usr/local/bin/ape" >&2 + $SUDO $INSTALL "$TMPDIR/ape.$$" /usr/local/bin/ape || exit + exit +fi + +if [ x"$(uname -m)" = xarm64 ] || [ x"$(uname -m)" = xaarch64 ]; then + MODE=aarch64 + EXT=elf + BEXT=aarch64 +elif [ x"$(uname -m)" = xx86_64 ]; then + MODE= + if [ x"$(uname -s)" = xDarwin ]; then + EXT=macho + else + EXT=elf + fi + BEXT=$EXT +else + echo "unsupported architecture $(uname -m)" >&2 exit fi ################################################################################ # INSTALL APE LOADER SYSTEMWIDE -if [ -f o/depend ] && make -j8 o//ape; then +if [ -f o/$MODE/depend ] && $MAKE -j8 o/$MODE/ape; then echo "successfully recompiled ape loader" >&2 -elif [ -x o//ape/ape.elf ] && [ -x o//ape/ape.macho ]; then +elif [ -x o/$MODE/ape/ape.$EXT ]; then echo "using ape loader you compiled earlier" >&2 elif [ -d build/bootstrap ]; then # if make isn't being used then it's unlikely the user changed the sources # in that case the prebuilt binaries should be completely up-to-date echo "using prebuilt ape loader from cosmo repo" >&2 - mkdir -p o//ape || exit - cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit - cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit + mkdir -p o/$MODE/ape || exit + cp -af build/bootstrap/ape.$BEXT o/$MODE/ape/ape.$EXT || exit else echo "no cosmopolitan libc repository here" >&2 - echo "fetching ape loader from justine.lol" >&2 - mkdir -p o//ape || exit + echo "fetching ape loader from justine.lol" >&2 + mkdir -p o/$MODE/ape || exit if command -v wget >/dev/null 2>&1; then - wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit - wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit + wget -qO o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit else - curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit - curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit + curl -Rso o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit fi - chmod +x o//ape/ape.elf || exit - chmod +x o//ape/ape.macho || exit + chmod +x o/$MODE/ape/ape.$EXT || exit fi -if [ "$(uname -s)" = "Darwin" ]; then - if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then - echo >&2 - echo "installing o//ape/ape.macho to /usr/bin/ape" >&2 - echo "$SUDO cp -f o//ape/ape.macho /usr/bin/ape" >&2 - $SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit - echo "done" >&2 - fi -else - if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then - echo >&2 - echo "installing o//ape/ape.elf to /usr/bin/ape" >&2 - echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2 - $SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit - echo "done" >&2 - fi +if ! [ /usr/bin/ape -nt o/$MODE/ape/ape.$EXT ]; then + echo >&2 + echo "installing o/$MODE/ape/ape.$EXT to /usr/bin/ape" >&2 + echo "$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape" >&2 + $SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape || exit + echo "done" >&2 fi ################################################################################ diff --git a/ape/apeuninstall.sh b/ape/apeuninstall.sh index cde7a7064..3e74d3ac4 100755 --- a/ape/apeuninstall.sh +++ b/ape/apeuninstall.sh @@ -11,8 +11,13 @@ fi if [ "$UID" = "0" ]; then SUDO= -else +elif command -v sudo >/dev/null 2>&1; then SUDO=sudo +elif command -v doas >/dev/null 2>&1; then + SUDO=doas +else + echo "need root or sudo" >&2 + exit fi { @@ -54,8 +59,7 @@ for x in .ape \ .ape-1.7 \ .ape-1.8 \ .ape-1.9 \ - .ape-blink-0.9.2 \ - .ape-blink-1.0.0; do + .ape-1.10; do rm -f \ ~/$x \ /tmp/$x \ diff --git a/ape/blink-linux-aarch64.gz b/ape/blink-linux-aarch64.gz deleted file mode 100644 index 66a6752d2..000000000 Binary files a/ape/blink-linux-aarch64.gz and /dev/null differ diff --git a/ape/blink-xnu-aarch64.gz b/ape/blink-xnu-aarch64.gz deleted file mode 100755 index 06718a190..000000000 Binary files a/ape/blink-xnu-aarch64.gz and /dev/null differ diff --git a/ape/launch.S b/ape/launch.S index 09d2f3697..ae2cb58a1 100644 --- a/ape/launch.S +++ b/ape/launch.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ @@ -31,17 +31,16 @@ // // @param rdi is passed through as-is // @param rsi is address of entrypoint (becomes zero) -// @param rdx is stack pointer (becomes zero) +// @param rdx is passed through as-is // @param rcx is passed through as-is +// @param r8 is stack pointer (becomes zero) // @noreturn Launch: #ifdef __aarch64__ mov x16,x1 - mov sp,x2 + mov sp,x4 mov x1,0 - mov x2,0 - mov x3,0 mov x4,0 mov x5,0 mov x6,0 @@ -71,6 +70,7 @@ Launch: #else + mov %r8,%rsp xor %r8d,%r8d xor %r9d,%r9d xor %r10d,%r10d @@ -79,8 +79,6 @@ Launch: xor %r13d,%r13d xor %r14d,%r14d xor %r15d,%r15d - mov %rdx,%rsp - xor %edx,%edx push %rsi xor %esi,%esi xor %ebp,%ebp diff --git a/ape/loader-macho.S b/ape/loader-macho.S index 2acc13b46..fd9fd55f8 100644 --- a/ape/loader-macho.S +++ b/ape/loader-macho.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ diff --git a/ape/loader.c b/ape/loader.c index b65bd147f..87822315e 100644 --- a/ape/loader.c +++ b/ape/loader.c @@ -87,6 +87,8 @@ #define MIN(X, Y) ((Y) > (X) ? (X) : (Y)) #define MAX(X, Y) ((Y) < (X) ? (X) : (Y)) +#define PATH_MAX 1024 /* XXX verify */ + #define SupportsLinux() (SUPPORT_VECTOR & LINUX) #define SupportsXnu() (SUPPORT_VECTOR & XNU) #define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD) @@ -111,41 +113,44 @@ #define EXTERN_C #endif -#define O_RDONLY 0 -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_FIXED 16 -#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096) -#define MAP_NORESERVE (IsLinux() ? 16384 : 0) -#define ELFCLASS32 1 -#define ELFDATA2LSB 1 -#define EM_NEXGEN32E 62 -#define EM_AARCH64 183 -#define ET_EXEC 2 -#define ET_DYN 3 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define PF_X 1 -#define PF_W 2 -#define PF_R 4 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_EXECFN_LINUX 31 -#define AT_EXECFN_NETBSD 2014 -#define X_OK 1 -#define XCR0_SSE 2 -#define XCR0_AVX 4 -#define PR_SET_MM 35 -#define PR_SET_MM_EXE_FILE 13 +#define O_RDONLY 0 +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_FIXED 16 +#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096) +#define MAP_NORESERVE (IsLinux() ? 16384 : 0) +#define ELFCLASS32 1 +#define ELFDATA2LSB 1 +#define EM_NEXGEN32E 62 +#define EM_AARCH64 183 +#define ET_EXEC 2 +#define ET_DYN 3 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define PF_X 1 +#define PF_W 2 +#define PF_R 4 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_FLAGS 8 +#define AT_FLAGS_PRESERVE_ARGV0_BIT 0 +#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT) +#define AT_EXECFN_LINUX 31 +#define AT_EXECFN_NETBSD 2014 +#define X_OK 1 +#define XCR0_SSE 2 +#define XCR0_AVX 4 +#define PR_SET_MM 35 +#define PR_SET_MM_EXE_FILE 13 #define READ32(S) \ ((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \ @@ -212,17 +217,18 @@ struct PathSearcher { const char *name; const char *syspath; unsigned long namelen; - char path[1024]; + char path[PATH_MAX]; }; struct ApeLoader { union ElfPhdrBuf phdr; struct PathSearcher ps; - char path[1024]; + char path[PATH_MAX]; }; EXTERN_C long SystemCall(long, long, long, long, long, long, long, int); -EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__)); +EXTERN_C void Launch(void *, long, void *, int, void *) + __attribute__((__noreturn__)); extern char __executable_start[]; extern char _end[]; @@ -239,12 +245,13 @@ static int StrCmp(const char *l, const char *r) { return (l[i] & 255) - (r[i] & 255); } -static const char *BaseName(const char *s) { - int c; - const char *b = ""; +#if 0 + +static const char *StrRChr(const char *s, int c) { + const char *b = 0; if (s) { - while ((c = *s++)) { - if (c == '/') { + for (; *s; ++s) { + if (*s == c) { b = s; } } @@ -252,6 +259,13 @@ static const char *BaseName(const char *s) { return b; } +static const char *BaseName(const char *s) { + const char *b = StrRChr(s, '/'); + return b ? b + 1 : s; +} + +#endif + static void Bzero(void *a, unsigned long n) { long z; char *p, *e; @@ -343,7 +357,7 @@ static char *Utox(char p[19], unsigned long x) { return p; } -static char *Utoa(char p[21], unsigned long x) { +static char *Utoa(char p[20], unsigned long x) { char t; unsigned long i, a, b; i = 0; @@ -561,45 +575,22 @@ static char SearchPath(struct PathSearcher *ps) { } } -static char FindCommand(struct PathSearcher *ps) { - ps->path[0] = 0; - - /* paths are always 100% taken literally when a slash exists - $ ape foo/bar.com arg1 arg2 */ - if (MemChr(ps->name, '/', ps->namelen)) { - return AccessCommand(ps, 0); - } - - /* we don't run files in the current directory - $ ape foo.com arg1 arg2 - unless $PATH has an empty string entry, e.g. - $ expert PATH=":/bin" - $ ape foo.com arg1 arg2 - however we will execute this - $ ape - foo.com foo.com arg1 arg2 - because cosmo's execve needs it */ - if (ps->literally && AccessCommand(ps, 0)) { - return 1; - } - - /* otherwise search for name on $PATH */ - return SearchPath(ps); -} - -static char *Commandv(struct PathSearcher *ps, int os, const char *name, +static char *Commandv(struct PathSearcher *ps, int os, char *name, const char *syspath) { + if (!(ps->namelen = StrLen((ps->name = name)))) return 0; + if (ps->literally || MemChr(ps->name, '/', ps->namelen)) return name; ps->os = os; ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin"; - if (!(ps->namelen = StrLen((ps->name = name)))) return 0; if (ps->namelen + 1 > sizeof(ps->path)) return 0; - if (FindCommand(ps)) { + ps->path[0] = 0; + if (SearchPath(ps)) { return ps->path; } else { return 0; } } -__attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, +__attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd, long *sp, unsigned long pagesz, struct ElfEhdr *e, struct ElfPhdr *p) { @@ -757,11 +748,11 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, Msyscall(dynbase + code, codesize, os); /* call program entrypoint */ - Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, sp, os); + Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, exe, os, sp); } static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf, - const char *exe, int fd, long *sp, long *auxv, + char *exe, int fd, long *sp, long *auxv, unsigned long pagesz, int os) { long i, rc; unsigned size; @@ -885,18 +876,13 @@ __attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) { "NAME\n" "\n" " actually portable executable loader version " APE_VERSION_STR "\n" - " copyright 2023 justine alexandra roberts tunney\n" + " copyrights 2024 justine alexandra roberts tunney\n" " https://justine.lol/ape.html\n" "\n" "USAGE\n" "\n" - " ape [FLAGS] PROG [ARGV1,ARGV2,...]\n" - " ape [FLAGS] - PROG [ARGV0,ARGV1,...]\n" - "\n" - "FLAGS\n" - "\n" - " -h show this help\n" - " -f force loading of program (do not use execve)\n" + " ape PROG [ARGV1,ARGV2,...]\n" + " ape - PROG [ARGV0,ARGV1,...]\n" "\n", 0l); Exit(rc, os); @@ -906,10 +892,10 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) { int rc, n; unsigned i; - char literally; const char *ape; int c, fd, os, argc; struct ApeLoader *M; + char arg0, literally; unsigned long pagesz; union ElfEhdrBuf *ebuf; long *auxv, *ap, *endp, *sp2; @@ -954,11 +940,15 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, /* detect netbsd and find end of words */ pagesz = 0; + arg0 = 0; for (ap = auxv; ap[0]; ap += 2) { if (ap[0] == AT_PAGESZ) { pagesz = ap[1]; } else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) { os = NETBSD; + } else if (SupportsLinux() && ap[0] == AT_FLAGS) { + // TODO(mrdomino): maybe set/insert this when we are called as "ape -". + arg0 = !!(ap[1] & AT_FLAGS_PRESERVE_ARGV0); } } if (!pagesz) { @@ -971,22 +961,13 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, os = LINUX; } - /* parse flags */ - while (argc > 1) { - if (argv[1][0] != '-') break; /* normal argument */ - if (!argv[1][1]) break; /* hyphen argument */ - if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) { - ShowUsage(os, 1, 0); - } else { - Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l); - Exit(1, os); - } - *++sp = --argc; - ++argv; - } - /* we can load via shell, shebang, or binfmt_misc */ - if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) { + if (arg0) { + literally = 1; + prog = (char *)sp[2]; + argc = sp[2] = sp[0] - 2; + argv = (char **)((sp += 2) + 1); + } else if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) { /* if the first argument is a hyphen then we give the user the power to change argv[0] or omit it entirely. most operating systems don't permit the omission of argv[0] but we do, b/c @@ -995,9 +976,13 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, argc = sp[3] = sp[0] - 3; argv = (char **)((sp += 3) + 1); } else if (argc < 2) { - Print(os, 2, ape, ": missing command name (pass -h for help)\n", 0l); - Exit(1, os); + ShowUsage(os, 2, 1); } else { + if (argv[1][0] == '-') { + rc = !((argv[1][1] == 'h' && !argv[1][2]) || + !StrCmp(argv[1] + 1, "-help")); + ShowUsage(os, 1 + rc, rc); + } prog = (char *)sp[2]; argc = sp[1] = sp[0] - 1; argv = (char **)((sp += 1) + 1); @@ -1042,12 +1027,6 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, } pe = ebuf->buf + rc; - /* change argv[0] to resolved path if it's ambiguous */ - if (argc > 0 && ((*prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) || - !StrCmp(BaseName(prog), argv[0]))) { - argv[0] = exe; - } - /* ape intended behavior 1. if ape, will scan shell script for elf printf statements 2. shell script may have multiple lines producing elf headers diff --git a/ape/loader.lds b/ape/loader.lds index 4fe6c4fd6..a27d29a12 100644 --- a/ape/loader.lds +++ b/ape/loader.lds @@ -1,5 +1,5 @@ /*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│ -│ vi: set noet sts=2 tw=2 fenc=utf-8 :vi │ +│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ diff --git a/ape/macros.internal.h b/ape/macros.internal.h index 0fab603ff..19733f0f7 100644 --- a/ape/macros.internal.h +++ b/ape/macros.internal.h @@ -22,119 +22,6 @@ #ifdef __ASSEMBLER__ /* clang-format off */ -/** - * @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε. - */ - -// Calls near (i.e. pc+pcrel<64kB) FUNCTION. -// @mode long,legacy,real -// @cost 9 bytes overhead -.macro rlcall function:req - .byte 0x50 # push %[er]ax - .byte 0xb8,0,0 # mov $?,%[e]ax - jmp 911f - .byte 0x58 # pop %[er]ax - .byte 0xe8 # call Jvds - .long \function\()-.-4 - jmp 912f -911: .byte 0x58 # pop %[er]ax - .byte 0xe8 # call Jvds - .short \function\()-.-2 -912: -.endm - -// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX. -// @mode long,legacy,real -.macro movesdi address:req - .byte 0xbf # mov $0x????xxxx,%[e]di - .short \address>>4 - .byte 0x8e,0xc7 # mov %di,%es - .byte 0xbf # mov $0x????xxxx,%[e]di - .short \address&0xf - jmp 297f - .byte 0xbf # mov $0x????xxxx,%edi - .long \address -297: -.endm - -// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend. -// @mode long,legacy,real -.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req - .ifnb \abcd - .if (\constexpr)<128 && (\constexpr)>=0 - pushpop \constexpr,\abcd - .exitm - .endif - .endif - movb $(\constexpr)>>8&0xff,\abcd.hi - movb $(\constexpr)&0xff,\abcd.lo -.endm - -// Compares 16-bit CONSTEXPR with Qw-register. -// @mode long,legacy,real -.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req - cmpb $(\constexpr)>>8&0xff,\abcd.hi - jnz 387f - cmpb $(\constexpr)&0xff,\abcd.lo -387: -.endm - -// Adds 16-bit CONSTEXPR to Qw-register. -// @mode long,legacy,real -.macro bbadd constexpr:req abcd.hi:req abcd.lo:req - addb $(\constexpr)&0xff,\abcd.lo - .if (\constexpr) != 0 - adcb $(\constexpr)>>8&0xff,\abcd.hi - .endif -.endm - -// Subtracts 16-bit CONSTEXPR from Qw-register. -// @mode long,legacy,real -.macro bbsub constexpr:req abcd.hi:req abcd.lo:req - subb $(\constexpr)&0xff,\abcd.lo - .if (\constexpr) != 0 - sbbb $(\constexpr)>>8&0xff,\abcd.hi - .endif -.endm - -// Ands Qw-register with 16-bit CONSTEXPR. -// @mode long,legacy,real -.macro bband constexpr:req abcd.hi:req abcd.lo:req - .if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff - andb $(\constexpr)&0xff,\abcd.lo - .endif - .if ((\constexpr)>>8&0xff) != 0xff - andb $(\constexpr)>>8&0xff,\abcd.hi - .endif -.endm - -// Ors Qw-register with 16-bit CONSTEXPR. -// @mode long,legacy,real -.macro bbor constexpr:req abcd.hi:req abcd.lo:req - .if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0 - orb $(\constexpr)&0xff,\abcd.lo - .endif - .if ((\constexpr)>>8&0xff) != 0 - orb $(\constexpr)>>8&0xff,\abcd.hi - .endif -.endm - -// Performs ACTION only if in real mode. -// @mode long,legacy,real -.macro rlo clobber:req action:vararg -990: mov $0,\clobber - .if .-990b!=3 - .error "bad clobber or assembler mode" - .endif -991: \action - .rept 2-(.-991b) - nop - .endr - .if .-991b!=2 - .error "ACTION must be 1-2 bytes" - .endif -.endm - // Initializes real mode stack. // The most holiest of holy code. // @mode real diff --git a/ape/start.S b/ape/start.S index f77cad2d2..c148966e1 100644 --- a/ape/start.S +++ b/ape/start.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ diff --git a/ape/systemcall.S b/ape/systemcall.S index f9a9944b6..c98632fd5 100644 --- a/ape/systemcall.S +++ b/ape/systemcall.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ diff --git a/build/bootstrap/ape.aarch64 b/build/bootstrap/ape.aarch64 index 1361430ea..c95c86c7f 100755 Binary files a/build/bootstrap/ape.aarch64 and b/build/bootstrap/ape.aarch64 differ diff --git a/build/bootstrap/ape.elf b/build/bootstrap/ape.elf index 69d9b269e..f56c3ef8e 100755 Binary files a/build/bootstrap/ape.elf and b/build/bootstrap/ape.elf differ diff --git a/build/bootstrap/ape.macho b/build/bootstrap/ape.macho index 434e36331..2b887117c 100755 Binary files a/build/bootstrap/ape.macho and b/build/bootstrap/ape.macho differ diff --git a/build/bootstrap/ar.com b/build/bootstrap/ar.com index bb6cf6e59..0a671a3b1 100755 Binary files a/build/bootstrap/ar.com and b/build/bootstrap/ar.com differ diff --git a/build/bootstrap/chmod.com b/build/bootstrap/chmod.com index 1a843b830..e42818495 100755 Binary files a/build/bootstrap/chmod.com and b/build/bootstrap/chmod.com differ diff --git a/build/bootstrap/cocmd.com b/build/bootstrap/cocmd.com index 72109dc78..58ecb0a0d 100755 Binary files a/build/bootstrap/cocmd.com and b/build/bootstrap/cocmd.com differ diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com index bc4e8733a..392c72017 100755 Binary files a/build/bootstrap/compile.com and b/build/bootstrap/compile.com differ diff --git a/build/bootstrap/cp.com b/build/bootstrap/cp.com index c16b1c17e..de2d52a67 100755 Binary files a/build/bootstrap/cp.com and b/build/bootstrap/cp.com differ diff --git a/build/bootstrap/echo.com b/build/bootstrap/echo.com index f521f3757..6ce62f8bd 100755 Binary files a/build/bootstrap/echo.com and b/build/bootstrap/echo.com differ diff --git a/build/bootstrap/fixupobj.com b/build/bootstrap/fixupobj.com index b6c7c3536..efc2ff872 100755 Binary files a/build/bootstrap/fixupobj.com and b/build/bootstrap/fixupobj.com differ diff --git a/build/bootstrap/gzip.com b/build/bootstrap/gzip.com index 5a77ee122..09bd2306b 100755 Binary files a/build/bootstrap/gzip.com and b/build/bootstrap/gzip.com differ diff --git a/build/bootstrap/make.com b/build/bootstrap/make.com index cc107f4b8..48aba621f 100755 Binary files a/build/bootstrap/make.com and b/build/bootstrap/make.com differ diff --git a/build/bootstrap/mkdeps.com b/build/bootstrap/mkdeps.com index bd83725fc..30b5e5f06 100755 Binary files a/build/bootstrap/mkdeps.com and b/build/bootstrap/mkdeps.com differ diff --git a/build/bootstrap/mkdir.com b/build/bootstrap/mkdir.com index 1fa861550..4c359071e 100755 Binary files a/build/bootstrap/mkdir.com and b/build/bootstrap/mkdir.com differ diff --git a/build/bootstrap/objbincopy.com b/build/bootstrap/objbincopy.com index a988f2c56..8cce21b7c 100755 Binary files a/build/bootstrap/objbincopy.com and b/build/bootstrap/objbincopy.com differ diff --git a/build/bootstrap/package.com b/build/bootstrap/package.com index 709626a7f..015964e47 100755 Binary files a/build/bootstrap/package.com and b/build/bootstrap/package.com differ diff --git a/build/bootstrap/pwd.com b/build/bootstrap/pwd.com deleted file mode 100755 index 0cdb8bc41..000000000 Binary files a/build/bootstrap/pwd.com and /dev/null differ diff --git a/build/bootstrap/rm.com b/build/bootstrap/rm.com index 03a152996..85f08d8b8 100755 Binary files a/build/bootstrap/rm.com and b/build/bootstrap/rm.com differ diff --git a/build/bootstrap/rollup.com b/build/bootstrap/rollup.com index 7b3ace4cb..47d2d505c 100755 Binary files a/build/bootstrap/rollup.com and b/build/bootstrap/rollup.com differ diff --git a/build/bootstrap/touch.com b/build/bootstrap/touch.com index 33d4b5bb4..7b6bc4943 100755 Binary files a/build/bootstrap/touch.com and b/build/bootstrap/touch.com differ diff --git a/build/bootstrap/unbundle.com b/build/bootstrap/unbundle.com deleted file mode 100755 index 4147431cc..000000000 Binary files a/build/bootstrap/unbundle.com and /dev/null differ diff --git a/build/bootstrap/zipcopy.com b/build/bootstrap/zipcopy.com index 682785d3d..8023194c7 100755 Binary files a/build/bootstrap/zipcopy.com and b/build/bootstrap/zipcopy.com differ diff --git a/build/bootstrap/zipobj.com b/build/bootstrap/zipobj.com index cd0086827..019751ea1 100755 Binary files a/build/bootstrap/zipobj.com and b/build/bootstrap/zipobj.com differ diff --git a/build/config.mk b/build/config.mk index 7bb0e35e7..3003b222d 100644 --- a/build/config.mk +++ b/build/config.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # Default Mode # diff --git a/build/definitions.mk b/build/definitions.mk index fa29c5094..8a023d2d9 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # # SYNOPSIS # @@ -53,91 +53,6 @@ # OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely) # -LC_ALL = C -SOURCE_DATE_EPOCH = 0 - -ARFLAGS = rcsD -ZFLAGS ?= -XARGS ?= xargs -P4 -rs8000 -DOT ?= dot -CLANG = clang -TMPDIR = o/tmp - -AR = build/bootstrap/ar.com -CP = build/bootstrap/cp.com -RM = build/bootstrap/rm.com -f -GZIP = build/bootstrap/gzip.com -ECHO = build/bootstrap/echo.com -CHMOD = build/bootstrap/chmod.com -TOUCH = build/bootstrap/touch.com -PKG = build/bootstrap/package.com -MKDEPS = build/bootstrap/mkdeps.com -ZIPOBJ = build/bootstrap/zipobj.com -ZIPCOPY = build/bootstrap/zipcopy.com -PECHECK = build/bootstrap/pecheck.com -FIXUPOBJ = build/bootstrap/fixupobj.com -MKDIR = build/bootstrap/mkdir.com -p -COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA) - -COMMA := , -PWD := $(shell build/bootstrap/pwd.com) - -IGNORE := $(shell $(MKDIR) $(TMPDIR)) - -ifneq ($(findstring aarch64,$(MODE)),) -ARCH = aarch64 -HOSTS ?= pi silicon -else -ARCH = x86_64 -HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd -endif - -ZIPOBJ_FLAGS += -a$(ARCH) - -ifeq ($(PREFIX),) -ifeq ($(USE_SYSTEM_TOOLCHAIN),) -ifeq ($(ARCH),x86_64) -ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") -PREFIX = o/third_party/gcc/bin/x86_64-linux-cosmo- -else -IGNORE := $(shell build/bootstrap/unbundle.com) -PREFIX = o/third_party/gcc/bin/x86_64-linux-musl- -endif -endif # ($(ARCH),x86_64)) -ifeq ($(ARCH),aarch64) -ifneq ("$(wildcard o/third_party/gcc/bin/aarch64-linux-cosmo-*)","") -PREFIX = o/third_party/gcc/bin/aarch64-linux-cosmo- -else -IGNORE := $(shell build/bootstrap/unbundle.com) -PREFIX = o/third_party/gcc/bin/aarch64-linux-musl- -endif -endif # ($(ARCH),aarch64) -endif # ($(USE_SYSTEM_TOOLCHAIN),) -endif # ($(PREFIX),) - -AS = $(PREFIX)as -CC = $(PREFIX)gcc -CXX = $(PREFIX)g++ -CXXFILT = $(PREFIX)c++filt -LD = $(PREFIX)ld.bfd -NM = $(PREFIX)nm -GCC = $(PREFIX)gcc -STRIP = $(PREFIX)strip -OBJCOPY = $(PREFIX)objcopy -OBJDUMP = $(PREFIX)objdump -ifneq ($(wildcard $(PWD)/$(PREFIX)addr2line),) -ADDR2LINE = $(PWD)/$(PREFIX)addr2line -else -ADDR2LINE = $(PREFIX)addr2line -endif - -export ADDR2LINE -export LC_ALL -export MKDIR -export MODE -export SOURCE_DATE_EPOCH -export TMPDIR - ifeq ($(LANDLOCKMAKE_VERSION),) TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp else diff --git a/build/download-cosmocc.sh b/build/download-cosmocc.sh new file mode 100755 index 000000000..13310a4e4 --- /dev/null +++ b/build/download-cosmocc.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# cosmocc downloader script +# https://justine.lol/cosmo3/#install +# https://github.com/jart/cosmopolitan/blob/master/tool/cosmocc/README.md + +# collect arguments +OUTPUT_DIR=${1:?OUTPUT_DIR} +COSMOCC_VERSION=${2:?COSMOCC_VERSION} +COSMOCC_SHA256SUM=${3:?COSMOCC_SHA256SUM} +URL1="https://github.com/jart/cosmopolitan/releases/download/${COSMOCC_VERSION}/cosmocc-${COSMOCC_VERSION}.zip" +URL2="https://cosmo.zip/pub/cosmocc/cosmocc-${COSMOCC_VERSION}.zip" + +# helper function +abort() { + printf '%s\n' "download terminated." >&2 + exit 1 +} + +# exit if already downloaded +# we need it because directory timestamps work wierdly +OUTPUT_DIR=${OUTPUT_DIR%/} +if [ -d "${OUTPUT_DIR}" ]; then + exit 0 +fi + +# find commands we need to securely download cosmocc +if ! UNZIP=$(command -v unzip 2>/dev/null); then + printf '%s\n' "$0: fatal error: you need the unzip command" >&2 + printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/unzip and put it on the system path" >&2 + abort +fi +if command -v sha256sum >/dev/null 2>&1; then + # can use system sha256sum + true +elif command -v shasum >/dev/null 2>&1; then + sha256sum() { + shasum -a 256 "$@" + } +else + if [ ! -f build/sha256sum.c ]; then + printf '%s\n' "$0: fatal error: you need to install sha256sum" >&2 + printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2 + abort + fi + if ! SHA256SUM=$(command -v "$PWD/o/build/sha256sum" 2>/dev/null); then + if ! CC=$(command -v "$CC" 2>/dev/null); then + if ! CC=$(command -v cc 2>/dev/null); then + if ! CC=$(command -v cosmocc 2>/dev/null); then + printf '%s\n' "$0: fatal error: you need to install either sha256sum, cc, or cosmocc" >&2 + printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2 + abort + fi + fi + fi + mkdir -p o/build || abort + SHA256SUM="$PWD/o/build/sha256sum" + printf '%s\n' "${CC} -w -O2 -o ${SHA256SUM} build/sha256sum.c" >&2 + "${CC}" -w -O2 -o "${SHA256SUM}.$$" build/sha256sum.c || abort + mv -f "${SHA256SUM}.$$" "${SHA256SUM}" || abort + fi + sha256sum() { + "${SHA256SUM}" "$@" + } +fi +if WGET=$(command -v wget 2>/dev/null); then + DOWNLOAD=$WGET + DOWNLOAD_ARGS=-O +elif CURL=$(command -v curl 2>/dev/null); then + DOWNLOAD=$CURL + DOWNLOAD_ARGS=-fLo +else + printf '%s\n' "$0: fatal error: you need to install either wget or curl" >&2 + printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/wget and put it on the system path" >&2 + abort +fi + +# create temporary output directory +OLDPWD=$PWD +OUTPUT_TMP="${OUTPUT_DIR}.tmp.$$/" +mkdir -p "${OUTPUT_TMP}" || abort +cd "${OUTPUT_TMP}" +die() { + cd "${OLDPWD}" + rm -rf "${OUTPUT_TMP}" + abort +} + +# download cosmocc toolchain +# multiple urls avoids outages and national firewalls +if ! "${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL1}"; then + rm -f cosmocc.zip + "${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL2}" || die +fi +printf '%s\n' "${COSMOCC_SHA256SUM} *cosmocc.zip" >cosmocc.zip.sha256sum +sha256sum -c cosmocc.zip.sha256sum || die +"${UNZIP}" cosmocc.zip || die +rm -f cosmocc.zip cosmocc.zip.sha256sum + +# commit output directory +cd "${OLDPWD}" || die +mv "${OUTPUT_TMP}" "${OUTPUT_DIR}" || die diff --git a/build/functions.mk b/build/functions.mk index d72556f06..e8af29a56 100644 --- a/build/functions.mk +++ b/build/functions.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # # SYNOPSIS # diff --git a/build/htags b/build/htags index a580edf29..698a4de2e 100755 --- a/build/htags +++ b/build/htags @@ -1,6 +1,6 @@ #!/bin/sh #-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐ -#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘ +#── vi: set et ft=sh ts=2 sts=2 fenc=utf-8 :vi ─────────────┘ # # OVERVIEW # @@ -66,7 +66,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@" # struct WorstSoftwareEver; set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@" -exec $TAGS \ +build/run $TAGS \ -e \ --langmap=c:.c.h \ --exclude=libc/nt/struct/imagefileheader.internal.h \ diff --git a/build/objdump b/build/objdump index 103269f7b..32a4e218a 100755 --- a/build/objdump +++ b/build/objdump @@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then fi find_objdump() { - if [ -x o/third_party/gcc/bin/$1-linux-cosmo-objdump ]; then - OBJDUMP=o/third_party/gcc/bin/$1-linux-cosmo-objdump - elif [ -x o/third_party/gcc/bin/$1-linux-musl-objdump ]; then - OBJDUMP=o/third_party/gcc/bin/$1-linux-musl-objdump - elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump" ]; then - OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump" - elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump" ]; then - OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump" + if [ -x .cosmocc/3.2/bin/$1-linux-cosmo-objdump ]; then + OBJDUMP=.cosmocc/3.2/bin/$1-linux-cosmo-objdump + elif [ -x .cosmocc/3.2/bin/$1-linux-musl-objdump ]; then + OBJDUMP=.cosmocc/3.2/bin/$1-linux-musl-objdump + elif [ -x "$COSMO/.cosmocc/3.2/bin/$1-linux-cosmo-objdump" ]; then + OBJDUMP="$COSMO/.cosmocc/3.2/bin/$1-linux-cosmo-objdump" + elif [ -x "$COSMO/.cosmocc/3.2/bin/$1-linux-musl-objdump" ]; then + OBJDUMP="$COSMO/.cosmocc/3.2/bin/$1-linux-musl-objdump" else echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2 exit 1 diff --git a/build/online.mk b/build/online.mk index ce84893b9..0d874e5e6 100644 --- a/build/online.mk +++ b/build/online.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # # SYNOPSIS # diff --git a/build/realify.sed b/build/realify.sed index 92a0f359d..b0ed376ca 100644 --- a/build/realify.sed +++ b/build/realify.sed @@ -1,5 +1,5 @@ #-*-mode:sed;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: et ft=sed ts=8 tw=8 fenc=utf-8 :vi─────────────────┘ +#── vi: et ft=sed ts=8 sw=8 fenc=utf-8 :vi ────────────────┘ # # SYNOPSIS # diff --git a/build/rules.mk b/build/rules.mk index e2a4c9f95..728df92fd 100644 --- a/build/rules.mk +++ b/build/rules.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ # # SYNOPSIS # @@ -40,6 +40,9 @@ o/$(MODE)/%.h: %.c o/$(MODE)/%.o: %.cc @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< +o/$(MODE)/%.o: %.cpp + @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< + o/$(MODE)/%.lds: %.lds @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $< diff --git a/build/run b/build/run index d1ada17a1..c7fc0c292 100755 --- a/build/run +++ b/build/run @@ -1,9 +1,8 @@ #!/bin/sh -if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then - if [ ! -f o/third_party/qemu/qemu-aarch64 ]; then - make -j8 o/third_party/qemu/qemu-aarch64 - fi - exec o/third_party/qemu/qemu-aarch64 "$@" +UNAMEM=$(uname -m) +UNAMES=$(uname -s) +if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then + exec ape "$@" else exec "$@" fi diff --git a/build/sha256sum.c b/build/sha256sum.c new file mode 100644 index 000000000..15aa45cf0 --- /dev/null +++ b/build/sha256sum.c @@ -0,0 +1,443 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// this file should not have dependencies, because everything will be +// re-downloaded if the o/tool/sha256sum artifact becomes invalidated + +#define PROG "sha256sum" +#define USAGE \ + "\ +Usage: " PROG " [-?hbctw] [PATH...]\n\ + -h help\n\ + -c check mode\n\ + -b binary mode\n\ + -t textual mode\n\ + -w warning mode\n" + +#define ROTR(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) +#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define EP0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define EP1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3)) +#define SIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10)) + +struct Sha256Ctx { + uint8_t data[64]; + uint32_t datalen; + uint64_t bitlen; + uint32_t state[8]; +}; + +static const uint32_t kSha256Tab[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, // + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, // + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, // + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, // + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, // + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, // + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, // + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, // + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, // + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, // + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, // + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, // + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, // + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, // + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, // + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, // +}; + +static bool g_warn; +static char g_mode; +static bool g_check; +static int g_mismatches; + +static void Sha256Transform(uint32_t state[8], const uint8_t data[64]) { + unsigned i; + uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64]; + for (i = 0; i < 16; ++i, data += 4) { + m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + } + for (; i < 64; ++i) { + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + } + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + for (i = 0; i < 64; ++i) { + t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i]; + t2 = EP0(a) + MAJ(a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; +} + +static void Sha256Init(struct Sha256Ctx *ctx) { + ctx->datalen = 0; + ctx->bitlen = 0; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; +} + +static void Sha256Update(struct Sha256Ctx *ctx, const uint8_t *data, + long size) { + long i; + for (i = 0; i < size; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == 64) { + Sha256Transform(ctx->state, ctx->data); + ctx->bitlen += 512; + ctx->datalen = 0; + } + } +} + +static void Sha256Final(struct Sha256Ctx *ctx, uint8_t *hash) { + long i; + i = ctx->datalen; + ctx->data[i++] = 0x80; + if (ctx->datalen < 56) { + memset(ctx->data + i, 0, 56 - i); + } else { + memset(ctx->data + i, 0, 64 - i); + Sha256Transform(ctx->state, ctx->data); + memset(ctx->data, 0, 56); + } + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + ctx->data[57] = ctx->bitlen >> 48; + ctx->data[56] = ctx->bitlen >> 56; + Sha256Transform(ctx->state, ctx->data); + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff; + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff; + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff; + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff; + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff; + } +} + +static char *FormatUint32(char *p, uint32_t x) { + char t; + size_t i, a, b; + i = 0; + do { + p[i++] = x % 10 + '0'; + x = x / 10; + } while (x > 0); + p[i] = '\0'; + if (i) { + for (a = 0, b = i - 1; a < b; ++a, --b) { + t = p[a]; + p[a] = p[b]; + p[b] = t; + } + } + return p + i; +} + +static char *FormatInt32(char *p, int32_t x) { + if (x < 0) *p++ = '-', x = -(uint32_t)x; + return FormatUint32(p, x); +} + +static size_t StrCat(char *dst, const char *src, size_t dsize) { + size_t m, n = dsize; + const char *p = dst; + const char *q = src; + while (n-- != 0 && *dst != '\0') dst++; + m = dst - p; + n = dsize - m; + if (n-- == 0) { + return m + strlen(src); + } + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; + return m + (src - q); +} + +static void GetOpts(int argc, char *argv[]) { + int opt; + g_mode = ' '; + while ((opt = getopt(argc, argv, "?hbctw")) != -1) { + switch (opt) { + case 'w': + g_warn = true; + break; + case 'c': + g_check = true; + break; + case 't': + g_mode = ' '; + break; + case 'b': + g_mode = '*'; + break; + case 'h': + case '?': + (void)write(1, USAGE, sizeof(USAGE) - 1); + exit(0); + default: + (void)write(2, USAGE, sizeof(USAGE) - 1); + exit(64); + } + } +} + +static void Write(int fd, const char *s, ...) { + va_list va; + char buf[512]; + buf[0] = 0; + va_start(va, s); + do { + StrCat(buf, s, sizeof(buf)); + } while ((s = va_arg(va, const char *))); + va_end(va); + (void)write(fd, buf, strlen(buf)); +} + +static bool IsModeCharacter(char c) { + switch (c) { + case ' ': + case '*': + return true; + default: + return false; + } +} + +static bool IsSupportedPath(const char *path) { + size_t i; + for (i = 0;; ++i) { + switch (path[i]) { + case 0: + if (i) return true; + // fallthrough + case '\r': + case '\n': + case '\\': + Write(2, PROG, ": ", path, ": unsupported path\n", NULL); + return false; + default: + break; + } + } +} + +static bool GetDigest(const char *path, FILE *f, uint8_t digest[32]) { + size_t got; + uint8_t buf[512]; + struct Sha256Ctx ctx; + Sha256Init(&ctx); + while ((got = fread(buf, 1, sizeof(buf), f))) { + Sha256Update(&ctx, buf, got); + } + if (ferror(f)) { + Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL); + return false; + } + Sha256Final(&ctx, digest); + return true; +} + +static char *CopyHex(char *s, const void *p, size_t n) { + const char *d, *e; + for (d = (const char *)p, e = d + n; d < e; ++d) { + *s++ = "0123456789abcdef"[(*d >> 4) & 15]; + *s++ = "0123456789abcdef"[(*d >> 0) & 15]; + } + *s = 0; + return s; +} + +static bool ProduceDigest(const char *path, FILE *f) { + char hexdigest[65]; + char mode[2] = {g_mode}; + unsigned char digest[32]; + if (!IsSupportedPath(path)) return false; + if (!GetDigest(path, f, digest)) return false; + CopyHex(hexdigest, digest, 32); + Write(1, hexdigest, " ", mode, path, "\n", NULL); + return true; +} + +static char *Chomp(char *line) { + size_t i; + if (line) { + for (i = strlen(line); i--;) { + if (line[i] == '\r' || line[i] == '\n') { + line[i] = '\0'; + } else { + break; + } + } + } + return line; +} + +static int HexToInt(int c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } else { + return -1; + } +} + +static bool CheckDigests(const char *path, FILE *f) { + FILE *f2; + bool k = true; + int a, b, i, line; + const char *path2, *status; + uint8_t wantdigest[32], gotdigest[32]; + char buf[64 + 2 + PATH_MAX + 1 + 1], *p; + for (line = 0; fgets(buf, sizeof(buf), f); ++line) { + if (!*Chomp(buf)) continue; + for (p = buf, i = 0; i < 32; ++i) { + if ((a = HexToInt(*p++ & 255)) == -1) goto InvalidLine; + if ((b = HexToInt(*p++ & 255)) == -1) goto InvalidLine; + wantdigest[i] = a << 4 | b; + } + if (*p++ != ' ') goto InvalidLine; + if (!IsModeCharacter(*p++)) goto InvalidLine; + path2 = p; + if (!*path2) goto InvalidLine; + if (!IsSupportedPath(path2)) continue; + if ((f2 = fopen(path2, "rb"))) { + if (GetDigest(path2, f2, gotdigest)) { + if (!memcmp(wantdigest, gotdigest, 32)) { + status = "OK"; + } else { + status = "FAILED"; + ++g_mismatches; + k = false; + } + Write(1, path2, ": ", status, "\n", NULL); + } else { + k = false; + } + fclose(f2); + } else { + Write(2, PROG, ": ", path2, ": ", strerror(errno), "\n", NULL); + k = false; + } + continue; + InvalidLine: + if (g_warn) { + char linestr[12]; + FormatInt32(linestr, line + 1); + Write(2, PROG, ": ", path, ":", linestr, ": ", + "improperly formatted checksum line", "\n", NULL); + } + } + if (ferror(f)) { + Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL); + k = false; + } + return k; +} + +static bool Process(const char *path, FILE *f) { + if (g_check) { + return CheckDigests(path, f); + } else { + return ProduceDigest(path, f); + } +} + +int main(int argc, char *argv[]) { + int i; + FILE *f; + bool k = true; + GetOpts(argc, argv); + if (optind == argc) { + f = stdin; + k &= Process("-", f); + } else { + for (i = optind; i < argc; ++i) { + if ((f = fopen(argv[i], "rb"))) { + k &= Process(argv[i], f); + fclose(f); + } else { + Write(2, PROG, ": ", argv[i], ": ", strerror(errno), "\n", NULL); + k = false; + } + } + } + if (g_mismatches) { + char ibuf[12]; + FormatInt32(ibuf, g_mismatches); + Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n", + NULL); + } + return !k; +} diff --git a/dsp/BUILD.mk b/dsp/BUILD.mk index a59765881..87e655809 100644 --- a/dsp/BUILD.mk +++ b/dsp/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ .PHONY: o/$(MODE)/dsp o/$(MODE)/dsp: o/$(MODE)/dsp/core \ diff --git a/dsp/bmp/bmp.mk b/dsp/bmp/bmp.mk index 7f9c19158..efb38128c 100644 --- a/dsp/bmp/bmp.mk +++ b/dsp/bmp/bmp.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘ PKGS += DSP_BMP diff --git a/dsp/core/BUILD.mk b/dsp/core/BUILD.mk index 4536dcb66..46e95ef71 100644 --- a/dsp/core/BUILD.mk +++ b/dsp/core/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += DSP_CORE diff --git a/dsp/core/core.h b/dsp/core/core.h index 714f3a392..eadf040f9 100644 --- a/dsp/core/core.h +++ b/dsp/core/core.h @@ -9,8 +9,9 @@ int mulaw(int); int unmulaw(int); void *double2byte(long, const void *, double, double) vallocesque; void *byte2double(long, const void *, double, double) vallocesque; -void *dct(float[8][8], float, float, float, float, float); -void *dctjpeg(float[8][8]); +void *dct(float[restrict hasatleast 8][8], unsigned, + float, float, float, float, float); +void *dctjpeg(float[restrict hasatleast 8][8], unsigned); double det3(const double[3][3]) nosideeffect; void *inv3(double[restrict 3][3], const double[restrict 3][3], double); void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]); diff --git a/dsp/core/dct.c b/dsp/core/dct.c index 506c96f86..cae19d596 100644 --- a/dsp/core/dct.c +++ b/dsp/core/dct.c @@ -18,40 +18,40 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "dsp/core/core.h" -#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \ - do { \ - T z1, z2, z3, z4, z5, z11, z13; \ - T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \ - t0 = A + H; \ - t7 = A - H; \ - t1 = B + G; \ - t6 = B - G; \ - t2 = C + F; \ - t5 = C - F; \ - t3 = D + E; \ - t4 = D - E; \ - t10 = t0 + t3; \ - t13 = t0 - t3; \ - t11 = t1 + t2; \ - t12 = t1 - t2; \ - A = t10 + t11; \ - E = t10 - t11; \ - z1 = (t12 + t13) * C0; \ - C = t13 + z1; \ - G = t13 - z1; \ - t10 = t4 + t5; \ - t11 = t5 + t6; \ - t12 = t6 + t7; \ - z5 = (t10 - t12) * C1; \ - z2 = t10 * C2 + z5; \ - z4 = t12 * C3 + z5; \ - z3 = t11 * C4; \ - z11 = t7 + z3; \ - z13 = t7 - z3; \ - F = z13 + z2; \ - D = z13 - z2; \ - B = z11 + z4; \ - H = z11 - z4; \ +#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \ + do { \ + T z1, z2, z3, z4, z5, z11, z13; \ + T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \ + t0 = A + H; \ + t7 = A - H; \ + t1 = B + G; \ + t6 = B - G; \ + t2 = C + F; \ + t5 = C - F; \ + t3 = D + E; \ + t4 = D - E; \ + t10 = t0 + t3; \ + t13 = t0 - t3; \ + t11 = t1 + t2; \ + t12 = t1 - t2; \ + A = t10 + t11; \ + E = t10 - t11; \ + z1 = (t12 + t13) * C0; \ + C = t13 + z1; \ + G = t13 - z1; \ + t10 = t4 + t5; \ + t11 = t5 + t6; \ + t12 = t6 + t7; \ + z5 = (t10 - t12) * C1; \ + z2 = t10 * C2 + z5; \ + z4 = t12 * C3 + z5; \ + z3 = t11 * C4; \ + z11 = t7 + z3; \ + z13 = t7 - z3; \ + F = z13 + z2; \ + D = z13 - z2; \ + B = z11 + z4; \ + H = z11 - z4; \ } while (0) /** @@ -65,20 +65,21 @@ * * @cost ~100ns */ -void *dct(float M[8][8], float c0, float c1, float c2, float c3, float c4) { +void *dct(float M[restrict hasatleast 8][8], unsigned stride, + float c0, float c1, float c2, float c3, float c4) { unsigned y, x; - for (y = 0; y < 8; ++y) { + for (y = 0; y < stride * 8; y += stride) { DCT(M[y][0], M[y][1], M[y][2], M[y][3], M[y][4], M[y][5], M[y][6], M[y][7], float, c0, c1, c2, c3, c4); } - for (x = 0; x < 8; ++x) { + for (x = 0; x < stride * 8; x += stride) { DCT(M[0][x], M[1][x], M[2][x], M[3][x], M[4][x], M[5][x], M[6][x], M[7][x], float, c0, c1, c2, c3, c4); } return M; } -void *dctjpeg(float M[8][8]) { - return dct(M, .707106781f, .382683433f, .541196100f, 1.306562965f, +void *dctjpeg(float M[restrict hasatleast 8][8], unsigned stride) { + return dct(M, stride, .707106781f, .382683433f, .541196100f, 1.306562965f, .707106781f); } diff --git a/dsp/mpeg/BUILD.mk b/dsp/mpeg/BUILD.mk index 17936a216..147bffc47 100644 --- a/dsp/mpeg/BUILD.mk +++ b/dsp/mpeg/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += DSP_MPEG diff --git a/dsp/mpeg/buffer.h b/dsp/mpeg/buffer.h index 5fefc72b5..5ab5faaa6 100644 --- a/dsp/mpeg/buffer.h +++ b/dsp/mpeg/buffer.h @@ -3,8 +3,6 @@ #include "dsp/mpeg/mpeg.h" COSMOPOLITAN_C_START_ -struct FILE; - enum plm_buffer_mode { PLM_BUFFER_MODE_FILE, PLM_BUFFER_MODE_FIXED_MEM, @@ -17,7 +15,7 @@ typedef struct plm_buffer_t { unsigned length; int free_when_done; int close_when_done; - struct FILE *fh; + FILE *fh; plm_buffer_load_callback load_callback; void *load_callback_user_data; unsigned char *bytes; diff --git a/dsp/mpeg/clamp4int256-core.S b/dsp/mpeg/clamp4int256-core.S index f395b8b66..3cd6797b1 100644 --- a/dsp/mpeg/clamp4int256-core.S +++ b/dsp/mpeg/clamp4int256-core.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/dsp/mpeg/idct.c b/dsp/mpeg/idct.c index 06645d8e1..87c17ae6a 100644 --- a/dsp/mpeg/idct.c +++ b/dsp/mpeg/idct.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi │ +│ vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer │ │ Dominic Szablewski - https://phoboslab.org │ diff --git a/dsp/mpeg/macroblock.c b/dsp/mpeg/macroblock.c index c94c3994b..10dee49ee 100644 --- a/dsp/mpeg/macroblock.c +++ b/dsp/mpeg/macroblock.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi │ +│ vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer │ │ Dominic Szablewski - https://phoboslab.org │ diff --git a/dsp/mpeg/mpeg.h b/dsp/mpeg/mpeg.h index b96c622b9..f49ed953b 100644 --- a/dsp/mpeg/mpeg.h +++ b/dsp/mpeg/mpeg.h @@ -1,9 +1,8 @@ #ifndef COSMOPOLITAN_DSP_MPEG_MPEG_H_ #define COSMOPOLITAN_DSP_MPEG_MPEG_H_ +#include "libc/stdio/stdio.h" COSMOPOLITAN_C_START_ -struct FILE; - typedef struct plm_t plm_t; typedef struct plm_buffer_t plm_buffer_t; typedef struct plm_demux_t plm_demux_t; @@ -112,7 +111,7 @@ plm_t *plm_create_with_filename(const char *filename); * to let plmpeg call fclose() on the handle when plm_destroy() is * called. */ -plm_t *plm_create_with_file(struct FILE *fh, int close_when_done); +plm_t *plm_create_with_file(FILE *fh, int close_when_done); /** * Create a plmpeg instance with pointer to memory as source. This assumes the @@ -257,7 +256,7 @@ plm_buffer_t *plm_buffer_create_with_filename(const char *filename); * to let plmpeg call fclose() on the handle when plm_destroy() is * called. */ -plm_buffer_t *plm_buffer_create_with_file(struct FILE *fh, int close_when_done); +plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done); /** * Create a buffer instance with a pointer to memory as source. This assumes diff --git a/dsp/mpeg/mpeg1.c b/dsp/mpeg/mpeg1.c index 873b5ab6d..f9c29910b 100644 --- a/dsp/mpeg/mpeg1.c +++ b/dsp/mpeg/mpeg1.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi │ +│ vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer │ │ Dominic Szablewski - https://phoboslab.org │ diff --git a/dsp/mpeg/slowrgb.c b/dsp/mpeg/slowrgb.c index 73b1881cd..16c819c38 100644 --- a/dsp/mpeg/slowrgb.c +++ b/dsp/mpeg/slowrgb.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=4 sw=4 fenc=utf-8 :vi │ +│ vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer │ │ Dominic Szablewski - https://phoboslab.org │ diff --git a/dsp/scale/BUILD.mk b/dsp/scale/BUILD.mk index be6ca2e1d..79c25a534 100644 --- a/dsp/scale/BUILD.mk +++ b/dsp/scale/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += DSP_SCALE diff --git a/dsp/scale/gyarados.c b/dsp/scale/gyarados.c index 19089ce8a..464ce2959 100644 --- a/dsp/scale/gyarados.c +++ b/dsp/scale/gyarados.c @@ -27,7 +27,7 @@ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/math.h" -#include "libc/mem/gc.internal.h" +#include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/str/str.h" #include "libc/testlib/testlib.h" diff --git a/dsp/tty/BUILD.mk b/dsp/tty/BUILD.mk index bf5bd289c..c87dcb028 100644 --- a/dsp/tty/BUILD.mk +++ b/dsp/tty/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += DSP_TTY diff --git a/dsp/tty/mpsadbw.S b/dsp/tty/mpsadbw.S index 1ff43b902..833824ea4 100644 --- a/dsp/tty/mpsadbw.S +++ b/dsp/tty/mpsadbw.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/dsp/tty/sendtitle.c b/dsp/tty/sendtitle.c index ca2567c27..ec4860ebb 100644 --- a/dsp/tty/sendtitle.c +++ b/dsp/tty/sendtitle.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "dsp/tty/tty.h" #include "libc/mem/arraylist2.internal.h" -#include "libc/mem/gc.internal.h" +#include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/x/x.h" diff --git a/dsp/tty/tty.h b/dsp/tty/tty.h index 99ca8f00e..2b4e8f46e 100644 --- a/dsp/tty/tty.h +++ b/dsp/tty/tty.h @@ -5,7 +5,6 @@ COSMOPOLITAN_C_START_ -struct FILE; struct termios; struct TtyIdent { diff --git a/dsp/tty/ttyraw.c b/dsp/tty/ttyraw.c index ec2f794c0..60ebeea8d 100644 --- a/dsp/tty/ttyraw.c +++ b/dsp/tty/ttyraw.c @@ -25,7 +25,7 @@ #include "libc/calls/ucontext.h" #include "libc/log/log.h" #include "libc/macros.internal.h" -#include "libc/mem/gc.internal.h" +#include "libc/mem/gc.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/fileno.h" diff --git a/dsp/tty/windex-avx2.S b/dsp/tty/windex-avx2.S index 650da112d..4ebf2931e 100644 --- a/dsp/tty/windex-avx2.S +++ b/dsp/tty/windex-avx2.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/dsp/tty/windex-sse4.S b/dsp/tty/windex-sse4.S index 291b7b1cc..0347cb763 100644 --- a/dsp/tty/windex-sse4.S +++ b/dsp/tty/windex-sse4.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/examples/BUILD.mk b/examples/BUILD.mk index 324479219..e69b297b0 100644 --- a/examples/BUILD.mk +++ b/examples/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += EXAMPLES @@ -44,7 +44,6 @@ EXAMPLES_DIRECTDEPS = \ DSP_TTY \ LIBC_CALLS \ LIBC_DLOPEN \ - LIBC_DNS \ LIBC_FMT \ LIBC_INTRIN \ LIBC_IRQ \ @@ -86,7 +85,6 @@ EXAMPLES_DIRECTDEPS = \ THIRD_PARTY_MUSL \ THIRD_PARTY_NSYNC \ THIRD_PARTY_NSYNC_MEM \ - THIRD_PARTY_QUICKJS \ THIRD_PARTY_SED \ THIRD_PARTY_STB \ THIRD_PARTY_TR \ @@ -154,7 +152,6 @@ o/$(MODE)/examples/picol.com.dbg: \ $(APE_NO_MODIFY_SELF) @$(APELINK) -o/$(MODE)/examples/nesemu1.o: private QUOTA += -M512m o/$(MODE)/usr/share/dict/words.zip.o: private ZIPOBJ_FLAGS += -C2 $(EXAMPLES_OBJS): examples/BUILD.mk diff --git a/examples/crashreport2.cc b/examples/crashreport2.cc new file mode 100644 index 000000000..06bb92548 --- /dev/null +++ b/examples/crashreport2.cc @@ -0,0 +1,23 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/math.h" +#include "libc/runtime/runtime.h" + +void crash(long x0, long x1, long x2, // + double v0, double v1, double v2) { + __builtin_trap(); +} + +void (*pCrash)(long, long, long, double, double, double) = crash; + +int main(int argc, char *argv[]) { + ShowCrashReports(); + pCrash(1, 2, 3, NAN, NAN, NAN); +} diff --git a/examples/env.c b/examples/env.c index 7fc971663..f3395ab36 100644 --- a/examples/env.c +++ b/examples/env.c @@ -2,9 +2,9 @@ #include "libc/runtime/runtime.h" int main(int argc, char* argv[]) { - printf("%s\n", argv[0]); + fprintf(stderr, "%s (%s)\n", argv[0], GetProgramExecutableName()); for (char **p = environ; *p; ++p) { - printf(" %s\n", *p); + printf("%s\n", *p); } return 0; } diff --git a/examples/greenbean.c b/examples/greenbean.c index 4bf386459..166b6e532 100644 --- a/examples/greenbean.c +++ b/examples/greenbean.c @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) { // print all the ips that 0.0.0.0 would bind // Cosmo's GetHostIps() API is much easier than ioctl(SIOCGIFCONF) uint32_t *hostips; - for (hostips = _gc(GetHostIps()), i = 0; hostips[i]; ++i) { + for (hostips = gc(GetHostIps()), i = 0; hostips[i]; ++i) { kprintf("listening on http://%hhu.%hhu.%hhu.%hhu:%hu\n", hostips[i] >> 24, hostips[i] >> 16, hostips[i] >> 8, hostips[i], PORT); } @@ -339,7 +339,7 @@ int main(int argc, char *argv[]) { unassert(!pthread_attr_setguardsize(&attr, pagesz)); unassert(!pthread_attr_setsigmask_np(&attr, &block)); unassert(!pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0)); - pthread_t *th = _gc(calloc(threads, sizeof(pthread_t))); + pthread_t *th = gc(calloc(threads, sizeof(pthread_t))); for (i = 0; i < threads; ++i) { int rc; ++a_workers; diff --git a/examples/ls.c b/examples/ls.c index c91f8c81f..7d8e509f1 100644 --- a/examples/ls.c +++ b/examples/ls.c @@ -50,7 +50,7 @@ void List(const char *path) { if (strcmp(path, ".") == 0) { vpath = ""; } else if (!endswith(path, "/")) { - vpath = _gc(xasprintf("%s/", path)); + vpath = gc(xasprintf("%s/", path)); } else { vpath = path; } diff --git a/examples/nc.c b/examples/nc.c index f484013bb..3e29a51d2 100644 --- a/examples/nc.c +++ b/examples/nc.c @@ -8,7 +8,6 @@ ╚─────────────────────────────────────────────────────────────────*/ #endif #include "libc/calls/calls.h" -#include "libc/dns/dns.h" #include "libc/fmt/conv.h" #include "libc/log/log.h" #include "libc/macros.internal.h" @@ -26,6 +25,7 @@ #include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sol.h" #include "third_party/getopt/getopt.internal.h" +#include "third_party/musl/netdb.h" /** * @fileoverview netcat clone @@ -60,9 +60,7 @@ int main(int argc, char *argv[]) { halfclose = false; break; case 'h': - fputs("Usage: ", stdout); - fputs(argv[0], stdout); - fputs(" [-hH] IP PORT\n", stdout); + tinyprint(1, "Usage: ", argv[0], " [-hH] IP PORT\n", NULL); exit(0); default: fprintf(stderr, "bad option %d\n", opt); @@ -76,17 +74,9 @@ int main(int argc, char *argv[]) { host = argv[optind + 0]; port = argv[optind + 1]; - switch ((rc = getaddrinfo(host, port, &hint, &ai))) { - case EAI_SUCCESS: - break; - case EAI_SYSTEM: - perror("getaddrinfo"); - exit(1); - default: - fputs("EAI_", stderr); - fputs(gai_strerror(rc), stderr); - fputs("\n", stderr); - exit(1); + if ((rc = getaddrinfo(host, port, &hint, &ai))) { + tinyprint(2, host, ": ", gai_strerror(rc), "\n", NULL); + exit(1); } if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) { @@ -95,12 +85,12 @@ int main(int argc, char *argv[]) { } if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) { - perror("setsockopt(SO_LINGER)"); + perror("SO_LINGER"); exit(1); } if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { - perror("connect"); + perror(host); exit(1); } diff --git a/examples/package/BUILD.mk b/examples/package/BUILD.mk index c4962df05..959b68469 100644 --- a/examples/package/BUILD.mk +++ b/examples/package/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/examples/package/lib/BUILD.mk b/examples/package/lib/BUILD.mk index 6472989ac..3fdbe344d 100644 --- a/examples/package/lib/BUILD.mk +++ b/examples/package/lib/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/examples/pyapp/BUILD.mk b/examples/pyapp/BUILD.mk index f565bd946..2207b2945 100644 --- a/examples/pyapp/BUILD.mk +++ b/examples/pyapp/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/examples/pylife/BUILD.mk b/examples/pylife/BUILD.mk index 83c01a650..4152b7890 100644 --- a/examples/pylife/BUILD.mk +++ b/examples/pylife/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/examples/script.c b/examples/script.c index a5d7a828e..3ea419caa 100644 --- a/examples/script.c +++ b/examples/script.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright (c) 2010, 2012 David E. O'Brien │ │ Copyright (c) 1980, 1992, 1993 │ diff --git a/examples/stat.c b/examples/stat.c index 987020ca0..f04025d98 100644 --- a/examples/stat.c +++ b/examples/stat.c @@ -80,10 +80,10 @@ void PrintFileMetadata(const char *pathname, struct stat *st) { DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id", st->st_gid, "flags", st->st_flags, "gen", st->st_gen, "device id (if special)", st->st_rdev, "block size", st->st_blksize, - "access time", _gc(xiso8601(&st->st_atim)), "modified time", - _gc(xiso8601(&st->st_mtim)), "c[omplicated]time", - _gc(xiso8601(&st->st_ctim)), "birthtime", - _gc(xiso8601(&st->st_birthtim))); + "access time", gc(xiso8601(&st->st_atim)), "modified time", + gc(xiso8601(&st->st_mtim)), "c[omplicated]time", + gc(xiso8601(&st->st_ctim)), "birthtime", + gc(xiso8601(&st->st_birthtim))); } int main(int argc, char *argv[]) { diff --git a/examples/unbourne.c b/examples/unbourne.c index c06a28ddb..6ad057a43 100644 --- a/examples/unbourne.c +++ b/examples/unbourne.c @@ -128,7 +128,7 @@ #include "libc/macros.internal.h" #include "libc/mem/alg.h" #include "libc/mem/alloca.h" -#include "libc/mem/gc.internal.h" +#include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/paths.h" #include "libc/runtime/runtime.h" @@ -157,14 +157,14 @@ /* * The follow should be set to reflect the type of system you have: - * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * SHORTNAMES -> 1 if your linker cannot handle long names. - * define BSD if you are running 4.2 BSD or later. - * define SYSV if you are running under System V. - * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) - * define DEBUG=2 to compile in and turn on debugging. - * define DO_SHAREDVFORK to indicate that vfork(2) shares its address - * with its parent. + * JOBS -> 1 if you have Berkeley job control, 0 otherwise. + * SHORTNAMES -> 1 if your linker cannot handle long names. + * define BSD if you are running 4.2 BSD or later. + * define SYSV if you are running under System V. + * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) + * define DEBUG=2 to compile in and turn on debugging. + * define DO_SHAREDVFORK to indicate that vfork(2) shares its address + * with its parent. * * When debugging is on, debugging info will be written to ./trace and * a quit signal will generate a core dump. @@ -6604,10 +6604,10 @@ static struct job *growjobtab(void) { * own process group. Jp is a job structure that the job is to be added to. * N is the command that will be evaluated by the child. Both jp and n may * be NULL. The mode parameter can be one of the following: - * FORK_FG - Fork off a foreground process. - * FORK_BG - Fork off a background process. - * FORK_NOJOB - Like FORK_FG, but don't give the process its own - * process group even if job control is on. + * FORK_FG - Fork off a foreground process. + * FORK_BG - Fork off a background process. + * FORK_NOJOB - Like FORK_FG, but don't give the process its own + * process group even if job control is on. * * When job control is turned off, background processes have their standard * input redirected to /dev/null (except for the second and later processes @@ -8403,10 +8403,10 @@ static void nlnoprompt(void) { /* * Read the next input token. * If the token is a word, we set backquotelist to the list of cmds in - * backquotes. We set quoteflag to true if any part of the word was - * quoted. + * backquotes. We set quoteflag to true if any part of the word was + * quoted. * If the token is TREDIR, then we set redirnode to a structure containing - * the redirection. + * the redirection. * * [Change comment: here documents and internal procedures] * [Readtoken shouldn't have any arguments. Perhaps we should make the @@ -9767,7 +9767,7 @@ out: /* * Print SysV echo(1) style escape string - * Halts processing string if a \c escape is encountered. + * Halts processing string if a \c escape is encountered. */ static int conv_escape_str(char *str, char **sp) { int c; @@ -9941,10 +9941,10 @@ static int echocmd(int argc, char **argv) { */ /* test(1) accepts the following grammar: - oexpr ::= aexpr | aexpr "-o" oexpr ; - aexpr ::= nexpr | nexpr "-a" aexpr ; - nexpr ::= primary | "!" primary - primary ::= unary-operator operand + oexpr ::= aexpr | aexpr "-o" oexpr ; + aexpr ::= nexpr | nexpr "-a" aexpr ; + nexpr ::= primary | "!" primary + primary ::= unary-operator operand | operand binary-operator operand | operand | "(" oexpr ")" diff --git a/examples/whois.c b/examples/whois.c index 1d55d230c..bae2bc359 100644 --- a/examples/whois.c +++ b/examples/whois.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright (c) 1980, 1993 │ │ The Regents of the University of California. All rights reserved. │ @@ -30,12 +30,13 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/weirdtypes.h" -#include "libc/dns/dns.h" #include "libc/errno.h" #include "libc/log/bsd.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" +#include "libc/sock/sock.h" #include "libc/sock/struct/pollfd.h" +#include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/sysv/consts/af.h" #include "libc/sysv/consts/ex.h" @@ -44,6 +45,7 @@ #include "libc/sysv/consts/poll.h" #include "libc/sysv/consts/sock.h" #include "third_party/getopt/getopt.internal.h" +#include "third_party/musl/netdb.h" // clang-format off asm(".ident\t\"\\n\\n\ diff --git a/libc/BUILD.mk b/libc/BUILD.mk index ffb365592..caff0ca1a 100644 --- a/libc/BUILD.mk +++ b/libc/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += LIBC @@ -142,6 +142,9 @@ libc/isystem/nsync_once.h \ libc/isystem/nsync_time.h \ libc/isystem/nsync_waiter.h \ libc/isystem/numeric \ +libc/isystem/omp-tools.h \ +libc/isystem/omp.h \ +libc/isystem/ompx.h \ libc/isystem/optional \ libc/isystem/ostream \ libc/isystem/paths.h \ @@ -164,6 +167,7 @@ libc/isystem/semaphore.h \ libc/isystem/set \ libc/isystem/setjmp.h \ libc/isystem/sgxintrin.h \ +libc/isystem/shadow.h \ libc/isystem/shared_mutex \ libc/isystem/signal.h \ libc/isystem/smmintrin.h \ @@ -250,6 +254,7 @@ libc/isystem/uio.h \ libc/isystem/unistd.h \ libc/isystem/unordered_map \ libc/isystem/unordered_set \ +libc/isystem/unwind.h \ libc/isystem/utility \ libc/isystem/utime.h \ libc/isystem/utmp.h \ @@ -272,11 +277,12 @@ LIBC_INCS = $(filter %.inc,$(LIBC_FILES)) LIBC_CHECKS = $(LIBC_HDRS_H:%=o/$(MODE)/%.ok) LIBC_FILES := $(wildcard libc/*) +o/$(MODE)/libc/isystem/ompx.h.ok: private CPPFLAGS += -Wno-unknown-pragmas + .PHONY: o/$(MODE)/libc o/$(MODE)/libc: o/$(MODE)/libc/calls \ o/$(MODE)/libc/crt \ o/$(MODE)/libc/dlopen \ - o/$(MODE)/libc/dns \ o/$(MODE)/libc/elf \ o/$(MODE)/libc/fmt \ o/$(MODE)/libc/intrin \ diff --git a/libc/assert.h b/libc/assert.h index 5ee54351d..6d011f0c6 100644 --- a/libc/assert.h +++ b/libc/assert.h @@ -14,8 +14,8 @@ #define _ASSERT_H COSMOPOLITAN_C_START_ -void __assert_fail(const char *, const char *, int); -void unassert(const char *, const char *, int); +void __assert_fail(const char *, const char *, int) libcesque; +void unassert(const char *, const char *, int) libcesque; #ifdef NDEBUG #define assert(x) ((void)0) diff --git a/libc/calls/BUILD.mk b/libc/calls/BUILD.mk index 63059144b..bbf134fc4 100644 --- a/libc/calls/BUILD.mk +++ b/libc/calls/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/libc/calls/calls.h b/libc/calls/calls.h index 01dfac77d..44811fe1d 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -72,184 +72,184 @@ COSMOPOLITAN_C_START_ typedef int sig_atomic_t; -bool32 isatty(int); -char *getcwd(char *, size_t); -char *realpath(const char *, char *) __wur; -char *ttyname(int); -int access(const char *, int) dontthrow; -int chdir(const char *); -int chmod(const char *, unsigned); -int chown(const char *, unsigned, unsigned); -int chroot(const char *); -int close(int); -int close_range(unsigned, unsigned, unsigned); -int closefrom(int); -int creat(const char *, unsigned); -int dup(int); -int dup2(int, int); -int dup3(int, int, int); -int execl(const char *, const char *, ...) nullterminated(); -int execle(const char *, const char *, ...) nullterminated((1)); -int execlp(const char *, const char *, ...) nullterminated(); -int execv(const char *, char *const[]); -int execve(const char *, char *const[], char *const[]); -int execvp(const char *, char *const[]); -int faccessat(int, const char *, int, int); -int fchdir(int); -int fchmod(int, unsigned) dontthrow; -int fchmodat(int, const char *, unsigned, int); -int fchown(int, unsigned, unsigned); -int fchownat(int, const char *, unsigned, unsigned, int); -int fcntl(int, int, ...); -int fdatasync(int); -int fexecve(int, char *const[], char *const[]); -int flock(int, int); -int fork(void); -int fsync(int); -int ftruncate(int, int64_t); -int getdomainname(char *, size_t); -int getgroups(int, unsigned[]); -int gethostname(char *, size_t); -int getloadavg(double *, int); +bool32 isatty(int) libcesque; +char *getcwd(char *, size_t) dontthrow; +char *realpath(const char *, char *) libcesque __wur; +char *ttyname(int) libcesque; +int access(const char *, int) libcesque; +int chdir(const char *) libcesque; +int chmod(const char *, unsigned) libcesque; +int chown(const char *, unsigned, unsigned) libcesque; +int chroot(const char *) libcesque; +int close(int) libcesque; +int close_range(unsigned, unsigned, unsigned) libcesque; +int closefrom(int) libcesque; +int creat(const char *, unsigned) libcesque; +int dup(int) libcesque; +int dup2(int, int) libcesque; +int dup3(int, int, int) libcesque; +int execl(const char *, const char *, ...) nullterminated() libcesque; +int execle(const char *, const char *, ...) nullterminated((1)) libcesque; +int execlp(const char *, const char *, ...) nullterminated() libcesque; +int execv(const char *, char *const[]) libcesque; +int execve(const char *, char *const[], char *const[]) libcesque; +int execvp(const char *, char *const[]) libcesque; +int faccessat(int, const char *, int, int) libcesque; +int fchdir(int) libcesque; +int fchmod(int, unsigned) libcesque; +int fchmodat(int, const char *, unsigned, int) libcesque; +int fchown(int, unsigned, unsigned) libcesque; +int fchownat(int, const char *, unsigned, unsigned, int) libcesque; +int fcntl(int, int, ...) libcesque; +int fdatasync(int) libcesque; +int fexecve(int, char *const[], char *const[]) libcesque; +int flock(int, int) libcesque; +int fork(void) libcesque; +int fsync(int) libcesque; +int ftruncate(int, int64_t) libcesque; +int getdomainname(char *, size_t) libcesque; +int getgroups(int, unsigned[]) libcesque; +int gethostname(char *, size_t) libcesque; +int getloadavg(double *, int) libcesque; int getpgid(int) libcesque; -int getpgrp(void) nosideeffect; -int getpid(void) nosideeffect libcesque; -int getppid(void); -int getpriority(int, unsigned); +int getpgrp(void) libcesque nosideeffect; +int getpid(void) libcesque nosideeffect; +int getppid(void) libcesque; +int getpriority(int, unsigned) libcesque; int getsid(int) nosideeffect libcesque; -int ioctl(int, unsigned long, ...); -int issetugid(void); -int kill(int, int); -int killpg(int, int); -int lchmod(const char *, unsigned); -int lchown(const char *, unsigned, unsigned); -int link(const char *, const char *) dontthrow; -int linkat(int, const char *, int, const char *, int); -int mincore(void *, size_t, unsigned char *); -int mkdir(const char *, unsigned); -int mkdirat(int, const char *, unsigned); -int mknod(const char *, unsigned, uint64_t); -int nice(int); -int open(const char *, int, ...); -int openat(int, const char *, int, ...); -int pause(void); -int pipe(int[hasatleast 2]); -int pipe2(int[hasatleast 2], int); -int posix_fadvise(int, int64_t, int64_t, int); -int posix_madvise(void *, uint64_t, int); -int raise(int); -int reboot(int); -int remove(const char *); -int rename(const char *, const char *); -int renameat(int, const char *, int, const char *); -int rmdir(const char *); -int sched_yield(void); -int setegid(unsigned); -int seteuid(unsigned); -int setfsgid(unsigned); -int setfsuid(unsigned); -int setgid(unsigned); -int setgroups(size_t, const unsigned[]); -int setpgid(int, int); -int setpgrp(void); -int setpriority(int, unsigned, int); -int setregid(unsigned, unsigned); -int setreuid(unsigned, unsigned); -int setsid(void); -int setuid(unsigned); -int shm_open(const char *, int, unsigned); -int shm_unlink(const char *); -int sigignore(int); -int siginterrupt(int, int); -int symlink(const char *, const char *); -int symlinkat(const char *, int, const char *); -int tcgetpgrp(int); -int tcsetpgrp(int, int); -int truncate(const char *, int64_t); -int ttyname_r(int, char *, size_t); -int unlink(const char *); -int unlinkat(int, const char *, int); -int usleep(uint64_t); -int vfork(void) returnstwice; -int wait(int *); -int waitpid(int, int *, int); -int64_t clock(void); -int64_t time(int64_t *); -ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned); -ssize_t lseek(int, int64_t, int); -ssize_t pread(int, void *, size_t, int64_t); -ssize_t pwrite(int, const void *, size_t, int64_t); -ssize_t read(int, void *, size_t); -ssize_t readlink(const char *, char *, size_t); -ssize_t readlinkat(int, const char *, char *, size_t); -ssize_t write(int, const void *, size_t); -unsigned alarm(unsigned); -unsigned getegid(void) nosideeffect; -unsigned geteuid(void) nosideeffect; -unsigned getgid(void) nosideeffect; +int ioctl(int, unsigned long, ...) libcesque; +int issetugid(void) libcesque; +int kill(int, int) libcesque; +int killpg(int, int) libcesque; +int lchmod(const char *, unsigned) libcesque; +int lchown(const char *, unsigned, unsigned) libcesque; +int link(const char *, const char *) libcesque; +int linkat(int, const char *, int, const char *, int) libcesque; +int mincore(void *, size_t, unsigned char *) libcesque; +int mkdir(const char *, unsigned) libcesque; +int mkdirat(int, const char *, unsigned) libcesque; +int mknod(const char *, unsigned, uint64_t) libcesque; +int nice(int) libcesque; +int open(const char *, int, ...) libcesque; +int openat(int, const char *, int, ...) libcesque; +int pause(void) libcesque; +int pipe(int[hasatleast 2]) libcesque; +int pipe2(int[hasatleast 2], int) libcesque; +int posix_fadvise(int, int64_t, int64_t, int) libcesque; +int posix_madvise(void *, uint64_t, int) libcesque; +int raise(int) libcesque; +int reboot(int) libcesque; +int remove(const char *) libcesque; +int rename(const char *, const char *) libcesque; +int renameat(int, const char *, int, const char *) libcesque; +int rmdir(const char *) libcesque; +int sched_yield(void) libcesque; +int setegid(unsigned) libcesque; +int seteuid(unsigned) libcesque; +int setfsgid(unsigned) libcesque; +int setfsuid(unsigned) libcesque; +int setgid(unsigned) libcesque; +int setgroups(size_t, const unsigned[]) libcesque; +int setpgid(int, int) libcesque; +int setpgrp(void) libcesque; +int setpriority(int, unsigned, int) libcesque; +int setregid(unsigned, unsigned) libcesque; +int setreuid(unsigned, unsigned) libcesque; +int setsid(void) libcesque; +int setuid(unsigned) libcesque; +int shm_open(const char *, int, unsigned) libcesque; +int shm_unlink(const char *) libcesque; +int sigignore(int) libcesque; +int siginterrupt(int, int) libcesque; +int symlink(const char *, const char *) libcesque; +int symlinkat(const char *, int, const char *) libcesque; +int tcgetpgrp(int) libcesque; +int tcsetpgrp(int, int) libcesque; +int truncate(const char *, int64_t) libcesque; +int ttyname_r(int, char *, size_t) libcesque; +int unlink(const char *) libcesque; +int unlinkat(int, const char *, int) libcesque; +int usleep(uint64_t) libcesque; +int vfork(void) libcesque returnstwice; +int wait(int *) libcesque; +int waitpid(int, int *, int) libcesque; +int64_t clock(void) libcesque; +int64_t time(int64_t *) libcesque; +ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned) libcesque; +ssize_t lseek(int, int64_t, int) libcesque; +ssize_t pread(int, void *, size_t, int64_t) libcesque; +ssize_t pwrite(int, const void *, size_t, int64_t) libcesque; +ssize_t read(int, void *, size_t) libcesque; +ssize_t readlink(const char *, char *, size_t) libcesque; +ssize_t readlinkat(int, const char *, char *, size_t) libcesque; +ssize_t write(int, const void *, size_t) libcesque; +unsigned alarm(unsigned) libcesque; +unsigned getegid(void) libcesque nosideeffect; +unsigned geteuid(void) libcesque nosideeffect; +unsigned getgid(void) libcesque nosideeffect; unsigned getuid(void) libcesque; -unsigned sleep(unsigned); -unsigned ualarm(unsigned, unsigned); -unsigned umask(unsigned); -void sync(void); +unsigned sleep(unsigned) libcesque; +unsigned ualarm(unsigned, unsigned) libcesque; +unsigned umask(unsigned) libcesque; +void sync(void) libcesque; #if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) -int syncfs(int); -int prctl(int, ...); +int syncfs(int) libcesque; +int prctl(int, ...) libcesque; int gettid(void) libcesque; -int setresgid(unsigned, unsigned, unsigned); -int setresuid(unsigned, unsigned, unsigned); -int getresgid(unsigned *, unsigned *, unsigned *); -int getresuid(unsigned *, unsigned *, unsigned *); -char *get_current_dir_name(void) __wur; -ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned); -int memfd_create(const char *, unsigned int); -int execvpe(const char *, char *const[], char *const[]); -int euidaccess(const char *, int); -int eaccess(const char *, int); -int madvise(void *, uint64_t, int); +int setresgid(unsigned, unsigned, unsigned) libcesque; +int setresuid(unsigned, unsigned, unsigned) libcesque; +int getresgid(unsigned *, unsigned *, unsigned *) libcesque; +int getresuid(unsigned *, unsigned *, unsigned *) libcesque; +char *get_current_dir_name(void) libcesque __wur; +ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned) libcesque; +int memfd_create(const char *, unsigned int) libcesque; +int execvpe(const char *, char *const[], char *const[]) libcesque; +int euidaccess(const char *, int) libcesque; +int eaccess(const char *, int) libcesque; +int madvise(void *, uint64_t, int) libcesque; #endif #ifdef _COSMO_SOURCE -bool32 fdexists(int); -bool32 fileexists(const char *); -bool32 ischardev(int); -bool32 isdirectory(const char *); -bool32 isexecutable(const char *); -bool32 isregularfile(const char *); -bool32 issymlink(const char *); -char *commandv(const char *, char *, size_t); -int __getcwd(char *, size_t); +bool32 fdexists(int) libcesque; +bool32 fileexists(const char *) libcesque; +bool32 ischardev(int) libcesque; +bool32 isdirectory(const char *) libcesque; +bool32 isexecutable(const char *) libcesque; +bool32 isregularfile(const char *) libcesque; +bool32 issymlink(const char *) libcesque; +char *commandv(const char *, char *, size_t) libcesque; +int __getcwd(char *, size_t) libcesque; int clone(void *, void *, size_t, int, void *, void *, void *, void *); -int fadvise(int, uint64_t, uint64_t, int); -int makedirs(const char *, unsigned); -int pivot_root(const char *, const char *); -int pledge(const char *, const char *); -int seccomp(unsigned, unsigned, void *); -int sys_iopl(int); -int sys_ioprio_get(int, int); -int sys_ioprio_set(int, int, int); -int sys_mlock(const void *, size_t); -int sys_mlock2(const void *, size_t, int); -int sys_mlockall(int); -int sys_munlock(const void *, size_t); -int sys_munlockall(void); -int sys_personality(uint64_t); -int sys_ptrace(int, ...); +int fadvise(int, uint64_t, uint64_t, int) libcesque; +int makedirs(const char *, unsigned) libcesque; +int pivot_root(const char *, const char *) libcesque; +int pledge(const char *, const char *) libcesque; +int seccomp(unsigned, unsigned, void *) libcesque; +int sys_iopl(int) libcesque; +int sys_ioprio_get(int, int) libcesque; +int sys_ioprio_set(int, int, int) libcesque; +int sys_mlock(const void *, size_t) libcesque; +int sys_mlock2(const void *, size_t, int) libcesque; +int sys_mlockall(int) libcesque; +int sys_munlock(const void *, size_t) libcesque; +int sys_munlockall(void) libcesque; +int sys_personality(uint64_t) libcesque; +int sys_ptrace(int, ...) libcesque; int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t); -int tmpfd(void); -int touch(const char *, unsigned); -int unveil(const char *, const char *); -long ptrace(int, ...); -ssize_t copyfd(int, int, size_t); -ssize_t readansi(int, char *, size_t); -ssize_t tinyprint(int, const char *, ...) nullterminated(); -void shm_path_np(const char *, char[hasatleast 78]); +int tmpfd(void) libcesque; +int touch(const char *, unsigned) libcesque; +int unveil(const char *, const char *) libcesque; +long ptrace(int, ...) libcesque; +ssize_t copyfd(int, int, size_t) libcesque; +ssize_t readansi(int, char *, size_t) libcesque; +ssize_t tinyprint(int, const char *, ...) libcesque nullterminated(); +void shm_path_np(const char *, char[hasatleast 78]) libcesque; #endif /* _COSMO_SOURCE */ -int __wifstopped(int) pureconst; -int __wifcontinued(int) pureconst; -int __wifsignaled(int) pureconst; +int __wifstopped(int) libcesque pureconst; +int __wifcontinued(int) libcesque pureconst; +int __wifsignaled(int) libcesque pureconst; #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) #define lseek64 lseek diff --git a/libc/calls/close.c b/libc/calls/close.c index b5c8fedbf..95068563e 100644 --- a/libc/calls/close.c +++ b/libc/calls/close.c @@ -16,10 +16,12 @@ │ 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/calls/internal.h" #include "libc/calls/state.internal.h" #include "libc/calls/struct/fd.internal.h" +#include "libc/calls/struct/sigset.internal.h" #include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" @@ -49,13 +51,8 @@ static int close_impl(int fd) { } if (__isfdkind(fd, kFdZip)) { - if (!__vforked && _weaken(__zipos_close)) { - return _weaken(__zipos_close)(fd); - } - if (!IsWindows() && !IsMetal()) { - sys_close(fd); - } - return 0; + unassert(_weaken(__zipos_close)); + return _weaken(__zipos_close)(fd); } if (!IsWindows() && !IsMetal()) { @@ -95,8 +92,18 @@ static int close_impl(int fd) { * @vforksafe */ int close(int fd) { - int rc = close_impl(fd); - if (!__vforked) __releasefd(fd); + int rc; + if (__isfdkind(fd, kFdZip)) { // XXX IsWindows()? + BLOCK_SIGNALS; + __fds_lock(); + rc = close_impl(fd); + if (!__vforked) __releasefd(fd); + __fds_unlock(); + ALLOW_SIGNALS; + } else { + rc = close_impl(fd); + if (!__vforked) __releasefd(fd); + } STRACE("close(%d) → %d% m", fd, rc); return rc; } diff --git a/libc/calls/fadvise.c b/libc/calls/fadvise.c index 799cd9fa5..fb191ff34 100644 --- a/libc/calls/fadvise.c +++ b/libc/calls/fadvise.c @@ -66,4 +66,4 @@ int fadvise(int fd, uint64_t offset, uint64_t len, int advice) { return rc; } -__strong_reference(fadvise, fadvise64); +__weak_reference(fadvise, fadvise64); diff --git a/libc/calls/fchmodat-linux.c b/libc/calls/fchmodat-linux.c index 9259cbd59..3036be97f 100644 --- a/libc/calls/fchmodat-linux.c +++ b/libc/calls/fchmodat-linux.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ -│ vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi │ ╚──────────────────────────────────────────────────────────────────────────────╝ │ │ │ Musl Libc │ diff --git a/libc/calls/finddebugbinary.c b/libc/calls/finddebugbinary.c index f19658556..b4bae854e 100644 --- a/libc/calls/finddebugbinary.c +++ b/libc/calls/finddebugbinary.c @@ -26,11 +26,11 @@ #include "libc/elf/def.h" #include "libc/elf/tinyelf.internal.h" #include "libc/errno.h" -#include "libc/serialize.h" #include "libc/intrin/directmap.internal.h" #include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/runtime/runtime.h" +#include "libc/serialize.h" #include "libc/str/str.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" @@ -80,8 +80,9 @@ static bool IsMyDebugBinary(const char *path) { // contains the same number of bytes of code as our .com executable // which is currently running in memory. if ((size = lseek(fd, 0, SEEK_END)) != -1 && - (dm = sys_mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)).addr != - MAP_FAILED) { + (dm = sys_mmap((void *)0x12345000000, size, PROT_READ, MAP_SHARED, fd, + 0)) + .addr != MAP_FAILED) { if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") && ((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() && GetElfSymbolValue(dm.addr, "_etext", &value)) { diff --git a/libc/calls/fstat.c b/libc/calls/fstat.c index ca465f7b7..5c24cb190 100644 --- a/libc/calls/fstat.c +++ b/libc/calls/fstat.c @@ -60,4 +60,4 @@ int fstat(int fd, struct stat *st) { return rc; } -__strong_reference(fstat, fstat64); +__weak_reference(fstat, fstat64); diff --git a/libc/calls/fstatat-nt.c b/libc/calls/fstatat-nt.c index 32c361702..821b07e6e 100644 --- a/libc/calls/fstatat-nt.c +++ b/libc/calls/fstatat-nt.c @@ -33,11 +33,27 @@ #include "libc/sysv/consts/fileno.h" #include "libc/sysv/errfuns.h" +static int Atoi(const char *str) { + int c; + unsigned x = 0; + if (!*str) return -1; + while ((c = *str++)) { + if ('0' <= c && c <= '9') { + x *= 10; + x += c - '0'; + } else { + return -1; + } + } + return x; +} + textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st, int flags) { // handle special files if (startswith(path, "/dev/")) { + int fd; if (!strcmp(path + 5, "tty")) { return sys_fstat_nt_special(kFdConsole, st); } else if (!strcmp(path + 5, "null")) { @@ -48,6 +64,8 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st, return sys_fstat_nt(STDOUT_FILENO, st); } else if (!strcmp(path + 5, "stderr")) { return sys_fstat_nt(STDERR_FILENO, st); + } else if (startswith(path + 5, "fd/") && (fd = Atoi(path + 8)) != -1) { + return sys_fstat_nt(fd, st); } else { return enoent(); } diff --git a/libc/calls/fstatat.c b/libc/calls/fstatat.c index 626244bcd..5c164df3e 100644 --- a/libc/calls/fstatat.c +++ b/libc/calls/fstatat.c @@ -102,4 +102,4 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) { return rc; } -__strong_reference(fstatat, fstatat64); +__weak_reference(fstatat, fstatat64); diff --git a/libc/calls/ftruncate.c b/libc/calls/ftruncate.c index a2c4804e9..e441d4617 100644 --- a/libc/calls/ftruncate.c +++ b/libc/calls/ftruncate.c @@ -87,4 +87,4 @@ int ftruncate(int fd, int64_t length) { return rc; } -__strong_reference(ftruncate, ftruncate64); +__weak_reference(ftruncate, ftruncate64); diff --git a/libc/calls/getcontext.S b/libc/calls/getcontext.S index 414ca174e..bf3400f43 100644 --- a/libc/calls/getcontext.S +++ b/libc/calls/getcontext.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/getcontext.inc b/libc/calls/getcontext.inc index 255dc3d11..ea0a8b4a8 100644 --- a/libc/calls/getcontext.inc +++ b/libc/calls/getcontext.inc @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/gethoststxtpath.c b/libc/calls/gethoststxtpath.c new file mode 100644 index 000000000..579f973a9 --- /dev/null +++ b/libc/calls/gethoststxtpath.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 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/sysdir.internal.h" +#include "libc/dce.h" + +const char *GetHostsTxtPath(char *path, size_t size) { + if (!IsWindows()) { + return "/etc/hosts"; + } else { + return GetSystemDirectoryPath(path, "\\drivers\\etc\\hosts", size); + } +} diff --git a/libc/calls/getntsyspath.S b/libc/calls/getntsyspath.S index b13663eef..62bd818f0 100644 --- a/libc/calls/getntsyspath.S +++ b/libc/calls/getntsyspath.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/getprogramexecutablename.greg.c b/libc/calls/getprogramexecutablename.greg.c index 247f2fae6..89cb8aa77 100644 --- a/libc/calls/getprogramexecutablename.greg.c +++ b/libc/calls/getprogramexecutablename.greg.c @@ -23,21 +23,34 @@ #include "libc/cosmo.h" #include "libc/dce.h" #include "libc/errno.h" +#include "libc/fmt/libgen.h" #include "libc/intrin/getenv.internal.h" -#include "libc/serialize.h" +#include "libc/intrin/strace.internal.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/nt/runtime.h" #include "libc/runtime/runtime.h" +#include "libc/serialize.h" #include "libc/str/str.h" #include "libc/sysv/consts/at.h" #include "libc/sysv/consts/ok.h" +#ifdef __x86_64__ +__static_yoink("_init_program_executable_name"); +#endif + #define CTL_KERN 1 #define KERN_PROC 14 #define KERN_PROC_PATHNAME_FREEBSD 12 #define KERN_PROC_PATHNAME_NETBSD 5 +#define DevFd() (IsBsd() ? "/dev/fd/" : IsLinux() ? "/proc/self/fd/" : 0) +#define StrlenDevFd() \ + ((IsBsd() ? sizeof("/dev/fd/") \ + : IsLinux() ? sizeof("/proc/self/fd/") \ + : 0) - \ + 1) + static struct { atomic_uint once; union { @@ -50,7 +63,89 @@ static inline int IsAlpha(int c) { return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'); } +static inline int AllNumDot(const char *s) { + while (true) { + switch (*s++) { + default: + return 0; + case 0: + return 1; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.':; /* continue */ + } + } +} + +// old loaders do not pass __program_executable_name, so we need to +// check for them when we use KERN_PROC_PATHNAME et al. +static int OldApeLoader(char *s) { + char *b; + return !strcmp(s, "/usr/bin/ape") || + (!strncmp((b = basename(s)), ".ape-", 5) && AllNumDot(b + 5)); +} + +static char *CopyWithCwd(const char *q, char *p, char *e) { + char c; + if (*q != '/') { + if (q[0] == '.' && q[1] == '/') { + q += 2; + } + int got = __getcwd(p, e - p - 1 /* '/' */); + if (got != -1) { + p += got - 1; + *p++ = '/'; + } + } + while ((c = *q++)) { + if (p + 1 /* nul */ < e) { + *p++ = c; + } else { + return NULL; + } + } + *p = 0; + return p; +} + +// if q exists then turn it into an absolute path. we also try adding +// a .com suffix since the ape auto-appends it when resolving +static int TryPath(const char *q, int com) { + char *p; + if (!(p = CopyWithCwd(q, g_prog.u.buf, + g_prog.u.buf + sizeof(g_prog.u.buf) - com * 4))) { + return 0; + } + if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return 1; + if (!com) return 0; + p = WRITE32LE(p, READ32LE(".com")); + *p = 0; + if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return 1; + return 0; +} + +// if the loader passed a relative path, prepend cwd to it. +// called early in init. +void __init_program_executable_name(void) { + if (__program_executable_name && *__program_executable_name != '/' && + CopyWithCwd(__program_executable_name, g_prog.u.buf, + g_prog.u.buf + sizeof(g_prog.u.buf))) { + __program_executable_name = g_prog.u.buf; + } +} + static inline void InitProgramExecutableNameImpl(void) { + size_t n; + ssize_t got; + char c, *q, *b; if (IsWindows()) { int n = GetModuleFileName(0, g_prog.u.buf16, ARRAYLEN(g_prog.u.buf16)); @@ -69,66 +164,35 @@ static inline void InitProgramExecutableNameImpl(void) { g_prog.u.buf16[2] = '/'; } tprecode16to8(g_prog.u.buf, sizeof(g_prog.u.buf), g_prog.u.buf16); - return; + goto UseBuf; } - - char c, *q; if (IsMetal()) { - q = APE_COM_NAME; - goto CopyString; - } - - /* the new-style loader supplies the full program path as the first - environment variable. in the spirit of Postel's Law ("be liberal - in what you accept"), we use __getenv to read it. */ - if ((q = __getenv(__envp, "COSMOPOLITAN_PROGRAM_EXECUTABLE").s)) { - strlcpy(g_prog.u.buf, q, sizeof(g_prog.u.buf)); + __program_executable_name = APE_COM_NAME; return; } - // if argv[0] exists then turn it into an absolute path. we also try - // adding a .com suffix since the ape auto-appends it when resolving - if ((q = __argv[0])) { - char *p = g_prog.u.buf; - char *e = p + sizeof(g_prog.u.buf); - if (*q != '/') { - if (q[0] == '.' && q[1] == '/') { - q += 2; - } - int got = __getcwd(p, e - p - 1 - 4); // for / and .com - if (got != -1) { - p += got - 1; - *p++ = '/'; + // see if the loader passed us a path. + if (__program_executable_name) { + if (issetugid()) { + /* we are running as a set-id interpreter script. this is highly unusual. + it means either someone installed their ape loader set-id, or they are + running a system that supports secure set-id interpreter scripts via a + /dev/fd/ path. check for the latter and allow that. otherwise, use the + empty string to obviate the TOCTOU problem between loader and binary. + */ + if (!(b = DevFd()) || + 0 != strncmp(b, __program_executable_name, (n = StrlenDevFd())) || + !__program_executable_name[n] || + __program_executable_name[n] == '.' || + strchr(__program_executable_name + n, '/')) { + goto UseEmpty; } } - while ((c = *q++)) { - if (p + 1 + 4 < e) { // for nul and .com - *p++ = c; - } - } - *p = 0; - if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return; - p = WRITE32LE(p, READ32LE(".com")); - *p = 0; - if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return; - } - - // if getenv("_") exists then use that - for (char **ep = __envp; (q = *ep); ++ep) { - if (*q++ == '_' && *q++ == '=') { - goto CopyString; - } - } - - // if argv[0] doesn't exist, then fallback to interpreter name - ssize_t got; - char *b = g_prog.u.buf; - size_t n = sizeof(g_prog.u.buf) - 1; - if ((got = sys_readlinkat(AT_FDCWD, "/proc/self/exe", b, n)) > 0 || - (got = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", b, n)) > 0) { - b[got] = 0; return; } + + b = g_prog.u.buf; + n = sizeof(g_prog.u.buf) - 1; if (IsFreebsd() || IsNetbsd()) { int cmd[4]; cmd[0] = CTL_KERN; @@ -140,13 +204,33 @@ static inline void InitProgramExecutableNameImpl(void) { } cmd[3] = -1; // current process if (sys_sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) { - return; + if (!OldApeLoader(b)) { + goto UseBuf; + } } } + if (IsLinux()) { + if ((got = sys_readlinkat(AT_FDCWD, "/proc/self/exe", b, n)) > 0 || + (got = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", b, n)) > 0) { + b[got] = 0; + if (!OldApeLoader(b)) { + goto UseBuf; + } + } + } + + // don't trust argument parsing if set-id. + if (issetugid()) { + goto UseEmpty; + } + + // try argv[0], then argv[0].com, then $_, then $_.com. + if (TryPath(__argv[0], 1) || TryPath(__getenv(__envp, "_").s, 1)) { + goto UseBuf; + } // give up and just copy argv[0] into it if ((q = __argv[0])) { - CopyString: char *p = g_prog.u.buf; char *e = p + sizeof(g_prog.u.buf); while ((c = *q++)) { @@ -155,14 +239,18 @@ static inline void InitProgramExecutableNameImpl(void) { } } *p = 0; - return; + goto UseBuf; } +UseEmpty: // if we don't even have that then empty the string g_prog.u.buf[0] = 0; + +UseBuf: + __program_executable_name = g_prog.u.buf; } -void __InitProgramExecutableName(void) { +static void InitProgramExecutableName(void) { int e = errno; InitProgramExecutableNameImpl(); errno = e; @@ -172,6 +260,7 @@ void __InitProgramExecutableName(void) { * Returns absolute path of program. */ char *GetProgramExecutableName(void) { - cosmo_once(&g_prog.once, __InitProgramExecutableName); - return g_prog.u.buf; + cosmo_once(&g_prog.once, InitProgramExecutableName); + STRACE("GetProgramExecutableName() → %#s", __program_executable_name); + return __program_executable_name; } diff --git a/libc/calls/getprotocolstxtpath.c b/libc/calls/getprotocolstxtpath.c new file mode 100644 index 000000000..2d31368bf --- /dev/null +++ b/libc/calls/getprotocolstxtpath.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 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/sysdir.internal.h" +#include "libc/dce.h" + +const char *GetProtocolsTxtPath(char *buf, size_t size) { + if (!IsWindows()) { + return "/etc/protocols"; + } else { + return GetSystemDirectoryPath(buf, "\\drivers\\etc\\protocol", size); + } +} diff --git a/libc/calls/getrandom.c b/libc/calls/getrandom.c index b5fac8f9d..65171f28c 100644 --- a/libc/calls/getrandom.c +++ b/libc/calls/getrandom.c @@ -88,12 +88,14 @@ static ssize_t GetDevUrandom(char *p, size_t n) { int fd; ssize_t rc; BLOCK_SIGNALS; + BLOCK_CANCELATION; fd = sys_openat(AT_FDCWD, "/dev/urandom", O_RDONLY | O_CLOEXEC, 0); if (fd != -1) { rc = sys_read(fd, p, n); } else { rc = -1; } + ALLOW_CANCELATION; ALLOW_SIGNALS; return rc; } diff --git a/libc/calls/getservicestxtpath.c b/libc/calls/getservicestxtpath.c new file mode 100644 index 000000000..765255b4f --- /dev/null +++ b/libc/calls/getservicestxtpath.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 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/sysdir.internal.h" +#include "libc/dce.h" + +const char *GetServicesTxtPath(char *path, size_t size) { + if (!IsWindows()) { + return "/etc/services"; + } else { + return GetSystemDirectoryPath(path, "\\drivers\\etc\\services", size); + } +} diff --git a/libc/dns/getsystemdirectorypath.c b/libc/calls/getsystemdirectorypath.c similarity index 88% rename from libc/dns/getsystemdirectorypath.c rename to libc/calls/getsystemdirectorypath.c index f382e2686..4030e3913 100644 --- a/libc/dns/getsystemdirectorypath.c +++ b/libc/calls/getsystemdirectorypath.c @@ -16,19 +16,16 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dns/dns.h" #include "libc/nt/systeminfo.h" #include "libc/str/str.h" -// e.g. GetSystemDirectoryPath(buf, size, "FOO") → "C:\WINDOWS\SYSTEM32\FOO" -textwindows char *GetSystemDirectoryPath(char *buf, size_t size, - const char *path) { +// e.g. GetSystemDirectoryPath(buf, "FOO", size) → "C:\WINDOWS\SYSTEM32\FOO" +textwindows char *GetSystemDirectoryPath(char *buf, const char *path, + size_t size) { uint32_t syslen = GetSystemDirectoryA(buf, size); size_t pathlen = strlen(path); if (syslen && syslen + pathlen + 1 < size) { - if (buf[syslen] == '\\') { - --syslen; - } + if (buf[syslen] == '\\') --syslen; memcpy(buf + syslen, path, pathlen + 1); return buf; } else { diff --git a/libc/calls/gettimeofday.c b/libc/calls/gettimeofday.c index 13954afbe..34fc8547c 100644 --- a/libc/calls/gettimeofday.c +++ b/libc/calls/gettimeofday.c @@ -38,8 +38,8 @@ * @param tz is completely ignored * @return 0 on success, or -1 w/ errno * @raise EFAULT if `tv` points to invalid memory - * @see clock_gettime() for nanosecond precision - * @see strftime() for string formatting + * @see clock_gettime() for nanosecond precision + * @see strftime() for string formatting * @asyncsignalsafe * @vforksafe */ diff --git a/libc/calls/h_errno.c b/libc/calls/h_errno.c deleted file mode 100644 index 401326c36..000000000 --- a/libc/calls/h_errno.c +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dns/ent.h" - -// error number global for gethostbyname*(), gethostbyaddr*(), etc. -static _Thread_local int __h_errno; - -errno_t *__h_errno_location(void) { - return &__h_errno; -} diff --git a/libc/calls/ipc.h b/libc/calls/ipc.h index 70c253ca5..9c9d4eb1b 100644 --- a/libc/calls/ipc.h +++ b/libc/calls/ipc.h @@ -12,7 +12,7 @@ COSMOPOLITAN_C_START_ -int ftok(const char *, int); +int ftok(const char *, int) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_IPC_H_ */ diff --git a/libc/calls/isqemu.c b/libc/calls/isqemu.c new file mode 100644 index 000000000..4746128cd --- /dev/null +++ b/libc/calls/isqemu.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2024 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 "ape/sections.internal.h" +#include "libc/calls/calls.h" +#include "libc/calls/syscall-sysv.internal.h" +#include "libc/errno.h" + +/** + * Returns true if process is running under qemu-x86_64 or qemu-aarch64. + */ +int IsQemuUser(void) { + static char rplus1; + if (!rplus1) { + // qemu doesn't validate the advice argument + // we could also check if __getcwd(0, 0) raises efault + int e = errno; + int r = !sys_madvise(__executable_start, 16384, 127); + errno = e; + rplus1 = r + 1; + } + return rplus1 - 1; +} diff --git a/libc/calls/kntsystemdirectory.S b/libc/calls/kntsystemdirectory.S index c10080c7a..85338d555 100644 --- a/libc/calls/kntsystemdirectory.S +++ b/libc/calls/kntsystemdirectory.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/kntwindowsdirectory.S b/libc/calls/kntwindowsdirectory.S index 0bb740674..de7418a62 100644 --- a/libc/calls/kntwindowsdirectory.S +++ b/libc/calls/kntwindowsdirectory.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/lseek.c b/libc/calls/lseek.c index 0faa0d707..696889f2b 100644 --- a/libc/calls/lseek.c +++ b/libc/calls/lseek.c @@ -93,4 +93,4 @@ int64_t lseek(int fd, int64_t offset, int whence) { return rc; } -__strong_reference(lseek, lseek64); +__weak_reference(lseek, lseek64); diff --git a/libc/calls/lstat.c b/libc/calls/lstat.c index e14cbcb12..9208e621d 100644 --- a/libc/calls/lstat.c +++ b/libc/calls/lstat.c @@ -27,4 +27,4 @@ int lstat(const char *pathname, struct stat *st) { return fstatat(AT_FDCWD, pathname, st, AT_SYMLINK_NOFOLLOW); } -__strong_reference(lstat, lstat64); +__weak_reference(lstat, lstat64); diff --git a/libc/calls/madvise-nt.c b/libc/calls/madvise-nt.c index fe29ac94a..77ad7351c 100644 --- a/libc/calls/madvise-nt.c +++ b/libc/calls/madvise-nt.c @@ -17,46 +17,43 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/syscall_support-nt.internal.h" -#include "libc/macros.internal.h" #include "libc/nt/enum/offerpriority.h" -#include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/memoryrangeentry.h" #include "libc/sysv/consts/madv.h" #include "libc/sysv/errfuns.h" -forceinline typeof(PrefetchVirtualMemory) *GetPrefetchVirtualMemory(void) { - static bool once; - static typeof(PrefetchVirtualMemory) *PrefetchVirtualMemory_; - if (!once) { +typedef bool32 (*__msabi PrefetchVirtualMemoryPtr)( + int64_t hProcess, uintptr_t NumberOfEntries, + struct NtMemoryRangeEntry *VirtualAddresses, uint32_t reserved_Flags); + +textwindows static PrefetchVirtualMemoryPtr GetPrefetchVirtualMemory(void) { + static PrefetchVirtualMemoryPtr PrefetchVirtualMemory_; + if (!PrefetchVirtualMemory_) { PrefetchVirtualMemory_ = /* win8.1+ */ GetProcAddressModule("Kernel32.dll", "PrefetchVirtualMemory"); - once = true; } return PrefetchVirtualMemory_; } -forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) { - static bool once; - static typeof(OfferVirtualMemory) *OfferVirtualMemory_; - if (!once) { +typedef bool32 (*__msabi OfferVirtualMemoryPtr)(void *inout_VirtualAddress, + size_t Size, int Priority); + +textwindows static OfferVirtualMemoryPtr GetOfferVirtualMemory(void) { + static OfferVirtualMemoryPtr OfferVirtualMemory_; + if (!OfferVirtualMemory_) { OfferVirtualMemory_ = /* win8.1+ */ GetProcAddressModule("Kernel32.dll", "OfferVirtualMemory"); - once = true; } return OfferVirtualMemory_; } textwindows int sys_madvise_nt(void *addr, size_t length, int advice) { - uint32_t rangecount; - struct NtMemoryRangeEntry ranges[1]; if (advice == MADV_WILLNEED || advice == MADV_SEQUENTIAL) { - typeof(PrefetchVirtualMemory) *fn = GetPrefetchVirtualMemory(); + PrefetchVirtualMemoryPtr fn = GetPrefetchVirtualMemory(); if (fn) { - ranges[0].VirtualAddress = addr; - ranges[0].NumberOfBytes = length; - rangecount = ARRAYLEN(ranges); - if (fn(GetCurrentProcess(), &rangecount, ranges, 0)) { + if (fn(GetCurrentProcess(), 1, &(struct NtMemoryRangeEntry){addr, length}, + 0)) { return 0; } else { return __winerr(); @@ -65,7 +62,7 @@ textwindows int sys_madvise_nt(void *addr, size_t length, int advice) { return enosys(); } } else if (advice == MADV_FREE) { - typeof(OfferVirtualMemory) *fn = GetOfferVirtualMemory(); + OfferVirtualMemoryPtr fn = GetOfferVirtualMemory(); if (fn) { if (fn(addr, length, kNtVmOfferPriorityNormal)) { return 0; diff --git a/libc/calls/madvise.c b/libc/calls/madvise.c index ebe6e6088..bb05aa0c7 100644 --- a/libc/calls/madvise.c +++ b/libc/calls/madvise.c @@ -29,21 +29,21 @@ * * @param advice can be MADV_WILLNEED, MADV_SEQUENTIAL, MADV_FREE, etc. * @return 0 on success, or -1 w/ errno + * @raise EINVAL if `advice` isn't valid or supported by system + * @raise EINVAL on Linux if addr/length isn't page size aligned with + * respect to `getauxval(AT_PAGESZ)` + * @raise ENOMEM on Linux if addr/length overlaps unmapped regions * @see libc/sysv/consts.sh * @see fadvise() */ int madvise(void *addr, size_t length, int advice) { int rc; - if (advice != 127 /* see consts.sh */) { - if (IsAsan() && !__asan_is_valid(addr, length)) { - rc = efault(); - } else if (!IsWindows()) { - rc = sys_madvise(addr, length, advice); - } else { - rc = sys_madvise_nt(addr, length, advice); - } + if (IsAsan() && !__asan_is_valid(addr, length)) { + rc = enomem(); + } else if (!IsWindows()) { + rc = sys_madvise(addr, length, advice); } else { - rc = einval(); + rc = sys_madvise_nt(addr, length, advice); } STRACE("madvise(%p, %'zu, %d) → %d% m", addr, length, advice, rc); return rc; diff --git a/libc/calls/makedev.h b/libc/calls/makedev.h index 8dc2b0049..dcd221026 100644 --- a/libc/calls/makedev.h +++ b/libc/calls/makedev.h @@ -1,9 +1,9 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_ #define COSMOPOLITAN_LIBC_CALLS_MAKEDEV_H_ -uint64_t makedev(uint32_t, uint32_t); -uint32_t major(uint64_t); -uint32_t minor(uint64_t); +uint64_t makedev(uint32_t, uint32_t) libcesque; +uint32_t major(uint64_t) libcesque; +uint32_t minor(uint64_t) libcesque; #define major(x) major(x) #define minor(x) minor(x) diff --git a/libc/calls/metalfile_init.S b/libc/calls/metalfile_init.S index 38f7516eb..72e7f8972 100644 --- a/libc/calls/metalfile_init.S +++ b/libc/calls/metalfile_init.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ This is free and unencumbered software released into the public domain. │ │ │ diff --git a/libc/calls/mkostemp.c b/libc/calls/mkostemp.c index 4ce8a520b..8ab41df7f 100644 --- a/libc/calls/mkostemp.c +++ b/libc/calls/mkostemp.c @@ -40,4 +40,4 @@ int mkostemp(char *template, unsigned flags) { return openatemp(AT_FDCWD, template, 0, flags, 0); } -__strong_reference(mkostemp, mkostemp64); +__weak_reference(mkostemp, mkostemp64); diff --git a/libc/calls/mkostemps.c b/libc/calls/mkostemps.c index 2babb7cec..44c624a7e 100644 --- a/libc/calls/mkostemps.c +++ b/libc/calls/mkostemps.c @@ -41,4 +41,4 @@ int mkostemps(char *template, int suffixlen, unsigned flags) { return openatemp(AT_FDCWD, template, suffixlen, flags, 0); } -__strong_reference(mkostemps, mkostemps64); +__weak_reference(mkostemps, mkostemps64); diff --git a/libc/calls/mkstemp.c b/libc/calls/mkstemp.c index 97e61ef70..98ba79799 100644 --- a/libc/calls/mkstemp.c +++ b/libc/calls/mkstemp.c @@ -40,4 +40,4 @@ int mkstemp(char *template) { return openatemp(AT_FDCWD, template, 0, 0, 0); } -__strong_reference(mkstemp, mkstemp64); +__weak_reference(mkstemp, mkstemp64); diff --git a/libc/calls/mkstemps.c b/libc/calls/mkstemps.c index f253ea383..6d079b3b5 100644 --- a/libc/calls/mkstemps.c +++ b/libc/calls/mkstemps.c @@ -42,4 +42,4 @@ int mkstemps(char *template, int suffixlen) { return openatemp(AT_FDCWD, template, suffixlen, 0, 0); } -__strong_reference(mkstemps, mkstemps64); +__weak_reference(mkstemps, mkstemps64); diff --git a/libc/calls/netbsdtramp.S b/libc/calls/netbsdtramp.S index 9eac76117..01fdca769 100644 --- a/libc/calls/netbsdtramp.S +++ b/libc/calls/netbsdtramp.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c index 10e84212a..50b7954ba 100644 --- a/libc/calls/open-nt.c +++ b/libc/calls/open-nt.c @@ -181,10 +181,25 @@ static textwindows int sys_open_nt_dup(int fd, int flags, int mode, int oldfd) { } } +static int Atoi(const char *str) { + int c; + unsigned x = 0; + if (!*str) return -1; + while ((c = *str++)) { + if ('0' <= c && c <= '9') { + x *= 10; + x += c - '0'; + } else { + return -1; + } + } + return x; +} + textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags, int32_t mode) { - int fd; ssize_t rc; + int fd, oldfd; BLOCK_SIGNALS; __fds_lock(); if (!(flags & _O_CREAT)) mode = 0; @@ -200,6 +215,9 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags, rc = sys_open_nt_dup(fd, flags, mode, STDOUT_FILENO); } else if (!strcmp(file + 5, "stderr")) { rc = sys_open_nt_dup(fd, flags, mode, STDERR_FILENO); + } else if (startswith(file + 5, "fd/") && + (oldfd = Atoi(file + 8)) != -1) { + rc = sys_open_nt_dup(fd, flags, mode, oldfd); } else { rc = enoent(); } diff --git a/libc/calls/open.c b/libc/calls/open.c index 3a4f29ea2..637041209 100644 --- a/libc/calls/open.c +++ b/libc/calls/open.c @@ -43,4 +43,4 @@ int open(const char *file, int flags, ...) { return openat(AT_FDCWD, file, flags, mode); } -__strong_reference(open, open64); +__weak_reference(open, open64); diff --git a/libc/calls/openat.c b/libc/calls/openat.c index ee96fbe7a..f7d15c473 100644 --- a/libc/calls/openat.c +++ b/libc/calls/openat.c @@ -241,4 +241,4 @@ int openat(int dirfd, const char *path, int flags, ...) { return rc; } -__strong_reference(openat, openat64); +__weak_reference(openat, openat64); diff --git a/libc/calls/posix_madvise.c b/libc/calls/posix_madvise.c index 4bf5b71eb..9503cd7a4 100644 --- a/libc/calls/posix_madvise.c +++ b/libc/calls/posix_madvise.c @@ -23,6 +23,10 @@ * Advises kernel about memory intentions, the POSIX way. * * @return 0 on success, or errno on error + * @raise EINVAL if `advice` isn't valid or supported by system + * @raise EINVAL on Linux if addr/length isn't page size aligned with + * respect to `getauxval(AT_PAGESZ)` + * @raise ENOMEM on Linux if addr/length overlaps unmapped regions * @returnserrno */ errno_t posix_madvise(void *addr, uint64_t len, int advice) { diff --git a/libc/calls/pread.c b/libc/calls/pread.c index 5db4277b1..c13dcab36 100644 --- a/libc/calls/pread.c +++ b/libc/calls/pread.c @@ -85,4 +85,4 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) { return rc; } -__strong_reference(pread, pread64); +__weak_reference(pread, pread64); diff --git a/libc/calls/program_executable_name_init.S b/libc/calls/program_executable_name_init.S new file mode 100644 index 000000000..99ed4db3e --- /dev/null +++ b/libc/calls/program_executable_name_init.S @@ -0,0 +1,27 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" + + .init.start 305,_init_program_executable_name + push %rdi + push %rsi + call __init_program_executable_name + pop %rsi + pop %rdi + .init.end 305,_init_program_executable_name diff --git a/libc/calls/pwrite.c b/libc/calls/pwrite.c index 39cae011b..b777e06ff 100644 --- a/libc/calls/pwrite.c +++ b/libc/calls/pwrite.c @@ -85,4 +85,4 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) { return rc; } -__strong_reference(pwrite, pwrite64); +__weak_reference(pwrite, pwrite64); diff --git a/libc/calls/restore.S b/libc/calls/restore.S index 1d49c8059..6ce347160 100644 --- a/libc/calls/restore.S +++ b/libc/calls/restore.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2023 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/sched_getcpu.c b/libc/calls/sched_getcpu.c new file mode 100644 index 000000000..761bba995 --- /dev/null +++ b/libc/calls/sched_getcpu.c @@ -0,0 +1,47 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2024 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/struct/cpuset.h" +#include "libc/dce.h" +#include "libc/nexgen32e/rdtscp.h" +#include "libc/nexgen32e/x86feature.h" +#include "libc/nt/struct/processornumber.h" +#include "libc/nt/synchronization.h" + +int sys_getcpu(unsigned *opt_cpu, unsigned *opt_node, void *tcache); + +/** + * Returns ID of CPU on which thread is currently scheduled. + */ +int sched_getcpu(void) { + if (X86_HAVE(RDTSCP)) { + unsigned tsc_aux; + rdtscp(&tsc_aux); + return TSC_AUX_CORE(tsc_aux); + } else if (IsWindows()) { + struct NtProcessorNumber pn; + GetCurrentProcessorNumberEx(&pn); + return 64 * pn.Group + pn.Number; + } else { + unsigned cpu = 0; + int rc = sys_getcpu(&cpu, 0, 0); + if (rc == -1) return -1; + return cpu; + } +} diff --git a/libc/calls/sched_yield.S b/libc/calls/sched_yield.S index 83e8fd205..6357c5fe8 100644 --- a/libc/calls/sched_yield.S +++ b/libc/calls/sched_yield.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/seccomp.c b/libc/calls/seccomp.c index 534ee099f..eaa1e4708 100644 --- a/libc/calls/seccomp.c +++ b/libc/calls/seccomp.c @@ -16,8 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/struct/seccomp.internal.h" #include "libc/calls/calls.h" +#include "libc/calls/struct/seccomp.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" @@ -62,16 +62,20 @@ int seccomp(unsigned operation, unsigned flags, void *args) { rc = -1; } #elif defined(__aarch64__) - register long r0 asm("x0") = (long)operation; - register long r1 asm("x1") = (long)flags; - register long r2 asm("x2") = (long)args; - register long res_x0 asm("x0"); - asm volatile("mov\tx8,%1\n\t" - "svc\t0" - : "=r"(res_x0) - : "i"(211), "r"(r0), "r"(r1), "r"(r2) - : "x8", "memory"); - rc = _sysret(res_x0); + if (IsLinux()) { + register long r0 asm("x0") = (long)operation; + register long r1 asm("x1") = (long)flags; + register long r2 asm("x2") = (long)args; + register long res_x0 asm("x0"); + asm volatile("mov\tx8,%1\n\t" + "svc\t0" + : "=r"(res_x0) + : "i"(211), "r"(r0), "r"(r1), "r"(r2) + : "x8", "memory"); + rc = _sysret(res_x0); + } else { + rc = enosys(); + } #else #error "arch unsupported" #endif diff --git a/libc/calls/sig.c b/libc/calls/sig.c index 628d7a01e..586e74f8a 100644 --- a/libc/calls/sig.c +++ b/libc/calls/sig.c @@ -33,6 +33,7 @@ #include "libc/intrin/describebacktrace.internal.h" #include "libc/intrin/dll.h" #include "libc/intrin/strace.internal.h" +#include "libc/intrin/weaken.h" #include "libc/nt/console.h" #include "libc/nt/enum/context.h" #include "libc/nt/enum/exceptionhandleractions.h" @@ -43,6 +44,7 @@ #include "libc/nt/struct/ntexceptionpointers.h" #include "libc/nt/synchronization.h" #include "libc/nt/thread.h" +#include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sicode.h" @@ -525,7 +527,9 @@ static void __sig_unmaskable(struct NtExceptionPointers *ep, int code, int sig, // otherwise it'll print a warning message about the lack of stack mem STRACE("win32 vectored exception 0x%08Xu raising %G " "cosmoaddr2line %s %lx %s", - ep->ExceptionRecord->ExceptionCode, sig, program_invocation_name, + ep->ExceptionRecord->ExceptionCode, sig, + _weaken(FindDebugBinary) ? _weaken(FindDebugBinary)() + : program_invocation_name, ep->ContextRecord->Rip, DescribeBacktrace((struct StackFrame *)ep->ContextRecord->Rbp)); diff --git a/libc/calls/sigenter-freebsd.c b/libc/calls/sigenter-freebsd.c index 6d5119f0e..0f29ad547 100644 --- a/libc/calls/sigenter-freebsd.c +++ b/libc/calls/sigenter-freebsd.c @@ -20,6 +20,7 @@ #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" +#include "libc/calls/struct/aarch64.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/siginfo-freebsd.internal.h" #include "libc/calls/struct/siginfo-meta.internal.h" @@ -33,18 +34,18 @@ #include "libc/str/str.h" #include "libc/sysv/consts/sa.h" -#ifdef __x86_64__ - privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, struct ucontext_freebsd *ctx) { + #pragma GCC push_options #pragma GCC diagnostic ignored "-Wframe-larger-than=" - struct Goodies { + struct { ucontext_t uc; siginfo_t si; } g; CheckLargeStackAllocation(&g, sizeof(g)); #pragma GCC pop_options + int rva, flags; rva = __sighandrvas[sig]; if (rva >= kSigactionMinRva) { @@ -52,12 +53,20 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, if (~flags & SA_SIGINFO) { ((sigaction_f)(__executable_start + rva))(sig, 0, 0); } else { + + // + // TRANSLATE FREEBSD SIGNAL TO LINUX SIGNAL + // + __repstosb(&g, 0, sizeof(g)); - g.uc.uc_mcontext.fpregs = &g.uc.__fpustate; + __siginfo2cosmo(&g.si, (void *)freebsdinfo); g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp; g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size; g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags; g.uc.uc_sigmask = ctx->uc_sigmask[0] | (uint64_t)ctx->uc_sigmask[0] << 32; + +#ifdef __x86_64__ + g.uc.uc_mcontext.fpregs = &g.uc.__fpustate; g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8; g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9; g.uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10; @@ -81,14 +90,39 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err; g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno; __repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512); - __siginfo2cosmo(&g.si, (void *)freebsdinfo); +#endif /* __x86_64__ */ + +#ifdef __aarch64__ + __memcpy(g.uc.uc_mcontext.regs, &ctx->uc_mcontext.mc_gpregs, 34 * 8); + if (ctx->uc_mcontext.mc_flags & _MC_FP_VALID) { + struct fpsimd_context *vc = + (struct fpsimd_context *)g.uc.uc_mcontext.__reserved; + vc->head.magic = FPSIMD_MAGIC; + vc->head.size = sizeof(*vc); + vc->fpsr = ctx->uc_mcontext.mc_fpregs.fp_sr; + vc->fpcr = ctx->uc_mcontext.mc_fpregs.fp_cr; + __memcpy(vc->vregs, ctx->uc_mcontext.mc_fpregs.fp_q, 32 * 16); + } +#endif /* __aarch64__ */ + + // + // INVOKE SIGNAL HANDLER + // + ((sigaction_f)(__executable_start + rva))(sig, &g.si, &g.uc); + + // + // TRANSLATE LINUX SIGNAL TO FREEBSD SIGNAL + // + ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp; ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size; ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags; ctx->uc_flags = g.uc.uc_flags; ctx->uc_sigmask[0] = g.uc.uc_sigmask; ctx->uc_sigmask[1] = g.uc.uc_sigmask >> 32; + +#ifdef __x86_64__ ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi; ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi; ctx->uc_mcontext.mc_rdx = g.uc.uc_mcontext.rdx; @@ -112,13 +146,24 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, ctx->uc_mcontext.mc_rip = g.uc.uc_mcontext.rip; ctx->uc_mcontext.mc_rsp = g.uc.uc_mcontext.rsp; __repmovsb(&ctx->uc_mcontext.mc_fpstate, &g.uc.__fpustate, 512); +#endif /* __x86_64__ */ + +#ifdef __aarch64__ + __memcpy(&ctx->uc_mcontext.mc_gpregs, g.uc.uc_mcontext.regs, 34 * 8); + struct fpsimd_context *vc = + (struct fpsimd_context *)g.uc.uc_mcontext.__reserved; + if (vc->head.magic == FPSIMD_MAGIC) { + ctx->uc_mcontext.mc_flags |= _MC_FP_VALID; + ctx->uc_mcontext.mc_fpregs.fp_sr = vc->fpsr; + ctx->uc_mcontext.mc_fpregs.fp_cr = vc->fpcr; + __memcpy(ctx->uc_mcontext.mc_fpregs.fp_q, vc->vregs, 32 * 16); + } +#endif /* __aarch64__ */ + + // done } } - /* - * When the FreeBSD kernel invokes this signal handler it pushes a - * trampoline on the stack which does two things: 1) it calls this - * function, and 2) calls sys_sigreturn() once this returns. - */ + // When the FreeBSD kernel invokes this signal handler it pushes a + // trampoline on the stack which does two things: 1) it calls this + // function, and 2) calls sys_sigreturn() once this returns. } - -#endif /* __x86_64__ */ diff --git a/libc/calls/stat.c b/libc/calls/stat.c index 552cbc4c8..0cc4d6a8b 100644 --- a/libc/calls/stat.c +++ b/libc/calls/stat.c @@ -34,4 +34,4 @@ int stat(const char *path, struct stat *st) { return fstatat(AT_FDCWD, path, st, 0); } -__strong_reference(stat, stat64); +__weak_reference(stat, stat64); diff --git a/libc/calls/statvfs.c b/libc/calls/statvfs.c index 9038951fe..277381f57 100644 --- a/libc/calls/statvfs.c +++ b/libc/calls/statvfs.c @@ -36,4 +36,4 @@ int statvfs(const char *path, struct statvfs *sv) { } } -__strong_reference(statvfs, statvfs64); +__weak_reference(statvfs, statvfs64); diff --git a/libc/calls/struct/cpuset.h b/libc/calls/struct/cpuset.h index 26e654bc9..ddae4de88 100644 --- a/libc/calls/struct/cpuset.h +++ b/libc/calls/struct/cpuset.h @@ -9,33 +9,33 @@ typedef struct cpu_set_t { uint64_t __bits[16]; } cpu_set_t; -int sched_getcpu(void); -int sched_getaffinity(int, size_t, cpu_set_t *); -int sched_setaffinity(int, size_t, const cpu_set_t *); +int sched_getcpu(void) libcesque; +int sched_getaffinity(int, size_t, cpu_set_t *) libcesque; +int sched_setaffinity(int, size_t, const cpu_set_t *) libcesque; #define CPU_SET(i, s) ((s)->__bits[(i) / 64] |= 1ull << ((i) % 64)) #define CPU_CLR(i, s) ((s)->__bits[(i) / 64] &= ~(1ull << ((i) % 64))) #define CPU_ISSET(i, s) (!!((s)->__bits[(i) / 64] & (1ull << ((i) % 64)))) -void CPU_ZERO(cpu_set_t *); +void CPU_ZERO(cpu_set_t *) libcesque; #define CPU_ZERO(x) CPU_ZERO(x) -int CPU_COUNT(cpu_set_t *); +int CPU_COUNT(cpu_set_t *) libcesque; #define CPU_COUNT(x) CPU_COUNT(x) -int CPU_EQUAL(cpu_set_t *, cpu_set_t *); +int CPU_EQUAL(cpu_set_t *, cpu_set_t *) libcesque; #define CPU_EQUAL(x, y) CPU_EQUAL(x, y) -void CPU_AND(cpu_set_t *, cpu_set_t *, cpu_set_t *); +void CPU_AND(cpu_set_t *, cpu_set_t *, cpu_set_t *) libcesque; #define CPU_AND(x, y, z) CPU_AND(x, y, z) -void CPU_OR(cpu_set_t *, cpu_set_t *, cpu_set_t *); +void CPU_OR(cpu_set_t *, cpu_set_t *, cpu_set_t *) libcesque; #define CPU_OR(x, y, z) CPU_OR(x, y, z) -void CPU_XOR(cpu_set_t *, cpu_set_t *, cpu_set_t *); +void CPU_XOR(cpu_set_t *, cpu_set_t *, cpu_set_t *) libcesque; #define CPU_XOR(x, y, z) CPU_XOR(x, y, z) -int CPU_COUNT_S(size_t, const cpu_set_t *); +int CPU_COUNT_S(size_t, const cpu_set_t *) libcesque; #define CPU_COUNT_S(x, y) CPU_COUNT_S(x, y) #define CPU_ALLOC_SIZE(n) \ @@ -53,5 +53,7 @@ int CPU_COUNT_S(size_t, const cpu_set_t *); #define CPU_CLR_S(i, size, set) _CPU_S(i, size, set, &= ~) #define CPU_ISSET_S(i, size, set) _CPU_S(i, size, set, &) +typedef cpu_set_t cpuset_t; /* for freebsd compatibility */ + COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_CPUSET_H_ */ diff --git a/libc/calls/struct/dirent.h b/libc/calls/struct/dirent.h index 39c387979..2c8f1e724 100644 --- a/libc/calls/struct/dirent.h +++ b/libc/calls/struct/dirent.h @@ -13,19 +13,19 @@ struct dirent { /* linux getdents64 abi */ struct dirstream; typedef struct dirstream DIR; -DIR *fdopendir(int) __wur; -DIR *opendir(const char *) __wur; -int closedir(DIR *); -int dirfd(DIR *); -long telldir(DIR *); -struct dirent *readdir(DIR *); -int readdir_r(DIR *, struct dirent *, struct dirent **); -void rewinddir(DIR *); -void seekdir(DIR *, long); -int alphasort(const struct dirent **, const struct dirent **); -int versionsort(const struct dirent **, const struct dirent **); +DIR *fdopendir(int) libcesque __wur; +DIR *opendir(const char *) libcesque __wur; +int closedir(DIR *) libcesque; +int dirfd(DIR *) libcesque; +long telldir(DIR *) libcesque; +struct dirent *readdir(DIR *) libcesque; +int readdir_r(DIR *, struct dirent *, struct dirent **) libcesque; +void rewinddir(DIR *) libcesque; +void seekdir(DIR *, long) libcesque; +int alphasort(const struct dirent **, const struct dirent **) libcesque; +int versionsort(const struct dirent **, const struct dirent **) libcesque; int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), - int (*)(const struct dirent **, const struct dirent **)); + int (*)(const struct dirent **, const struct dirent **)) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */ diff --git a/libc/calls/struct/iovec.h b/libc/calls/struct/iovec.h index cc984c997..4d9d77a5f 100644 --- a/libc/calls/struct/iovec.h +++ b/libc/calls/struct/iovec.h @@ -7,11 +7,11 @@ struct iovec { size_t iov_len; }; -ssize_t preadv(int, struct iovec *, int, int64_t); -ssize_t pwritev(int, const struct iovec *, int, int64_t); -ssize_t readv(int, const struct iovec *, int); -ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t); -ssize_t writev(int, const struct iovec *, int); +ssize_t preadv(int, struct iovec *, int, int64_t) libcesque; +ssize_t pwritev(int, const struct iovec *, int, int64_t) libcesque; +ssize_t readv(int, const struct iovec *, int) libcesque; +ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t) libcesque; +ssize_t writev(int, const struct iovec *, int) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_IOVEC_H_ */ diff --git a/libc/calls/struct/rlimit.h b/libc/calls/struct/rlimit.h index 4d6f10369..9e46d38d5 100644 --- a/libc/calls/struct/rlimit.h +++ b/libc/calls/struct/rlimit.h @@ -7,8 +7,8 @@ struct rlimit { uint64_t rlim_max; /* maximum limit in bytes */ }; -int getrlimit(int, struct rlimit *); -int setrlimit(int, const struct rlimit *); +int getrlimit(int, struct rlimit *) libcesque; +int setrlimit(int, const struct rlimit *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_RLIMIT_H_ */ diff --git a/libc/calls/struct/rusage.h b/libc/calls/struct/rusage.h index edd451aac..5e0058e33 100644 --- a/libc/calls/struct/rusage.h +++ b/libc/calls/struct/rusage.h @@ -22,10 +22,10 @@ struct rusage { int64_t ru_nivcsw; /* involuntary context switches */ }; -int getrusage(int, struct rusage *); -int wait3(int *, int, struct rusage *); -int wait4(int, int *, int, struct rusage *); -void rusage_add(struct rusage *, const struct rusage *); +int getrusage(int, struct rusage *) libcesque; +int wait3(int *, int, struct rusage *) libcesque; +int wait4(int, int *, int, struct rusage *) libcesque; +void rusage_add(struct rusage *, const struct rusage *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_RUSAGE_H_ */ diff --git a/libc/calls/struct/sched_param.h b/libc/calls/struct/sched_param.h index 69de69f35..0d65f65fa 100644 --- a/libc/calls/struct/sched_param.h +++ b/libc/calls/struct/sched_param.h @@ -7,13 +7,13 @@ struct sched_param { int32_t sched_priority; }; -int sched_get_priority_max(int); -int sched_get_priority_min(int); -int sched_getparam(int, struct sched_param *); -int sched_getscheduler(int); -int sched_rr_get_interval(int, struct timespec *); -int sched_setparam(int, const struct sched_param *); -int sched_setscheduler(int, int, const struct sched_param *); +int sched_get_priority_max(int) libcesque; +int sched_get_priority_min(int) libcesque; +int sched_getparam(int, struct sched_param *) libcesque; +int sched_getscheduler(int) libcesque; +int sched_rr_get_interval(int, struct timespec *) libcesque; +int sched_setparam(int, const struct sched_param *) libcesque; +int sched_setscheduler(int, int, const struct sched_param *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SCHED_PARAM_H_ */ diff --git a/libc/calls/struct/sigaction.h b/libc/calls/struct/sigaction.h index 657a18fa9..49d0d6fe3 100644 --- a/libc/calls/struct/sigaction.h +++ b/libc/calls/struct/sigaction.h @@ -17,8 +17,8 @@ struct sigaction { sigset_t sa_mask; }; -sighandler_t signal(int, sighandler_t); -int sigaction(int, const struct sigaction *, struct sigaction *); +sighandler_t signal(int, sighandler_t) libcesque; +int sigaction(int, const struct sigaction *, struct sigaction *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_H_ */ diff --git a/libc/calls/struct/sigaltstack.h b/libc/calls/struct/sigaltstack.h index fcff879c3..d72ab1dd2 100644 --- a/libc/calls/struct/sigaltstack.h +++ b/libc/calls/struct/sigaltstack.h @@ -10,7 +10,7 @@ struct sigaltstack { typedef struct sigaltstack stack_t; -int sigaltstack(const struct sigaltstack *, struct sigaltstack *); +int sigaltstack(const struct sigaltstack *, struct sigaltstack *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGALTSTACK_H_ */ diff --git a/libc/calls/struct/siginfo.h b/libc/calls/struct/siginfo.h index 967d6d6ed..a321c9404 100644 --- a/libc/calls/struct/siginfo.h +++ b/libc/calls/struct/siginfo.h @@ -57,8 +57,8 @@ struct siginfo { typedef struct siginfo siginfo_t; #ifdef _COSMO_SOURCE -void __minicrash(int, siginfo_t *, void *); -char __is_stack_overflow(siginfo_t *, void *); +void __minicrash(int, siginfo_t *, void *) libcesque; +char __is_stack_overflow(siginfo_t *, void *) libcesque; #endif COSMOPOLITAN_C_END_ diff --git a/libc/calls/struct/statfs.h b/libc/calls/struct/statfs.h index 2c2e648fc..eddb23600 100644 --- a/libc/calls/struct/statfs.h +++ b/libc/calls/struct/statfs.h @@ -20,8 +20,8 @@ struct statfs { /* cosmo abi */ char f_fstypename[16]; }; -int statfs(const char *, struct statfs *); -int fstatfs(int, struct statfs *); +int statfs(const char *, struct statfs *) libcesque; +int fstatfs(int, struct statfs *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_STATFS_H_ */ diff --git a/libc/calls/struct/sysinfo.h b/libc/calls/struct/sysinfo.h index f839f81c2..980841d84 100644 --- a/libc/calls/struct/sysinfo.h +++ b/libc/calls/struct/sysinfo.h @@ -19,7 +19,7 @@ struct sysinfo { uint32_t mem_unit; /* ram stuff above is multiples of this */ }; -int sysinfo(struct sysinfo *); +int sysinfo(struct sysinfo *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SYSINFO_H_ */ diff --git a/libc/calls/struct/timespec.h b/libc/calls/struct/timespec.h index 3b8b04c31..b49eadb60 100644 --- a/libc/calls/struct/timespec.h +++ b/libc/calls/struct/timespec.h @@ -8,35 +8,38 @@ struct timespec { int64_t tv_nsec; /* nanoseconds */ }; -int clock_getres(int, struct timespec *); -int clock_gettime(int, struct timespec *); -int clock_settime(int, const struct timespec *); +int clock_getres(int, struct timespec *) libcesque; +int clock_gettime(int, struct timespec *) libcesque; +int clock_settime(int, const struct timespec *) libcesque; int clock_nanosleep(int, int, const struct timespec *, struct timespec *); -int futimens(int, const struct timespec[2]); -int nanosleep(const struct timespec *, struct timespec *); -int utimensat(int, const char *, const struct timespec[2], int); -int timespec_getres(struct timespec *, int); -int timespec_get(struct timespec *, int); +int futimens(int, const struct timespec[2]) libcesque; +int nanosleep(const struct timespec *, struct timespec *) libcesque; +int utimensat(int, const char *, const struct timespec[2], int) libcesque; +int timespec_getres(struct timespec *, int) libcesque; +int timespec_get(struct timespec *, int) libcesque; #ifdef _COSMO_SOURCE /* cosmopolitan libc's non-posix timespec library removed by default due to emacs codebase clash */ #define timespec_zero ((struct timespec){0}) #define timespec_max ((struct timespec){0x7fffffffffffffff, 999999999}) -int timespec_cmp(struct timespec, struct timespec) pureconst; -int64_t timespec_tomicros(struct timespec) pureconst; -int64_t timespec_tomillis(struct timespec) pureconst; -int64_t timespec_tonanos(struct timespec) pureconst; -struct timespec timespec_add(struct timespec, struct timespec) pureconst; -struct timespec timespec_fromnanos(int64_t) pureconst; -struct timespec timespec_frommicros(int64_t) pureconst; -struct timespec timespec_frommillis(int64_t) pureconst; -struct timespec timespec_real(void); -struct timespec timespec_mono(void); -struct timespec timespec_sleep(struct timespec); -int timespec_sleep_until(struct timespec); -struct timespec timespec_sub(struct timespec, struct timespec) pureconst; -struct timespec timespec_subz(struct timespec, struct timespec) pureconst; +libcesque int timespec_cmp(struct timespec, struct timespec) pureconst; +libcesque int64_t timespec_tomicros(struct timespec) pureconst; +libcesque int64_t timespec_tomillis(struct timespec) pureconst; +libcesque int64_t timespec_tonanos(struct timespec) pureconst; +libcesque struct timespec timespec_add(struct timespec, + struct timespec) pureconst; +libcesque struct timespec timespec_fromnanos(int64_t) pureconst; +libcesque struct timespec timespec_frommicros(int64_t) pureconst; +libcesque struct timespec timespec_frommillis(int64_t) pureconst; +libcesque struct timespec timespec_real(void) libcesque; +libcesque struct timespec timespec_mono(void) libcesque; +libcesque struct timespec timespec_sleep(struct timespec) libcesque; +libcesque int timespec_sleep_until(struct timespec) libcesque; +libcesque struct timespec timespec_sub(struct timespec, + struct timespec) pureconst; +libcesque struct timespec timespec_subz(struct timespec, + struct timespec) pureconst; int sys_futex(int *, int, int, const struct timespec *, int *); static inline struct timespec timespec_fromseconds(int64_t __x) { return (struct timespec){__x}; diff --git a/libc/calls/struct/tms.h b/libc/calls/struct/tms.h index a6af1392b..1ac33786a 100644 --- a/libc/calls/struct/tms.h +++ b/libc/calls/struct/tms.h @@ -9,7 +9,7 @@ struct tms { int64_t tms_cstime; /* children kernelspace time */ }; -long times(struct tms *); +long times(struct tms *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TMS_H_ */ diff --git a/libc/calls/struct/ucontext-freebsd.internal.h b/libc/calls/struct/ucontext-freebsd.internal.h index facb16fa6..28e469f47 100644 --- a/libc/calls/struct/ucontext-freebsd.internal.h +++ b/libc/calls/struct/ucontext-freebsd.internal.h @@ -2,6 +2,22 @@ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_ COSMOPOLITAN_C_START_ +struct gpregs_freebsd_aarch64 { + int64_t gp_x[30]; + int64_t gp_lr; + int64_t gp_sp; + int64_t gp_elr; /* pc */ + uint64_t gp_spsr; /* pstate or cpsr */ +}; + +struct fpregs_freebsd_aarch64 { + uint128_t fp_q[32]; + uint32_t fp_sr; + uint32_t fp_cr; + int fp_flags; + int fp_pad; +}; + struct stack_freebsd { void *ss_sp; uint64_t ss_size; @@ -9,6 +25,7 @@ struct stack_freebsd { }; struct mcontext_freebsd { +#ifdef __x86_64__ int64_t mc_onstack; int64_t mc_rdi; int64_t mc_rsi; @@ -47,6 +64,14 @@ struct mcontext_freebsd { int64_t mc_xfpustate; int64_t mc_xfpustate_len; int64_t mc_spare[4]; +#elif defined(__aarch64__) + struct gpregs_freebsd_aarch64 mc_gpregs; + struct fpregs_freebsd_aarch64 mc_fpregs; + int mc_flags; +#define _MC_FP_VALID 0x1 /* Set when mc_fpregs has valid data */ + int mc_pad; /* Padding */ + uint64_t mc_spare[8]; /* Space for expansion, set to zero */ +#endif }; struct ucontext_freebsd { diff --git a/libc/calls/struct/utsname.h b/libc/calls/struct/utsname.h index c2e1094d1..705e3ac20 100644 --- a/libc/calls/struct/utsname.h +++ b/libc/calls/struct/utsname.h @@ -14,7 +14,7 @@ struct utsname { /* cosmo abi */ char domainname[SYS_NMLN]; /* domain name */ }; -int uname(struct utsname *); +int uname(struct utsname *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_UTSNAME_H_ */ diff --git a/libc/calls/swapcontext.S b/libc/calls/swapcontext.S index b9fc8c117..6dd78947f 100644 --- a/libc/calls/swapcontext.S +++ b/libc/calls/swapcontext.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/sysdir.internal.h b/libc/calls/sysdir.internal.h new file mode 100644 index 000000000..be2ab710c --- /dev/null +++ b/libc/calls/sysdir.internal.h @@ -0,0 +1,11 @@ +#ifndef COSMOPOLITAN_LIBC_CALLS_SYSDIR_H_ +#define COSMOPOLITAN_LIBC_CALLS_SYSDIR_H_ +COSMOPOLITAN_C_START_ + +const char *GetHostsTxtPath(char *, size_t); +const char *GetServicesTxtPath(char *, size_t); +const char *GetProtocolsTxtPath(char *, size_t); +char *GetSystemDirectoryPath(char *, const char *, size_t); + +COSMOPOLITAN_C_END_ +#endif /* COSMOPOLITAN_LIBC_CALLS_SYSDIR_H_ */ diff --git a/libc/calls/tailcontext.S b/libc/calls/tailcontext.S index 814a4265e..a55163dce 100644 --- a/libc/calls/tailcontext.S +++ b/libc/calls/tailcontext.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/calls/termios.h b/libc/calls/termios.h index afb9a1cf8..7517106a3 100644 --- a/libc/calls/termios.h +++ b/libc/calls/termios.h @@ -8,34 +8,34 @@ COSMOPOLITAN_C_START_ │ cosmopolitan § teletypewriter control ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -int tcgetattr(int, struct termios *); -int tcsetattr(int, int, const struct termios *); +int tcgetattr(int, struct termios *) libcesque; +int tcsetattr(int, int, const struct termios *) libcesque; int openpty(int *, int *, char *, const struct termios *, - const struct winsize *) paramsnonnull((1, 2)); -int forkpty(int *, char *, const struct termios *, const struct winsize *) - paramsnonnull((1, 2)) __wur; -char *ptsname(int); -errno_t ptsname_r(int, char *, size_t); + const struct winsize *) libcesque paramsnonnull((1, 2)); +int forkpty(int *, char *, const struct termios *, + const struct winsize *) libcesque paramsnonnull((1, 2)) __wur; +char *ptsname(int) libcesque; +errno_t ptsname_r(int, char *, size_t) libcesque; -int grantpt(int); -int unlockpt(int); -int posix_openpt(int) __wur; +int grantpt(int) libcesque; +int unlockpt(int) libcesque; +int posix_openpt(int) libcesque __wur; -int tcdrain(int); -int tcgetsid(int); -int tcflow(int, int); -int tcflush(int, int); -int tcsetsid(int, int); -int tcsendbreak(int, int); -void cfmakeraw(struct termios *); -int cfsetspeed(struct termios *, uint32_t); -int cfsetospeed(struct termios *, uint32_t); -int cfsetispeed(struct termios *, uint32_t); -uint32_t cfgetospeed(const struct termios *); -uint32_t cfgetispeed(const struct termios *); -int tcsetwinsize(int, const struct winsize *); -int tcgetwinsize(int, struct winsize *); +int tcdrain(int) libcesque; +int tcgetsid(int) libcesque; +int tcflow(int, int) libcesque; +int tcflush(int, int) libcesque; +int tcsetsid(int, int) libcesque; +int tcsendbreak(int, int) libcesque; +void cfmakeraw(struct termios *) libcesque; +int cfsetspeed(struct termios *, uint32_t) libcesque; +int cfsetospeed(struct termios *, uint32_t) libcesque; +int cfsetispeed(struct termios *, uint32_t) libcesque; +uint32_t cfgetospeed(const struct termios *) libcesque; +uint32_t cfgetispeed(const struct termios *) libcesque; +int tcsetwinsize(int, const struct winsize *) libcesque; +int tcgetwinsize(int, struct winsize *) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_CALLS_TERMIOS_H_ */ diff --git a/libc/calls/tmpfd.c b/libc/calls/tmpfd.c index a65b9088f..b33b147df 100644 --- a/libc/calls/tmpfd.c +++ b/libc/calls/tmpfd.c @@ -53,7 +53,7 @@ int _mkstemp(char *, int); * On newer Linux only (c. 2013) it's possible to turn the anonymous * returned file back into a real file, by doing this: * - * linkat(AT_FDCWD, _gc(xasprintf("/proc/self/fd/%d", fd)), + * linkat(AT_FDCWD, gc(xasprintf("/proc/self/fd/%d", fd)), * AT_FDCWD, "real.txt", AT_SYMLINK_FOLLOW) * * On the New Technology, temporary files created by this function diff --git a/libc/calls/virtualmax.S b/libc/calls/virtualmax.S index 14505ece4..b563f432d 100644 --- a/libc/calls/virtualmax.S +++ b/libc/calls/virtualmax.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ diff --git a/libc/complex.h b/libc/complex.h index e7fb8ad95..0f761fcaa 100644 --- a/libc/complex.h +++ b/libc/complex.h @@ -1,85 +1,85 @@ -#ifndef _COMPLEX_H -#define _COMPLEX_H +#ifndef COSMOPOLITAN_LIBC_COMPLEX_H_ +#define COSMOPOLITAN_LIBC_COMPLEX_H_ COSMOPOLITAN_C_START_ #if __STDC_VERSION__ + 0 >= 201112 && !defined(__STDC_NO_COMPLEX__) #define complex _Complex #define imaginary _Imaginary -double cabs(complex double); -double carg(complex double); -double cimag(complex double); -double creal(complex double); +double cabs(complex double) libcesque; +double carg(complex double) libcesque; +double cimag(complex double) libcesque; +double creal(complex double) libcesque; -float cabsf(complex float); -float cargf(complex float); -float cimagf(complex float); -float crealf(complex float); +float cabsf(complex float) libcesque; +float cargf(complex float) libcesque; +float cimagf(complex float) libcesque; +float crealf(complex float) libcesque; -long double cabsl(complex long double); -long double cargl(complex long double); -long double cimagl(complex long double); -long double creall(complex long double); +long double cabsl(complex long double) libcesque; +long double cargl(complex long double) libcesque; +long double cimagl(complex long double) libcesque; +long double creall(complex long double) libcesque; -complex double cacos(complex double); -complex double cacosh(complex double); -complex double casin(complex double); -complex double casinh(complex double); -complex double catan(complex double); -complex double catanh(complex double); -complex double ccos(complex double); -complex double ccosh(complex double); -complex double cexp(complex double); -complex double cexp2(complex double); -complex double clog(complex double); -complex double conj(complex double); -complex double cpow(complex double, complex double); -complex double cproj(complex double); -complex double csin(complex double); -complex double csinh(complex double); -complex double csqrt(complex double); -complex double ctan(complex double); -complex double ctanh(complex double); +complex double cacos(complex double) libcesque; +complex double cacosh(complex double) libcesque; +complex double casin(complex double) libcesque; +complex double casinh(complex double) libcesque; +complex double catan(complex double) libcesque; +complex double catanh(complex double) libcesque; +complex double ccos(complex double) libcesque; +complex double ccosh(complex double) libcesque; +complex double cexp(complex double) libcesque; +complex double cexp2(complex double) libcesque; +complex double clog(complex double) libcesque; +complex double conj(complex double) libcesque; +complex double cpow(complex double, complex double) libcesque; +complex double cproj(complex double) libcesque; +complex double csin(complex double) libcesque; +complex double csinh(complex double) libcesque; +complex double csqrt(complex double) libcesque; +complex double ctan(complex double) libcesque; +complex double ctanh(complex double) libcesque; -complex float cacosf(complex float); -complex float cacoshf(complex float); -complex float casinf(complex float); -complex float casinhf(complex float); -complex float catanf(complex float); -complex float catanhf(complex float); -complex float ccosf(complex float); -complex float ccoshf(complex float); -complex float cexpf(complex float); -complex float cexp2f(complex float); -complex float clogf(complex float); -complex float conjf(complex float); -complex float cpowf(complex float, complex float); -complex float cprojf(complex float); -complex float csinf(complex float); -complex float csinhf(complex float); -complex float csqrtf(complex float); -complex float ctanf(complex float); -complex float ctanhf(complex float); +complex float cacosf(complex float) libcesque; +complex float cacoshf(complex float) libcesque; +complex float casinf(complex float) libcesque; +complex float casinhf(complex float) libcesque; +complex float catanf(complex float) libcesque; +complex float catanhf(complex float) libcesque; +complex float ccosf(complex float) libcesque; +complex float ccoshf(complex float) libcesque; +complex float cexpf(complex float) libcesque; +complex float cexp2f(complex float) libcesque; +complex float clogf(complex float) libcesque; +complex float conjf(complex float) libcesque; +complex float cpowf(complex float, complex float) libcesque; +complex float cprojf(complex float) libcesque; +complex float csinf(complex float) libcesque; +complex float csinhf(complex float) libcesque; +complex float csqrtf(complex float) libcesque; +complex float ctanf(complex float) libcesque; +complex float ctanhf(complex float) libcesque; -complex long double cprojl(complex long double); -complex long double csinhl(complex long double); -complex long double csinl(complex long double); -complex long double csqrtl(complex long double); -complex long double ctanhl(complex long double); -complex long double ctanl(complex long double); -complex long double cacoshl(complex long double); -complex long double cacosl(complex long double); -complex long double casinhl(complex long double); -complex long double casinl(complex long double); -complex long double catanhl(complex long double); -complex long double catanl(complex long double); -complex long double ccoshl(complex long double); -complex long double ccosl(complex long double); -complex long double cexpl(complex long double); -complex long double cexp2l(complex long double); -complex long double clogl(complex long double); -complex long double conjl(complex long double); -complex long double cpowl(complex long double, complex long double); +complex long double cprojl(complex long double) libcesque; +complex long double csinhl(complex long double) libcesque; +complex long double csinl(complex long double) libcesque; +complex long double csqrtl(complex long double) libcesque; +complex long double ctanhl(complex long double) libcesque; +complex long double ctanl(complex long double) libcesque; +complex long double cacoshl(complex long double) libcesque; +complex long double cacosl(complex long double) libcesque; +complex long double casinhl(complex long double) libcesque; +complex long double casinl(complex long double) libcesque; +complex long double catanhl(complex long double) libcesque; +complex long double catanl(complex long double) libcesque; +complex long double ccoshl(complex long double) libcesque; +complex long double ccosl(complex long double) libcesque; +complex long double cexpl(complex long double) libcesque; +complex long double cexp2l(complex long double) libcesque; +complex long double clogl(complex long double) libcesque; +complex long double conjl(complex long double) libcesque; +complex long double cpowl(complex long double, complex long double) libcesque; #ifndef __cplusplus #define __CIMAG(x, t) \ @@ -116,4 +116,4 @@ complex long double cpowl(complex long double, complex long double); #endif /* C11 */ COSMOPOLITAN_C_END_ -#endif /* _COMPLEX_H */ +#endif /* COSMOPOLITAN_LIBC_COMPLEX_H_ */ diff --git a/libc/cosmo.h b/libc/cosmo.h index 60f4f4112..35c1a47eb 100644 --- a/libc/cosmo.h +++ b/libc/cosmo.h @@ -3,7 +3,7 @@ COSMOPOLITAN_C_START_ errno_t cosmo_once(_Atomic(uint32_t) *, void (*)(void)); -int systemvpe(const char *, char *const[], char *const[]); +int systemvpe(const char *, char *const[], char *const[]) libcesque; COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_LIBC_COSMO_H_ */ diff --git a/libc/crt/BUILD.mk b/libc/crt/BUILD.mk index 05a17df1b..b1502e889 100644 --- a/libc/crt/BUILD.mk +++ b/libc/crt/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ # # SYNOPSIS # diff --git a/libc/crt/crt.S b/libc/crt/crt.S index 3049a6056..f55042d09 100644 --- a/libc/crt/crt.S +++ b/libc/crt/crt.S @@ -1,5 +1,5 @@ /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│ vi: set noet ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -62,6 +62,8 @@ _start: // set operating system when already detected 1: mov %cl,__hostos(%rip) + mov %rdx,__program_executable_name(%rip) + // get startup timestamp as early as possible // its used by --strace flag and kprintf() %T rdtsc @@ -123,6 +125,11 @@ _start: //////////////////////////////////////////////////////////////////////////////// #elif defined(__aarch64__) +#if SupportsFreebsd() +// save first arg + mov x4,x0 +#endif + // save original stack pointer // this is the first argument to cosmo() below mov x0,sp @@ -140,6 +147,9 @@ _start: // should be set to zero on other platforms mov x1,x15 +// third arg is program path passed by loader +// fourth arg is detected os passed by loader + // switch to c code bl cosmo .unreachable diff --git a/libc/cxxabi.h b/libc/cxxabi.h index 4e3d9a4a9..ed1dca20a 100644 --- a/libc/cxxabi.h +++ b/libc/cxxabi.h @@ -2,16 +2,18 @@ #define _CXXABI_H COSMOPOLITAN_C_START_ -union CxaGuardValue; +#ifdef __cplusplus +namespace __cxxabiv1 { +#endif /* __cplusplus */ char *__cxa_demangle(const char *, char *, size_t *, int *); int __cxa_atexit(void (*)(void *), void *, void *) paramsnonnull((1)) dontthrow; -int __cxa_guard_acquire(union CxaGuardValue *); -int __cxa_thread_atexit(void *, void *, void *) dontthrow; +int __cxa_thread_atexit(void (*)(void *), void *, void *) dontthrow; void __cxa_finalize(void *); -void __cxa_guard_abort(union CxaGuardValue *) dontthrow; -void __cxa_guard_release(union CxaGuardValue *) dontthrow; -void __cxa_pure_virtual(void) wontreturn; + +#ifdef __cplusplus +} /* namespace __cxxabiv1 */ +#endif /* __cplusplus */ COSMOPOLITAN_C_END_ #endif /* _CXXABI_H */ diff --git a/libc/dce.h b/libc/dce.h index b96bb6e2b..5b9f7e0fb 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -13,7 +13,7 @@ */ #define SUPPORT_VECTOR 255 #else -#define SUPPORT_VECTOR (_HOSTLINUX | _HOSTXNU) +#define SUPPORT_VECTOR (_HOSTLINUX | _HOSTXNU | _HOSTFREEBSD) #endif #endif @@ -62,8 +62,10 @@ #endif #ifdef __aarch64__ +#define IsAarch64() 1 #define IsXnuSilicon() IsXnu() #else +#define IsAarch64() 0 #define IsXnuSilicon() 0 #endif @@ -119,6 +121,8 @@ COSMOPOLITAN_C_START_ extern const int __hostos; +int IsQemuUser(void); + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* _COSMO_SOURCE */ diff --git a/libc/dlopen/BUILD.mk b/libc/dlopen/BUILD.mk index d8e38f98a..4db5aa081 100644 --- a/libc/dlopen/BUILD.mk +++ b/libc/dlopen/BUILD.mk @@ -1,5 +1,5 @@ #-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ +#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘ PKGS += LIBC_DLOPEN @@ -8,8 +8,13 @@ LIBC_DLOPEN = $(LIBC_DLOPEN_A_DEPS) $(LIBC_DLOPEN_A) LIBC_DLOPEN_A = o/$(MODE)/libc/dlopen/dlopen.a LIBC_DLOPEN_A_FILES := $(wildcard libc/dlopen/*) LIBC_DLOPEN_A_HDRS = $(filter %.h,$(LIBC_DLOPEN_A_FILES)) -LIBC_DLOPEN_A_SRCS = $(filter %.c,$(LIBC_DLOPEN_A_FILES)) -LIBC_DLOPEN_A_OBJS = $(LIBC_DLOPEN_A_SRCS:%.c=o/$(MODE)/%.o) +LIBC_DLOPEN_A_SRCS_C = $(filter %.c,$(LIBC_DLOPEN_A_FILES)) +LIBC_DLOPEN_A_SRCS_S = $(filter %.S,$(LIBC_DLOPEN_A_FILES)) +LIBC_DLOPEN_A_SRCS = $(LIBC_DLOPEN_A_SRCS_C) $(LIBC_DLOPEN_A_SRCS_S) + +LIBC_DLOPEN_A_OBJS = \ + $(LIBC_DLOPEN_A_SRCS_C:%.c=o/$(MODE)/%.o) \ + $(LIBC_DLOPEN_A_SRCS_S:%.S=o/$(MODE)/%.o) LIBC_DLOPEN_A_CHECKS = \ $(LIBC_DLOPEN_A).pkg \ @@ -45,6 +50,10 @@ $(LIBC_DLOPEN_A_OBJS): private \ -Wframe-larger-than=4096 \ -Walloca-larger-than=4096 +# these assembly files are safe to build on aarch64 +o/$(MODE)/libc/dlopen/foreign_tramp.o: libc/dlopen/foreign_tramp.S + @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< + LIBC_DLOPEN_LIBS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x))) LIBC_DLOPEN_SRCS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_SRCS)) LIBC_DLOPEN_HDRS = $(foreach x,$(LIBC_DLOPEN_ARTIFACTS),$($(x)_HDRS)) diff --git a/libc/dlopen/dlfcn.h b/libc/dlopen/dlfcn.h index c50dcc891..57eecd2f8 100644 --- a/libc/dlopen/dlfcn.h +++ b/libc/dlopen/dlfcn.h @@ -11,16 +11,17 @@ COSMOPOLITAN_C_START_ #define RTLD_NEXT ((void *)-1) #define RTLD_DEFAULT ((void *)0) -char *dlerror(void); -void *dlopen(const char *, int); -void *dlsym(void *, const char *); -int dlclose(void *); +char *dlerror(void) libcesque; +void *dlopen(const char *, int) libcesque; +void *dlsym(void *, const char *) libcesque; +int dlclose(void *) libcesque; #ifdef _COSMO_SOURCE -char *cosmo_dlerror(void); -void *cosmo_dlopen(const char *, int); -void *cosmo_dlsym(void *, const char *); -int cosmo_dlclose(void *); +char *cosmo_dlerror(void) libcesque; +void *cosmo_dlopen(const char *, int) libcesque; +void *cosmo_dlsym(void *, const char *) libcesque; +void *cosmo_dltramp(void *) libcesque; +int cosmo_dlclose(void *) libcesque; #endif COSMOPOLITAN_C_END_ diff --git a/libc/dlopen/dlopen.c b/libc/dlopen/dlopen.c index a62797993..9dcda52f6 100644 --- a/libc/dlopen/dlopen.c +++ b/libc/dlopen/dlopen.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/atomic.h" +#include "libc/calls/blockcancel.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/sigset.internal.h" #include "libc/calls/struct/stat.h" @@ -45,6 +46,7 @@ #include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/proc/posix_spawn.h" +#include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/syslib.internal.h" #include "libc/serialize.h" @@ -116,7 +118,7 @@ struct Loaded { Elf64_Phdr ph[25]; }; -static struct { +struct { atomic_uint once; bool is_supported; struct CosmoTib *tib; @@ -125,9 +127,10 @@ static struct { int (*dlclose)(void *); char *(*dlerror)(void); jmp_buf jb; -} foreign; +} __foreign; long __sysv2nt14(); +long foreign_tramp(); static _Thread_local char dlerror_buf[128]; @@ -156,28 +159,6 @@ static int is_file_newer_than(const char *path, const char *other) { return timespec_cmp(st1.st_mtim, st2.st_mtim) > 0; } -// on system five we sadly need this brutal trampoline -// todo(jart): add tls trampoline to sigaction() handlers -// todo(jart): morph binary to get tls from host c library -static long foreign_tramp(long a, long b, long c, long d, long e, - long func(long, long, long, long, long, double, - double, double, double, double, double), - double A, double B, double C, double D, double E, - double F) { - long res; - BLOCK_SIGNALS; -#ifdef __x86_64__ - struct CosmoTib *tib = __get_tls(); - __set_tls(foreign.tib); -#endif - res = func(a, b, c, d, e, A, B, C, D, E, F); -#ifdef __x86_64__ - __set_tls(tib); -#endif - ALLOW_SIGNALS; - return res; -} - static unsigned elf2prot(unsigned x) { unsigned r = 0; if (x & PF_R) r += PROT_READ; @@ -308,11 +289,11 @@ static long *push_strs(long *sp, char **list, int count) { } static wontreturn dontinstrument void foreign_helper(void **p) { - foreign.dlopen = p[0]; - foreign.dlsym = p[1]; - foreign.dlclose = p[2]; - foreign.dlerror = p[3]; - longjmp(foreign.jb, 1); + __foreign.dlopen = p[0]; + __foreign.dlsym = p[1]; + __foreign.dlclose = p[2]; + __foreign.dlerror = p[3]; + _longjmp(__foreign.jb, 1); } static dontinline void elf_exec(const char *file, char **envp) { @@ -515,11 +496,13 @@ static uint8_t *movimm(uint8_t p[static 16], int reg, uint64_t val) { static void *foreign_thunk_sysv(void *func) { uint8_t *code, *p; #ifdef __x86_64__ - // movabs $func,%r9 + // it is no longer needed + if (1) return func; + // movabs $func,%rax // movabs $foreign_tramp,%r10 // jmp *%r10 if (!(p = code = foreign_alloc(23))) return 0; // 10 + 10 + 3 = 23 - p = movimm(p, 9, (uintptr_t)func); + p = movimm(p, 0, (uintptr_t)func); p = movimm(p, 10, (uintptr_t)foreign_tramp); *p++ = 0x41; *p++ = 0xff; @@ -527,7 +510,7 @@ static void *foreign_thunk_sysv(void *func) { #elif defined(__aarch64__) __jit_begin(); if ((p = code = foreign_alloc(36))) { - p = movimm(p, 5, (uintptr_t)func); + p = movimm(p, 8, (uintptr_t)func); p = movimm(p, 10, (uintptr_t)foreign_tramp); *(uint32_t *)p = 0xd61f0140; // br x10 __clear_cache(code, p + 4); @@ -636,7 +619,15 @@ static dontinline bool foreign_compile(char exe[hasatleast PATH_MAX]) { } int pid, ws; char *args[] = { - "cc", "-pie", "-fPIC", src, "-o", tmp, IsNetbsd() ? 0 : "-ldl", 0, + "cc", + "-pie", + "-fPIC", + src, + "-o", + tmp, + IsLinux() ? "-Wl,-z,execstack" : "-DIGNORE", + IsNetbsd() ? 0 : "-ldl", + 0, }; errno_t err = posix_spawnp(&pid, args[0], NULL, NULL, args, environ); if (err) { @@ -671,19 +662,19 @@ static bool foreign_setup(void) { #ifdef __x86_64__ struct CosmoTib *cosmo_tib = __get_tls(); #endif - if (!setjmp(foreign.jb)) { + if (!setjmp(__foreign.jb)) { elf_exec(exe, environ); return false; // if elf_exec() returns, it failed } #ifdef __x86_64__ - foreign.tib = __get_tls(); + __foreign.tib = __get_tls(); __set_tls(cosmo_tib); #endif - foreign.dlopen = foreign_thunk_sysv(foreign.dlopen); - foreign.dlsym = foreign_thunk_sysv(foreign.dlsym); - foreign.dlclose = foreign_thunk_sysv(foreign.dlclose); - foreign.dlerror = foreign_thunk_sysv(foreign.dlerror); - foreign.is_supported = true; + __foreign.dlopen = foreign_thunk_sysv(__foreign.dlopen); + __foreign.dlsym = foreign_thunk_sysv(__foreign.dlsym); + __foreign.dlclose = foreign_thunk_sysv(__foreign.dlclose); + __foreign.dlerror = foreign_thunk_sysv(__foreign.dlerror); + __foreign.is_supported = true; return true; } @@ -693,8 +684,8 @@ static void foreign_once(void) { static bool foreign_init(void) { bool res; - cosmo_once(&foreign.once, foreign_once); - if (!(res = foreign.is_supported)) { + cosmo_once(&__foreign.once, foreign_once); + if (!(res = __foreign.is_supported)) { dlerror_set("dlopen() isn't supported on this platform"); } return res; @@ -740,14 +731,13 @@ static void *dlopen_nt(const char *path, int mode) { static void *dlsym_nt(void *handle, const char *name) { void *x64_abi_func; - void *sysv_abi_func = 0; if ((x64_abi_func = GetProcAddress((uintptr_t)handle, name))) { - sysv_abi_func = foreign_thunk_nt(x64_abi_func); + return x64_abi_func; } else { dlerror_set("symbol not found: "); strlcat(dlerror_buf, name, sizeof(dlerror_buf)); + return 0; } - return sysv_abi_func; } static void *dlopen_silicon(const char *path, int mode) { @@ -792,13 +782,10 @@ static void *dlopen_silicon(const char *path, int mode) { * WARNING: Our API uses a different naming because cosmo_dlopen() lacks * many of the features one would reasonably expect from a UNIX dlopen() * implementation; and we don't want to lead ./configure scripts astray. - * You're limited to 5 integral function parameters maximum. Calling an - * imported function currently goes much slower than a normal function - * call. You can't pass callback function pointers to foreign libraries - * safely. Foreign libraries also can't link symbols defined by your - * executable; that means using this for high-level language plugins is - * completely out of the question. What cosmo_dlopen() can do is help - * you talk to GPU and GUI libraries like CUDA and SDL. + * Foreign libraries also can't link symbols defined by your executable, + * which means using this for high-level language plugins is completely + * out of the question. What cosmo_dlopen() can do is help you talk to + * GPU and GUI libraries like CUDA and SDL. * * @param mode is a bitmask that can contain: * - `RTLD_LOCAL` (default) @@ -812,6 +799,7 @@ static void *dlopen_silicon(const char *path, int mode) { void *cosmo_dlopen(const char *path, int mode) { void *res; BLOCK_SIGNALS; + BLOCK_CANCELATION; if (IsWindows()) { res = dlopen_nt(path, mode); } else if (IsXnuSilicon()) { @@ -824,10 +812,11 @@ void *cosmo_dlopen(const char *path, int mode) { dlerror_set("dlopen() isn't supported on OpenBSD yet"); res = 0; } else if (foreign_init()) { - res = foreign.dlopen(path, mode); + res = __foreign.dlopen(path, mode); } else { res = 0; } + ALLOW_CANCELATION; ALLOW_SIGNALS; STRACE("dlopen(%#s, %d) → %p% m", path, mode, res); return res; @@ -836,8 +825,26 @@ void *cosmo_dlopen(const char *path, int mode) { /** * Obtains address of symbol from dynamic shared object. * - * On Windows you can only use this to lookup function addresses. - * Returned functions are trampolined to conform to System V ABI. + * WARNING: You almost always want to say this: + * + * pFunction = cosmo_dltramp(cosmo_dlsym(dso, "function")); + * + * That will generate code at runtime for automatically translating to + * Microsoft's x64 calling convention when appropriate. However the + * automated solution doesn't always work. For example, the prototype: + * + * void func(int, float); + * + * Won't be translated correctly, due to the differences in ABI. We're + * able to smooth over most of them, but that's just one of several + * examples where we can't. A good rule of thumb is: + * + * - More than four float/double args is problematic + * - Having both integral and floating point parameters is bad + * + * For those kinds of functions, you need to translate the ABI by hand. + * This can be accomplished using the GCC `__ms_abi__` attribute, where + * you'd have two function pointer types branched upon `IsWindows()`. * * @param handle was opened by dlopen() * @return address of symbol, or NULL w/ dlerror() @@ -847,16 +854,12 @@ void *cosmo_dlsym(void *handle, const char *name) { if (IsWindows()) { func = dlsym_nt(handle, name); } else if (IsXnuSilicon()) { - if ((func = __syslib->__dlsym(handle, name))) { - func = foreign_thunk_sysv(func); - } + func = __syslib->__dlsym(handle, name); } else if (IsXnu()) { dlerror_set("dlopen() isn't supported on x86-64 MacOS"); func = 0; } else if (foreign_init()) { - if ((func = foreign.dlsym(handle, name))) { - func = foreign_thunk_sysv(func); - } + func = __foreign.dlsym(handle, name); } else { func = 0; } @@ -864,6 +867,17 @@ void *cosmo_dlsym(void *handle, const char *name) { return func; } +/** + * Trampolines foreign function pointer so it can be called safely. + */ +void *cosmo_dltramp(void *foreign_func) { + if (!IsWindows()) { + return foreign_thunk_sysv(foreign_func); + } else { + return foreign_thunk_nt(foreign_func); + } +} + /** * Closes dynamic shared object. * @@ -880,7 +894,7 @@ int cosmo_dlclose(void *handle) { dlerror_set("dlopen() isn't supported on x86-64 MacOS"); res = -1; } else if (foreign_init()) { - res = foreign.dlclose(handle); + res = __foreign.dlclose(handle); } else { res = -1; } @@ -898,7 +912,7 @@ char *cosmo_dlerror(void) { } else if (IsWindows() || IsXnu()) { res = dlerror_buf; } else if (foreign_init()) { - res = foreign.dlerror(); + res = __foreign.dlerror(); res = dlerror_set(res); } else { res = dlerror_buf; @@ -906,3 +920,17 @@ char *cosmo_dlerror(void) { STRACE("dlerror() → %#s", res); return res; } + +#ifdef __x86_64__ +static textstartup void dlopen_init() { + if (IsLinux() || IsFreebsd()) { + // switch from %fs to %gs for tls + struct CosmoTib *tib = __get_tls(); + __morph_tls(); + __set_tls(tib); + } +} +const void *const dlopen_ctor[] initarray = { + dlopen_init, +}; +#endif diff --git a/libc/dlopen/foreign_tramp.S b/libc/dlopen/foreign_tramp.S new file mode 100644 index 000000000..f44c2edbe --- /dev/null +++ b/libc/dlopen/foreign_tramp.S @@ -0,0 +1,236 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│ vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2024 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" + +#define SIZE 0x0200 +#define SKEW 0x10 + +foreign_tramp: + +#ifdef __x86_64__ + + push %rbp + mov %rsp,%rbp + sub $SIZE,%rsp + +// save vector arguments + movdqu %xmm0,-0x10(%rbp) + movdqu %xmm1,-0x20(%rbp) + movdqu %xmm2,-0x30(%rbp) + movdqu %xmm3,-0x40(%rbp) + movdqu %xmm4,-0x50(%rbp) + movdqu %xmm5,-0x60(%rbp) + movdqu %xmm6,-0x70(%rbp) + movdqu %xmm7,-0x80(%rbp) + +// save register arguments + mov %rdi,-0x88(%rbp) + mov %rsi,-0x90(%rbp) + mov %rdx,-0x98(%rbp) + mov %rcx,-0xa0(%rbp) + mov %r8,-0xa8(%rbp) + mov %r9,-0xb0(%rbp) + +// save function pointer + mov %rax,-0xb8(%rbp) + +// block signals + call __sig_block + mov %rax,-0xc0(%rbp) + +// switch to foreign tls + mov %fs:0,%rax + mov %rax,-0xc8(%rbp) + mov __foreign+8(%rip),%rdi + call __set_tls + +// move stack arguments + movdqu SKEW+0x00(%rbp),%xmm0 + movdqu SKEW+0x10(%rbp),%xmm1 + movdqu SKEW+0x20(%rbp),%xmm2 + movdqu SKEW+0x30(%rbp),%xmm3 + movdqu SKEW+0x40(%rbp),%xmm4 + movdqu SKEW+0x50(%rbp),%xmm5 + movdqu SKEW+0x60(%rbp),%xmm6 + movdqu SKEW+0x70(%rbp),%xmm7 + movdqu %xmm0,-SIZE+0x00(%rbp) + movdqu %xmm1,-SIZE+0x10(%rbp) + movdqu %xmm2,-SIZE+0x20(%rbp) + movdqu %xmm3,-SIZE+0x30(%rbp) + movdqu %xmm4,-SIZE+0x40(%rbp) + movdqu %xmm5,-SIZE+0x50(%rbp) + movdqu %xmm6,-SIZE+0x60(%rbp) + movdqu %xmm7,-SIZE+0x70(%rbp) + movdqu SKEW+0x80(%rbp),%xmm0 + movdqu SKEW+0x90(%rbp),%xmm1 + movdqu SKEW+0xa0(%rbp),%xmm2 + movdqu SKEW+0xb0(%rbp),%xmm3 + movdqu SKEW+0xc0(%rbp),%xmm4 + movdqu SKEW+0xd0(%rbp),%xmm5 + movdqu SKEW+0xe0(%rbp),%xmm6 + movdqu SKEW+0xf0(%rbp),%xmm7 + movdqu %xmm0,-SIZE+0x80(%rbp) + movdqu %xmm1,-SIZE+0x90(%rbp) + movdqu %xmm2,-SIZE+0xa0(%rbp) + movdqu %xmm3,-SIZE+0xb0(%rbp) + movdqu %xmm4,-SIZE+0xc0(%rbp) + movdqu %xmm5,-SIZE+0xd0(%rbp) + movdqu %xmm6,-SIZE+0xe0(%rbp) + movdqu %xmm7,-SIZE+0xf0(%rbp) + +// restore vector arguments + movdqu -0x10(%rbp),%xmm0 + movdqu -0x20(%rbp),%xmm1 + movdqu -0x30(%rbp),%xmm2 + movdqu -0x40(%rbp),%xmm3 + movdqu -0x50(%rbp),%xmm4 + movdqu -0x60(%rbp),%xmm5 + movdqu -0x70(%rbp),%xmm6 + movdqu -0x80(%rbp),%xmm7 + +// restore register arguments + mov -0x88(%rbp),%rdi + mov -0x90(%rbp),%rsi + mov -0x98(%rbp),%rdx + mov -0xa0(%rbp),%rcx + mov -0xa8(%rbp),%r8 + mov -0xb0(%rbp),%r9 + +// call function + mov -0xb8(%rbp),%rax + call *%rax + +// save function result + movdqu %xmm0,-0x10(%rbp) + movdqu %xmm1,-0x20(%rbp) + mov %rax,-0x28(%rbp) + mov %rdx,-0x30(%rbp) + +// restore tls + mov -0xc8(%rbp),%rdi + call __set_tls + +// unblock signals + mov -0xc0(%rbp),%rdi + call __sig_unblock + +// restore function result + mov -0x28(%rbp),%rax + mov -0x30(%rbp),%rdx + movdqu -0x10(%rbp),%xmm0 + movdqu -0x20(%rbp),%xmm1 + + add $SIZE,%rsp + pop %rbp + ret + +#elif defined(__aarch64__) + + stp x29,x30,[sp,-0x100]! + mov x29,sp + +// save vector arguments + stp q0,q1,[sp,0x10] + stp q2,q3,[sp,0x30] + stp q4,q5,[sp,0x50] + stp q6,q7,[sp,0x70] + +// save register arguments + stp x0,x1,[sp,0x90] + stp x2,x3,[sp,0xa0] + stp x4,x5,[sp,0xb0] + stp x6,x7,[sp,0xc0] + +// save function pointer + str x8,[sp,0xd0] + +// block signals + bl __sig_block + str x0,[sp,0xd8] + +// move stack arguments + sub sp,sp,#0x100 + ldp q0,q1,[sp,SIZE+0x00] + ldp q2,q3,[sp,SIZE+0x20] + ldp q4,q5,[sp,SIZE+0x40] + ldp q6,q7,[sp,SIZE+0x60] + stp q0,q1,[sp,0x00] + stp q2,q3,[sp,0x20] + stp q4,q5,[sp,0x40] + stp q6,q7,[sp,0x60] + ldp q0,q1,[sp,SIZE+0x80] + ldp q2,q3,[sp,SIZE+0xa0] + ldp q4,q5,[sp,SIZE+0xc0] + ldp q6,q7,[sp,SIZE+0xe0] + stp q0,q1,[sp,0x80] + stp q2,q3,[sp,0xa0] + stp q4,q5,[sp,0xc0] + stp q6,q7,[sp,0xe0] + +// restore vector arguments + ldp q0,q1,[sp,0x100+0x10] + ldp q2,q3,[sp,0x100+0x30] + ldp q4,q5,[sp,0x100+0x50] + ldp q6,q7,[sp,0x100+0x70] + +// restore register arguments + ldp x0,x1,[sp,0x100+0x90] + ldp x2,x3,[sp,0x100+0xa0] + ldp x4,x5,[sp,0x100+0xb0] + ldp x6,x7,[sp,0x100+0xc0] + +// call function + ldr x8,[sp,0x100+0xd0] + blr x8 + add sp,sp,#0x100 + +// save vector results + stp q0,q1,[sp,0x10] + stp q2,q3,[sp,0x30] + stp q4,q5,[sp,0x50] + stp q6,q7,[sp,0x70] + +// save register results + stp x0,x1,[sp,0x90] + stp x2,x3,[sp,0xa0] + stp x4,x5,[sp,0xb0] + stp x6,x7,[sp,0xc0] + +// unblock signals + ldr x0,[sp,0xd8] + bl __sig_unblock + +// restore vector results + ldp q0,q1,[sp,0x10] + ldp q2,q3,[sp,0x30] + ldp q4,q5,[sp,0x50] + ldp q6,q7,[sp,0x70] + +// restore register results + ldp x0,x1,[sp,0x90] + ldp x2,x3,[sp,0xa0] + ldp x4,x5,[sp,0xb0] + ldp x6,x7,[sp,0xc0] + + ldp x29,x30,[sp],0x100 + ret + +#endif // __x86_64__ + + .endfn foreign_tramp,globl diff --git a/libc/dns/BUILD.mk b/libc/dns/BUILD.mk deleted file mode 100644 index 951c90289..000000000 --- a/libc/dns/BUILD.mk +++ /dev/null @@ -1,59 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += LIBC_DNS - -LIBC_DNS_ARTIFACTS += LIBC_DNS_A -LIBC_DNS = $(LIBC_DNS_A_DEPS) $(LIBC_DNS_A) -LIBC_DNS_A = o/$(MODE)/libc/dns/dns.a -LIBC_DNS_A_FILES := $(wildcard libc/dns/*) -LIBC_DNS_A_HDRS = $(filter %.h,$(LIBC_DNS_A_FILES)) -LIBC_DNS_A_SRCS_C = $(filter %.c,$(LIBC_DNS_A_FILES)) -LIBC_DNS_A_SRCS_S = $(filter %.S,$(LIBC_DNS_A_FILES)) - -LIBC_DNS_A_SRCS = \ - $(LIBC_DNS_A_SRCS_S) \ - $(LIBC_DNS_A_SRCS_C) - -LIBC_DNS_A_OBJS = \ - $(LIBC_DNS_A_SRCS_S:%.S=o/$(MODE)/%.o) \ - $(LIBC_DNS_A_SRCS_C:%.c=o/$(MODE)/%.o) - -LIBC_DNS_A_CHECKS = \ - $(LIBC_DNS_A).pkg \ - $(LIBC_DNS_A_HDRS:%=o/$(MODE)/%.ok) - -LIBC_DNS_A_DIRECTDEPS = \ - LIBC_CALLS \ - LIBC_FMT \ - LIBC_INTRIN \ - LIBC_MEM \ - LIBC_NEXGEN32E \ - LIBC_NT_ADVAPI32 \ - LIBC_NT_KERNEL32 \ - LIBC_RUNTIME \ - LIBC_SOCK \ - LIBC_STDIO \ - LIBC_STR \ - LIBC_SYSV - -LIBC_DNS_A_DEPS := \ - $(call uniq,$(foreach x,$(LIBC_DNS_A_DIRECTDEPS),$($(x)))) - -$(LIBC_DNS_A): libc/dns/ \ - $(LIBC_DNS_A).pkg \ - $(LIBC_DNS_A_OBJS) - -$(LIBC_DNS_A).pkg: \ - $(LIBC_DNS_A_OBJS) \ - $(foreach x,$(LIBC_DNS_A_DIRECTDEPS),$($(x)_A).pkg) - -LIBC_DNS_LIBS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x))) -LIBC_DNS_SRCS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_SRCS)) -LIBC_DNS_HDRS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_HDRS)) -LIBC_DNS_CHECKS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_CHECKS)) -LIBC_DNS_OBJS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_OBJS)) -$(LIBC_DNS_OBJS): $(BUILD_FILES) libc/dns/BUILD.mk - -.PHONY: o/$(MODE)/libc/dns -o/$(MODE)/libc/dns: $(LIBC_DNS_CHECKS) diff --git a/libc/dns/comparednsnames.c b/libc/dns/comparednsnames.c deleted file mode 100644 index bc8a56a1c..000000000 --- a/libc/dns/comparednsnames.c +++ /dev/null @@ -1,77 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/macros.internal.h" -#include "libc/str/str.h" - -forceinline void FindDnsLabel(const char *A, size_t *i, size_t *n) { - while (*i) { - if (A[*i - 1] == '.') { - if (*i == *n) { - --(*n); - } else { - break; - } - } - --(*i); - } -} - -/** - * Compares DNS hostnames in reverse lexicographical asciibetical order. - * @return <0, 0, or >0 - * @see test/libc/dns/comparednsnames_test.c (the code that matters) - */ -int CompareDnsNames(const char *A, const char *B) { - int res; - bool first; - size_t n, m, i, j; - if (A == B) return 0; - n = strlen(A); - m = strlen(B); - if (!n || !m || ((A[n - 1] == '.') ^ (B[m - 1] == '.'))) { - if (n && m && A[n - 1] == '.' && strchr(B, '.')) { - --m; - } else if (n && m && B[m - 1] == '.' && strchr(A, '.')) { - --n; - } else { - return A[n ? n - 1 : 0] - B[m ? m - 1 : 0]; - } - } - i = n; - j = m; - first = true; - for (;;) { - FindDnsLabel(A, &i, &n); - FindDnsLabel(B, &j, &m); - if (first) { - first = false; - if (!i && j) return 1; - if (!j && i) return -1; - } - if ((res = strncasecmp(&A[i], &B[j], MIN(n - i + 1, m - j + 1)))) { - return res; - } - if (!i || !j) { - return i - j; - } - n = i; - m = j; - } -} diff --git a/libc/dns/consts.h b/libc/dns/consts.h deleted file mode 100644 index 03136ac79..000000000 --- a/libc/dns/consts.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_CONSTS_H_ -#define COSMOPOLITAN_LIBC_DNS_CONSTS_H_ -#include "libc/sock/sock.h" - -#define DNS_TYPE_A 1 -#define DNS_TYPE_NS 2 -#define DNS_TYPE_CNAME 5 -#define DNS_TYPE_SOA 6 -#define DNS_TYPE_PTR 12 -#define DNS_TYPE_MX 15 -#define DNS_TYPE_TXT 16 - -#define DNS_CLASS_IN 1 - - -#define kMinSockaddr4Size \ - (offsetof(struct sockaddr_in, sin_addr) + sizeof(struct in_addr)) - -#endif /* COSMOPOLITAN_LIBC_DNS_CONSTS_H_ */ diff --git a/libc/dns/dns.h b/libc/dns/dns.h deleted file mode 100644 index 0332b3077..000000000 --- a/libc/dns/dns.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_DNS_H_ -#define COSMOPOLITAN_LIBC_DNS_DNS_H_ -#include "libc/dns/resolvconf.h" -#include "libc/sock/struct/sockaddr.h" - -#define DNS_PORT 53 -#define DNS_NAME_MAX 253 -#define DNS_LABEL_MAX 63 - -#define EAI_SUCCESS 0 -#define EAI_BADFLAGS -1 -#define EAI_NONAME -2 -#define EAI_AGAIN -3 -#define EAI_FAIL -4 -#define EAI_NODATA -5 -#define EAI_FAMILY -6 -#define EAI_SOCKTYPE -7 -#define EAI_SERVICE -8 -#define EAI_ADDRFAMILY -9 -#define EAI_MEMORY -10 -#define EAI_OVERFLOW -12 -#define EAI_SYSTEM -11 -#define EAI_ALLDONE -103 -#define EAI_CANCELED -101 -#define EAI_IDN_ENCODE -105 -#define EAI_INPROGRESS -100 -#define EAI_INTR -104 -#define EAI_NOTCANCELED -102 - -/* AI_* conforms to NT ABI */ -#define AI_PASSIVE 1 -#define AI_CANONNAME 2 -#define AI_NUMERICHOST 4 -#define AI_NUMERICSERV 8 -#define AI_ALL 0x0100 -#define AI_ADDRCONFIG 0x0400 -#define AI_V4MAPPED 0x0800 - -#define NI_NUMERICSCOPE 0 -#define NI_NUMERICHOST 1 -#define NI_NUMERICSERV 2 -#define NI_NOFQDN 4 -#define NI_NAMEREQD 8 -#define NI_DGRAM 16 -#define NI_MAXSERV 32 -#define NI_MAXHOST 1025 - -COSMOPOLITAN_C_START_ - -struct addrinfo { - int32_t ai_flags; /* AI_XXX */ - int32_t ai_family; /* AF_INET */ - int32_t ai_socktype; /* SOCK_XXX */ - int32_t ai_protocol; /* IPPROTO_XXX */ - uint32_t ai_addrlen; - union { - struct sockaddr *ai_addr; - struct sockaddr_in *ai_addr4; - }; - char *ai_canonname /*[DNS_NAME_MAX + 1]*/; - struct addrinfo *ai_next; -}; - -int getaddrinfo(const char *, const char *, const struct addrinfo *, - struct addrinfo **); -void freeaddrinfo(struct addrinfo *); -int getnameinfo(const struct sockaddr *, uint32_t, char *, uint32_t, char *, - uint32_t, int); -const char *gai_strerror(int); -int CompareDnsNames(const char *, const char *) paramsnonnull(); -int PascalifyDnsName(uint8_t *, size_t, const char *) paramsnonnull(); -int ResolveDns(const struct ResolvConf *, int, const char *, struct sockaddr *, - uint32_t) paramsnonnull(); -int ResolveDnsReverse(const struct ResolvConf *, int, const char *, char *, - size_t) paramsnonnull(); -struct addrinfo *newaddrinfo(uint16_t); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_DNS_H_ */ diff --git a/libc/dns/dnsheader.c b/libc/dns/dnsheader.c deleted file mode 100644 index 906517504..000000000 --- a/libc/dns/dnsheader.c +++ /dev/null @@ -1,57 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dnsheader.h" -#include "libc/serialize.h" -#include "libc/sysv/errfuns.h" - -/** - * Serializes DNS message h to wire. - * - * @return number of bytes written (always 12) or -1 w/ errno - * @see pascalifydnsname() - */ -void SerializeDnsHeader(uint8_t p[restrict 12], const struct DnsHeader *h) { - p[0x0] = h->id >> 8; - p[0x1] = h->id; - p[0x2] = h->bf1; - p[0x3] = h->bf2; - p[0x4] = h->qdcount >> 8; - p[0x5] = h->qdcount; - p[0x6] = h->ancount >> 8; - p[0x7] = h->ancount; - p[0x8] = h->nscount >> 8; - p[0x9] = h->nscount; - p[0xa] = h->arcount >> 8; - p[0xb] = h->arcount; -} - -/** - * Serializes DNS message h to wire. - * - * @return number of bytes read (always 12) or -1 w/ errno - */ -void DeserializeDnsHeader(struct DnsHeader *h, const uint8_t p[restrict 12]) { - h->id = READ16BE(p); - h->bf1 = p[2]; - h->bf2 = p[3]; - h->qdcount = READ16BE(p + 4); - h->ancount = READ16BE(p + 6); - h->nscount = READ16BE(p + 8); - h->arcount = READ16BE(p + 10); -} diff --git a/libc/dns/dnsheader.h b/libc/dns/dnsheader.h deleted file mode 100644 index 15318b9b9..000000000 --- a/libc/dns/dnsheader.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_ -#define COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_ -COSMOPOLITAN_C_START_ - -struct DnsHeader { - uint16_t id; /* transaction id */ - uint8_t bf1; /* bit field 1 */ - uint8_t bf2; /* bit field 2 */ - uint16_t qdcount; /* question count */ - uint16_t ancount; /* answer count */ - uint16_t nscount; /* nameserver count */ - uint16_t arcount; /* additional record count */ -}; - -void SerializeDnsHeader(uint8_t[restrict 12], const struct DnsHeader *); -void DeserializeDnsHeader(struct DnsHeader *, const uint8_t[restrict 12]); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_ */ diff --git a/libc/dns/dnsquestion.h b/libc/dns/dnsquestion.h deleted file mode 100644 index 0047747cb..000000000 --- a/libc/dns/dnsquestion.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_ -#define COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_ -COSMOPOLITAN_C_START_ - -struct DnsQuestion { - const char *qname; - uint16_t qtype; - uint16_t qclass; -}; - -int SerializeDnsQuestion(uint8_t *, size_t, const struct DnsQuestion *); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_ */ diff --git a/libc/dns/ent.h b/libc/dns/ent.h deleted file mode 100644 index 4902038ce..000000000 --- a/libc/dns/ent.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_ENT_H_ -#define COSMOPOLITAN_LIBC_DNS_ENT_H_ -#include "libc/dns/dns.h" - -#define HOST_NOT_FOUND 1 -#define TRY_AGAIN 2 -#define NO_RECOVERY 3 -#define NO_DATA 4 -#define NO_ADDRESS NO_DATA - -COSMOPOLITAN_C_START_ - -struct netent { - char *n_name; /* official network name */ - char **n_aliases; /* alias list */ - int n_addrtype; /* net address type */ - uint32_t n_net; /* network number */ -}; - -struct protoent { - char *p_name; /* official protocol name */ - char **p_aliases; /* alias list */ - int p_proto; /* protocol number */ -}; - -struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses */ -}; -#define h_addr h_addr_list[0] - -struct servent { - char *s_name; /* official service name */ - char **s_aliases; /* alias list */ - int s_port; /* port number (in network byte order) */ - char *s_proto; /* protocol to use */ -}; - -#define h_errno (*__h_errno_location()) -errno_t *__h_errno_location(void) dontthrow pureconst; - -void herror(const char *); -const char *hstrerror(int); - -struct netent *getnetent(void); -struct netent *getnetbyname(const char *); -struct netent *getnetbyaddr(uint32_t, int); -void setnetent(int); -void endnetent(void); - -struct protoent *getprotoent(void); -struct protoent *getprotobyname(const char *); -struct protoent *getprotobynumber(int); -void setprotoent(int); -void endprotoent(void); - -struct hostent *gethostent(void); -struct hostent *gethostbyname(const char *); -struct hostent *gethostbyaddr(const void *, uint32_t, int); -void sethostent(int); -void endhostent(void); - -struct servent *getservent(void); -struct servent *getservbyname(const char *, const char *); -struct servent *getservbyport(int, const char *); -void setservent(int); -void endservent(void); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_ENT_H_ */ diff --git a/libc/dns/freeaddrinfo.c b/libc/dns/freeaddrinfo.c deleted file mode 100644 index f9fe85e10..000000000 --- a/libc/dns/freeaddrinfo.c +++ /dev/null @@ -1,33 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/mem/mem.h" - -/** - * Frees addresses returned by getaddrinfo(). - */ -void freeaddrinfo(struct addrinfo *ai) { - struct addrinfo *next; - while (ai) { - /* we assume ai_addr and ai_canonname are shoehorned */ - next = ai->ai_next; - free(ai); - ai = next; - } -} diff --git a/libc/dns/gai_strerror.c b/libc/dns/gai_strerror.c deleted file mode 100644 index ef1ced002..000000000 --- a/libc/dns/gai_strerror.c +++ /dev/null @@ -1,67 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" - -/** - * Turns getaddrinfo() return code into string. - */ -const char *gai_strerror(int code) { - switch (code) { - case EAI_ADDRFAMILY: - return "ADDRFAMILY"; - case EAI_AGAIN: - return "AGAIN"; - case EAI_ALLDONE: - return "ALLDONE"; - case EAI_BADFLAGS: - return "BADFLAGS"; - case EAI_CANCELED: - return "CANCELED"; - case EAI_FAIL: - return "FAIL"; - case EAI_FAMILY: - return "FAMILY"; - case EAI_IDN_ENCODE: - return "ENCODE"; - case EAI_INPROGRESS: - return "INPROGRESS"; - case EAI_INTR: - return "INTR"; - case EAI_MEMORY: - return "MEMORY"; - case EAI_NODATA: - return "NODATA"; - case EAI_NONAME: - return "NONAME"; - case EAI_NOTCANCELED: - return "NOTCANCELED"; - case EAI_OVERFLOW: - return "OVERFLOW"; - case EAI_SERVICE: - return "SERVICE"; - case EAI_SOCKTYPE: - return "SOCKTYPE"; - case EAI_SUCCESS: - return "SUCCESS"; - case EAI_SYSTEM: - return "SYSTEM"; - default: - return "???"; - } -} diff --git a/libc/dns/getaddrinfo.c b/libc/dns/getaddrinfo.c deleted file mode 100644 index c59c1ce51..000000000 --- a/libc/dns/getaddrinfo.c +++ /dev/null @@ -1,116 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/calls/calls.h" -#include "libc/dns/dns.h" -#include "libc/dns/hoststxt.h" -#include "libc/dns/resolvconf.h" -#include "libc/dns/servicestxt.h" -#include "libc/fmt/conv.h" -#include "libc/macros.internal.h" -#include "libc/mem/gc.h" -#include "libc/mem/mem.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/inaddr.h" -#include "libc/sysv/consts/sock.h" -#include "libc/sysv/errfuns.h" - -/** - * Resolves address for internet name. - * - * @param name is either an ip string or a utf-8 hostname - * @param service is the port number as a string - * @param hints may be passed to specialize behavior (optional) - * @param res receives a pointer that must be freed with freeaddrinfo(), - * and won't be modified if non-zero is returned - * @return 0 on success or EAI_xxx value - */ -int getaddrinfo(const char *name, const char *service, - const struct addrinfo *hints, struct addrinfo **res) { - char *eptr; - int rc, port; - char proto[32]; - const char *canon; - struct addrinfo *ai; - port = 0; - if (!name && !service) { - return EAI_NONAME; - } - if (!name && hints && (hints->ai_flags & AI_CANONNAME)) { - return EAI_BADFLAGS; - } - if (service && ((port = strtol(service, &eptr, 10)), *eptr)) { - if (hints && hints->ai_socktype == SOCK_STREAM) { - strcpy(proto, "tcp"); - } else if (hints && hints->ai_socktype == SOCK_DGRAM) { - strcpy(proto, "udp"); - } else { // ai_socktype == 0 - strcpy(proto, ""); - } - if ((port = LookupServicesByName(service, proto, sizeof(proto), NULL, 0, - NULL)) == -1) { - return EAI_NONAME; - } - } - if (!(ai = newaddrinfo(port))) { - return EAI_MEMORY; - } - if (service) { - // if service isn't specified, port is left uninitialized - ai->ai_addr4->sin_port = htons(port); - } - if (hints) { - ai->ai_socktype = hints->ai_socktype; - ai->ai_protocol = hints->ai_protocol; - } - if (!name) { - ai->ai_addr4->sin_addr.s_addr = - (hints && (hints->ai_flags & AI_PASSIVE) == AI_PASSIVE) - ? htonl(INADDR_ANY) - : htonl(INADDR_LOOPBACK); - *res = ai; - return 0; - } - if (inet_pton(AF_INET, name, &ai->ai_addr4->sin_addr.s_addr) == 1) { - *res = ai; - return 0; - } else if (hints && (hints->ai_flags & AI_NUMERICHOST) == AI_NUMERICHOST) { - freeaddrinfo(ai); - return EAI_NONAME; - } else if (ResolveHostsTxt(GetHostsTxt(), AF_INET, name, ai->ai_addr, - sizeof(ai->ai_addr4), &canon) > 0) { - strlcpy(ai->ai_canonname, canon, DNS_NAME_MAX + 1); - *res = ai; - return 0; - } else { - rc = ResolveDns(GetResolvConf(), AF_INET, name, ai->ai_addr, - sizeof(ai->ai_addr4)); - if (rc > 0) { - *res = ai; - return 0; - } - freeaddrinfo(ai); - if (rc == 0) { - return EAI_NONAME; - } else { - return EAI_SYSTEM; - } - } -} diff --git a/libc/dns/gethostbyaddr.c b/libc/dns/gethostbyaddr.c deleted file mode 100644 index f250de7ba..000000000 --- a/libc/dns/gethostbyaddr.c +++ /dev/null @@ -1,58 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/mem/mem.h" -#include "libc/sysv/consts/af.h" - -struct hostent *gethostbyaddr(const void *s_addr, uint32_t len, int type) { - static struct hostent *ptr1, he1; - static char h_name[DNS_NAME_MAX + 1]; - static char *h_aliases[1]; - static char *h_addr_list[2]; - static char h_addr_list0[4]; - struct sockaddr_in addr; - if (!ptr1) { - he1.h_name = h_name; - he1.h_aliases = h_aliases; - he1.h_aliases[0] = NULL; - he1.h_addrtype = AF_INET; - he1.h_length = 4; - he1.h_addr_list = h_addr_list; - he1.h_addr_list[0] = h_addr_list0; - he1.h_addr_list[1] = NULL; - ptr1 = &he1; - } - if (type != AF_INET || len != sizeof(uint32_t)) return NULL; - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = *(uint32_t *)(s_addr); - if (getnameinfo((struct sockaddr *)&addr, sizeof(addr), ptr1->h_name, - DNS_NAME_MAX, NULL, 0, 0)) - return NULL; - *((uint32_t *)ptr1->h_addr_list[0]) = (addr.sin_addr.s_addr); - return ptr1; -} diff --git a/libc/dns/gethostbyname.c b/libc/dns/gethostbyname.c deleted file mode 100644 index f30d87af9..000000000 --- a/libc/dns/gethostbyname.c +++ /dev/null @@ -1,70 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" - -struct hostent *gethostbyname(const char *name) { - static struct hostent *ptr0, he0; - static char h_name[DNS_NAME_MAX + 1]; - static char *h_aliases[1]; - static char *h_addr_list[2]; - static char h_addr_list0[4]; - struct addrinfo *result = NULL; - - if (!ptr0) { - he0.h_name = h_name; - - he0.h_aliases = h_aliases; - he0.h_aliases[0] = NULL; - - he0.h_addrtype = AF_INET; - he0.h_length = 4; - he0.h_addr_list = h_addr_list; - - he0.h_addr_list[0] = h_addr_list0; - he0.h_addr_list[1] = NULL; - - ptr0 = &he0; - } - - if (getaddrinfo(name, NULL, NULL, &result) || result == NULL) { - return NULL; - } - - /* if getaddrinfo is successful, result->ai_canonname is non-NULL, - * (see newaddrinfo) but the string can still be empty */ - strlcpy(ptr0->h_name, *result->ai_canonname ? result->ai_canonname : name, - sizeof(h_name)); - - *((uint32_t *)ptr0->h_addr_list[0]) = result->ai_addr4->sin_addr.s_addr; - /* TODO: if result has ai_next, fit multiple entries for h_addr_list */ - - freeaddrinfo(result); - return ptr0; -} diff --git a/libc/dns/gethoststxt.c b/libc/dns/gethoststxt.c deleted file mode 100644 index eeca919b1..000000000 --- a/libc/dns/gethoststxt.c +++ /dev/null @@ -1,94 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/calls/calls.h" -#include "libc/cxxabi.h" -#include "libc/dce.h" -#include "libc/dns/hoststxt.h" -#include "libc/dns/servicestxt.h" -#include "libc/intrin/pushpop.internal.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/thread/thread.h" - -static struct HostsTxt *g_hoststxt; -static struct HostsTxtInitialStaticMemory { - struct HostsTxt ht; - pthread_mutex_t lock; - struct HostsTxtEntry entries[8]; - char strings[64]; -} g_hoststxt_init; - -static const char *GetHostsTxtPath(char *path, size_t size) { - if (!IsWindows()) { - return "/etc/hosts"; - } else { - return GetSystemDirectoryPath(path, size, "drivers\\etc\\hosts"); - } -} - -/** - * Returns hosts.txt map. - * - * @note yoinking realloc() ensures there's no size limits - */ -const struct HostsTxt *GetHostsTxt(void) { - FILE *f; - char pathbuf[256]; - struct HostsTxtInitialStaticMemory *init; - init = &g_hoststxt_init; - pthread_mutex_lock(&init->lock); - if (!g_hoststxt) { - g_hoststxt = &init->ht; - init->ht.entries.n = pushpop(ARRAYLEN(init->entries)); - init->ht.entries.p = init->entries; - init->ht.strings.n = pushpop(ARRAYLEN(init->strings)); - init->ht.strings.p = init->strings; - __cxa_atexit((void *)FreeHostsTxt, &g_hoststxt, NULL); - if ((f = fopen(GetHostsTxtPath(pathbuf, sizeof(pathbuf)), "r"))) { - if (ParseHostsTxt(g_hoststxt, f) == -1) { - /* TODO(jart): Elevate robustness. */ - } - fclose(f); - } - } - pthread_mutex_unlock(&init->lock); - return g_hoststxt; -} - -/** - * Frees HOSTS.TXT data structure populated by ParseHostsTxt(). - */ -void FreeHostsTxt(struct HostsTxt **ht) { - if (*ht) { - if ((*ht)->entries.p != g_hoststxt_init.entries) { - free((*ht)->entries.p); - } - if ((*ht)->strings.p != g_hoststxt_init.strings) { - free((*ht)->strings.p); - } - if (*ht != &g_hoststxt_init.ht) { - free(*ht); - } - *ht = 0; - } -} diff --git a/libc/dns/getnameinfo.c b/libc/dns/getnameinfo.c deleted file mode 100644 index 7b8324efc..000000000 --- a/libc/dns/getnameinfo.c +++ /dev/null @@ -1,115 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/calls/calls.h" -#include "libc/dns/consts.h" -#include "libc/dns/dns.h" -#include "libc/dns/hoststxt.h" -#include "libc/dns/resolvconf.h" -#include "libc/dns/servicestxt.h" -#include "libc/fmt/conv.h" -#include "libc/fmt/itoa.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/inaddr.h" -#include "libc/sysv/errfuns.h" - -/** - * Resolves name/service for socket address. - * - * @param addr - * @param addrlen - * @param name - * @param namelen - * @param service - * @param servicelen - * @param flags - * - * @return 0 on success or EAI_xxx value - */ -int getnameinfo(const struct sockaddr *addr, uint32_t addrlen, char *name, - uint32_t namelen, char *service, uint32_t servicelen, - int flags) { - char *p, rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"]; - char info[NI_MAXHOST + 1]; - int port; - uint8_t *ip; - unsigned int valid_flags; - - valid_flags = - (NI_NAMEREQD | NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN | NI_DGRAM); - - if (flags & ~(valid_flags)) return EAI_BADFLAGS; - if (!name && !service) return EAI_NONAME; - if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) - return EAI_FAMILY; - - ip = (uint8_t *)&(((struct sockaddr_in *)addr)->sin_addr); - p = rdomain; - p = FormatUint32(p, ip[3]), *p++ = '.'; - p = FormatUint32(p, ip[2]), *p++ = '.'; - p = FormatUint32(p, ip[1]), *p++ = '.'; - p = FormatUint32(p, ip[0]), stpcpy(p, ".in-addr.arpa"); - info[0] = '\0'; - if (name != NULL && namelen != 0) { - if ((flags & NI_NUMERICHOST) && (flags & NI_NAMEREQD)) return EAI_NONAME; - - if ((flags & NI_NUMERICHOST) && - inet_ntop(AF_INET, ip, info, sizeof(info)) == NULL) - return EAI_SYSTEM; - else if (!info[0] && ResolveHostsReverse(GetHostsTxt(), AF_INET, ip, info, - sizeof(info)) < 0) - return EAI_SYSTEM; - else if (!info[0] && ResolveDnsReverse(GetResolvConf(), AF_INET, rdomain, - info, sizeof(info)) < 0) - return EAI_SYSTEM; - else if (!info[0] && (flags & NI_NAMEREQD)) - return EAI_NONAME; - else if (!info[0] && inet_ntop(AF_INET, ip, info, sizeof(info)) == NULL) - return EAI_SYSTEM; - - if (strlen(info) + 1 > namelen) return EAI_OVERFLOW; - strcpy(name, info); - } - - port = ntohs(((struct sockaddr_in *)addr)->sin_port); - info[0] = '\0'; - if (service != NULL && servicelen != 0) { - if ((flags & NI_NUMERICSERV) || - LookupServicesByPort(port, ((flags & NI_DGRAM) ? "udp" : "tcp"), 4, - info, sizeof(info), NULL) == -1) { - FormatInt32(info, port); - } - if (strlen(info) + 1 > servicelen) { - return EAI_OVERFLOW; - } - strcpy(service, info); - } - - return 0; -} diff --git a/libc/dns/getntnameservers.c b/libc/dns/getntnameservers.c deleted file mode 100644 index ebf3827c6..000000000 --- a/libc/dns/getntnameservers.c +++ /dev/null @@ -1,93 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/calls/calls.h" -#include "libc/calls/syscall_support-nt.internal.h" -#include "libc/dns/dns.h" -#include "libc/dns/resolvconf.h" -#include "libc/mem/arraylist.internal.h" -#include "libc/nt/enum/keyaccess.h" -#include "libc/nt/enum/reggetvalueflags.h" -#include "libc/nt/registry.h" -#include "libc/nt/runtime.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" - -/** - * Extracts DNS nameserver IPs from Windows Registry. - * - * @param resolv points to a ResolvConf object, which should be zero - * initialized by the caller; or if it already contains items, - * this function will append - * @return number of nameservers appended, or -1 w/ errno - */ -textwindows int GetNtNameServers(struct ResolvConf *resolv) { - int rc; - char value8[128]; - int64_t hkInterfaces; - char *state, *addr, *tmp; - struct sockaddr_in nameserver; - char16_t value[128], uuid[64]; - uint32_t i, keycount, valuebytes, uuidlen; - keycount = 0; - hkInterfaces = kNtInvalidHandleValue; - if (!RegOpenKeyEx( - kNtHkeyLocalMachine, - u"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", - 0, kNtKeyRead, &hkInterfaces) && - !RegQueryInfoKey(hkInterfaces, 0, 0, 0, &keycount, 0, 0, 0, 0, 0, 0, 0)) { - nameserver.sin_family = AF_INET; - nameserver.sin_port = htons(DNS_PORT); - rc = 0; - for (i = 0; i < keycount; ++i) { - uuidlen = sizeof(uuid); - if (!RegEnumKeyEx(hkInterfaces, i, uuid, &uuidlen, 0, 0, 0, 0) && - ((!RegGetValue(hkInterfaces, uuid, u"DhcpIpAddress", - kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value, - ((valuebytes = sizeof(value)), &valuebytes)) && - valuebytes > 2 * sizeof(char16_t)) || - (!RegGetValue(hkInterfaces, uuid, u"IpAddress", - kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value, - ((valuebytes = sizeof(value)), &valuebytes)) && - valuebytes > 2 * sizeof(char16_t))) && - ((!RegGetValue(hkInterfaces, uuid, u"DhcpNameServer", - kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value, - ((valuebytes = sizeof(value)), &valuebytes)) && - valuebytes > 2 * sizeof(char16_t)) || - (!RegGetValue(hkInterfaces, uuid, u"NameServer", - kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value, - ((valuebytes = sizeof(value)), &valuebytes)) && - valuebytes > 2 * sizeof(char16_t)))) { - tprecode16to8(value8, sizeof(value8), value); - tmp = value8; - while ((addr = strtok_r(tmp, ", ", &state))) { - if (inet_pton(AF_INET, addr, &nameserver.sin_addr.s_addr) == 1) { - if (append(&resolv->nameservers, &nameserver) != -1) ++rc; - } - tmp = NULL; - } - } - } - } else { - rc = __winerr(); - } - RegCloseKey(hkInterfaces); - return rc; -} diff --git a/libc/dns/getntprotocolstxtpath.c b/libc/dns/getntprotocolstxtpath.c deleted file mode 100644 index 880e4b258..000000000 --- a/libc/dns/getntprotocolstxtpath.c +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/prototxt.h" -#include "libc/dns/servicestxt.h" - -const char *GetProtocolsTxtPath(char *buf, size_t size) { - if (!IsWindows()) { - return "/etc/protocols"; - } else { - return GetSystemDirectoryPath(buf, size, "drivers\\etc\\protocol"); - } -} diff --git a/libc/dns/getntservicestxtpath.c b/libc/dns/getntservicestxtpath.c deleted file mode 100644 index f952dfa0d..000000000 --- a/libc/dns/getntservicestxtpath.c +++ /dev/null @@ -1,36 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/servicestxt.h" - -const char *GetServicesTxtPath(char *path, size_t size) { - if (!IsWindows()) { - return "/etc/services"; - } else { - return GetSystemDirectoryPath(path, size, "drivers\\etc\\services"); - } -} diff --git a/libc/dns/getprotobyname.c b/libc/dns/getprotobyname.c deleted file mode 100644 index 2735cf2b6..000000000 --- a/libc/dns/getprotobyname.c +++ /dev/null @@ -1,46 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/dns/prototxt.h" -#include "libc/mem/mem.h" - -struct protoent *getprotobyname(const char *name) { - static struct protoent *ptr0, pe0; - static char p_name[DNS_NAME_MAX + 1]; - - if (!ptr0) { - pe0.p_name = p_name; - if (!(pe0.p_aliases = calloc(1, sizeof(char *)))) return NULL; - pe0.p_proto = -1; - ptr0 = &pe0; - } - - ptr0->p_proto = LookupProtoByName(name, ptr0->p_name, DNS_NAME_MAX, NULL); - if (ptr0->p_proto == -1) return NULL; - - return ptr0; -} diff --git a/libc/dns/getprotobynumber.c b/libc/dns/getprotobynumber.c deleted file mode 100644 index 23f2ea00b..000000000 --- a/libc/dns/getprotobynumber.c +++ /dev/null @@ -1,47 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/dns/prototxt.h" -#include "libc/mem/mem.h" - -struct protoent *getprotobynumber(int proto) { - static struct protoent *ptr1, pe1; - static char p_name[DNS_NAME_MAX + 1]; - - if (!ptr1) { - pe1.p_name = p_name; - if (!(pe1.p_aliases = calloc(1, sizeof(char *)))) return NULL; - pe1.p_proto = -1; - ptr1 = &pe1; - } - - if (LookupProtoByNumber(proto, ptr1->p_name, DNS_NAME_MAX, NULL) == -1) - return NULL; - - ptr1->p_proto = proto; - return ptr1; -} diff --git a/libc/dns/getresolvconf.c b/libc/dns/getresolvconf.c deleted file mode 100644 index a2d75a856..000000000 --- a/libc/dns/getresolvconf.c +++ /dev/null @@ -1,83 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/cxxabi.h" -#include "libc/dce.h" -#include "libc/dns/resolvconf.h" -#include "libc/intrin/pushpop.internal.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/sock/struct/sockaddr.h" -#include "libc/stdio/stdio.h" -#include "libc/thread/thread.h" - -static struct ResolvConf *g_resolvconf; -static struct ResolvConfInitialStaticMemory { - struct ResolvConf rv; - pthread_mutex_t lock; - struct sockaddr_in nameservers[3]; -} g_resolvconf_init; - -/** - * Returns singleton with DNS server address. - */ -const struct ResolvConf *GetResolvConf(void) { - int rc; - FILE *f; - struct ResolvConfInitialStaticMemory *init; - init = &g_resolvconf_init; - pthread_mutex_lock(&init->lock); - if (!g_resolvconf) { - g_resolvconf = &init->rv; - pushmov(&init->rv.nameservers.n, ARRAYLEN(init->nameservers)); - init->rv.nameservers.p = init->nameservers; - __cxa_atexit((void *)FreeResolvConf, &g_resolvconf, NULL); - if (!IsWindows()) { - if ((f = fopen("/etc/resolv.conf", "r"))) { - rc = ParseResolvConf(g_resolvconf, f); - } else { - rc = -1; - } - fclose(f); - } else { - rc = GetNtNameServers(g_resolvconf); - } - if (rc == -1 && !IsTiny()) { - /* TODO(jart): Elevate robustness. */ - } - } - pthread_mutex_unlock(&init->lock); - return g_resolvconf; -} - -/** - * Frees resolv.conf data structure populated by ParseResolvConf(). - */ -void FreeResolvConf(struct ResolvConf **rvp) { - if (*rvp) { - if ((*rvp)->nameservers.p != g_resolvconf_init.nameservers) { - free((*rvp)->nameservers.p); - } - if (*rvp != &g_resolvconf_init.rv) { - free(*rvp); - } - *rvp = 0; - } -} diff --git a/libc/dns/getservbyname.c b/libc/dns/getservbyname.c deleted file mode 100644 index 02a5cf9fd..000000000 --- a/libc/dns/getservbyname.c +++ /dev/null @@ -1,55 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/dns/servicestxt.h" -#include "libc/mem/mem.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" - -struct servent *getservbyname(const char *name, const char *proto) { - static struct servent *ptr0, se0; - static char s_name[DNS_NAME_MAX + 1]; - static char localproto[DNS_NAME_MAX + 1]; - int p; - if (!ptr0) { - se0.s_name = s_name; - if (!(se0.s_aliases = calloc(1, sizeof(char *)))) return NULL; - se0.s_port = 0; - se0.s_proto = localproto; - ptr0 = &se0; - } - if (proto) { - strlcpy(localproto, proto, sizeof(localproto)); - } else { - *localproto = 0; - } - p = LookupServicesByName(name, ptr0->s_proto, DNS_NAME_MAX, ptr0->s_name, - DNS_NAME_MAX, NULL); - if (p == -1) return NULL; - ptr0->s_port = htons(p); - return ptr0; -} diff --git a/libc/dns/getservbyport.c b/libc/dns/getservbyport.c deleted file mode 100644 index ce0189060..000000000 --- a/libc/dns/getservbyport.c +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/dns/servicestxt.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" - -struct servent *getservbyport(int port, const char *proto) { - static struct servent *ptr1, se1; - static char s_name[DNS_NAME_MAX + 1]; - static char localproto[DNS_NAME_MAX + 1]; - if (!ptr1) { - se1.s_name = s_name; - if (!(se1.s_aliases = calloc(1, sizeof(char *)))) return NULL; - se1.s_port = 0; - se1.s_proto = localproto; - ptr1 = &se1; - } - if (proto) { - if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) { - return NULL; - } - } else { - *localproto = 0; - } - if (LookupServicesByPort(ntohs(port), ptr1->s_proto, DNS_NAME_MAX, - ptr1->s_name, DNS_NAME_MAX, NULL) == -1) { - return NULL; - } - ptr1->s_port = port; - return ptr1; -} diff --git a/libc/dns/herror.c b/libc/dns/herror.c deleted file mode 100644 index 5977b4fe2..000000000 --- a/libc/dns/herror.c +++ /dev/null @@ -1,36 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" -#include "libc/stdio/stdio.h" - -/** - * Prints `h_errno` description to stderr. - * @see perror() - */ -void herror(const char *s) { - fprintf(stderr, "%s%s%s\n", s ? s : "", s ? ": " : "", hstrerror(h_errno)); -} diff --git a/libc/dns/hostent.c b/libc/dns/hostent.c deleted file mode 100644 index 54b86d0a4..000000000 --- a/libc/dns/hostent.c +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" - -struct hostent *gethostent(void) { - return NULL; -} - -void sethostent(int stayopen) { -} - -void endhostent(void) { -} diff --git a/libc/dns/hoststxt.h b/libc/dns/hoststxt.h deleted file mode 100644 index f413fea51..000000000 --- a/libc/dns/hoststxt.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_ -#define COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_ -#include "libc/sock/struct/sockaddr.h" -#include "libc/stdio/stdio.h" -COSMOPOLITAN_C_START_ - -struct HostsTxtEntry { - uint8_t ip[4]; /* inet_ntop(AF_INET, he->ip, buf, size) */ - uint32_t name; /* &ht->strings.p[he->name] */ - uint32_t canon; /* &ht->strings.p[he->canon] */ -}; - -struct HostsTxtEntries { - size_t i, n; - struct HostsTxtEntry *p; -}; - -struct HostsTxtStrings { - size_t i, n; - char *p; -}; - -struct HostsTxt { - struct HostsTxtEntries entries; - struct HostsTxtStrings strings; -}; - -const struct HostsTxt *GetHostsTxt(void) returnsnonnull; -void FreeHostsTxt(struct HostsTxt **) paramsnonnull(); -int ParseHostsTxt(struct HostsTxt *, FILE *) paramsnonnull(); -int ResolveHostsTxt(const struct HostsTxt *, int, const char *, - struct sockaddr *, uint32_t, const char **) - paramsnonnull((1, 3)); -int ResolveHostsReverse(const struct HostsTxt *, int, const uint8_t *, char *, - size_t) paramsnonnull((1, 3)); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_ */ diff --git a/libc/dns/hstrerror.c b/libc/dns/hstrerror.c deleted file mode 100644 index 4344ed6b7..000000000 --- a/libc/dns/hstrerror.c +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dns/ent.h" - -/** - * Turns `h_errno` value into string. - */ -const char *hstrerror(int err) { - switch (err) { - case HOST_NOT_FOUND: - return "HOST_NOT_FOUND"; - case TRY_AGAIN: - return "TRY_AGAIN"; - case NO_RECOVERY: - return "NO_RECOVERY"; - case NO_DATA: - return "NO_DATA"; - default: - return "UNKNOWN"; - } -} diff --git a/libc/dns/lookupprotobyname.c b/libc/dns/lookupprotobyname.c deleted file mode 100644 index 281b46004..000000000 --- a/libc/dns/lookupprotobyname.c +++ /dev/null @@ -1,101 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/prototxt.h" -#include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" - -/** - * Opens and searches /etc/protocols to find number for a given name. - * - * @param protoname is a NULL-terminated string - * @param buf is a buffer to store the official name of the protocol - * @param bufsize is the size of buf - * @param filepath is the location of protocols file - * (if NULL, uses /etc/protocols) - * @return -1 on error, or - * positive protocol number - * - * @note aliases are read from file for comparison, but not returned. - * @see LookupProtoByNumber - */ -int LookupProtoByName(const char *protoname, char *buf, size_t bufsize, - const char *filepath) { - FILE *f; - char *line; - size_t linesize; - const char *path; - int found, result; - char pathbuf[256]; - char *name, *number, *alias, *comment, *tok; - if (!(path = filepath)) { - path = - !IsWindows() - ? "/etc/protocols" - : firstnonnull(GetProtocolsTxtPath(pathbuf, sizeof(pathbuf)), path); - } - if (bufsize == 0 || !(f = fopen(path, "r"))) { - return -1; - } - line = NULL; - linesize = 0; - found = 0; - result = -1; - while (found == 0 && getline(&line, &linesize, f) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - name = strtok_r(line, " \t\r\n\v", &tok); - number = strtok_r(NULL, "/ \t\r\n\v", &tok); - if (name && number) { - alias = name; - while (alias && strcasecmp(alias, protoname)) { - alias = strtok_r(NULL, " \t\r\n\v", &tok); - } - if (alias) { /* alias matched with protoname */ - if (!memccpy(buf, name, '\0', bufsize)) { - if (bufsize) { - *buf = 0; - } - break; - } - result = atoi(number); - found = 1; - } - } - } - free(line); - if (ferror(f)) { - errno = ferror(f); - return -1; - } - fclose(f); - if (!found) return -1; - return result; -} diff --git a/libc/dns/lookupprotobynumber.c b/libc/dns/lookupprotobynumber.c deleted file mode 100644 index 7aac82ab3..000000000 --- a/libc/dns/lookupprotobynumber.c +++ /dev/null @@ -1,90 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/prototxt.h" -#include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" - -/** - * Opens and searches /etc/protocols to find name for a given number. - * - * The format of /etc/protocols is like this: - * - * # comment - * # NAME PROTOCOL ALIASES - * ip 0 IP - * icmp 1 ICMP - * - * @param protonum is the protocol number - * @param buf is a buffer to store the official name of the protocol - * @param bufsize is the size of buf - * @param path is the location of the protocols file, which may be NULL - * to use the system-wide default - * @return 0 on success, -1 on error - * @note aliases are not read from the file. - */ -int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize, - const char *path) { - FILE *f; - int found; - char *line; - size_t linesize; - char pathbuf[256]; - char *name, *number, *comment, *tok; - if (!bufsize || - !(f = fopen(path ? path : GetProtocolsTxtPath(pathbuf, sizeof(pathbuf)), - "r"))) { - return -1; - } - line = NULL; - linesize = 0; - found = 0; - while (found == 0 && (getline(&line, &linesize, f)) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - name = strtok_r(line, " \t\r\n\v", &tok); - number = strtok_r(NULL, " \t\r\n\v", &tok); - if (name && number && protonum == atoi(number)) { - if (!memccpy(buf, name, '\0', bufsize)) { - strcpy(buf, ""); - break; - } - found = 1; - } - } - free(line); - if (ferror(f)) { - errno = ferror(f); - fclose(f); - return -1; - } - fclose(f); - if (!found) return -1; - return 0; -} diff --git a/libc/dns/lookupservicesbyname.c b/libc/dns/lookupservicesbyname.c deleted file mode 100644 index d41ea3fcd..000000000 --- a/libc/dns/lookupservicesbyname.c +++ /dev/null @@ -1,107 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/servicestxt.h" -#include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" - -/** - * Opens and searches /etc/services to find port for a given name. - * - * @param servname is a NULL-terminated string - * @param servproto is a NULL-terminated string (eg "tcp", "udp") - * (if servproto is an empty string, - * if is filled with the first matching - * protocol) - * @param servprotolen the size of servproto - * @param buf is a buffer to store the official name of the service - * (if NULL, the official name is not stored) - * @param bufsize is the size of buf - * @param path is the location of services file - * (if NULL, uses /etc/services) - * @return -1 on error, or positive port number - * @note aliases are read from file for comparison, but not returned. - * @see LookupServicesByPort - */ -int LookupServicesByName(const char *servname, char *servproto, - size_t servprotolen, char *buf, size_t bufsize, - const char *path) { - FILE *f; - char *line; - size_t linesize; - char pathbuf[256]; - int found, result; - char *name, *port, *proto, *alias, *comment, *tok; - if (servprotolen == 0 || - !(f = fopen(path ? path : GetServicesTxtPath(pathbuf, sizeof(pathbuf)), - "r"))) { - return -1; - } - line = NULL; - linesize = 0; - found = 0; - result = -1; - if (bufsize) strcpy(buf, ""); - while (found == 0 && (getline(&line, &linesize, f)) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - name = strtok_r(line, " \t\r\n\v", &tok); - port = strtok_r(NULL, "/ \t\r\n\v", &tok); - proto = strtok_r(NULL, " \t\r\n\v", &tok); - if (name && port && proto) { - alias = name; - while (alias && strcasecmp(alias, servname) != 0) - alias = strtok_r(NULL, " \t\r\n\v", &tok); - if (alias) /* alias matched with servname */ - { - if (!servproto[0] || strncasecmp(proto, servproto, servprotolen) == 0) { - if (!servproto[0] && !memccpy(servproto, proto, '\0', servprotolen)) { - strcpy(servproto, ""); - break; - } - if (bufsize && !memccpy(buf, name, '\0', bufsize)) { - *buf = 0; - break; - } - result = atoi(port); - found = 1; - } - } - } - } - free(line); - if (ferror(f)) { - errno = ferror(f); - return -1; - } - fclose(f); - if (!found) return -1; - return result; -} diff --git a/libc/dns/lookupservicesbyport.c b/libc/dns/lookupservicesbyport.c deleted file mode 100644 index 42af3aefc..000000000 --- a/libc/dns/lookupservicesbyport.c +++ /dev/null @@ -1,107 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dce.h" -#include "libc/dns/servicestxt.h" -#include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" - -/** - * Opens and searches /etc/services to find name for a given port. - * - * The format of /etc/services is like this: - * - * # comment - * # NAME PORT/PROTOCOL ALIASES - * ftp 21/tcp - * fsp 21/udp fspd - * ssh 22/tcp - * - * @param servport is the port number - * @param servproto is a NULL-terminated string (eg "tcp", "udp") - * (if servproto is an empty string, - * if is filled with the first matching - * protocol) - * @param servprotolen the size of servproto - * @param buf is a buffer to store the official name of the service - * @param bufsize is the size of buf - * @param path is the location of the services file, which may be NULL - * to use the system-wide default - * @return 0 on success, -1 on error - * @note aliases are not read from the file. - */ -int LookupServicesByPort(const int servport, char *servproto, - size_t servprotolen, char *buf, size_t bufsize, - const char *path) { - FILE *f; - int found; - char *line; - size_t linesize; - char pathbuf[256]; - char *name, *port, *proto, *comment, *tok; - if (!servprotolen || - !(f = fopen(path ? path : GetServicesTxtPath(pathbuf, sizeof(pathbuf)), - "r"))) { - return -1; - } - found = 0; - line = NULL; - linesize = 0; - if (bufsize) *buf = 0; - while (!found && (getline(&line, &linesize, f)) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - name = strtok_r(line, " \t\r\n\v", &tok); - port = strtok_r(NULL, "/ \t\r\n\v", &tok); - proto = strtok_r(NULL, " \t\r\n\v", &tok); - if (name && port && proto && servport == atoi(port)) { - if (!servproto[0] || strncasecmp(proto, servproto, servprotolen) == 0) { - if (!servproto[0] && !memccpy(servproto, proto, '\0', servprotolen)) { - strcpy(servproto, ""); - break; - } - if (!memccpy(buf, name, '\0', bufsize)) { - if (bufsize) { - *buf = 0; - } - break; - } - found = 1; - } - } - } - free(line); - if (ferror(f)) { - errno = ferror(f); - return -1; - } - fclose(f); - if (!found) return -1; - return 0; -} diff --git a/libc/dns/netent.c b/libc/dns/netent.c deleted file mode 100644 index 91dbca0b8..000000000 --- a/libc/dns/netent.c +++ /dev/null @@ -1,45 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" - -struct netent *getnetent(void) { - return NULL; -} - -struct netent *getnetbyname(const char *name) { - return NULL; -} - -struct netent *getnetbyaddr(uint32_t net, int type) { - return NULL; -} - -void setnetent(int stayopen) { -} - -void endnetent(void) { -} diff --git a/libc/dns/newaddrinfo.c b/libc/dns/newaddrinfo.c deleted file mode 100644 index 76f918b34..000000000 --- a/libc/dns/newaddrinfo.c +++ /dev/null @@ -1,39 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/sock/sock.h" -#include "libc/sysv/consts/af.h" - -#define SIZE sizeof(struct addrinfo) -#define ADDRLEN sizeof(struct sockaddr_in) - -struct addrinfo *newaddrinfo(uint16_t port) { - struct addrinfo *ai; - if ((ai = calloc(1, SIZE + ADDRLEN + DNS_NAME_MAX + 1))) { - ai->ai_family = AF_INET; - ai->ai_addrlen = ADDRLEN; - ai->ai_addr4 = (struct sockaddr_in *)((char *)ai + SIZE); - ai->ai_addr4->sin_family = AF_INET; - ai->ai_addr4->sin_port = htons(port); - ai->ai_canonname = (char *)ai + SIZE + ADDRLEN; - } - return ai; -} diff --git a/libc/dns/parsehoststxt.c b/libc/dns/parsehoststxt.c deleted file mode 100644 index 331722175..000000000 --- a/libc/dns/parsehoststxt.c +++ /dev/null @@ -1,72 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/dns/hoststxt.h" -#include "libc/errno.h" -#include "libc/mem/arraylist.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" - -/** - * Parses HOSTS.TXT contents. - * - * Hostnames were invented by Peggy Karp; her format looks like this: - * - * # this is a comment - * # IP CANON [ALT...] - * 203.0.113.1 lol.example. lol - * 203.0.113.2 cat.example. cat - * - * @param htp points to a HostsTxt object, which should be zero - * initialized by the caller; or if it already contains items, - * this function will append - * @param f is the file content; see fopen() and fmemopen() - * @return 0 on success, or -1 w/ errno - * @see hoststxtsort() which is the logical next step - */ -int ParseHostsTxt(struct HostsTxt *ht, FILE *f) { - char *line; - size_t linesize; - struct HostsTxtEntry entry; - char *addr, *name, *tok, *comment; - line = NULL; - linesize = 0; - while ((getline(&line, &linesize, f)) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - if ((addr = strtok_r(line, " \t\r\n\v", &tok)) && - inet_pton(AF_INET, addr, entry.ip) == 1) { - entry.canon = ht->strings.i; - while ((name = strtok_r(NULL, " \t\r\n\v", &tok))) { - entry.name = ht->strings.i; - concat(&ht->strings, name, strnlen(name, DNS_NAME_MAX) + 1); - append(&ht->entries, &entry); - } - } - } - free(line); - if (ferror(f)) { - errno = ferror(f); - return -1; - } - return 0; -} diff --git a/libc/dns/parseresolvconf.c b/libc/dns/parseresolvconf.c deleted file mode 100644 index f9a5cf05d..000000000 --- a/libc/dns/parseresolvconf.c +++ /dev/null @@ -1,68 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/dns/resolvconf.h" -#include "libc/mem/arraylist.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/inaddr.h" - -/** - * Parses /etc/resolv.conf file. - * - * The content of the file usually looks like this: - * - * nameserver 8.8.8.8 - * nameserver 8.8.4.4 - * - * @param resolv points to a ResolvConf object, which should be zero - * initialized by the caller; or if it already contains items, - * this function will append - * @param f is an open stream with file content - * @return number of nameservers appended, or -1 w/ errno - */ -int ParseResolvConf(struct ResolvConf *resolv, struct FILE *f) { - /* TODO(jart): options ndots:5 */ - int rc; - char *line; - size_t linesize; - struct sockaddr_in nameserver; - char *directive, *value, *tok, *comment; - rc = 0; - line = 0; - linesize = 0; - nameserver.sin_family = AF_INET; - nameserver.sin_port = htons(DNS_PORT); - while (getline(&line, &linesize, f) != -1) { - if ((comment = strchr(line, '#'))) *comment = '\0'; - if ((directive = strtok_r(line, " \t\r\n\v", &tok)) && - (value = strtok_r(NULL, " \t\r\n\v", &tok))) { - if ((strcmp(directive, "nameserver") == 0 && - inet_pton(AF_INET, value, &nameserver.sin_addr.s_addr) == 1)) { - if (append(&resolv->nameservers, &nameserver) != -1) ++rc; - } - } - } - free(line); - return rc | ferror(f); -} diff --git a/libc/dns/pascalifydnsname.c b/libc/dns/pascalifydnsname.c deleted file mode 100644 index 966f3dc6a..000000000 --- a/libc/dns/pascalifydnsname.c +++ /dev/null @@ -1,58 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/dns.h" -#include "libc/str/str.h" -#include "libc/sysv/errfuns.h" - -/** - * Writes dotted hostname to DNS message wire. - * - * The wire format is basically a sequence of Pascal strings, for each - * label in the name. We only do enough validation to maintain protocol - * invariants. - * - * @param name is a dotted NUL-terminated hostname string - * @return bytes written (excluding NUL) or -1 w/ errno - */ -int PascalifyDnsName(uint8_t *buf, size_t size, const char *name) { - size_t i, j, k, namelen; - if ((namelen = strlen(name)) > DNS_NAME_MAX) return enametoolong(); - i = 0; - if (size || namelen) { - if (namelen + 1 > size) return enospc(); - buf[0] = '\0'; - j = 0; - for (;;) { - for (k = 0; name[j + k] && name[j + k] != '.'; ++k) { - buf[i + k + 1] = name[j + k]; - } - if (k) { - if (k > DNS_LABEL_MAX) return enametoolong(); - buf[i] = k; - i += k + 1; - } - j += k + 1; - if (!name[j - 1]) { - break; - } - } - buf[i] = '\0'; - } - return i; -} diff --git a/libc/dns/protoent.c b/libc/dns/protoent.c deleted file mode 100644 index 772bcecc6..000000000 --- a/libc/dns/protoent.c +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/dns/ent.h" - -struct protoent *getprotoent(void) { - return NULL; -} - -void setprotoent(int stayopen) { -} - -void endprotoent(void) { -} diff --git a/libc/dns/prototxt.h b/libc/dns/prototxt.h deleted file mode 100644 index 8746f044d..000000000 --- a/libc/dns/prototxt.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_PROTOTXT_H_ -#define COSMOPOLITAN_LIBC_DNS_PROTOTXT_H_ -#include "libc/sock/sock.h" -#include "libc/stdio/stdio.h" -COSMOPOLITAN_C_START_ - -const char *GetProtocolsTxtPath(char *, size_t); - -int LookupProtoByNumber(const int, char *, size_t, const char *) - paramsnonnull((2)); -int LookupProtoByName(const char *, char *, size_t, const char *) - paramsnonnull((1, 2)); - -/* TODO: implement like struct HostsTxt? */ - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_PROTOTXT_H_ */ diff --git a/libc/dns/resolvconf.h b/libc/dns/resolvconf.h deleted file mode 100644 index 46a24064f..000000000 --- a/libc/dns/resolvconf.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_ -#define COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_ -#include "libc/sock/sock.h" -#include "libc/stdio/stdio.h" -COSMOPOLITAN_C_START_ - -struct Nameservers { - size_t i, n; - struct sockaddr_in *p; -}; - -struct ResolvConf { - struct Nameservers nameservers; -}; - -const struct ResolvConf *GetResolvConf(void) returnsnonnull; -int ParseResolvConf(struct ResolvConf *, struct FILE *) paramsnonnull(); -void FreeResolvConf(struct ResolvConf **) paramsnonnull(); -int GetNtNameServers(struct ResolvConf *) paramsnonnull(); - -COSMOPOLITAN_C_END_ -#endif /* COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_ */ diff --git a/libc/dns/resolvedns.c b/libc/dns/resolvedns.c deleted file mode 100644 index 83c6c4ac7..000000000 --- a/libc/dns/resolvedns.c +++ /dev/null @@ -1,113 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/calls/calls.h" -#include "libc/dns/consts.h" -#include "libc/dns/dns.h" -#include "libc/dns/dnsheader.h" -#include "libc/dns/dnsquestion.h" -#include "libc/dns/resolvconf.h" -#include "libc/serialize.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/internal.h" -#include "libc/sock/sock.h" -#include "libc/sock/struct/sockaddr.h" -#include "libc/stdio/rand.h" -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/ipproto.h" -#include "libc/sysv/consts/sock.h" -#include "libc/sysv/errfuns.h" - -#define kMsgMax 512 - -/** - * Queries Domain Name System for address associated with name. - * - * @param resolvconf can be GetResolvConf() - * @param af can be AF_INET, AF_UNSPEC - * @param name can be a local or fully-qualified hostname - * @param addr should point to a struct sockaddr_in; if this function - * succeeds, its sin_family and sin_addr fields will be modified - * @param addrsize is the byte size of addr - * @return number of matches found, or -1 w/ errno - * @error EAFNOSUPPORT. ENETDOWN, ENAMETOOLONG, EBADMSG - */ -int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name, - struct sockaddr *addr, uint32_t addrsize) { - int rc, fd, n; - struct DnsQuestion q; - struct DnsHeader h, h2; - struct sockaddr_in *a4; - uint8_t *p, *pe, msg[512]; - uint16_t rtype, rclass, rdlength; - if (addrsize < kMinSockaddr4Size) return einval(); - if (af != AF_INET && af != AF_UNSPEC) return eafnosupport(); - if (!resolvconf->nameservers.i) return 0; - bzero(&h, sizeof(h)); - rc = ebadmsg(); - h.id = _rand64(); - h.bf1 = 1; /* recursion desired */ - h.qdcount = 1; - q.qname = name; - q.qtype = DNS_TYPE_A; - q.qclass = DNS_CLASS_IN; - bzero(msg, sizeof(msg)); - SerializeDnsHeader(msg, &h); - if ((n = SerializeDnsQuestion(msg + 12, 500, &q)) == -1) return -1; - if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1; - if (sendto(fd, msg, 12 + n, 0, (struct sockaddr *)resolvconf->nameservers.p, - sizeof(*resolvconf->nameservers.p)) == 12 + n && - (n = read(fd, msg, 512)) >= 12) { - DeserializeDnsHeader(&h2, msg); - if (h2.id == h.id) { - rc = 0; - p = msg + 12; - pe = msg + n; - while (p < pe && h2.qdcount--) { - p += strnlen((char *)p, pe - p) + 1 + 4; - } - while (p < pe && h2.ancount--) { - if ((p[0] & 0xc0) == 0xc0) { /* name pointer */ - p += 2; - } else { - p += strnlen((char *)p, pe - p) + 1; - } - if (p + 10 <= pe) { - rtype = READ16BE(p); - rclass = READ16BE(p + 2); - // ttl = READ32BE(p + 4); - rdlength = READ16BE(p + 8); - if (p + 10 + rdlength <= pe && rdlength == 4 && - rclass == DNS_CLASS_IN && rtype == DNS_TYPE_A) { - rc = 1; - a4 = (struct sockaddr_in *)addr; - a4->sin_family = AF_INET; - memcpy(&a4->sin_addr.s_addr, p + 10, 4); - break; - } - p += 10 + rdlength; - } - } - } - } - close(fd); - return rc; -} diff --git a/libc/dns/resolvednsreverse.c b/libc/dns/resolvednsreverse.c deleted file mode 100644 index e6c4871df..000000000 --- a/libc/dns/resolvednsreverse.c +++ /dev/null @@ -1,128 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ This is free and unencumbered software released into the public domain. │ -│ │ -│ Anyone is free to copy, modify, publish, use, compile, sell, or │ -│ distribute this software, either in source code form or as a compiled │ -│ binary, for any purpose, commercial or non-commercial, and by any │ -│ means. │ -│ │ -│ In jurisdictions that recognize copyright laws, the author or authors │ -│ of this software dedicate any and all copyright interest in the │ -│ software to the public domain. We make this dedication for the benefit │ -│ of the public at large and to the detriment of our heirs and │ -│ successors. We intend this dedication to be an overt act of │ -│ relinquishment in perpetuity of all present and future rights to this │ -│ software under copyright law. │ -│ │ -│ 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 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/calls/calls.h" -#include "libc/dns/consts.h" -#include "libc/dns/dns.h" -#include "libc/dns/dnsheader.h" -#include "libc/dns/dnsquestion.h" -#include "libc/dns/resolvconf.h" -#include "libc/serialize.h" -#include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" -#include "libc/sock/sock.h" -#include "libc/sock/struct/sockaddr.h" -#include "libc/stdio/rand.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/ipproto.h" -#include "libc/sysv/consts/sock.h" -#include "libc/sysv/errfuns.h" - -#define kMsgMax 512 - -/** - * Performs reverse DNS lookup with IP address. - * - * @param resolvconf can be GetResolvConf() - * @param af can be AF_INET, AF_UNSPEC - * @param name is a reversed IP address string ending with .in-addr.arpa - * @param buf to store the obtained hostname if any - * @param bufsize is size of buf - * @return 0 on success, or -1 w/ errno - * @error EAFNOSUPPORT, ENETDOWN, ENAMETOOLONG, EBADMSG - */ -int ResolveDnsReverse(const struct ResolvConf *resolvconf, int af, - const char *name, char *buf, size_t bufsize) { - int rc, fd, n; - struct DnsQuestion q; - struct DnsHeader h, h2; - uint8_t *p, *pe, msg[512]; - uint16_t rtype, rclass, rdlength; - if (af != AF_INET && af != AF_UNSPEC) return eafnosupport(); - if (!resolvconf->nameservers.i) return 0; - bzero(&h, sizeof(h)); - rc = ebadmsg(); - h.id = _rand64(); - h.bf1 = 1; /* recursion desired */ - h.qdcount = 1; - q.qname = name; - q.qtype = DNS_TYPE_PTR; - q.qclass = DNS_CLASS_IN; - bzero(msg, sizeof(msg)); - SerializeDnsHeader(msg, &h); - if ((n = SerializeDnsQuestion(msg + 12, 500, &q)) == -1) return -1; - if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1; - if (sendto(fd, msg, 12 + n, 0, (struct sockaddr *)resolvconf->nameservers.p, - sizeof(*resolvconf->nameservers.p)) == 12 + n && - (n = read(fd, msg, 512)) >= 12) { - DeserializeDnsHeader(&h2, msg); - if (h2.id == h.id) { - rc = 0; - if (h2.ancount) { - p = msg + 12; - pe = msg + n; - while (p < pe && h2.qdcount) { - p += strnlen((char *)p, pe - p) + 1 + 4; - h2.qdcount--; - } - if (p + 1 < pe) { - if ((p[0] & 0b11000000) == 0b11000000) { /* name pointer */ - p += 2; - } else { - p += strnlen((char *)p, pe - p) + 1; - } - if (p + 2 + 2 + 4 + 2 < pe) { - rtype = READ16BE(p), p += 2; - rclass = READ16BE(p), p += 2; - /* ttl */ p += 4; - rdlength = READ16BE(p), p += 2; - if (p + rdlength <= pe && rtype == DNS_TYPE_PTR && - rclass == DNS_CLASS_IN) { - if (strnlen((char *)p, pe - p) + 1 > bufsize) - rc = -1; - else { - /* domain name starts with a letter */ - for (; !isalnum((char)(*p)) && p < pe; p++) rdlength--; - for (char *tmp = (char *)p; rdlength > 0 && *tmp != '\0'; - tmp++) { - /* each label is alphanumeric or hyphen - * any other character is assumed separator */ - if (!isalnum(*tmp) && *tmp != '-') *tmp = '.'; - rdlength--; - } - strcpy(buf, (char *)p); - } - } else - rc = -1; - } - } - } - } - } - close(fd); - return rc; -} diff --git a/libc/dns/resolvehostsreverse.c b/libc/dns/resolvehostsreverse.c deleted file mode 100644 index db21822c0..000000000 --- a/libc/dns/resolvehostsreverse.c +++ /dev/null @@ -1,52 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/consts.h" -#include "libc/dns/dns.h" -#include "libc/dns/hoststxt.h" -#include "libc/serialize.h" -#include "libc/mem/alg.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/errfuns.h" - -/** - * Finds name associated with address in HOSTS.TXT table. - * - * @param ht can be GetHostsTxt() - * @param af can be AF_INET - * @param ip is IP address in binary (sin_addr) - * @param buf is buffer to store the name - * @param bufsize is length of buf - * @return 1 if found, 0 if not found, or -1 w/ errno - * @error EAFNOSUPPORT - */ -int ResolveHostsReverse(const struct HostsTxt *ht, int af, const uint8_t *ip, - char *buf, size_t bufsize) { - size_t i; - if (af != AF_INET && af != AF_UNSPEC) return eafnosupport(); - for (i = 0; i < ht->entries.i; ++i) { - if (READ32LE(ip) == READ32LE(ht->entries.p[i].ip)) { - if (memccpy(buf, ht->strings.p + ht->entries.p[i].name, 0, bufsize)) { - return 1; - } - } - } - return 0; -} diff --git a/libc/dns/resolvehoststxt.c b/libc/dns/resolvehoststxt.c deleted file mode 100644 index 96125e26f..000000000 --- a/libc/dns/resolvehoststxt.c +++ /dev/null @@ -1,62 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│ vi: set et 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/dns/consts.h" -#include "libc/dns/dns.h" -#include "libc/dns/hoststxt.h" -#include "libc/mem/alg.h" -#include "libc/sock/sock.h" -#include "libc/str/str.h" -#include "libc/sysv/consts/af.h" -#include "libc/sysv/errfuns.h" - -/** - * Finds address associated with name in HOSTS.TXT table. - * - * @param ht can be GetHostsTxt() - * @param af can be AF_INET, AF_UNSPEC - * @param name can be a local or fully-qualified hostname - * @param addr should point to a struct sockaddr_in; if this function - * succeeds, its sin_family and sin_addr fields will be modified - * @param addrsize is the byte size of addr - * @param canon be used to return a pointer to the canonical name - * @return number of matches found, or -1 w/ errno - * @error EAFNOSUPPORT - */ -int ResolveHostsTxt(const struct HostsTxt *ht, int af, const char *name, - struct sockaddr *addr, uint32_t addrsize, - const char **canon) { - size_t i; - struct sockaddr_in *addr4; - if (af != AF_INET && af != AF_UNSPEC) return eafnosupport(); - for (i = 0; i < ht->entries.i; ++i) { - if (!CompareDnsNames(name, ht->strings.p + ht->entries.p[i].name)) { - if (addr) { - if (addrsize < kMinSockaddr4Size) return einval(); - addr4 = (struct sockaddr_in *)addr; - addr4->sin_family = AF_INET; - memcpy(&addr4->sin_addr.s_addr, &ht->entries.p[i].ip[0], 4); - } - if (canon) { - *canon = ht->strings.p + ht->entries.p[i].canon; - } - return 1; - } - } - return 0; -} diff --git a/libc/dns/rfc0226.txt b/libc/dns/rfc0226.txt deleted file mode 100644 index 961828314..000000000 --- a/libc/dns/rfc0226.txt +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - -NETWORK WORKING GROUP PEGGY KARP -REQUEST FOR COMMENTS #226 MITRE -NIC #7625 20 SEPT 71 -CATEGORIES: D.3 -UPDATES: NONE -OBSOLETES: NONE - - STANDARDIZATION OF HOST MNEUMONICS - -IN EACH TELNET IMPLEMENTATION, A LIST OF HOST NMEUMONICS IS PROVIDED -FOR THE USER TO INDICATE THE SERVING HOST DESIRED. CURRENTLY, EACH -SITE EMPLOYS THEIR OWN SPECIAL LIST. RATHER THAN REQUIRE THE USER TO -BE COGNIZANT OF THE IDIOSYNCRASIES OF EACH LIST, ESPECIALLY WHEN -CHAINED THROUGH SEVERAL HOSTS VIA TELNET, IT HAS BEEN RECOMMENDED THAT -STANDARD HOST DESIGNATORS BE ADOPTED. - -THE FOLLOWING LIST OF SIX CHARACTER DESIGNATORS IS PROPOSED AS THE -STANDARD LIST. REGISTER ANY OBJECTIONS BY 3 OCTOBER TO P. KARP (703) -893-3500 X2391, X2318. AN OFFICIAL POLICY AND IMPLEMENTATION DATE WILL -BE SET ON 8 OCTOBER. - -THE LIST: - HOST # DESIGNATOR - 1 UCLA - 65 UCLA36 - 2 SRIARC - 66 SRIAI - 3 UCSB - 4 UTAH - 6 MULTCS - 70 MITDM - 7 RAND - 8 SDC - 9 HARV - 10 LNCTX2 - 74 LNC360 - 11 STAN - 12 ILL - 69 BBN - 133 BBNB - 144 AMES - 145 MITRE - 158 TIP - - [ This RFC was put into machine readable form for entry ] - [ into the online RFC archives by BBN Corp. under the ] - [ direction of Alex McKenzie. 12/96 ] - - - - - [Page 1] - diff --git a/libc/dns/rfc0247.txt b/libc/dns/rfc0247.txt deleted file mode 100644 index 57e320915..000000000 --- a/libc/dns/rfc0247.txt +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -Network Working Group Peggy Karp -Request for Comments: #247 MITRE -NIC 7688 12 October 1971 -Categories: Policy, Telnet -Related: #226, 236, 239, 233, 237 -Obsoletes: #226 - - Proferred Set of Standard Host Names - - In RFC #226, BBN's TENEX list of Host names was set up as a strawman - set of standard Host names. Comments received since then (an RFC - actually generated comments!!!) have influenced me to propose the - following general rules for forming Host names. - - The Host names will be 8 characters in length. The general form is - - '-' - - will be at most 4 characters, formed as follows: - - (a) Use the keyword in the site name, if not more than - four characters, e.g., NASA Ames, Case Western - Reserve. ---- ---- - - (b) Use the standard acronym, if not more than four - characters, e.g., UCLA, RADC, NBS. - - (c) If a standard abbreviation exists, use it, e.g., Ill. - - (d) If none of the above apply, use the first four letters - in the site name, e.g., Burr, Mitr, Harv. - - (e) If none of the above is acceptable to the site, the - technical liaison should select the site mnemonic. - - will be at most 4 characters of the form - . - Examples of mfg. # are: - - IBM 360 2 digit model number - IBM 370 3 digit model number - PDP 1 - 2 digit model number - Burroughs 4 digits - CDC 4 digits - etc. - - - - - - - - [Page 1] - -RFC #247 - - - will be used when more than one machine of the same - type is located at a site (e.g., 2 PDP-10s at MIT, at SRI, and - at BBN). - - Limiting to 4 characters does not permit distinctions - to be made between machines with 4 digit mfg. #s. I expect - the situation will be handled in an ad hoc manner by the NIC if - it arises. - - TIPs are identified as 'TIP' rather than by '316'. If a Host - is not to be permanently addressable, the machine is identified - as 'TEST'. - - A list of Host names, formed according to these rules, is - attached. Alternate Host names should be provided, as - suggested by Jon Postel (RFC #236). RFC's 206, 233, and - 236 present lists with 4-character alternate names. The - Technical Liaison should select the alternate name for his - site and communicate the selection to the NIC. - - - The preceding rules and the attached list of Host names are - subject to the approval of the NWG. Hereafter, the list will - be generated and maintained by the NIC in cooperation with - the Technical Liaison at each site, as suggested in RFC #237. - Comments should be addressed to Dick Watson. - - - - - - - - [ This RFC was put into machine readable form for entry ] - - [ into the online RFC archives by BBN Corp. under the ] - - [ direction of Alex McKenzie. 12/96 ] - - - - - - - - - - - - [Page 2] - -RFC #247 -Attachment 1 - - NETWORK ADDRESS STANDARD NAME - --------------- ------------- - 1 UCLA-7 - 65 UCLA-91 - 2 SRI-10NI - 66 SRI-10AI - 3 UCSB-75 - 4 UTAH-10 - 5 BBN-516 - 69 BBN-10A - 133 BBN-10B - 6 MIT-645 - 70 MIT-10DM - 134 MIT-10AI - 7 RAND-65 - 71 RAND-10 - 8 SDC-75 - 9 HARV-10 - 73 HARV-1 - 137 HARV-11 - 10 LL-67 - 74 LL-TX2 - 138 LL-TSP - 11 SAIL-10 - 12 ILL-11 - 76 ILL-6500 - 13 CASE-10 - 14 CMU-10 - 15 BURR-6500 - 79 BURR-TEST - 16 AMES-67 - 144 AMES-TIP - 145 MITR-TIP - 18 RADC-645 - 146 RADC-TIP - 19 NBS-11 - 147 NBS-TIP - 148 ETAC-TIP - 21 TINK-418 - 22 MCCL-418 - 23 USC-44 - 151 USC-TIP - 152 GWC-TIP - 25 NCAR-7600 - 153 NCAR-TIP - 158 BBNX-TEST - - - - [Page 3] - -RFC #247 -Attachment 2 - - An Implementation Scheme - -If the standard Host names are formed according to the proposed -rules, the following implementation scheme, suggested by Steve -Crocker, can be used. - - Map into an 8-bit number, S and - map into an 8-bit number, M, - where - S + M = Network Address. - - S and M can be selected such that specification of - alone could cause a default to the "primary" Host at - the site. Note that this scheme depends on a unique - designator for each IMP. - -Some examples: - -If the "primary" Host at UCLA is the 91, let - UCLA -> S = X'41' - 7 -> M = X'40' - 91 -> M = X'00' -then for - UCLA-7, S + M = X'01' = 1 base 10 - UCLA-91,S + M = X'41' = 65 base 10 - -and - UCLA alone = X'41' = 65 base 10 - -If the primary Host at BBN is TENEX System A, let - BBN -> S = X'45' - 516 -> M = X'40' - 10A -> M = X'00' - 10B -> M = X'C0' -then for - BBN-516, S + M = X'05' = 5 base 10 - BBN-10A, S + M = X'45' = 69 base 10 - BBN-10B, S + M = X'85' = 133 base 10 - -and - BBN alone = X'45' = 69 base 10 - -The primary Host for each IMP would be designated by the -site and such information disseminated by the NIC. - - - - - - [Page 4] - diff --git a/libc/dns/rfc1035.txt b/libc/dns/rfc1035.txt deleted file mode 100644 index b1a9bf5a9..000000000 --- a/libc/dns/rfc1035.txt +++ /dev/null @@ -1,3077 +0,0 @@ -Network Working Group P. Mockapetris -Request for Comments: 1035 ISI - November 1987 -Obsoletes: RFCs 882, 883, 973 - - DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION - - -1. STATUS OF THIS MEMO - -This RFC describes the details of the domain system and protocol, and -assumes that the reader is familiar with the concepts discussed in a -companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034]. - -The domain system is a mixture of functions and data types which are an -official protocol and functions and data types which are still -experimental. Since the domain system is intentionally extensible, new -data types and experimental behavior should always be expected in parts -of the system beyond the official protocol. The official protocol parts -include standard queries, responses and the Internet class RR data -formats (e.g., host addresses). Since the previous RFC set, several -definitions have changed, so some previous definitions are obsolete. - -Experimental or obsolete features are clearly marked in these RFCs, and -such information should be used with caution. - -The reader is especially cautioned not to depend on the values which -appear in examples to be current or complete, since their purpose is -primarily pedagogical. Distribution of this memo is unlimited. - - Table of Contents - - 1. STATUS OF THIS MEMO 1 - 2. INTRODUCTION 3 - 2.1. Overview 3 - 2.2. Common configurations 4 - 2.3. Conventions 7 - 2.3.1. Preferred name syntax 7 - 2.3.2. Data Transmission Order 8 - 2.3.3. Character Case 9 - 2.3.4. Size limits 10 - 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 - 3.1. Name space definitions 10 - 3.2. RR definitions 11 - 3.2.1. Format 11 - 3.2.2. TYPE values 12 - 3.2.3. QTYPE values 12 - 3.2.4. CLASS values 13 - - - -Mockapetris [Page 1] - -RFC 1035 Domain Implementation and Specification November 1987 - - - 3.2.5. QCLASS values 13 - 3.3. Standard RRs 13 - 3.3.1. CNAME RDATA format 14 - 3.3.2. HINFO RDATA format 14 - 3.3.3. MB RDATA format (EXPERIMENTAL) 14 - 3.3.4. MD RDATA format (Obsolete) 15 - 3.3.5. MF RDATA format (Obsolete) 15 - 3.3.6. MG RDATA format (EXPERIMENTAL) 16 - 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 - 3.3.8. MR RDATA format (EXPERIMENTAL) 17 - 3.3.9. MX RDATA format 17 - 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 - 3.3.11. NS RDATA format 18 - 3.3.12. PTR RDATA format 18 - 3.3.13. SOA RDATA format 19 - 3.3.14. TXT RDATA format 20 - 3.4. ARPA Internet specific RRs 20 - 3.4.1. A RDATA format 20 - 3.4.2. WKS RDATA format 21 - 3.5. IN-ADDR.ARPA domain 22 - 3.6. Defining new types, classes, and special namespaces 24 - 4. MESSAGES 25 - 4.1. Format 25 - 4.1.1. Header section format 26 - 4.1.2. Question section format 28 - 4.1.3. Resource record format 29 - 4.1.4. Message compression 30 - 4.2. Transport 32 - 4.2.1. UDP usage 32 - 4.2.2. TCP usage 32 - 5. MASTER FILES 33 - 5.1. Format 33 - 5.2. Use of master files to define zones 35 - 5.3. Master file example 36 - 6. NAME SERVER IMPLEMENTATION 37 - 6.1. Architecture 37 - 6.1.1. Control 37 - 6.1.2. Database 37 - 6.1.3. Time 39 - 6.2. Standard query processing 39 - 6.3. Zone refresh and reload processing 39 - 6.4. Inverse queries (Optional) 40 - 6.4.1. The contents of inverse queries and responses 40 - 6.4.2. Inverse query and response example 41 - 6.4.3. Inverse query processing 42 - - - - - - -Mockapetris [Page 2] - -RFC 1035 Domain Implementation and Specification November 1987 - - - 6.5. Completion queries and responses 42 - 7. RESOLVER IMPLEMENTATION 43 - 7.1. Transforming a user request into a query 43 - 7.2. Sending the queries 44 - 7.3. Processing responses 46 - 7.4. Using the cache 47 - 8. MAIL SUPPORT 47 - 8.1. Mail exchange binding 48 - 8.2. Mailbox binding (Experimental) 48 - 9. REFERENCES and BIBLIOGRAPHY 50 - Index 54 - -2. INTRODUCTION - -2.1. Overview - -The goal of domain names is to provide a mechanism for naming resources -in such a way that the names are usable in different hosts, networks, -protocol families, internets, and administrative organizations. - -From the user's point of view, domain names are useful as arguments to a -local agent, called a resolver, which retrieves information associated -with the domain name. Thus a user might ask for the host address or -mail information associated with a particular domain name. To enable -the user to request a particular type of information, an appropriate -query type is passed to the resolver with the domain name. To the user, -the domain tree is a single information space; the resolver is -responsible for hiding the distribution of data among name servers from -the user. - -From the resolver's point of view, the database that makes up the domain -space is distributed among various name servers. Different parts of the -domain space are stored in different name servers, although a particular -data item will be stored redundantly in two or more name servers. The -resolver starts with knowledge of at least one name server. When the -resolver processes a user query it asks a known name server for the -information; in return, the resolver either receives the desired -information or a referral to another name server. Using these -referrals, resolvers learn the identities and contents of other name -servers. Resolvers are responsible for dealing with the distribution of -the domain space and dealing with the effects of name server failure by -consulting redundant databases in other servers. - -Name servers manage two kinds of data. The first kind of data held in -sets called zones; each zone is the complete database for a particular -"pruned" subtree of the domain space. This data is called -authoritative. A name server periodically checks to make sure that its -zones are up to date, and if not, obtains a new copy of updated zones - - - -Mockapetris [Page 3] - -RFC 1035 Domain Implementation and Specification November 1987 - - -from master files stored locally or in another name server. The second -kind of data is cached data which was acquired by a local resolver. -This data may be incomplete, but improves the performance of the -retrieval process when non-local data is repeatedly accessed. Cached -data is eventually discarded by a timeout mechanism. - -This functional structure isolates the problems of user interface, -failure recovery, and distribution in the resolvers and isolates the -database update and refresh problems in the name servers. - -2.2. Common configurations - -A host can participate in the domain name system in a number of ways, -depending on whether the host runs programs that retrieve information -from the domain system, name servers that answer queries from other -hosts, or various combinations of both functions. The simplest, and -perhaps most typical, configuration is shown below: - - Local Host | Foreign - | - +---------+ +----------+ | +--------+ - | | user queries | |queries | | | - | User |-------------->| |---------|->|Foreign | - | Program | | Resolver | | | Name | - | |<--------------| |<--------|--| Server | - | | user responses| |responses| | | - +---------+ +----------+ | +--------+ - | A | - cache additions | | references | - V | | - +----------+ | - | cache | | - +----------+ | - -User programs interact with the domain name space through resolvers; the -format of user queries and user responses is specific to the host and -its operating system. User queries will typically be operating system -calls, and the resolver and its cache will be part of the host operating -system. Less capable hosts may choose to implement the resolver as a -subroutine to be linked in with every program that needs its services. -Resolvers answer user queries with information they acquire via queries -to foreign name servers and the local cache. - -Note that the resolver may have to make several queries to several -different foreign name servers to answer a particular user query, and -hence the resolution of a user query may involve several network -accesses and an arbitrary amount of time. The queries to foreign name -servers and the corresponding responses have a standard format described - - - -Mockapetris [Page 4] - -RFC 1035 Domain Implementation and Specification November 1987 - - -in this memo, and may be datagrams. - -Depending on its capabilities, a name server could be a stand alone -program on a dedicated machine or a process or processes on a large -timeshared host. A simple configuration might be: - - Local Host | Foreign - | - +---------+ | - / /| | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - -Here a primary name server acquires information about one or more zones -by reading master files from its local file system, and answers queries -about those zones that arrive from foreign resolvers. - -The DNS requires that all zones be redundantly supported by more than -one name server. Designated secondary servers can acquire zones and -check for updates from the primary server using the zone transfer -protocol of the DNS. This configuration is shown below: - - Local Host | Foreign - | - +---------+ | - / /| | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - A |maintenance | +--------+ - | +------------|->| | - | queries | |Foreign | - | | | Name | - +------------------|--| Server | - maintenance responses | +--------+ - -In this configuration, the name server periodically establishes a -virtual circuit to a foreign name server to acquire a copy of a zone or -to check that an existing copy has not changed. The messages sent for - - - -Mockapetris [Page 5] - -RFC 1035 Domain Implementation and Specification November 1987 - - -these maintenance activities follow the same form as queries and -responses, but the message sequences are somewhat different. - -The information flow in a host that supports all aspects of the domain -name system is shown below: - - Local Host | Foreign - | - +---------+ +----------+ | +--------+ - | | user queries | |queries | | | - | User |-------------->| |---------|->|Foreign | - | Program | | Resolver | | | Name | - | |<--------------| |<--------|--| Server | - | | user responses| |responses| | | - +---------+ +----------+ | +--------+ - | A | - cache additions | | references | - V | | - +----------+ | - | Shared | | - | database | | - +----------+ | - A | | - +---------+ refreshes | | references | - / /| | V | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - A |maintenance | +--------+ - | +------------|->| | - | queries | |Foreign | - | | | Name | - +------------------|--| Server | - maintenance responses | +--------+ - -The shared database holds domain space data for the local name server -and resolver. The contents of the shared database will typically be a -mixture of authoritative data maintained by the periodic refresh -operations of the name server and cached data from previous resolver -requests. The structure of the domain data and the necessity for -synchronization between name servers and resolvers imply the general -characteristics of this database, but the actual format is up to the -local implementor. - - - - -Mockapetris [Page 6] - -RFC 1035 Domain Implementation and Specification November 1987 - - -Information flow can also be tailored so that a group of hosts act -together to optimize activities. Sometimes this is done to offload less -capable hosts so that they do not have to implement a full resolver. -This can be appropriate for PCs or hosts which want to minimize the -amount of new network code which is required. This scheme can also -allow a group of hosts can share a small number of caches rather than -maintaining a large number of separate caches, on the premise that the -centralized caches will have a higher hit ratio. In either case, -resolvers are replaced with stub resolvers which act as front ends to -resolvers located in a recursive server in one or more name servers -known to perform that service: - - Local Hosts | Foreign - | - +---------+ | - | | responses | - | Stub |<--------------------+ | - | Resolver| | | - | |----------------+ | | - +---------+ recursive | | | - queries | | | - V | | - +---------+ recursive +----------+ | +--------+ - | | queries | |queries | | | - | Stub |-------------->| Recursive|---------|->|Foreign | - | Resolver| | Server | | | Name | - | |<--------------| |<--------|--| Server | - +---------+ responses | |responses| | | - +----------+ | +--------+ - | Central | | - | cache | | - +----------+ | - -In any case, note that domain components are always replicated for -reliability whenever possible. - -2.3. Conventions - -The domain system has several conventions dealing with low-level, but -fundamental, issues. While the implementor is free to violate these -conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in -ALL behavior observed from other hosts. - -2.3.1. Preferred name syntax - -The DNS specifications attempt to be as general as possible in the rules -for constructing domain names. The idea is that the name of any -existing object can be expressed as a domain name with minimal changes. - - - -Mockapetris [Page 7] - -RFC 1035 Domain Implementation and Specification November 1987 - - -However, when assigning a domain name for an object, the prudent user -will select a name which satisfies both the rules of the domain system -and any existing rules for the object, whether these rules are published -or implied by existing programs. - -For example, when naming a mail domain, the user should satisfy both the -rules of this memo and those in RFC-822. When creating a new host name, -the old rules for HOSTS.TXT should be followed. This avoids problems -when old software is converted to use domain names. - -The following syntax will result in fewer problems with many - -applications that use domain names (e.g., mail, TELNET). - - ::= | " " - - ::=